"use strict"; const test = require("node:test"); const assert = require("node:assert/strict"); const { PriceWatcher } = require("../src/priceWatcher"); function createSilentLogger() { return { log() {}, error() {}, }; } test("global crawling toggle skips polling", async () => { let crawlerCalls = 0; const watcher = new PriceWatcher({ crawler: { async getQuotes() { crawlerCalls += 1; return [{ provider: "x", price: 1000, currency: "KRW" }]; }, }, notifier: { async notify() {}, }, logger: createSilentLogger(), }); const watchId = watcher.addWatch({ rawInput: "테스트", searchParams: { segments: [{ from: "ICN", to: "MAD" }], departureDateWindow: { from: "2026-06-01" } }, alertRules: { targetPrice: 900, notifyOnPriceChange: true }, }); watcher.setGlobalControls({ crawlingEnabled: false }); const result = await watcher.pollWatch(watchId); assert.equal(crawlerCalls, 0); assert.equal(result.skipped.reason, "global_crawling_disabled"); }); test("watch-level polling toggle skips polling", async () => { let crawlerCalls = 0; const watcher = new PriceWatcher({ crawler: { async getQuotes() { crawlerCalls += 1; return [{ provider: "x", price: 1000, currency: "KRW" }]; }, }, notifier: { async notify() {}, }, logger: createSilentLogger(), }); const watchId = watcher.addWatch({ rawInput: "테스트", searchParams: { segments: [{ from: "ICN", to: "MAD" }], departureDateWindow: { from: "2026-06-01" } }, alertRules: { targetPrice: null, notifyOnPriceChange: true }, pollingEnabled: false, }); const result = await watcher.pollWatch(watchId); assert.equal(crawlerCalls, 0); assert.equal(result.skipped.reason, "watch_polling_disabled"); }); test("alerts can be suppressed while still computing alert events", async () => { const notifications = []; let call = 0; const watcher = new PriceWatcher({ crawler: { async getQuotes() { call += 1; if (call === 1) { return [{ provider: "x", price: 1000, currency: "KRW" }]; } return [{ provider: "x", price: 900, currency: "KRW" }]; }, }, notifier: { async notify(event) { notifications.push(event); }, }, logger: createSilentLogger(), }); const watchId = watcher.addWatch({ rawInput: "테스트", searchParams: { segments: [{ from: "ICN", to: "MAD" }], departureDateWindow: { from: "2026-06-01" } }, alertRules: { targetPrice: 950, notifyOnPriceChange: true }, alertsEnabled: false, }); await watcher.pollWatch(watchId); const second = await watcher.pollWatch(watchId); assert.equal(notifications.length, 0); assert.equal(second.alert.eventType, "target_price"); assert.equal(second.alert.notificationSuppressed, true); }); test("poll interval under 1 hour throws immediately", () => { assert.throws( () => new PriceWatcher({ crawler: { async getQuotes() { return [{ provider: "x", price: 1000, currency: "KRW" }]; }, }, notifier: { async notify() {}, }, pollIntervalMs: 1000, logger: createSilentLogger(), }), /3600000 이상이어야 합니다/ ); });