sync-unsubscribes.test.js
1 /** 2 * Tests for src/utils/sync-unsubscribes.js 3 * 4 * Tests the pure synchronous exports that query the local DB: 5 * - isEmailUnsubscribed 6 * - getUnsubscribeCount 7 * 8 * syncUnsubscribes() requires a live Cloudflare Worker endpoint — not tested here. 9 * 10 * Uses pg-mock pattern since sync-unsubscribes.js imports from db.js. 11 */ 12 13 import { test, describe, before, mock } from 'node:test'; 14 import assert from 'node:assert/strict'; 15 import Database from 'better-sqlite3'; 16 import { createPgMock } from '../helpers/pg-mock.js'; 17 18 const db = new Database(':memory:'); 19 db.exec(` 20 CREATE TABLE IF NOT EXISTS unsubscribed_emails ( 21 id INTEGER PRIMARY KEY AUTOINCREMENT, 22 email TEXT NOT NULL UNIQUE, 23 created_at TEXT NOT NULL DEFAULT (datetime('now')) 24 ); 25 `); 26 27 mock.module('../../src/utils/db.js', { namedExports: createPgMock(db) }); 28 29 const { isEmailUnsubscribed, getUnsubscribeCount } = 30 await import('../../src/utils/sync-unsubscribes.js'); 31 32 before(() => { 33 db.exec(`INSERT INTO unsubscribed_emails (email) VALUES ('unsubbed@example.com')`); 34 db.exec(`INSERT INTO unsubscribed_emails (email) VALUES ('UPPERCASE@EXAMPLE.COM')`); 35 }); 36 37 // ─── isEmailUnsubscribed ────────────────────────────────────────────────────── 38 39 describe('isEmailUnsubscribed', () => { 40 test('returns true for a known unsubscribed email', async () => { 41 assert.equal(await isEmailUnsubscribed('unsubbed@example.com'), true); 42 }); 43 44 test('is case-insensitive (COLLATE NOCASE)', async () => { 45 assert.equal(await isEmailUnsubscribed('UNSUBBED@EXAMPLE.COM'), true); 46 assert.equal(await isEmailUnsubscribed('Unsubbed@Example.Com'), true); 47 }); 48 49 test('returns false for an email not in the list', async () => { 50 assert.equal(await isEmailUnsubscribed('other@example.com'), false); 51 }); 52 53 test('returns false for empty string', async () => { 54 assert.equal(await isEmailUnsubscribed(''), false); 55 }); 56 57 test('returns false for null', async () => { 58 assert.equal(await isEmailUnsubscribed(null), false); 59 }); 60 }); 61 62 // ─── getUnsubscribeCount ────────────────────────────────────────────────────── 63 64 describe('getUnsubscribeCount', () => { 65 test('returns the number of unsubscribed emails', async () => { 66 const count = await getUnsubscribeCount(); 67 assert.equal(typeof count, 'number'); 68 assert.equal(count, 2); // inserted 2 in before() 69 }); 70 71 test('returns 0 when table is empty', async () => { 72 // Temporarily clear the table 73 db.exec('DELETE FROM unsubscribed_emails'); 74 75 const count = await getUnsubscribeCount(); 76 assert.equal(count, 0); 77 78 // Restore 79 db.exec(`INSERT INTO unsubscribed_emails (email) VALUES ('unsubbed@example.com')`); 80 db.exec(`INSERT INTO unsubscribed_emails (email) VALUES ('UPPERCASE@EXAMPLE.COM')`); 81 }); 82 });