Adds 215 tests across three tiers using node:test + node:assert/strict (no new test framework dependencies): - test/tools/ — middleware and utility tests (token, hash, authenticate, jsonBody, convertError, validators) - test/shared/ — DbInterface/BackendDbInterface contract suites reusable across backends (users, abodes, residents, apikeys, sessions, auth) - test/backends/sqlite/ — SQLite-private tests (sql builder, WrappedDb, migrator) + shared suites via SqliteInterface - test/backends/api/ — ApiInterface unit tests + shared suites via a live Koa server backed by SQLite Also fixes four bugs uncovered by the tests: - ApiInterface: path params leaked into query string (slice(1) fix) - ApiInterface: calling res.json() on 204 No Content responses - SqliteInterface.updateResident: missing comma in SET clause - WrappedBetterSqlite3Db: readonly:undefined rejected by better-sqlite3 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
182 lines
4.5 KiB
TypeScript
182 lines
4.5 KiB
TypeScript
import { describe, it } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import {
|
|
createuser,
|
|
updateuser,
|
|
clientuser,
|
|
loginuser,
|
|
createabode,
|
|
updateabode,
|
|
createresident,
|
|
createapikey,
|
|
} from "../../src/schema/validators.js";
|
|
|
|
describe("createuser validator", () => {
|
|
it("accepts a valid CreateUser object", () => {
|
|
const result = createuser({
|
|
email: "user@example.com",
|
|
name: "Alice",
|
|
password: "#unset",
|
|
flags: {},
|
|
});
|
|
assert.equal(result, true);
|
|
});
|
|
|
|
it("rejects missing name", () => {
|
|
const result = createuser({
|
|
email: "user@example.com",
|
|
password: "#unset",
|
|
flags: {},
|
|
});
|
|
assert.equal(result, false);
|
|
assert.ok(createuser.errors && createuser.errors.length > 0);
|
|
});
|
|
|
|
it("rejects missing email", () => {
|
|
const result = createuser({
|
|
name: "Alice",
|
|
password: "#unset",
|
|
flags: {},
|
|
});
|
|
assert.equal(result, false);
|
|
});
|
|
|
|
it("rejects missing password", () => {
|
|
const result = createuser({
|
|
email: "user@example.com",
|
|
name: "Alice",
|
|
flags: {},
|
|
});
|
|
assert.equal(result, false);
|
|
});
|
|
});
|
|
|
|
describe("updateuser validator", () => {
|
|
it("accepts update with just uid", () => {
|
|
const result = updateuser({ uid: "11111111-1111-1111-1111-111111111111" });
|
|
assert.equal(result, true);
|
|
});
|
|
|
|
it("accepts update with uid and name", () => {
|
|
const result = updateuser({
|
|
uid: "11111111-1111-1111-1111-111111111111",
|
|
name: "New Name",
|
|
});
|
|
assert.equal(result, true);
|
|
});
|
|
|
|
it("rejects missing uid", () => {
|
|
const result = updateuser({ name: "Alice" });
|
|
assert.equal(result, false);
|
|
});
|
|
});
|
|
|
|
describe("clientuser validator", () => {
|
|
it("accepts a valid ClientUser (no password)", () => {
|
|
const result = clientuser({
|
|
uid: "11111111-1111-1111-1111-111111111111",
|
|
email: "user@example.com",
|
|
name: "Alice",
|
|
flags: {},
|
|
created_at: "2024-01-01T00:00:00Z",
|
|
updated_at: "2024-01-01T00:00:00Z",
|
|
});
|
|
assert.equal(result, true);
|
|
});
|
|
|
|
it("rejects object with password field", () => {
|
|
const result = clientuser({
|
|
uid: "11111111-1111-1111-1111-111111111111",
|
|
email: "user@example.com",
|
|
name: "Alice",
|
|
password: "#unset",
|
|
flags: {},
|
|
created_at: "2024-01-01T00:00:00Z",
|
|
updated_at: "2024-01-01T00:00:00Z",
|
|
});
|
|
assert.equal(result, false);
|
|
});
|
|
});
|
|
|
|
describe("loginuser validator", () => {
|
|
it("accepts valid LoginUser", () => {
|
|
const result = loginuser({ email: "user@example.com", password: "secret" });
|
|
assert.equal(result, true);
|
|
});
|
|
|
|
it("rejects missing password", () => {
|
|
const result = loginuser({ email: "user@example.com" });
|
|
assert.equal(result, false);
|
|
});
|
|
|
|
it("rejects missing email", () => {
|
|
const result = loginuser({ password: "secret" });
|
|
assert.equal(result, false);
|
|
});
|
|
});
|
|
|
|
describe("createabode validator", () => {
|
|
it("accepts valid CreateAbode", () => {
|
|
const result = createabode({ name: "My Abode" });
|
|
assert.equal(result, true);
|
|
});
|
|
|
|
it("rejects missing name", () => {
|
|
const result = createabode({});
|
|
assert.equal(result, false);
|
|
});
|
|
});
|
|
|
|
describe("updateabode validator", () => {
|
|
it("accepts update with just aid", () => {
|
|
const result = updateabode({ aid: "22222222-2222-2222-2222-222222222222" });
|
|
assert.equal(result, true);
|
|
});
|
|
|
|
it("accepts update with aid and name", () => {
|
|
const result = updateabode({
|
|
aid: "22222222-2222-2222-2222-222222222222",
|
|
name: "New Name",
|
|
});
|
|
assert.equal(result, true);
|
|
});
|
|
});
|
|
|
|
describe("createresident validator", () => {
|
|
it("accepts valid CreateResident", () => {
|
|
const result = createresident({
|
|
uid: "11111111-1111-1111-1111-111111111111",
|
|
aid: "22222222-2222-2222-2222-222222222222",
|
|
flags: {},
|
|
});
|
|
assert.equal(result, true);
|
|
});
|
|
|
|
it("rejects missing uid", () => {
|
|
const result = createresident({
|
|
aid: "22222222-2222-2222-2222-222222222222",
|
|
flags: {},
|
|
});
|
|
assert.equal(result, false);
|
|
});
|
|
});
|
|
|
|
describe("createapikey validator", () => {
|
|
it("accepts valid CreateApikey", () => {
|
|
const result = createapikey({
|
|
uid: "11111111-1111-1111-1111-111111111111",
|
|
name: "My Key",
|
|
permissions: {},
|
|
});
|
|
assert.equal(result, true);
|
|
});
|
|
|
|
it("rejects missing name", () => {
|
|
const result = createapikey({
|
|
uid: "11111111-1111-1111-1111-111111111111",
|
|
permissions: {},
|
|
});
|
|
assert.equal(result, false);
|
|
});
|
|
});
|