134 lines
3.3 KiB
JavaScript
134 lines
3.3 KiB
JavaScript
"use strict";
|
|
|
|
const test = require("node:test");
|
|
const assert = require("node:assert/strict");
|
|
const { createDashboardRuntime } = require("../src/dashboardRuntime");
|
|
|
|
function createStore({ controls }) {
|
|
const events = [];
|
|
const watches = [
|
|
{
|
|
id: "watch-1",
|
|
rawInput: "인천->도쿄",
|
|
searchParams: { segments: [{ from: "ICN", to: "NRT" }], departureDateWindow: { from: "2026-06-01" } },
|
|
alertRules: {
|
|
targetPrice: null,
|
|
notifyOnPriceChange: true,
|
|
notifyOnFirstResult: true,
|
|
},
|
|
pollingEnabled: true,
|
|
alertsEnabled: true,
|
|
createdAt: "2026-02-19T00:00:00.000Z",
|
|
updatedAt: "2026-02-19T00:00:00.000Z",
|
|
lastSnapshot: null,
|
|
lastError: null,
|
|
},
|
|
];
|
|
|
|
return {
|
|
events,
|
|
async init() {},
|
|
async close() {},
|
|
async listWatches() {
|
|
return watches;
|
|
},
|
|
async getWatch() {
|
|
return null;
|
|
},
|
|
async saveWatch(watch) {
|
|
return watch;
|
|
},
|
|
async deleteWatch() {
|
|
return true;
|
|
},
|
|
async savePollResult() {},
|
|
async saveEvent(event) {
|
|
events.push(event);
|
|
return event;
|
|
},
|
|
async listEvents() {
|
|
return events;
|
|
},
|
|
async getGlobalControls() {
|
|
return controls;
|
|
},
|
|
async setGlobalControls(patch = {}) {
|
|
controls = { ...controls, ...patch };
|
|
return controls;
|
|
},
|
|
};
|
|
}
|
|
|
|
test("runtime stores failed notification state when notifier throws", async () => {
|
|
const store = createStore({
|
|
controls: { crawlingEnabled: true, alertsEnabled: true },
|
|
});
|
|
const crawler = {
|
|
async getQuotes() {
|
|
return [{ provider: "mock", price: 120000, currency: "KRW" }];
|
|
},
|
|
};
|
|
const notifier = {
|
|
async notify() {
|
|
throw new Error("network down");
|
|
},
|
|
};
|
|
|
|
const runtime = await createDashboardRuntime({
|
|
store,
|
|
crawler,
|
|
notifier,
|
|
logger: { error: () => {} },
|
|
pollIntervalSec: 3600,
|
|
});
|
|
|
|
try {
|
|
assert.equal(store.events.length, 1);
|
|
const payload = store.events[0].payload;
|
|
assert.equal(payload.notificationState, "failed");
|
|
assert.equal(payload.notificationSent, false);
|
|
assert.equal(payload.notificationSuppressed, undefined);
|
|
assert.equal(payload.notificationError.phase, "notify");
|
|
assert.match(payload.notificationError.message, /Notifier failed/);
|
|
} finally {
|
|
await runtime.close();
|
|
}
|
|
});
|
|
|
|
test("runtime stores suppressed notification state when alerts are disabled", async () => {
|
|
let notifyCalls = 0;
|
|
const store = createStore({
|
|
controls: { crawlingEnabled: true, alertsEnabled: false },
|
|
});
|
|
const crawler = {
|
|
async getQuotes() {
|
|
return [{ provider: "mock", price: 120000, currency: "KRW" }];
|
|
},
|
|
};
|
|
const notifier = {
|
|
async notify() {
|
|
notifyCalls += 1;
|
|
},
|
|
};
|
|
|
|
const runtime = await createDashboardRuntime({
|
|
store,
|
|
crawler,
|
|
notifier,
|
|
logger: { error: () => {} },
|
|
pollIntervalSec: 3600,
|
|
});
|
|
|
|
try {
|
|
assert.equal(store.events.length, 1);
|
|
const payload = store.events[0].payload;
|
|
assert.equal(payload.notificationState, "suppressed");
|
|
assert.equal(payload.notificationSent, false);
|
|
assert.equal(payload.notificationSuppressed, true);
|
|
assert.equal(payload.notificationError, null);
|
|
assert.equal(notifyCalls, 0);
|
|
} finally {
|
|
await runtime.close();
|
|
}
|
|
});
|