import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; import { fileURLToPath } from "node:url"; import test from "node:test"; import { startPostgresFixture } from "./helpers/postgres-fixture.ts"; const runnerPath = fileURLToPath(new URL("../scripts/db-migrate.mjs", import.meta.url)); const userId = "93000000-0000-4000-8000-000000000079"; const personId = "93000000-0000-4000-8000-000000000179"; const fingerprint = "a".repeat(64); const otherFingerprint = "b".repeat(64); const rulesVersion = "bde5d615:marriage_match_product_v1"; function dockerAvailable(): boolean { return spawnSync("docker", ["version", "--format", "{{.Server.Version}}"], { encoding: "utf8", stdio: "ignore" }).status === 0; } function lastLine(value: string): string { const lines = value.split(/\r?\n/).map((line) => line.trim()).filter(Boolean); return lines[lines.length - 1] ?? ""; } test("marriage match rows are reused by fingerprint and removed with the person", { skip: dockerAvailable() ? false : "docker unavailable on this host", }, () => { const fixture = startPostgresFixture(); try { const migration = spawnSync(process.execPath, [runnerPath], { encoding: "utf8", env: { ...process.env, SCHEMA_DATABASE_URL: fixture.connectionUrl("schema_owner", "schema-owner-test-password") }, }); assert.equal(migration.status, 0, `${migration.stdout}${migration.stderr}`); assert.match(migration.stdout ?? "", /applied 20261018010000_synastry_reports_marriage_match\.sql/); fixture.psql(` insert into identity.users (id, name, email, email_verified, email_verified_at) values ('${userId}', 'Fictional Match', '${userId}@example.invalid', true, now()); insert into public.chart_profiles (id, user_id, role, profile) values ('${personId}', '${userId}', 'other', '{}'::jsonb); insert into public.synastry_reports ( user_id, partner_name, report, subject_low, subject_high, fingerprint_low, fingerprint_high, rules_version, structured_result ) values ( '${userId}', '婚恋合盘', '{"rules_version":"${rulesVersion}","default":{},"raman":{}}'::jsonb, '${personId}', 'self', '${fingerprint}', '${otherFingerprint}', '${rulesVersion}', '{"rules_version":"${rulesVersion}","default":{},"raman":{}}'::jsonb ); `); const shape = lastLine(fixture.psql(` select (octet_length(structured_result::text) < 65536) and (structured_result ? 'default') and (structured_result ? 'raman') and not (structured_result ? 'dossier') and not (structured_result ? 'chart_snapshots') from public.synastry_reports where user_id = '${userId}'; `)); assert.equal(shape, "t"); assert.throws(() => fixture.psql(` insert into public.synastry_reports ( user_id, partner_name, report, subject_low, subject_high, fingerprint_low, fingerprint_high, rules_version, structured_result ) values ( '${userId}', '婚恋合盘', '{"rules_version":"${rulesVersion}","default":{},"raman":{}}'::jsonb, '${personId}', 'self', '${fingerprint}', '${otherFingerprint}', '${rulesVersion}', '{"rules_version":"${rulesVersion}","default":{},"raman":{}}'::jsonb ); `), (error: unknown) => { const stderr = error && typeof error === "object" && "stderr" in error ? String(error.stderr) : ""; return /duplicate key|23505/.test(`${stderr}\n${String(error)}`); }); const again = lastLine(fixture.psql(` select count(*) from public.synastry_reports where user_id = '${userId}' and subject_low = '${personId}' and subject_high = 'self' and fingerprint_low = '${fingerprint}' and fingerprint_high = '${otherFingerprint}' and rules_version = '${rulesVersion}'; `)); assert.equal(again, "1"); const changed = lastLine(fixture.psql(` select count(*) from public.synastry_reports where user_id = '${userId}' and subject_low = '${personId}' and fingerprint_low = '${"c".repeat(64)}' and rules_version = '${rulesVersion}'; `)); assert.equal(changed, "0"); fixture.psql(`delete from public.chart_profiles where id = '${personId}';`); const remaining = lastLine(fixture.psql(` select count(*) from public.synastry_reports where user_id = '${userId}'; `)); assert.equal(remaining, "0"); } finally { fixture.stop(); } });