chore: 현재 작업 중간 커밋
This commit is contained in:
@@ -2,7 +2,38 @@
|
||||
|
||||
const test = require("node:test");
|
||||
const assert = require("node:assert/strict");
|
||||
const { InMemoryDashboardStore } = require("../src/dashboardStore");
|
||||
const {
|
||||
InMemoryDashboardStore,
|
||||
MySqlDashboardStore,
|
||||
createDashboardStore,
|
||||
} = require("../src/dashboardStore");
|
||||
|
||||
async function withPatchedEnv(patch, fn) {
|
||||
const backup = {};
|
||||
for (const [key] of Object.entries(patch)) {
|
||||
backup[key] = process.env[key];
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(patch)) {
|
||||
if (value === undefined) {
|
||||
delete process.env[key];
|
||||
} else {
|
||||
process.env[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return await fn();
|
||||
} finally {
|
||||
for (const [key, value] of Object.entries(backup)) {
|
||||
if (value === undefined) {
|
||||
delete process.env[key];
|
||||
} else {
|
||||
process.env[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test("in-memory store persists watch, poll result, events and controls", async () => {
|
||||
const store = new InMemoryDashboardStore();
|
||||
@@ -63,3 +94,130 @@ test("in-memory store persists watch, poll result, events and controls", async (
|
||||
assert.equal(controlsAfter.crawlingEnabled, false);
|
||||
assert.equal(controlsAfter.alertsEnabled, false);
|
||||
});
|
||||
|
||||
test("mysql mode fails closed without fallback when configuration is missing", async () => {
|
||||
await withPatchedEnv(
|
||||
{
|
||||
DASHBOARD_DB: undefined,
|
||||
MYSQL_URL: undefined,
|
||||
MYSQL_HOST: undefined,
|
||||
MYSQL_USER: undefined,
|
||||
MYSQL_DATABASE: undefined,
|
||||
DASHBOARD_ALLOW_MEMORY_FALLBACK: undefined,
|
||||
},
|
||||
async () => {
|
||||
await assert.rejects(
|
||||
() =>
|
||||
createDashboardStore({
|
||||
mode: "mysql",
|
||||
allowMemoryFallback: false,
|
||||
}),
|
||||
/MySQL 연결 정보가 필요합니다/
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("mysql mode can fallback to memory only when explicitly allowed", async () => {
|
||||
await withPatchedEnv(
|
||||
{
|
||||
DASHBOARD_DB: undefined,
|
||||
MYSQL_URL: undefined,
|
||||
MYSQL_HOST: undefined,
|
||||
MYSQL_USER: undefined,
|
||||
MYSQL_DATABASE: undefined,
|
||||
DASHBOARD_ALLOW_MEMORY_FALLBACK: undefined,
|
||||
},
|
||||
async () => {
|
||||
const setup = await createDashboardStore({
|
||||
mode: "mysql",
|
||||
allowMemoryFallback: true,
|
||||
});
|
||||
|
||||
assert.equal(setup.engine, "memory");
|
||||
assert.match(setup.warning, /메모리 저장소/);
|
||||
await setup.store.close();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("mysql store init fails when required tables are missing", async () => {
|
||||
const calls = [];
|
||||
const store = new MySqlDashboardStore(
|
||||
{
|
||||
query: async (sql) => {
|
||||
calls.push(sql);
|
||||
return [[{ TABLE_NAME: "projects" }], []];
|
||||
},
|
||||
end: async () => {},
|
||||
}
|
||||
);
|
||||
|
||||
await assert.rejects(
|
||||
() => store.init(),
|
||||
/MySQL playground 스키마가 준비되지 않았습니다\..*project_documents.*project_events.*project_settings/
|
||||
);
|
||||
assert.equal(calls.length, 1);
|
||||
});
|
||||
|
||||
test("mysql store init succeeds when all required tables exist", async () => {
|
||||
const calls = [];
|
||||
const store = new MySqlDashboardStore(
|
||||
{
|
||||
query: async (sql, params) => {
|
||||
calls.push(sql);
|
||||
if (String(sql).includes("FROM information_schema.TABLES")) {
|
||||
return [
|
||||
[
|
||||
{ TABLE_NAME: "projects" },
|
||||
{ TABLE_NAME: "project_documents" },
|
||||
{ TABLE_NAME: "project_events" },
|
||||
{ TABLE_NAME: "project_settings" },
|
||||
],
|
||||
[],
|
||||
];
|
||||
}
|
||||
if (String(sql).includes("INSERT INTO projects")) {
|
||||
assert.equal(params[0], "air-watcher");
|
||||
return [{ affectedRows: 1 }, []];
|
||||
}
|
||||
throw new Error(`unexpected query: ${sql}`);
|
||||
},
|
||||
end: async () => {},
|
||||
}
|
||||
);
|
||||
|
||||
await assert.doesNotReject(() => store.init());
|
||||
assert.equal(store.schemaMode, "playground");
|
||||
assert.equal(calls.length, 2);
|
||||
});
|
||||
|
||||
test("mysql store supports custom projectKey", async () => {
|
||||
let insertedProjectKey = null;
|
||||
const store = new MySqlDashboardStore({
|
||||
query: async (sql, params) => {
|
||||
if (String(sql).includes("FROM information_schema.TABLES")) {
|
||||
return [
|
||||
[
|
||||
{ TABLE_NAME: "projects" },
|
||||
{ TABLE_NAME: "project_documents" },
|
||||
{ TABLE_NAME: "project_events" },
|
||||
{ TABLE_NAME: "project_settings" },
|
||||
],
|
||||
[],
|
||||
];
|
||||
}
|
||||
if (String(sql).includes("INSERT INTO projects")) {
|
||||
insertedProjectKey = params[0];
|
||||
return [{ affectedRows: 1 }, []];
|
||||
}
|
||||
throw new Error(`unexpected query: ${sql}`);
|
||||
},
|
||||
end: async () => {},
|
||||
}, {
|
||||
projectKey: "mini-app-a",
|
||||
});
|
||||
|
||||
await store.init();
|
||||
assert.equal(insertedProjectKey, "mini-app-a");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user