import { mkdtemp, rm } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { CatalogDatabase } from '../src/database/store.js'; import { runCatalog } from '../src/run/runCatalog.js'; let dir = ''; beforeEach(async () => { dir = await mkdtemp(join(tmpdir(), 'nlc-run-')); }); afterEach(async () => { await rm(dir, { force: true, recursive: true }); }); describe('run orchestration', () => { it('does not write output or state during dry run', async () => { const stateFile = join(dir, 'state.json'); const writes: unknown[] = []; const result = await runCatalog({ dryRun: 1, skipEnrich: true, config: { gmail: { folder: 'Newsletters' }, output: { name: 'Catalog', excel: { enabled: true, path: join(dir, 'out.xlsx') } }, stateFile }, messages: [ { id: 'msg-1', messageId: '', from: 'A ', date: '2026-05-16T00:00:00.000Z', html: '

Python

Article

' } ], writers: [{ write: async (payload) => writes.push(payload) }] }); expect(result.linksExtracted).toBe(1); expect(writes).toHaveLength(0); }); it('only sends locally marked sponsored links to the sponsored output', async () => { const stateFile = join(dir, 'state.json'); const writes: any[] = []; await runCatalog({ config: { gmail: { folder: 'Newsletters' }, output: { name: 'Catalog', excel: { enabled: true, path: join(dir, 'out.xlsx') } }, stateFile }, messages: [ { id: 'msg-1', messageId: '', from: 'Web Tools Weekly ', date: '2026-05-16T00:00:00.000Z', html: `
Cascade - CSS property icons. Fancy Frames - Decorative borders. SPONSORED flexboxle - A daily puzzle game. Typescale AI - A typescale generator.
` } ], writers: [{ write: async (payload) => writes.push(payload) }] }); expect(writes[0].sponsors).toEqual([ { Newsletter: 'Web Tools Weekly', Sponsor: 'flexboxle', Link: 'https://flexboxle.example/', Description: 'A daily puzzle game.' } ]); expect(writes[0].rows.map((row: any) => row.Title)).toEqual([ 'Cascade', 'Fancy Frames', 'Typescale AI' ]); }); it('can persist run output to SQLite through a database writer', async () => { const path = join(dir, 'catalog.sqlite'); const db = new CatalogDatabase(path); db.migrate(); const result = await runCatalog({ config: { gmail: { folder: 'Newsletters' }, output: { name: 'Catalog', excel: { enabled: false } }, stateFile: join(dir, 'state.json') }, messages: [ { id: 'msg-1', messageId: '', from: 'SQLite Weekly ', date: '2026-05-17T00:00:00.000Z', html: '

Databases

SQLite Post - Local data.' } ], writers: [ { write: async (payload) => db.saveCatalogRun({ mode: 'test', newslettersProcessed: 1, linksExtracted: payload.rows.length, sponsorCount: payload.sponsors.length, deadLinkCount: payload.deadLinks.length, errors: 0, ...payload }) } ] }); expect(result.linksExtracted).toBe(1); expect(db.count('link_occurrences')).toBe(1); db.close(); }); });