Files
token/test/database.test.ts

44 lines
2.0 KiB
TypeScript

import { test } from "node:test";
import assert from "node:assert/strict";
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { openDatabase, migrate } from "../src/database.js";
const steps = [{ version: 1, name: "projects", sql: "CREATE TABLE projects (id INTEGER PRIMARY KEY, name TEXT NOT NULL) STRICT;" }];
test("migrations persist, reopen idempotently, and allow unrelated tables", () => {
const directory = mkdtempSync(join(tmpdir(), "token-db-"));
try {
const path = join(directory, "nested/state.sqlite");
const first = openDatabase(path, steps);
first.prepare("INSERT INTO projects (name) VALUES (?)").run("garden");
first.close();
const second = openDatabase(path, steps);
try {
assert.equal(second.prepare("SELECT name FROM projects").get()?.name, "garden");
assert.equal(second.prepare("PRAGMA foreign_keys").get()?.foreign_keys, 1);
assert.equal(second.prepare("PRAGMA journal_mode").get()?.journal_mode, "wal");
assert.throws(() => migrate(second, []), /history differs/);
assert.throws(() => migrate(second, [{ version: 1, name: "projects", sql: "SELECT 1" }]), /history differs/);
} finally {
second.close();
}
} finally {
rmSync(directory, { recursive: true, force: true });
}
});
test("failed migrations roll back schema changes and history", () => {
const database = openDatabase(":memory:", steps);
try {
assert.throws(() => migrate(database, [...steps, {
version: 2, name: "broken", sql: "CREATE TABLE temporary_table (id INTEGER); INVALID SQL;",
}]));
assert.equal(database.prepare("SELECT count(*) AS count FROM schema_migrations").get()?.count, 1);
assert.equal(database.prepare("SELECT name FROM sqlite_master WHERE name = 'temporary_table'").get(), undefined);
} finally {
database.close();
}
});