import assert from 'node:assert/strict' import { afterEach, beforeEach, test } from 'node:test' import moveToPaperTrail from '../src/paper-trail.js' import { HEY, installFetch, jsonResponse, resetKodySecrets } from './helpers.mjs' // Fixture only: the Logos weekly newsletter thread. Never a live app.hey.com call. const LOGOS_TOPIC_ID = 2153822589 const TRAILBOX_ID = 33 const ENTRY_ID = 8001 const BOXES = [ { id: 11, kind: 'imbox', name: 'Imbox' }, { id: 22, kind: 'feedbox', name: 'The Feed' }, { id: TRAILBOX_ID, kind: 'trailbox', name: 'Paper Trail' }, ] let fixture beforeEach(() => { resetKodySecrets() fixture = installFetch(async (url, init) => { const method = String(init.method || 'GET').toUpperCase() const handler = fixture.routes.get(`${method} ${url}`) if (handler) return handler(url, init) throw new Error(`unexpected ${method} ${url}`) }) fixture.routes = new Map() }) afterEach(() => { fixture?.restore() }) function on(method, url, handler) { fixture.routes.set(`${method} ${url}`, handler) } function writes() { return fixture.requests.filter((row) => row.method !== 'GET') } function routeBoxes(boxes = BOXES) { on('GET', `${HEY}/boxes.json`, () => jsonResponse(200, boxes)) } function routeMove(topicId = LOGOS_TOPIC_ID) { on('POST', `${HEY}/topics/${topicId}/moves.json`, () => new Response(null, { status: 204 })) } test('moveToPaperTrail posts the single-topic MoveTopic body to the Paper Trail box', async () => { routeBoxes() routeMove() const moved = await moveToPaperTrail({ topicId: LOGOS_TOPIC_ID }) const [post] = writes() assert.equal(post.method, 'POST') assert.equal(post.url, `${HEY}/topics/${LOGOS_TOPIC_ID}/moves.json`) assert.equal(post.headers['content-type'], 'application/json') assert.deepEqual(JSON.parse(post.body), { box_id: TRAILBOX_ID }) assert.equal(moved.topicId, LOGOS_TOPIC_ID) assert.equal(moved.boxId, TRAILBOX_ID) assert.equal(moved.status, 204) assert.equal(moved.url, `${HEY}/topics/${LOGOS_TOPIC_ID}`) assert.equal(writes().length, 1) assert.equal( fixture.requests.some((row) => /clearance|contacts|postings\/moves|designation/i.test(row.url)), false, ) }) test('moveToPaperTrail with entryId reads the message topic then posts the same single-topic move', async () => { on('GET', `${HEY}/messages/${ENTRY_ID}.json`, () => jsonResponse(200, { id: ENTRY_ID, topic_id: LOGOS_TOPIC_ID, subject: 'New resources are coming soon to Logos' }), ) routeBoxes() routeMove() await moveToPaperTrail({ entryId: ENTRY_ID }) const [post] = writes() assert.equal(post.method, 'POST') assert.equal(post.url, `${HEY}/topics/${LOGOS_TOPIC_ID}/moves.json`) assert.deepEqual(JSON.parse(post.body), { box_id: TRAILBOX_ID }) assert.equal( fixture.requests.some((row) => /clearance|contacts|postings\/moves/i.test(row.url)), false, ) }) test('moveToPaperTrail throws before any request without topicId or entryId', async () => { await assert.rejects(() => moveToPaperTrail({}), /topicId or entryId is required/) assert.equal(fixture.requests.length, 0) })