Files
Jyotisha/frontend/tests/database-synastry-full-create.test.ts
T
jesse-uxandCursor dd9efb3447 fix(synastry): keep the picker order in the report title
The pair key stays sorted for dedup, and generation now loads the two people in the order they were chosen. The report back link uses Link so the new route passes the page-link lint.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-21 18:26:26 +08:00

144 lines
7.0 KiB
TypeScript

import assert from "node:assert/strict";
import { randomUUID } from "node:crypto";
import { spawnSync } from "node:child_process";
import { register } from "node:module";
import test from "node:test";
import { fileURLToPath } from "node:url";
import { closeLocalPostgresDataPool, createLocalPostgresDataClient } from "../src/lib/db/local-postgres-client-core.ts";
import { startPostgresFixture, type PostgresFixture } from "./helpers/postgres-fixture.ts";
// The synastry create path must reach a real reservation and a queued job
// through the self-hosted client. The model catalog is stubbed. Fictional rows only.
const runner = fileURLToPath(new URL("../scripts/db-migrate.mjs", import.meta.url));
const docker = spawnSync("docker", ["version", "--format", "{{.Server.Version}}"], { stdio: "ignore" }).status === 0;
const MODEL_ID = "synastry-fixture-model";
function applyMigrations(fixture: PostgresFixture): void {
const result = spawnSync(process.execPath, [runner], {
encoding: "utf8",
env: {
...process.env,
SCHEMA_DATABASE_URL: fixture.connectionUrl("schema_owner", "schema-owner-test-password"),
},
});
assert.equal(result.status, 0, result.stderr || result.stdout);
}
test("createSynastryFullReport reserves synastry.full and enqueues a job on the real client", {
skip: docker ? false : "docker unavailable",
}, async () => {
await register(new URL("./support/stub-server-only.mjs", import.meta.url).href, import.meta.url);
const fixture = startPostgresFixture();
const serviceUrl = fixture.connectionUrl("service_runtime", "service-runtime-test-password");
const appUrl = fixture.connectionUrl("app_runtime", "app-runtime-test-password");
const adminUrl = fixture.connectionUrl("admin_runtime", "admin-runtime-test-password");
const previousAuth = process.env.AUTH_PROVIDER;
const previousAdminUrl = process.env.ADMIN_DATABASE_URL;
process.env.AUTH_PROVIDER = "self-hosted";
process.env.ADMIN_DATABASE_URL = adminUrl;
try {
applyMigrations(fixture);
const userId = randomUUID();
const personId = randomUUID();
fixture.psql(`
insert into identity.users (id, name, email, email_verified, email_verified_at)
values ('${userId}', '虚构甲', '${userId}@example.invalid', true, now());
update public.profiles set
name = '虚构甲',
credits = 100,
birth_date = '1991-04-07',
reported_birth_time = '09:15',
birth_time_status = 'reported',
birth_time_source = 'family_exact',
latitude = 31.2,
longitude = 121.4,
timezone_offset = 8,
timezone_id = 'Asia/Shanghai',
ayanamsa = 'lahiri',
birth_place_label = '虚构市'
where id = '${userId}';
insert into public.chart_profiles (
id, user_id, role, profile, updated_at, name, birth_date, reported_birth_time,
birth_time_source, latitude, longitude, timezone_id, timezone_offset,
birth_place_label, ayanamsa, birth_time_status
) values (
'${personId}', '${userId}', 'other', '{"name":"虚构乙"}'::jsonb, now(),
'虚构乙', '1992-05-06', '10:20', 'family_exact', 22.3, 114.1,
'Asia/Shanghai', 8, '虚构港', 'lahiri', 'reported'
);
with provider as (
insert into public.model_providers (code, name, provider_type, encrypted_api_key, enabled)
values ('synastry-fixture', 'Synastry Fixture', 'openai', 'test-ciphertext', true)
returning id
), config as (
insert into public.model_configs (model_id) values ('${MODEL_ID}') returning id
)
insert into public.model_config_versions (
config_id, version, provider_id, label, provider_model, enabled, is_default, status, published_at
)
select config.id, 1, provider.id, 'Fixture', 'gpt-test', true, true, 'published', now()
from config cross join provider;
`);
const catalog = await import("../src/lib/model-catalog.ts");
catalog.setModelCatalogIoForTests({
queryAdminRows: (async () => [{
model_id: MODEL_ID,
version: 1,
label: "Fixture",
description: "",
provider_model: "gpt-test",
credit_cost: 1,
is_default: true,
provider_code: "synastry-fixture",
provider_type: "openai" as const,
base_url: null,
encrypted_api_key: "test-ciphertext",
input_cost: 0,
output_cost: 0,
context_window: null,
}]) as typeof catalog.setModelCatalogIoForTests extends (next: infer T) => void
? T extends { queryAdminRows?: infer Q } ? Q : never
: never,
decryptModelProviderApiKey: () => "sk-test",
});
catalog.invalidateLanguageModelCatalog();
const { createSynastryFullReport } = await import("../src/lib/synastry-full-create.ts");
const user = createLocalPostgresDataClient(appUrl, { id: userId, email: `${userId}@example.invalid` });
const admin = createLocalPostgresDataClient(serviceUrl, null, "service_role");
const created = await createSynastryFullReport({
userId,
body: { reportType: "synastry_full", subjectA: "self", subjectB: personId },
supabase: user,
admin,
});
assert.equal(created.status, 202, JSON.stringify(created.body));
const report = created.body.report as { id?: string; status?: string } | undefined;
assert.equal(typeof report?.id, "string");
assert.equal(report?.status, "generating");
assert.equal(typeof created.body.jobId, "string");
assert.equal(fixture.psql(`select status from public.personal_reports where id = '${report?.id}'`), "generating");
assert.equal(fixture.psql(`select status from public.personal_report_jobs where user_id = '${userId}'`), "queued");
assert.equal(fixture.psql(`select status from public.usage_reservations where user_id = '${userId}'`), "reserved");
assert.equal(fixture.psql(`select credits from public.profiles where id = '${userId}'`), "81");
assert.equal(fixture.psql(`select payload->>'first' from public.personal_report_sections where user_id = '${userId}' and section_id = 'synastry_order'`), "self");
assert.equal(fixture.psql(`select payload->>'second' from public.personal_report_sections where user_id = '${userId}' and section_id = 'synastry_order'`), personId);
assert.equal(fixture.psql(`select subject_low from public.personal_reports where id = '${report?.id}'`), personId);
assert.equal(fixture.psql(`select subject_high from public.personal_reports where id = '${report?.id}'`), "self");
catalog.setModelCatalogIoForTests(null);
catalog.invalidateLanguageModelCatalog();
} finally {
const database = await import("../src/lib/admin/database.ts");
await database.adminDatabasePool().end().catch(() => undefined);
if (previousAuth === undefined) delete process.env.AUTH_PROVIDER;
else process.env.AUTH_PROVIDER = previousAuth;
if (previousAdminUrl === undefined) delete process.env.ADMIN_DATABASE_URL;
else process.env.ADMIN_DATABASE_URL = previousAdminUrl;
await closeLocalPostgresDataPool(serviceUrl);
await closeLocalPostgresDataPool(appUrl);
fixture.stop();
}
});