chore: enable formatting over the entire codebase in CI (#6655)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Frank Elsinga
2026-01-09 02:10:36 +01:00
committed by GitHub
co-authored by autofix-ci[bot]
parent 6658f2ce41
commit 0f61d7ee1b
422 changed files with 30897 additions and 27377 deletions
+3 -12
View File
@@ -44,10 +44,7 @@ describe("GameDig Monitor", () => {
const gamedigMonitor = new GameDigMonitorType();
mock.method(GameDig, "query", async (options) => {
assert.ok(
net.isIP(options.host) !== 0,
`Expected IP address, got ${options.host}`
);
assert.ok(net.isIP(options.host) !== 0, `Expected IP address, got ${options.host}`);
return {
name: "Test Server",
ping: 50,
@@ -234,10 +231,7 @@ describe("GameDig Monitor", () => {
status: PENDING,
};
await assert.rejects(
gamedigMonitor.check(monitor, heartbeat, {}),
/Error/
);
await assert.rejects(gamedigMonitor.check(monitor, heartbeat, {}), /Error/);
});
test("resolveHostname() returns IP address when given valid hostname", async () => {
@@ -245,10 +239,7 @@ describe("GameDig Monitor", () => {
const resolvedIP = await gamedigMonitor.resolveHostname("localhost");
assert.ok(
net.isIP(resolvedIP) !== 0,
`Expected valid IP address, got ${resolvedIP}`
);
assert.ok(net.isIP(resolvedIP) !== 0, `Expected valid IP address, got ${resolvedIP}`);
});
test("resolveHostname() rejects when DNS resolution fails for invalid hostname", async () => {
+193 -205
View File
@@ -43,7 +43,7 @@ async function createTestGrpcServer(port, methodHandlers) {
longs: String,
enums: String,
defaults: true,
oneofs: true
oneofs: true,
});
const protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
const testPackage = protoDescriptor.test;
@@ -62,245 +62,233 @@ async function createTestGrpcServer(port, methodHandlers) {
});
return new Promise((resolve, reject) => {
server.bindAsync(
`0.0.0.0:${port}`,
grpc.ServerCredentials.createInsecure(),
(err) => {
if (err) {
reject(err);
} else {
server.start();
// Clean up temp file
fs.unlinkSync(protoPath);
resolve(server);
}
server.bindAsync(`0.0.0.0:${port}`, grpc.ServerCredentials.createInsecure(), (err) => {
if (err) {
reject(err);
} else {
server.start();
// Clean up temp file
fs.unlinkSync(protoPath);
resolve(server);
}
);
});
});
}
describe("GrpcKeywordMonitorType", {
skip: !!process.env.CI && (process.platform !== "linux" || process.arch !== "x64"),
}, () => {
test("check() sets status to UP when keyword is found in response", async () => {
const port = 50051;
const server = await createTestGrpcServer(port, {
Echo: (call, callback) => {
callback(null, { message: "Hello World with SUCCESS keyword" });
describe(
"GrpcKeywordMonitorType",
{
skip: !!process.env.CI && (process.platform !== "linux" || process.arch !== "x64"),
},
() => {
test("check() sets status to UP when keyword is found in response", async () => {
const port = 50051;
const server = await createTestGrpcServer(port, {
Echo: (call, callback) => {
callback(null, { message: "Hello World with SUCCESS keyword" });
},
});
const grpcMonitor = new GrpcKeywordMonitorType();
const monitor = {
grpcUrl: `localhost:${port}`,
grpcProtobuf: testProto,
grpcServiceName: "test.TestService",
grpcMethod: "echo",
grpcBody: JSON.stringify({ message: "test" }),
keyword: "SUCCESS",
invertKeyword: false,
grpcEnableTls: false,
isInvertKeyword: () => false,
};
const heartbeat = {
msg: "",
status: PENDING,
};
try {
await grpcMonitor.check(monitor, heartbeat, {});
assert.strictEqual(heartbeat.status, UP);
assert.ok(heartbeat.msg.includes("SUCCESS"));
assert.ok(heartbeat.msg.includes("is"));
} finally {
server.forceShutdown();
}
});
const grpcMonitor = new GrpcKeywordMonitorType();
const monitor = {
grpcUrl: `localhost:${port}`,
grpcProtobuf: testProto,
grpcServiceName: "test.TestService",
grpcMethod: "echo",
grpcBody: JSON.stringify({ message: "test" }),
keyword: "SUCCESS",
invertKeyword: false,
grpcEnableTls: false,
isInvertKeyword: () => false,
};
test("check() rejects when keyword is not found in response", async () => {
const port = 50052;
const server = await createTestGrpcServer(port, {
Echo: (call, callback) => {
callback(null, { message: "Hello World without the expected keyword" });
},
});
const heartbeat = {
msg: "",
status: PENDING,
};
const grpcMonitor = new GrpcKeywordMonitorType();
const monitor = {
grpcUrl: `localhost:${port}`,
grpcProtobuf: testProto,
grpcServiceName: "test.TestService",
grpcMethod: "echo",
grpcBody: JSON.stringify({ message: "test" }),
keyword: "MISSING",
invertKeyword: false,
grpcEnableTls: false,
isInvertKeyword: () => false,
};
try {
await grpcMonitor.check(monitor, heartbeat, {});
assert.strictEqual(heartbeat.status, UP);
assert.ok(heartbeat.msg.includes("SUCCESS"));
assert.ok(heartbeat.msg.includes("is"));
} finally {
server.forceShutdown();
}
});
const heartbeat = {
msg: "",
status: PENDING,
};
test("check() rejects when keyword is not found in response", async () => {
const port = 50052;
const server = await createTestGrpcServer(port, {
Echo: (call, callback) => {
callback(null, { message: "Hello World without the expected keyword" });
}
});
const grpcMonitor = new GrpcKeywordMonitorType();
const monitor = {
grpcUrl: `localhost:${port}`,
grpcProtobuf: testProto,
grpcServiceName: "test.TestService",
grpcMethod: "echo",
grpcBody: JSON.stringify({ message: "test" }),
keyword: "MISSING",
invertKeyword: false,
grpcEnableTls: false,
isInvertKeyword: () => false,
};
const heartbeat = {
msg: "",
status: PENDING,
};
try {
await assert.rejects(
grpcMonitor.check(monitor, heartbeat, {}),
(err) => {
try {
await assert.rejects(grpcMonitor.check(monitor, heartbeat, {}), (err) => {
assert.ok(err.message.includes("MISSING"));
assert.ok(err.message.includes("not"));
return true;
}
);
} finally {
server.forceShutdown();
}
});
test("check() rejects when inverted keyword is present in response", async () => {
const port = 50053;
const server = await createTestGrpcServer(port, {
Echo: (call, callback) => {
callback(null, { message: "Response with ERROR keyword" });
});
} finally {
server.forceShutdown();
}
});
const grpcMonitor = new GrpcKeywordMonitorType();
const monitor = {
grpcUrl: `localhost:${port}`,
grpcProtobuf: testProto,
grpcServiceName: "test.TestService",
grpcMethod: "echo",
grpcBody: JSON.stringify({ message: "test" }),
keyword: "ERROR",
invertKeyword: true,
grpcEnableTls: false,
isInvertKeyword: () => true,
};
test("check() rejects when inverted keyword is present in response", async () => {
const port = 50053;
const server = await createTestGrpcServer(port, {
Echo: (call, callback) => {
callback(null, { message: "Response with ERROR keyword" });
},
});
const heartbeat = {
msg: "",
status: PENDING,
};
const grpcMonitor = new GrpcKeywordMonitorType();
const monitor = {
grpcUrl: `localhost:${port}`,
grpcProtobuf: testProto,
grpcServiceName: "test.TestService",
grpcMethod: "echo",
grpcBody: JSON.stringify({ message: "test" }),
keyword: "ERROR",
invertKeyword: true,
grpcEnableTls: false,
isInvertKeyword: () => true,
};
try {
await assert.rejects(
grpcMonitor.check(monitor, heartbeat, {}),
(err) => {
const heartbeat = {
msg: "",
status: PENDING,
};
try {
await assert.rejects(grpcMonitor.check(monitor, heartbeat, {}), (err) => {
assert.ok(err.message.includes("ERROR"));
assert.ok(err.message.includes("present"));
return true;
}
);
} finally {
server.forceShutdown();
}
});
test("check() sets status to UP when inverted keyword is not present in response", async () => {
const port = 50054;
const server = await createTestGrpcServer(port, {
Echo: (call, callback) => {
callback(null, { message: "Response without error keyword" });
});
} finally {
server.forceShutdown();
}
});
const grpcMonitor = new GrpcKeywordMonitorType();
const monitor = {
grpcUrl: `localhost:${port}`,
grpcProtobuf: testProto,
grpcServiceName: "test.TestService",
grpcMethod: "echo",
grpcBody: JSON.stringify({ message: "test" }),
keyword: "ERROR",
invertKeyword: true,
grpcEnableTls: false,
isInvertKeyword: () => true,
};
test("check() sets status to UP when inverted keyword is not present in response", async () => {
const port = 50054;
const server = await createTestGrpcServer(port, {
Echo: (call, callback) => {
callback(null, { message: "Response without error keyword" });
},
});
const heartbeat = {
msg: "",
status: PENDING,
};
const grpcMonitor = new GrpcKeywordMonitorType();
const monitor = {
grpcUrl: `localhost:${port}`,
grpcProtobuf: testProto,
grpcServiceName: "test.TestService",
grpcMethod: "echo",
grpcBody: JSON.stringify({ message: "test" }),
keyword: "ERROR",
invertKeyword: true,
grpcEnableTls: false,
isInvertKeyword: () => true,
};
try {
await grpcMonitor.check(monitor, heartbeat, {});
assert.strictEqual(heartbeat.status, UP);
assert.ok(heartbeat.msg.includes("ERROR"));
assert.ok(heartbeat.msg.includes("not"));
} finally {
server.forceShutdown();
}
});
const heartbeat = {
msg: "",
status: PENDING,
};
test("check() rejects when gRPC server is unreachable", async () => {
const grpcMonitor = new GrpcKeywordMonitorType();
const monitor = {
grpcUrl: "localhost:50099",
grpcProtobuf: testProto,
grpcServiceName: "test.TestService",
grpcMethod: "echo",
grpcBody: JSON.stringify({ message: "test" }),
keyword: "SUCCESS",
invertKeyword: false,
grpcEnableTls: false,
isInvertKeyword: () => false,
};
try {
await grpcMonitor.check(monitor, heartbeat, {});
assert.strictEqual(heartbeat.status, UP);
assert.ok(heartbeat.msg.includes("ERROR"));
assert.ok(heartbeat.msg.includes("not"));
} finally {
server.forceShutdown();
}
});
const heartbeat = {
msg: "",
status: PENDING,
};
test("check() rejects when gRPC server is unreachable", async () => {
const grpcMonitor = new GrpcKeywordMonitorType();
const monitor = {
grpcUrl: "localhost:50099",
grpcProtobuf: testProto,
grpcServiceName: "test.TestService",
grpcMethod: "echo",
grpcBody: JSON.stringify({ message: "test" }),
keyword: "SUCCESS",
invertKeyword: false,
grpcEnableTls: false,
isInvertKeyword: () => false,
};
await assert.rejects(
grpcMonitor.check(monitor, heartbeat, {}),
(err) => {
const heartbeat = {
msg: "",
status: PENDING,
};
await assert.rejects(grpcMonitor.check(monitor, heartbeat, {}), (err) => {
// Should fail with connection error
return true;
}
);
});
test("check() truncates long response messages in error output", async () => {
const port = 50055;
const longMessage = "A".repeat(100) + " with SUCCESS keyword";
const server = await createTestGrpcServer(port, {
Echo: (call, callback) => {
callback(null, { message: longMessage });
}
});
});
const grpcMonitor = new GrpcKeywordMonitorType();
const monitor = {
grpcUrl: `localhost:${port}`,
grpcProtobuf: testProto,
grpcServiceName: "test.TestService",
grpcMethod: "echo",
grpcBody: JSON.stringify({ message: "test" }),
keyword: "MISSING",
invertKeyword: false,
grpcEnableTls: false,
isInvertKeyword: () => false,
};
test("check() truncates long response messages in error output", async () => {
const port = 50055;
const longMessage = "A".repeat(100) + " with SUCCESS keyword";
const heartbeat = {
msg: "",
status: PENDING,
};
const server = await createTestGrpcServer(port, {
Echo: (call, callback) => {
callback(null, { message: longMessage });
},
});
try {
await assert.rejects(
grpcMonitor.check(monitor, heartbeat, {}),
(err) => {
const grpcMonitor = new GrpcKeywordMonitorType();
const monitor = {
grpcUrl: `localhost:${port}`,
grpcProtobuf: testProto,
grpcServiceName: "test.TestService",
grpcMethod: "echo",
grpcBody: JSON.stringify({ message: "test" }),
keyword: "MISSING",
invertKeyword: false,
grpcEnableTls: false,
isInvertKeyword: () => false,
};
const heartbeat = {
msg: "",
status: PENDING,
};
try {
await assert.rejects(grpcMonitor.check(monitor, heartbeat, {}), (err) => {
// Should truncate message to 50 characters with "..."
assert.ok(err.message.includes("..."));
return true;
}
);
} finally {
server.forceShutdown();
}
});
});
});
} finally {
server.forceShutdown();
}
});
}
);
+161 -150
View File
@@ -15,7 +15,14 @@ const { UP, PENDING } = require("../../../src/util");
* @param {string|null} conditions JSON string of conditions or null
* @returns {Promise<Heartbeat>} the heartbeat produced by the check
*/
async function testMqtt(mqttSuccessMessage, mqttCheckType, receivedMessage, monitorTopic = "test", publishTopic = "test", conditions = null) {
async function testMqtt(
mqttSuccessMessage,
mqttCheckType,
receivedMessage,
monitorTopic = "test",
publishTopic = "test",
conditions = null
) {
const hiveMQContainer = await new HiveMQContainer().start();
const connectionString = hiveMQContainer.getConnectionString();
const mqttMonitorType = new MqttMonitorType();
@@ -56,170 +63,174 @@ async function testMqtt(mqttSuccessMessage, mqttCheckType, receivedMessage, moni
return heartbeat;
}
describe("MqttMonitorType", {
concurrency: 4,
skip: !!process.env.CI && (process.platform !== "linux" || process.arch !== "x64")
}, () => {
test("check() sets status to UP when keyword is found in message (type=default)", async () => {
const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: test; Message: -> KEYWORD <-");
});
describe(
"MqttMonitorType",
{
concurrency: 4,
skip: !!process.env.CI && (process.platform !== "linux" || process.arch !== "x64"),
},
() => {
test("check() sets status to UP when keyword is found in message (type=default)", async () => {
const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: test; Message: -> KEYWORD <-");
});
test("check() sets status to UP when keyword is found in nested topic", async () => {
const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/b/c", "a/b/c");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: a/b/c; Message: -> KEYWORD <-");
});
test("check() sets status to UP when keyword is found in nested topic", async () => {
const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/b/c", "a/b/c");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: a/b/c; Message: -> KEYWORD <-");
});
test("check() sets status to UP when keyword is found in nested topic with special characters", async () => {
const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/'/$/./*/%", "a/'/$/./*/%");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: a/'/$/./*/%; Message: -> KEYWORD <-");
});
test("check() sets status to UP when keyword is found in nested topic with special characters", async () => {
const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/'/$/./*/%", "a/'/$/./*/%");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: a/'/$/./*/%; Message: -> KEYWORD <-");
});
test("check() sets status to UP when keyword is found using # wildcard", async () => {
const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/#", "a/b/c");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: a/b/c; Message: -> KEYWORD <-");
});
test("check() sets status to UP when keyword is found using # wildcard", async () => {
const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/#", "a/b/c");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: a/b/c; Message: -> KEYWORD <-");
});
test("check() sets status to UP when keyword is found using + wildcard", async () => {
const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/+/c", "a/b/c");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: a/b/c; Message: -> KEYWORD <-");
});
test("check() sets status to UP when keyword is found using + wildcard", async () => {
const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/+/c", "a/b/c");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: a/b/c; Message: -> KEYWORD <-");
});
test("check() sets status to UP when keyword is found using + and # wildcards", async () => {
const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/+/c/#", "a/b/c/d/e");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: a/b/c/d/e; Message: -> KEYWORD <-");
});
test("check() sets status to UP when keyword is found using + and # wildcards", async () => {
const heartbeat = await testMqtt("KEYWORD", null, "-> KEYWORD <-", "a/+/c/#", "a/b/c/d/e");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: a/b/c/d/e; Message: -> KEYWORD <-");
});
test("check() rejects with timeout when topic does not match", async () => {
await assert.rejects(
testMqtt("keyword will not be checked anyway", null, "message", "x/y/z", "a/b/c"),
new Error("Timeout, Message not received"),
);
});
test("check() rejects with timeout when topic does not match", async () => {
await assert.rejects(
testMqtt("keyword will not be checked anyway", null, "message", "x/y/z", "a/b/c"),
new Error("Timeout, Message not received")
);
});
test("check() rejects with timeout when # wildcard is not last character", async () => {
await assert.rejects(
testMqtt("", null, "# should be last character", "#/c", "a/b/c"),
new Error("Timeout, Message not received"),
);
});
test("check() rejects with timeout when # wildcard is not last character", async () => {
await assert.rejects(
testMqtt("", null, "# should be last character", "#/c", "a/b/c"),
new Error("Timeout, Message not received")
);
});
test("check() rejects with timeout when + wildcard topic does not match", async () => {
await assert.rejects(
testMqtt("", null, "message", "x/+/z", "a/b/c"),
new Error("Timeout, Message not received"),
);
});
test("check() rejects with timeout when + wildcard topic does not match", async () => {
await assert.rejects(
testMqtt("", null, "message", "x/+/z", "a/b/c"),
new Error("Timeout, Message not received")
);
});
test("check() sets status to UP when keyword is found in message (type=keyword)", async () => {
const heartbeat = await testMqtt("KEYWORD", "keyword", "-> KEYWORD <-");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: test; Message: -> KEYWORD <-");
});
test("check() sets status to UP when keyword is found in message (type=keyword)", async () => {
const heartbeat = await testMqtt("KEYWORD", "keyword", "-> KEYWORD <-");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: test; Message: -> KEYWORD <-");
});
test("check() rejects when keyword is not found in message (type=default)", async () => {
await assert.rejects(
testMqtt("NOT_PRESENT", null, "-> KEYWORD <-"),
new Error("Message Mismatch - Topic: test; Message: -> KEYWORD <-"),
);
});
test("check() rejects when keyword is not found in message (type=default)", async () => {
await assert.rejects(
testMqtt("NOT_PRESENT", null, "-> KEYWORD <-"),
new Error("Message Mismatch - Topic: test; Message: -> KEYWORD <-")
);
});
test("check() rejects when keyword is not found in message (type=keyword)", async () => {
await assert.rejects(
testMqtt("NOT_PRESENT", "keyword", "-> KEYWORD <-"),
new Error("Message Mismatch - Topic: test; Message: -> KEYWORD <-"),
);
});
test("check() rejects when keyword is not found in message (type=keyword)", async () => {
await assert.rejects(
testMqtt("NOT_PRESENT", "keyword", "-> KEYWORD <-"),
new Error("Message Mismatch - Topic: test; Message: -> KEYWORD <-")
);
});
test("check() sets status to UP when json-query finds expected value", async () => {
// works because the monitors' jsonPath is hard-coded to "firstProp"
const heartbeat = await testMqtt("present", "json-query", "{\"firstProp\":\"present\"}");
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Message received, expected value is found");
});
test("check() sets status to UP when json-query finds expected value", async () => {
// works because the monitors' jsonPath is hard-coded to "firstProp"
const heartbeat = await testMqtt("present", "json-query", '{"firstProp":"present"}');
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Message received, expected value is found");
});
test("check() rejects when json-query path returns undefined", async () => {
// works because the monitors' jsonPath is hard-coded to "firstProp"
await assert.rejects(
testMqtt("[not_relevant]", "json-query", "{}"),
new Error("Message received but value is not equal to expected value, value was: [undefined]"),
);
});
test("check() rejects when json-query path returns undefined", async () => {
// works because the monitors' jsonPath is hard-coded to "firstProp"
await assert.rejects(
testMqtt("[not_relevant]", "json-query", "{}"),
new Error("Message received but value is not equal to expected value, value was: [undefined]")
);
});
test("check() rejects when json-query value does not match expected value", async () => {
// works because the monitors' jsonPath is hard-coded to "firstProp"
await assert.rejects(
testMqtt("[wrong_success_messsage]", "json-query", "{\"firstProp\":\"present\"}"),
new Error("Message received but value is not equal to expected value, value was: [present]")
);
});
test("check() rejects when json-query value does not match expected value", async () => {
// works because the monitors' jsonPath is hard-coded to "firstProp"
await assert.rejects(
testMqtt("[wrong_success_messsage]", "json-query", '{"firstProp":"present"}'),
new Error("Message received but value is not equal to expected value, value was: [present]")
);
});
// Conditions system tests
test("check() sets status to UP when message condition matches (contains)", async () => {
const conditions = JSON.stringify([
{
type: "expression",
variable: "message",
operator: "contains",
value: "KEYWORD"
}
]);
const heartbeat = await testMqtt("", null, "-> KEYWORD <-", "test", "test", conditions);
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: test; Message: -> KEYWORD <-");
});
// Conditions system tests
test("check() sets status to UP when message condition matches (contains)", async () => {
const conditions = JSON.stringify([
{
type: "expression",
variable: "message",
operator: "contains",
value: "KEYWORD",
},
]);
const heartbeat = await testMqtt("", null, "-> KEYWORD <-", "test", "test", conditions);
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Topic: test; Message: -> KEYWORD <-");
});
test("check() sets status to UP when topic condition matches (equals)", async () => {
const conditions = JSON.stringify([
{
type: "expression",
variable: "topic",
operator: "equals",
value: "sensors/temp"
}
]);
const heartbeat = await testMqtt("", null, "any message", "sensors/temp", "sensors/temp", conditions);
assert.strictEqual(heartbeat.status, UP);
});
test("check() sets status to UP when topic condition matches (equals)", async () => {
const conditions = JSON.stringify([
{
type: "expression",
variable: "topic",
operator: "equals",
value: "sensors/temp",
},
]);
const heartbeat = await testMqtt("", null, "any message", "sensors/temp", "sensors/temp", conditions);
assert.strictEqual(heartbeat.status, UP);
});
test("check() rejects when message condition does not match", async () => {
const conditions = JSON.stringify([
{
type: "expression",
variable: "message",
operator: "contains",
value: "EXPECTED"
}
]);
await assert.rejects(
testMqtt("", null, "actual message without keyword", "test", "test", conditions),
new Error("Conditions not met - Topic: test; Message: actual message without keyword")
);
});
test("check() rejects when message condition does not match", async () => {
const conditions = JSON.stringify([
{
type: "expression",
variable: "message",
operator: "contains",
value: "EXPECTED",
},
]);
await assert.rejects(
testMqtt("", null, "actual message without keyword", "test", "test", conditions),
new Error("Conditions not met - Topic: test; Message: actual message without keyword")
);
});
test("check() sets status to UP with multiple conditions (AND)", async () => {
const conditions = JSON.stringify([
{
type: "expression",
variable: "topic",
operator: "equals",
value: "test"
},
{
type: "expression",
variable: "message",
operator: "contains",
value: "success",
andOr: "and"
}
]);
const heartbeat = await testMqtt("", null, "operation success", "test", "test", conditions);
assert.strictEqual(heartbeat.status, UP);
});
});
test("check() sets status to UP with multiple conditions (AND)", async () => {
const conditions = JSON.stringify([
{
type: "expression",
variable: "topic",
operator: "equals",
value: "test",
},
{
type: "expression",
variable: "message",
operator: "contains",
value: "success",
andOr: "and",
},
]);
const heartbeat = await testMqtt("", null, "operation success", "test", "test", conditions);
assert.strictEqual(heartbeat.status, UP);
});
}
);
+15 -59
View File
@@ -9,9 +9,7 @@ const { UP, PENDING } = require("../../../src/util");
* @returns {Promise<{container: MSSQLServerContainer, connectionString: string}>} The started container and connection string
*/
async function createAndStartMSSQLContainer() {
const container = await new MSSQLServerContainer(
"mcr.microsoft.com/mssql/server:2022-latest"
)
const container = await new MSSQLServerContainer("mcr.microsoft.com/mssql/server:2022-latest")
.acceptLicense()
// The default timeout of 30 seconds might not be enough for the container to start
.withStartupTimeout(60000)
@@ -19,16 +17,14 @@ async function createAndStartMSSQLContainer() {
return {
container,
connectionString: container.getConnectionUri(false)
connectionString: container.getConnectionUri(false),
};
}
describe(
"MSSQL Monitor",
{
skip:
!!process.env.CI &&
(process.platform !== "linux" || process.arch !== "x64"),
skip: !!process.env.CI && (process.platform !== "linux" || process.arch !== "x64"),
},
() => {
test("check() sets status to UP when MSSQL server is reachable", async () => {
@@ -47,11 +43,7 @@ describe(
try {
await mssqlMonitor.check(monitor, heartbeat, {});
assert.strictEqual(
heartbeat.status,
UP,
`Expected status ${UP} but got ${heartbeat.status}`
);
assert.strictEqual(heartbeat.status, UP, `Expected status ${UP} but got ${heartbeat.status}`);
} finally {
await container.stop();
}
@@ -76,11 +68,7 @@ describe(
"Database connection/query failed: Failed to connect to localhost:15433 - Could not connect (sequence)"
)
);
assert.notStrictEqual(
heartbeat.status,
UP,
`Expected status should not be ${heartbeat.status}`
);
assert.notStrictEqual(heartbeat.status, UP, `Expected status should not be ${heartbeat.status}`);
});
test("check() sets status to UP when custom query returns single value", async () => {
@@ -100,11 +88,7 @@ describe(
try {
await mssqlMonitor.check(monitor, heartbeat, {});
assert.strictEqual(
heartbeat.status,
UP,
`Expected status ${UP} but got ${heartbeat.status}`
);
assert.strictEqual(heartbeat.status, UP, `Expected status ${UP} but got ${heartbeat.status}`);
} finally {
await container.stop();
}
@@ -135,11 +119,7 @@ describe(
try {
await mssqlMonitor.check(monitor, heartbeat, {});
assert.strictEqual(
heartbeat.status,
UP,
`Expected status ${UP} but got ${heartbeat.status}`
);
assert.strictEqual(heartbeat.status, UP, `Expected status ${UP} but got ${heartbeat.status}`);
} finally {
await container.stop();
}
@@ -171,15 +151,9 @@ describe(
try {
await assert.rejects(
mssqlMonitor.check(monitor, heartbeat, {}),
new Error(
"Query result did not meet the specified conditions (99)"
)
);
assert.strictEqual(
heartbeat.status,
PENDING,
`Expected status should not be ${heartbeat.status}`
new Error("Query result did not meet the specified conditions (99)")
);
assert.strictEqual(heartbeat.status, PENDING, `Expected status should not be ${heartbeat.status}`);
} finally {
await container.stop();
}
@@ -211,15 +185,9 @@ describe(
try {
await assert.rejects(
mssqlMonitor.check(monitor, heartbeat, {}),
new Error(
"Database connection/query failed: Query returned no results"
)
);
assert.strictEqual(
heartbeat.status,
PENDING,
`Expected status should not be ${heartbeat.status}`
new Error("Database connection/query failed: Query returned no results")
);
assert.strictEqual(heartbeat.status, PENDING, `Expected status should not be ${heartbeat.status}`);
} finally {
await container.stop();
}
@@ -251,15 +219,9 @@ describe(
try {
await assert.rejects(
mssqlMonitor.check(monitor, heartbeat, {}),
new Error(
"Database connection/query failed: Multiple values were found, expected only one value"
)
);
assert.strictEqual(
heartbeat.status,
PENDING,
`Expected status should not be ${heartbeat.status}`
new Error("Database connection/query failed: Multiple values were found, expected only one value")
);
assert.strictEqual(heartbeat.status, PENDING, `Expected status should not be ${heartbeat.status}`);
} finally {
await container.stop();
}
@@ -291,15 +253,9 @@ describe(
try {
await assert.rejects(
mssqlMonitor.check(monitor, heartbeat, {}),
new Error(
"Database connection/query failed: Multiple columns were found, expected only one value"
)
);
assert.strictEqual(
heartbeat.status,
PENDING,
`Expected status should not be ${heartbeat.status}`
new Error("Database connection/query failed: Multiple columns were found, expected only one value")
);
assert.strictEqual(heartbeat.status, PENDING, `Expected status should not be ${heartbeat.status}`);
} finally {
await container.stop();
}
+16 -42
View File
@@ -9,24 +9,20 @@ const { UP, PENDING } = require("../../../src/util");
* @returns {Promise<{container: MariaDbContainer, connectionString: string}>} The started container and connection string
*/
async function createAndStartMariaDBContainer() {
const container = await new MariaDbContainer("mariadb:10.11")
.withStartupTimeout(90000)
.start();
const container = await new MariaDbContainer("mariadb:10.11").withStartupTimeout(90000).start();
const connectionString = `mysql://${container.getUsername()}:${container.getUserPassword()}@${container.getHost()}:${container.getPort()}/${container.getDatabase()}`;
return {
container,
connectionString
connectionString,
};
}
describe(
"MySQL/MariaDB Monitor",
{
skip:
!!process.env.CI &&
(process.platform !== "linux" || process.arch !== "x64"),
skip: !!process.env.CI && (process.platform !== "linux" || process.arch !== "x64"),
},
() => {
test("check() sets status to UP when MariaDB server is reachable", async () => {
@@ -45,11 +41,7 @@ describe(
try {
await mysqlMonitor.check(monitor, heartbeat, {});
assert.strictEqual(
heartbeat.status,
UP,
`Expected status ${UP} but got ${heartbeat.status}`
);
assert.strictEqual(heartbeat.status, UP, `Expected status ${UP} but got ${heartbeat.status}`);
} finally {
await container.stop();
}
@@ -58,8 +50,7 @@ describe(
test("check() rejects when MariaDB server is not reachable", async () => {
const mysqlMonitor = new MysqlMonitorType();
const monitor = {
databaseConnectionString:
"mysql://invalid:invalid@localhost:13306/test",
databaseConnectionString: "mysql://invalid:invalid@localhost:13306/test",
conditions: "[]",
};
@@ -68,21 +59,14 @@ describe(
status: PENDING,
};
await assert.rejects(
mysqlMonitor.check(monitor, heartbeat, {}),
(err) => {
assert.ok(
err.message.includes("Database connection/query failed"),
`Expected error message to include "Database connection/query failed" but got: ${err.message}`
);
return true;
}
);
assert.notStrictEqual(
heartbeat.status,
UP,
`Expected status should not be ${UP}`
);
await assert.rejects(mysqlMonitor.check(monitor, heartbeat, {}), (err) => {
assert.ok(
err.message.includes("Database connection/query failed"),
`Expected error message to include "Database connection/query failed" but got: ${err.message}`
);
return true;
});
assert.notStrictEqual(heartbeat.status, UP, `Expected status should not be ${UP}`);
});
test("check() sets status to UP when custom query result meets condition", async () => {
@@ -110,11 +94,7 @@ describe(
try {
await mysqlMonitor.check(monitor, heartbeat, {});
assert.strictEqual(
heartbeat.status,
UP,
`Expected status ${UP} but got ${heartbeat.status}`
);
assert.strictEqual(heartbeat.status, UP, `Expected status ${UP} but got ${heartbeat.status}`);
} finally {
await container.stop();
}
@@ -146,15 +126,9 @@ describe(
try {
await assert.rejects(
mysqlMonitor.check(monitor, heartbeat, {}),
new Error(
"Query result did not meet the specified conditions (99)"
)
);
assert.strictEqual(
heartbeat.status,
PENDING,
`Expected status should not be ${heartbeat.status}`
new Error("Query result did not meet the specified conditions (99)")
);
assert.strictEqual(heartbeat.status, PENDING, `Expected status should not be ${heartbeat.status}`);
} finally {
await container.stop();
}
+3 -10
View File
@@ -7,16 +7,12 @@ const { UP, PENDING } = require("../../../src/util");
describe(
"Postgres Single Node",
{
skip:
!!process.env.CI &&
(process.platform !== "linux" || process.arch !== "x64"),
skip: !!process.env.CI && (process.platform !== "linux" || process.arch !== "x64"),
},
() => {
test("check() sets status to UP when Postgres server is reachable", async () => {
// The default timeout of 30 seconds might not be enough for the container to start
const postgresContainer = await new PostgreSqlContainer(
"postgres:latest"
)
const postgresContainer = await new PostgreSqlContainer("postgres:latest")
.withStartupTimeout(60000)
.start();
const postgresMonitor = new PostgresMonitorType();
@@ -51,10 +47,7 @@ describe(
// regex match any string
const regex = /.+/;
await assert.rejects(
postgresMonitor.check(monitor, heartbeat, {}),
regex
);
await assert.rejects(postgresMonitor.check(monitor, heartbeat, {}), regex);
});
}
);
+89 -104
View File
@@ -4,101 +4,99 @@ const { RabbitMQContainer } = require("@testcontainers/rabbitmq");
const { RabbitMqMonitorType } = require("../../../server/monitor-types/rabbitmq");
const { UP, PENDING } = require("../../../src/util");
describe("RabbitMQ Single Node", {
skip: !!process.env.CI && (process.platform !== "linux" || process.arch !== "x64"),
}, () => {
test("check() sets status to UP when RabbitMQ server is reachable", async () => {
// The default timeout of 30 seconds might not be enough for the container to start
const rabbitMQContainer = await new RabbitMQContainer().withStartupTimeout(60000).start();
const rabbitMQMonitor = new RabbitMqMonitorType();
const connectionString = `http://${rabbitMQContainer.getHost()}:${rabbitMQContainer.getMappedPort(15672)}`;
describe(
"RabbitMQ Single Node",
{
skip: !!process.env.CI && (process.platform !== "linux" || process.arch !== "x64"),
},
() => {
test("check() sets status to UP when RabbitMQ server is reachable", async () => {
// The default timeout of 30 seconds might not be enough for the container to start
const rabbitMQContainer = await new RabbitMQContainer().withStartupTimeout(60000).start();
const rabbitMQMonitor = new RabbitMqMonitorType();
const connectionString = `http://${rabbitMQContainer.getHost()}:${rabbitMQContainer.getMappedPort(15672)}`;
const monitor = {
rabbitmqNodes: JSON.stringify([ connectionString ]),
rabbitmqUsername: "guest",
rabbitmqPassword: "guest",
timeout: 10,
};
const monitor = {
rabbitmqNodes: JSON.stringify([connectionString]),
rabbitmqUsername: "guest",
rabbitmqPassword: "guest",
timeout: 10,
};
const heartbeat = {
msg: "",
status: PENDING,
};
const heartbeat = {
msg: "",
status: PENDING,
};
try {
await rabbitMQMonitor.check(monitor, heartbeat, {});
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Node is reachable and there are no alerts in the cluster");
} finally {
rabbitMQContainer.stop();
}
});
try {
await rabbitMQMonitor.check(monitor, heartbeat, {});
assert.strictEqual(heartbeat.status, UP);
assert.strictEqual(heartbeat.msg, "Node is reachable and there are no alerts in the cluster");
} finally {
rabbitMQContainer.stop();
}
});
test("check() rejects when RabbitMQ server is not reachable", async () => {
const rabbitMQMonitor = new RabbitMqMonitorType();
const monitor = {
rabbitmqNodes: JSON.stringify([ "http://localhost:15672" ]),
rabbitmqUsername: "rabbitmqUser",
rabbitmqPassword: "rabbitmqPass",
timeout: 10,
};
test("check() rejects when RabbitMQ server is not reachable", async () => {
const rabbitMQMonitor = new RabbitMqMonitorType();
const monitor = {
rabbitmqNodes: JSON.stringify(["http://localhost:15672"]),
rabbitmqUsername: "rabbitmqUser",
rabbitmqPassword: "rabbitmqPass",
timeout: 10,
};
const heartbeat = {
msg: "",
status: PENDING,
};
const heartbeat = {
msg: "",
status: PENDING,
};
// regex match any string
const regex = /.+/;
// regex match any string
const regex = /.+/;
await assert.rejects(
rabbitMQMonitor.check(monitor, heartbeat, {}),
regex
);
});
await assert.rejects(rabbitMQMonitor.check(monitor, heartbeat, {}), regex);
});
test("checkSingleNode() succeeds when node is healthy", async () => {
const rabbitMQContainer = await new RabbitMQContainer().withStartupTimeout(60000).start();
const rabbitMQMonitor = new RabbitMqMonitorType();
const connectionString = `http://${rabbitMQContainer.getHost()}:${rabbitMQContainer.getMappedPort(15672)}`;
test("checkSingleNode() succeeds when node is healthy", async () => {
const rabbitMQContainer = await new RabbitMQContainer().withStartupTimeout(60000).start();
const rabbitMQMonitor = new RabbitMqMonitorType();
const connectionString = `http://${rabbitMQContainer.getHost()}:${rabbitMQContainer.getMappedPort(15672)}`;
const monitor = {
name: "Test Monitor",
rabbitmqUsername: "guest",
rabbitmqPassword: "guest",
timeout: 10,
};
const monitor = {
name: "Test Monitor",
rabbitmqUsername: "guest",
rabbitmqPassword: "guest",
timeout: 10,
};
try {
// Should not throw - just validates the node is healthy
await rabbitMQMonitor.checkSingleNode(monitor, connectionString, "1/1");
} finally {
rabbitMQContainer.stop();
}
});
try {
// Should not throw - just validates the node is healthy
await rabbitMQMonitor.checkSingleNode(monitor, connectionString, "1/1");
} finally {
rabbitMQContainer.stop();
}
});
test("checkSingleNode() throws error when node is unreachable", async () => {
const rabbitMQMonitor = new RabbitMqMonitorType();
const monitor = {
name: "Test Monitor",
rabbitmqUsername: "guest",
rabbitmqPassword: "guest",
timeout: 10,
};
test("checkSingleNode() throws error when node is unreachable", async () => {
const rabbitMQMonitor = new RabbitMqMonitorType();
const monitor = {
name: "Test Monitor",
rabbitmqUsername: "guest",
rabbitmqPassword: "guest",
timeout: 10,
};
// Should reject with any error (connection refused, timeout, etc.)
await assert.rejects(
rabbitMQMonitor.checkSingleNode(monitor, "http://localhost:15672", "1/1"),
Error
);
});
});
// Should reject with any error (connection refused, timeout, etc.)
await assert.rejects(rabbitMQMonitor.checkSingleNode(monitor, "http://localhost:15672", "1/1"), Error);
});
}
);
describe("RabbitMQ Multi-Node (Mocked)", () => {
test("check() succeeds when first node is healthy", async () => {
const rabbitMQMonitor = new RabbitMqMonitorType();
const monitor = {
rabbitmqNodes: JSON.stringify([ "http://node1:15672", "http://node2:15672" ]),
rabbitmqNodes: JSON.stringify(["http://node1:15672", "http://node2:15672"]),
rabbitmqUsername: "guest",
rabbitmqPassword: "guest",
timeout: 10,
@@ -125,7 +123,7 @@ describe("RabbitMQ Multi-Node (Mocked)", () => {
test("check() succeeds when second node is healthy after first fails", async () => {
const rabbitMQMonitor = new RabbitMqMonitorType();
const monitor = {
rabbitmqNodes: JSON.stringify([ "http://node1:15672", "http://node2:15672" ]),
rabbitmqNodes: JSON.stringify(["http://node1:15672", "http://node2:15672"]),
rabbitmqUsername: "guest",
rabbitmqPassword: "guest",
timeout: 10,
@@ -155,11 +153,7 @@ describe("RabbitMQ Multi-Node (Mocked)", () => {
test("check() fails with consolidated error when all nodes are down", async () => {
const rabbitMQMonitor = new RabbitMqMonitorType();
const monitor = {
rabbitmqNodes: JSON.stringify([
"http://node1:15672",
"http://node2:15672",
"http://node3:15672"
]),
rabbitmqNodes: JSON.stringify(["http://node1:15672", "http://node2:15672", "http://node3:15672"]),
rabbitmqUsername: "guest",
rabbitmqPassword: "guest",
timeout: 10,
@@ -177,16 +171,13 @@ describe("RabbitMQ Multi-Node (Mocked)", () => {
throw new Error(`Connection failed to node ${callCount}`);
};
await assert.rejects(
rabbitMQMonitor.check(monitor, heartbeat, {}),
(error) => {
assert.match(error.message, /All 3 nodes failed/);
assert.match(error.message, /Node 1:/);
assert.match(error.message, /Node 2:/);
assert.match(error.message, /Node 3:/);
return true;
}
);
await assert.rejects(rabbitMQMonitor.check(monitor, heartbeat, {}), (error) => {
assert.match(error.message, /All 3 nodes failed/);
assert.match(error.message, /Node 1:/);
assert.match(error.message, /Node 2:/);
assert.match(error.message, /Node 3:/);
return true;
});
assert.strictEqual(callCount, 3, "Should check all three nodes");
});
@@ -204,10 +195,7 @@ describe("RabbitMQ Multi-Node (Mocked)", () => {
status: PENDING,
};
await assert.rejects(
rabbitMQMonitor.check(monitor, heartbeat, {}),
/No RabbitMQ nodes configured/
);
await assert.rejects(rabbitMQMonitor.check(monitor, heartbeat, {}), /No RabbitMQ nodes configured/);
});
test("check() tries all nodes before failing", async () => {
@@ -217,7 +205,7 @@ describe("RabbitMQ Multi-Node (Mocked)", () => {
"http://node1:15672",
"http://node2:15672",
"http://node3:15672",
"http://node4:15672"
"http://node4:15672",
]),
rabbitmqUsername: "guest",
rabbitmqPassword: "guest",
@@ -235,11 +223,8 @@ describe("RabbitMQ Multi-Node (Mocked)", () => {
throw new Error(`Failed: ${url}`);
};
await assert.rejects(
rabbitMQMonitor.check(monitor, heartbeat, {}),
/All 4 nodes failed/
);
await assert.rejects(rabbitMQMonitor.check(monitor, heartbeat, {}), /All 4 nodes failed/);
assert.strictEqual(checkedNodes.length, 4, "Should check all 4 nodes");
assert.strictEqual(checkedNodes[0], "http://node1:15672");
assert.strictEqual(checkedNodes[1], "http://node2:15672");
+10 -19
View File
@@ -25,7 +25,7 @@ describe("TCP Monitor", () => {
heartbeat.status = PENDING;
// Wait a bit before retrying with exponential backoff
if (attempt < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, 500 * 2 ** (attempt - 1)));
await new Promise((resolve) => setTimeout(resolve, 500 * 2 ** (attempt - 1)));
}
}
}
@@ -45,7 +45,7 @@ describe("TCP Monitor", () => {
resolve(server);
});
server.on("error", err => {
server.on("error", (err) => {
reject(err);
});
});
@@ -91,10 +91,7 @@ describe("TCP Monitor", () => {
status: PENDING,
};
await assert.rejects(
tcpMonitor.check(monitor, heartbeat, {}),
new Error("Connection failed")
);
await assert.rejects(tcpMonitor.check(monitor, heartbeat, {}), new Error("Connection failed"));
});
test("check() rejects when TLS certificate is expired or invalid", async () => {
@@ -105,7 +102,7 @@ describe("TCP Monitor", () => {
port: 443,
smtpSecurity: "secure",
isEnabledExpiryNotification: () => true,
handleTlsInfo: async tlsInfo => {
handleTlsInfo: async (tlsInfo) => {
return tlsInfo;
},
};
@@ -118,10 +115,7 @@ describe("TCP Monitor", () => {
// Regex: contains with "TLS Connection failed:" or "Certificate is invalid"
const regex = /TLS Connection failed:|Certificate is invalid/;
await assert.rejects(
tcpMonitor.check(monitor, heartbeat, {}),
regex
);
await assert.rejects(tcpMonitor.check(monitor, heartbeat, {}), regex);
});
test("check() sets status to UP when TLS certificate is valid (SSL)", async () => {
@@ -132,7 +126,7 @@ describe("TCP Monitor", () => {
port: 465,
smtpSecurity: "secure",
isEnabledExpiryNotification: () => true,
handleTlsInfo: async tlsInfo => {
handleTlsInfo: async (tlsInfo) => {
return tlsInfo;
},
};
@@ -156,7 +150,7 @@ describe("TCP Monitor", () => {
port: 587,
smtpSecurity: "starttls",
isEnabledExpiryNotification: () => true,
handleTlsInfo: async tlsInfo => {
handleTlsInfo: async (tlsInfo) => {
return tlsInfo;
},
};
@@ -180,7 +174,7 @@ describe("TCP Monitor", () => {
port: 587,
smtpSecurity: "starttls",
isEnabledExpiryNotification: () => true,
handleTlsInfo: async tlsInfo => {
handleTlsInfo: async (tlsInfo) => {
return tlsInfo;
},
};
@@ -192,10 +186,7 @@ describe("TCP Monitor", () => {
const regex = /does not match certificate/;
await assert.rejects(
tcpMonitor.check(monitor, heartbeat, {}),
regex
);
await assert.rejects(tcpMonitor.check(monitor, heartbeat, {}), regex);
});
test("check() sets status to UP for XMPP server with valid certificate (STARTTLS)", async () => {
const tcpMonitor = new TCPMonitorType();
@@ -205,7 +196,7 @@ describe("TCP Monitor", () => {
port: 5222,
smtpSecurity: "starttls",
isEnabledExpiryNotification: () => true,
handleTlsInfo: async tlsInfo => {
handleTlsInfo: async (tlsInfo) => {
return tlsInfo;
},
};
+26 -40
View File
@@ -13,16 +13,15 @@ const http = require("node:http");
function nonCompliantWS() {
const srv = net.createServer((socket) => {
socket.once("data", (buf) => {
socket.write("HTTP/1.1 101 Switching Protocols\r\n" +
"Upgrade: websocket\r\n" +
"Connection: Upgrade\r\n\r\n");
socket.write(
"HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n\r\n"
);
socket.destroy();
});
});
return new Promise((resolve) => {
srv.listen(0, () => {
resolve({ server: srv,
port: srv.address().port });
resolve({ server: srv, port: srv.address().port });
});
});
}
@@ -38,8 +37,7 @@ function httpServer() {
});
return new Promise((resolve) => {
srv.listen(0, () => {
resolve({ server: srv,
port: srv.address().port });
resolve({ server: srv, port: srv.address().port });
});
});
}
@@ -51,17 +49,14 @@ function httpServer() {
*/
function createWebSocketServer(options = {}) {
return new Promise((resolve) => {
const wss = new WebSocketServer({ port: 0,
...options });
const wss = new WebSocketServer({ port: 0, ...options });
wss.on("listening", () => {
resolve({ server: wss,
port: wss.address().port });
resolve({ server: wss, port: wss.address().port });
});
});
}
describe("WebSocket Monitor", {
}, () => {
describe("WebSocket Monitor", {}, () => {
test("check() rejects with unexpected server response when connecting to non-WebSocket server", {}, async (t) => {
const websocketMonitor = new WebSocketMonitorType();
const { server: srv, port } = await httpServer();
@@ -92,7 +87,7 @@ describe("WebSocket Monitor", {
const monitor = {
url: `ws://localhost:${port}`,
wsIgnoreSecWebsocketAcceptHeader: false,
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
accepted_statuscodes_json: JSON.stringify(["1000"]),
timeout: 30,
};
@@ -118,7 +113,7 @@ describe("WebSocket Monitor", {
const monitor = {
url: `ws://localhost:${port}`,
wsIgnoreSecWebsocketAcceptHeader: false,
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
accepted_statuscodes_json: JSON.stringify(["1000"]),
timeout: 30,
};
@@ -144,7 +139,7 @@ describe("WebSocket Monitor", {
const monitor = {
url: `ws://localhost:${port}`,
wsIgnoreSecWebsocketAcceptHeader: false,
accepted_statuscodes_json: JSON.stringify([ "1001" ]),
accepted_statuscodes_json: JSON.stringify(["1001"]),
timeout: 30,
};
@@ -153,10 +148,7 @@ describe("WebSocket Monitor", {
status: PENDING,
};
await assert.rejects(
websocketMonitor.check(monitor, heartbeat, {}),
new Error("Unexpected status code: 1000")
);
await assert.rejects(websocketMonitor.check(monitor, heartbeat, {}), new Error("Unexpected status code: 1000"));
});
test("check() rejects when expected status code is empty", async (t) => {
@@ -167,7 +159,7 @@ describe("WebSocket Monitor", {
const monitor = {
url: `ws://localhost:${port}`,
wsIgnoreSecWebsocketAcceptHeader: false,
accepted_statuscodes_json: JSON.stringify([ "" ]),
accepted_statuscodes_json: JSON.stringify([""]),
timeout: 30,
};
@@ -176,10 +168,7 @@ describe("WebSocket Monitor", {
status: PENDING,
};
await assert.rejects(
websocketMonitor.check(monitor, heartbeat, {}),
new Error("Unexpected status code: 1000")
);
await assert.rejects(websocketMonitor.check(monitor, heartbeat, {}), new Error("Unexpected status code: 1000"));
});
test("check() rejects when Sec-WebSocket-Accept header is invalid", async (t) => {
@@ -190,7 +179,7 @@ describe("WebSocket Monitor", {
const monitor = {
url: `ws://localhost:${port}`,
wsIgnoreSecWebsocketAcceptHeader: false,
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
accepted_statuscodes_json: JSON.stringify(["1000"]),
timeout: 30,
};
@@ -213,7 +202,7 @@ describe("WebSocket Monitor", {
const monitor = {
url: `ws://localhost:${port}`,
wsIgnoreSecWebsocketAcceptHeader: true,
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
accepted_statuscodes_json: JSON.stringify(["1000"]),
timeout: 30,
};
@@ -239,7 +228,7 @@ describe("WebSocket Monitor", {
const monitor = {
url: `ws://localhost:${port}`,
wsIgnoreSecWebsocketAcceptHeader: true,
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
accepted_statuscodes_json: JSON.stringify(["1000"]),
timeout: 30,
};
@@ -265,7 +254,7 @@ describe("WebSocket Monitor", {
const monitor = {
url: `ws://localhost:${port}`,
wsIgnoreSecWebsocketAcceptHeader: true,
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
accepted_statuscodes_json: JSON.stringify(["1000"]),
timeout: 30,
};
@@ -286,7 +275,7 @@ describe("WebSocket Monitor", {
handleProtocols: (protocols) => {
// Explicitly reject all subprotocols
return null;
}
},
});
t.after(() => wss.close());
@@ -294,7 +283,7 @@ describe("WebSocket Monitor", {
url: `ws://localhost:${port}`,
wsIgnoreSecWebsocketAcceptHeader: false,
wsSubprotocol: "ocpp1.6",
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
accepted_statuscodes_json: JSON.stringify(["1000"]),
timeout: 30,
};
@@ -303,10 +292,7 @@ describe("WebSocket Monitor", {
status: PENDING,
};
await assert.rejects(
websocketMonitor.check(monitor, heartbeat, {}),
new Error("Server sent no subprotocol")
);
await assert.rejects(websocketMonitor.check(monitor, heartbeat, {}), new Error("Server sent no subprotocol"));
});
test("check() rejects when multiple subprotocols contain invalid characters", async (t) => {
@@ -318,7 +304,7 @@ describe("WebSocket Monitor", {
url: `ws://localhost:${port}`,
wsIgnoreSecWebsocketAcceptHeader: false,
wsSubprotocol: " # & ,ocpp2.0 [] , ocpp1.6 , ,, ; ",
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
accepted_statuscodes_json: JSON.stringify(["1000"]),
timeout: 30,
};
@@ -338,7 +324,7 @@ describe("WebSocket Monitor", {
const { server: wss, port } = await createWebSocketServer({
handleProtocols: (protocols) => {
return Array.from(protocols).includes("test") ? "test" : null;
}
},
});
t.after(() => wss.close());
@@ -346,7 +332,7 @@ describe("WebSocket Monitor", {
url: `ws://localhost:${port}`,
wsIgnoreSecWebsocketAcceptHeader: false,
wsSubprotocol: "invalid , test ",
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
accepted_statuscodes_json: JSON.stringify(["1000"]),
timeout: 30,
};
@@ -369,7 +355,7 @@ describe("WebSocket Monitor", {
const { server: wss, port } = await createWebSocketServer({
handleProtocols: (protocols) => {
return Array.from(protocols).includes("test") ? "test" : null;
}
},
});
t.after(() => wss.close());
@@ -377,7 +363,7 @@ describe("WebSocket Monitor", {
url: `ws://localhost:${port}`,
wsIgnoreSecWebsocketAcceptHeader: false,
wsSubprotocol: "invalid,test",
accepted_statuscodes_json: JSON.stringify([ "1000" ]),
accepted_statuscodes_json: JSON.stringify(["1000"]),
timeout: 30,
};