uptime-kuma/test/backend-test/test-mssql.js

303 lines
10 KiB
JavaScript

const { describe, test } = require("node:test");
const assert = require("node:assert");
const { MSSQLServerContainer } = require("@testcontainers/mssqlserver");
const { MssqlMonitorType } = require("../../server/monitor-types/mssql");
const { UP, PENDING } = require("../../src/util");
/**
* Helper function to create and start a MSSQL container
* @returns {Promise<MSSQLServerContainer>} The started MSSQL container
*/
async function createAndStartMSSQLContainer() {
return 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)
.start();
}
describe(
"MSSQL Single Node",
{
skip:
!!process.env.CI &&
(process.platform !== "linux" || process.arch !== "x64"),
},
() => {
test("MSSQL is running", async () => {
let mssqlContainer;
try {
mssqlContainer = await createAndStartMSSQLContainer();
const mssqlMonitor = new MssqlMonitorType();
const monitor = {
databaseConnectionString:
mssqlContainer.getConnectionUri(false),
conditions: "[]",
};
const heartbeat = {
msg: "",
status: PENDING,
};
await mssqlMonitor.check(monitor, heartbeat, {});
assert.strictEqual(
heartbeat.status,
UP,
`Expected status ${UP} but got ${heartbeat.status}`
);
} catch (error) {
console.error("Test failed with error:", error.message);
console.error("Error stack:", error.stack);
if (mssqlContainer) {
console.error("Container ID:", mssqlContainer.getId());
console.error(
"Container logs:",
await mssqlContainer.logs()
);
}
throw error;
} finally {
if (mssqlContainer) {
console.log("Stopping MSSQL container...");
await mssqlContainer.stop();
}
}
});
test("MSSQL with custom query returning single value", async () => {
const mssqlContainer = await createAndStartMSSQLContainer();
const mssqlMonitor = new MssqlMonitorType();
const monitor = {
databaseConnectionString:
mssqlContainer.getConnectionUri(false),
databaseQuery: "SELECT 42",
conditions: "[]",
};
const heartbeat = {
msg: "",
status: PENDING,
};
try {
await mssqlMonitor.check(monitor, heartbeat, {});
assert.strictEqual(
heartbeat.status,
UP,
`Expected status ${UP} but got ${heartbeat.status}`
);
} finally {
await mssqlContainer.stop();
}
});
test("MSSQL with custom query and condition that passes", async () => {
const mssqlContainer = await createAndStartMSSQLContainer();
const mssqlMonitor = new MssqlMonitorType();
const monitor = {
databaseConnectionString:
mssqlContainer.getConnectionUri(false),
databaseQuery: "SELECT 42 as value",
conditions: JSON.stringify([
{
type: "expression",
andOr: "and",
variable: "result",
operator: "equals",
value: "42",
},
]),
};
const heartbeat = {
msg: "",
status: PENDING,
};
try {
await mssqlMonitor.check(monitor, heartbeat, {});
assert.strictEqual(
heartbeat.status,
UP,
`Expected status ${UP} but got ${heartbeat.status}`
);
} finally {
await mssqlContainer.stop();
}
});
test("MSSQL with custom query and condition that fails", async () => {
const mssqlContainer = await createAndStartMSSQLContainer();
const mssqlMonitor = new MssqlMonitorType();
const monitor = {
databaseConnectionString:
mssqlContainer.getConnectionUri(false),
databaseQuery: "SELECT 99 as value",
conditions: JSON.stringify([
{
type: "expression",
andOr: "and",
variable: "result",
operator: "equals",
value: "42",
},
]),
};
const heartbeat = {
msg: "",
status: PENDING,
};
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}`
);
} finally {
await mssqlContainer.stop();
}
});
test("MSSQL query returns no results", async () => {
const mssqlContainer = await createAndStartMSSQLContainer();
const mssqlMonitor = new MssqlMonitorType();
const monitor = {
databaseConnectionString:
mssqlContainer.getConnectionUri(false),
databaseQuery: "SELECT 1 WHERE 1 = 0",
conditions: "[]",
};
const heartbeat = {
msg: "",
status: PENDING,
};
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}`
);
} finally {
await mssqlContainer.stop();
}
});
test("MSSQL query returns multiple rows", async () => {
const mssqlContainer = await createAndStartMSSQLContainer();
const mssqlMonitor = new MssqlMonitorType();
const monitor = {
databaseConnectionString:
mssqlContainer.getConnectionUri(false),
databaseQuery: "SELECT 1 UNION ALL SELECT 2",
conditions: "[]",
};
const heartbeat = {
msg: "",
status: PENDING,
};
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}`
);
} finally {
await mssqlContainer.stop();
}
});
test("MSSQL query returns multiple columns", async () => {
const mssqlContainer = await createAndStartMSSQLContainer();
const mssqlMonitor = new MssqlMonitorType();
const monitor = {
databaseConnectionString:
mssqlContainer.getConnectionUri(false),
databaseQuery: "SELECT 1 AS col1, 2 AS col2",
conditions: "[]",
};
const heartbeat = {
msg: "",
status: PENDING,
};
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}`
);
} finally {
await mssqlContainer.stop();
}
});
test("MSSQL is not running", async () => {
const mssqlMonitor = new MssqlMonitorType();
const monitor = {
databaseConnectionString:
"Server=localhost,15433;Database=master;User Id=Fail;Password=Fail;Encrypt=false",
conditions: "[]",
};
const heartbeat = {
msg: "",
status: PENDING,
};
await assert.rejects(
mssqlMonitor.check(monitor, heartbeat, {}),
new Error(
"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}`
);
});
}
);