Files
notification-wakeup-service/test/alertSearch/smsChannel.test.ts
T

120 lines
3.5 KiB
TypeScript

import assert from "node:assert/strict";
import { mkdtemp, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, it } from "node:test";
import {
alertSearchCursorsDb,
smsAlertSearchCursorsDb,
} from "../../src/db/alertSearchCursorsSqlite.js";
import { closeDatabase } from "../../src/db/sqlite.js";
import {
advanceAlertSearchCursors,
loadAlertSearchCursors,
} from "../../src/alertSearch/cursors.js";
import type { AlertSearchSourceResult, RetrieveAlertSearchResult } from "../../src/alertSearch/retrieve.js";
import type { EndorserAlertSearchData, PartnerAlertSearchData } from "../../src/alertSearch/types.js";
const USER = "did:ethr:0xchanneluser";
let dir: string;
let savedDataDir: string | undefined;
beforeEach(async () => {
savedDataDir = process.env.NOTIFY_DATA_DIR;
dir = await mkdtemp(path.join(tmpdir(), "sms-channel-"));
process.env.NOTIFY_DATA_DIR = dir;
closeDatabase();
});
afterEach(async () => {
closeDatabase();
if (savedDataDir === undefined) delete process.env.NOTIFY_DATA_DIR;
else process.env.NOTIFY_DATA_DIR = savedDataDir;
await rm(dir, { recursive: true, force: true });
});
function ulid(n: number): string {
return `01H${String(n).padStart(23, "0")}`;
}
function retrieved(endorserUlid: string, partnerAt: string): RetrieveAlertSearchResult {
const endorser: AlertSearchSourceResult<EndorserAlertSearchData> = {
outcome: "success",
pageCount: 1,
data: {
claims: [{ id: endorserUlid, issuedAt: "2026-09-05T00:00:00Z", issuer: USER }],
personalPlanContributions: [],
trackedPlanUpdates: [],
trackedPlanClaims: [],
plansNearby: [],
},
};
const partner: AlertSearchSourceResult<PartnerAlertSearchData> = {
outcome: "success",
pageCount: 1,
data: { profilesNearby: [{ rowId: "r1", updatedAt: partnerAt } as never] },
};
return {
data: { ...endorser.data, ...partner.data },
empty: false,
endorser,
partner,
} as RetrieveAlertSearchResult;
}
describe("per-channel alertSearch cursors", () => {
it("advances only the SMS table for an SMS run", async () => {
await advanceAlertSearchCursors(
USER,
retrieved(ulid(5), "2026-09-05T00:00:00Z"),
"sms"
);
assert.equal(
(await smsAlertSearchCursorsDb.get(USER))?.endorserAfterId,
ulid(5)
);
assert.equal(await alertSearchCursorsDb.get(USER), undefined);
});
it("defaults to the FCM table when no channel is named", async () => {
await advanceAlertSearchCursors(
USER,
retrieved(ulid(9), "2026-09-06T00:00:00Z")
);
assert.equal(
(await alertSearchCursorsDb.get(USER))?.endorserAfterId,
ulid(9)
);
assert.equal(await smsAlertSearchCursorsDb.get(USER), undefined);
});
it("lets the two channels sit at different positions", async () => {
await advanceAlertSearchCursors(
USER,
retrieved(ulid(1), "2026-09-01T00:00:00Z"),
"fcm"
);
await advanceAlertSearchCursors(
USER,
retrieved(ulid(2), "2026-09-02T00:00:00Z"),
"sms"
);
assert.deepEqual(await loadAlertSearchCursors(USER, "fcm"), {
endorserAfterId: ulid(1),
partnerAfterDate: "2026-09-01T00:00:00Z",
});
assert.deepEqual(await loadAlertSearchCursors(USER, "sms"), {
endorserAfterId: ulid(2),
partnerAfterDate: "2026-09-02T00:00:00Z",
});
});
it("reports an empty position for a channel that has never run", async () => {
assert.deepEqual(await loadAlertSearchCursors(USER, "sms"), {});
});
});