// Generated, do not edit. sha256:db9b5ce5c6a3dba8e3c23b58d01a079d11c9184ff6a8915c824e00ac45006d20 import { describe, it, before, after, beforeEach, afterEach } from 'node:test'; import assert from 'node:assert/strict'; import { DatabaseSync } from 'node:sqlite'; import { mkdtemp, rm } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { openDatabase, closeDatabase, database, pragmaStand, run, all, one, lastId, BUSY_TIMEOUT_MS, } from '../../server/db/conn.mjs'; const DDL = ` CREATE TABLE Ouder (id INTEGER PRIMARY KEY, naam TEXT NOT NULL) STRICT; CREATE TABLE Kind ( id INTEGER PRIMARY KEY, ouderId INTEGER NOT NULL REFERENCES Ouder(id) ON DELETE CASCADE, tekst TEXT NOT NULL ) STRICT; CREATE INDEX IxKindOuder ON Kind (ouderId); `; describe('server/db/conn: de verbinding en zijn PRAGMA\'s', () => { beforeEach(() => { openDatabase(':memory:'); run(DDL); }); afterEach(() => closeDatabase()); it('dwingt foreign keys écht af, en niet alleen op papier', () => { run(`INSERT INTO Ouder (naam) VALUES (?)`, ['een']); const ouderId = lastId(); run(`INSERT INTO Kind (ouderId, tekst) VALUES (?,?)`, [ouderId, 'hoort erbij']); assert.throws( () => run(`INSERT INTO Kind (ouderId, tekst) VALUES (?,?)`, [9999, 'wees']), /FOREIGN KEY constraint failed/); run(`DELETE FROM Ouder WHERE id = ?`, [ouderId]); assert.equal(all(`SELECT * FROM Kind`).length, 0); }); it('TEGENPROEF: zonder handhaving slaagt exact dezelfde INSERT', () => { const zonder = new DatabaseSync(':memory:', { enableForeignKeyConstraints: false }); zonder.exec(DDL); zonder.prepare(`INSERT INTO Kind (ouderId, tekst) VALUES (?,?)`).run(9999n, 'wees'); assert.equal(zonder.prepare(`SELECT COUNT(*) AS n FROM Kind`).get().n, 1, 'zonder handhaving hoort de wees er gewoon in te staan; anders bewijst de test hierboven niets'); zonder.close(); }); it('zet de vier PRAGMA\'s op de verbinding', () => { const stand = pragmaStand(); assert.equal(stand.foreignKeys, true); assert.equal(stand.journalMode, 'memory'); assert.equal(stand.synchronous, 1); assert.equal(stand.busyTimeout, BUSY_TIMEOUT_MS); }); it('weigert een tweede verbinding zolang de eerste openstaat', () => { assert.throws(() => openDatabase(':memory:'), /already open/); }); it('geeft gewone objecten terug, geen rijen met null-prototype', () => { run(`INSERT INTO Ouder (naam) VALUES (?)`, ['een']); const rij = one(`SELECT * FROM Ouder`); assert.equal(Object.getPrototypeOf(rij), Object.prototype); assert.deepEqual(rij, { id: 1, naam: 'een' }); }); it('geeft null bij one() zonder treffer, en null uit lastId() zonder insert', () => { assert.equal(one(`SELECT * FROM Ouder WHERE id = ?`, [404]), null); }); }); describe('server/db/conn: bindwaarden gelijk aan wat de browser deed', () => { beforeEach(() => { openDatabase(':memory:'); run(`CREATE TABLE Waarde (id INTEGER PRIMARY KEY, tekst TEXT, getal INTEGER) STRICT;`); }); afterEach(() => closeDatabase()); it('maakt van undefined een NULL in plaats van te gooien', () => { run(`INSERT INTO Waarde (tekst, getal) VALUES (?,?)`, [undefined, 1]); assert.equal(one(`SELECT tekst FROM Waarde`).tekst, null); }); it('maakt van true/false een 1/0', () => { run(`INSERT INTO Waarde (tekst, getal) VALUES (?,?)`, ['x', true]); run(`INSERT INTO Waarde (tekst, getal) VALUES (?,?)`, ['y', false]); assert.deepEqual(all(`SELECT getal FROM Waarde ORDER BY id`).map(r => r.getal), [1, 0]); }); it('schrijft een heel getal in een TEXT-kolom als \'1\' en niet als \'1.0\'', () => { run(`INSERT INTO Waarde (tekst) VALUES (?)`, [1]); assert.equal(one(`SELECT tekst FROM Waarde`).tekst, '1'); }); }); describe('server/db/conn: run() zonder params voert meerdere statements uit', () => { beforeEach(() => openDatabase(':memory:')); afterEach(() => closeDatabase()); it('voert een meerdelige DDL-string volledig uit', () => { run(DDL); const tabellen = all(`SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name`).map(r => r.name); assert.deepEqual(tabellen, ['Kind', 'Ouder']); }); it('voert met params alleen het eerste statement uit', () => { run(`CREATE TABLE A (id INTEGER PRIMARY KEY, t TEXT) STRICT;`); run(`INSERT INTO A (t) VALUES (?); INSERT INTO A (t) VALUES ('tweede');`, ['eerste']); assert.deepEqual(all(`SELECT t FROM A`).map(r => r.t), ['eerste']); }); }); describe('server/db/conn: op een echt bestand', () => { let dir, pad; before(async () => { dir = await mkdtemp(join(tmpdir(), 'assetapp-db-')); pad = join(dir, 'test.sqlite'); }); after(async () => { closeDatabase(); await rm(dir, { recursive: true, force: true }); }); it('zet WAL aan, en die blijft in het bestand staan', () => { openDatabase(pad); run(DDL); assert.equal(pragmaStand().journalMode, 'wal'); closeDatabase(); const kaal = new DatabaseSync(pad); assert.equal(kaal.prepare(`PRAGMA journal_mode`).get().journal_mode, 'wal'); kaal.close(); }); it('zet synchronous en busy_timeout élke keer opnieuw, want die zijn NIET persistent', () => { const kaal = new DatabaseSync(pad); assert.equal(kaal.prepare(`PRAGMA synchronous`).get().synchronous, 2); assert.equal(kaal.prepare(`PRAGMA busy_timeout`).get().timeout, 0); kaal.close(); openDatabase(pad); const stand = pragmaStand(); assert.equal(stand.synchronous, 1); assert.equal(stand.busyTimeout, BUSY_TIMEOUT_MS); closeDatabase(); }); it('bewaart de data tussen twee sessies door, zonder persist()', () => { openDatabase(pad); run(`INSERT INTO Ouder (naam) VALUES (?)`, ['blijft staan']); closeDatabase(); openDatabase(pad); assert.equal(one(`SELECT naam FROM Ouder ORDER BY id DESC`).naam, 'blijft staan'); assert.equal(database().constructor.name, 'DatabaseSync'); closeDatabase(); }); });