// test/notes.test.mjs import assert from 'node:assert/strict'; import { after, before, beforeEach, test } from 'node:test'; import { fileURLToPath } from 'node:url'; import { PGlite } from '@electric-sql/pglite'; import { createDatabaseDouble, migrationsFrom } from '@turnzero/database/testing'; import { createDataLayer } from '../src/db.mjs'; import { createAppServer } from '../src/server.mjs'; const MIGRATIONS = fileURLToPath(new URL('../migrations/', import.meta.url)); // One test double for the file: a PostgreSQL engine inside this process, with // the migrations applied, and the server over it on a port of this machine. let double; let db; let server; let base; before(async () => { double = await createDatabaseDouble({ engine: new PGlite(), files: migrationsFrom(MIGRATIONS) }); db = createDataLayer(double.pool); server = createAppServer(db); await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); base = `http://127.0.0.1:${server.address().port}`; }); // Every table emptied between tests, so each test starts from empty tables. beforeEach(() => double.reset()); after(async () => { await new Promise((resolve) => server.close(resolve)); await double.close(); }); test('the migration applies', () => { assert.deepEqual(double.applied, ['0001_notes.sql']); }); test('addNote adds a row and listNotes lists it', async () => { assert.deepEqual(await db.addNote('first'), { id: '1', title: 'first' }); assert.deepEqual(await db.listNotes(), [{ id: '1', title: 'first' }]); }); test('GET /health reads the database and returns 200', async () => { const response = await fetch(`${base}/health`); assert.equal(response.status, 200); assert.deepEqual(await response.json(), { ok: true }); }); test('POST /notes keeps a title with characters outside ASCII, and GET /notes returns it', async () => { const title = 'café ☕ 東京'; const response = await fetch(`${base}/notes`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ title }), }); assert.equal(response.status, 201); assert.equal((await response.json()).title, title); const listed = await fetch(`${base}/notes`); assert.equal(listed.status, 200); assert.deepEqual((await listed.json()).map((row) => row.title), [title]); }); test('POST /notes refuses an empty title, and GET /notes returns no row', async () => { const response = await fetch(`${base}/notes`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ title: '' }), }); assert.equal(response.status, 400); assert.deepEqual(await response.json(), { error: 'invalid_note' }); assert.deepEqual(await (await fetch(`${base}/notes`)).json(), []); }); test('POST /notes answers 400 invalid_json for a body that is not JSON, and GET /notes returns no row', async () => { const response = await fetch(`${base}/notes`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: '{', }); assert.equal(response.status, 400); assert.deepEqual(await response.json(), { error: 'invalid_json' }); assert.deepEqual(await (await fetch(`${base}/notes`)).json(), []); });