Files
Jyotisha/frontend/tests/database-onboarding-journey.test.ts
T
jesse-uxandGrok (agent loop) fdd592d3f3 feat: 新账户首问免费,档案可标明关系
只做启程(一):同一笔预扣覆盖已公布的标准档,更贵的只扣差价;引导状态与人物关系只加列。tsc 与 lint 通过。test:db 91 项,失败 14,其中 13 条为 Windows 已知失败;校正遥测单独重跑通过。

Co-Authored-By: Grok (agent loop)
2026-10-23 00:34:28 +08:00

143 lines
11 KiB
TypeScript

import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
import test from "node:test";
import pg from "pg";
import { startPostgresFixture } from "./helpers/postgres-fixture.ts";
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 sessionA = "99999999-9999-4999-8999-999999999981";
const sessionB = "99999999-9999-4999-8999-999999999982";
const sessionC = "99999999-9999-4999-8999-999999999983";
const chartOld = "99999999-9999-4999-8999-999999999984";
const chartChild = "99999999-9999-4999-8999-999999999985";
test("first consult is free once, onboarding state is service-owned, and relation is constrained", { skip: docker ? false : "docker unavailable" }, async () => {
const fixture = startPostgresFixture();
try {
const migration = spawnSync(process.execPath, [runner], {
encoding: "utf8",
env: { ...process.env, SCHEMA_DATABASE_URL: fixture.connectionUrl("schema_owner", "schema-owner-test-password") },
});
assert.equal(migration.status, 0, migration.stderr);
fixture.psql(`insert into identity.users(name,email,email_verified,email_verified_at) values
('Fictional A','onboarding-a@example.com',true,now()),
('Fictional B','onboarding-b@example.com',true,now()),
('Fictional C','onboarding-c@example.com',true,now()),
('Fictional D','onboarding-d@example.com',true,now());`);
const user = (email: string) => fixture.psql(`select id from identity.users where email='${email}'`);
const a = user("onboarding-a@example.com");
const b = user("onboarding-b@example.com");
const c = user("onboarding-c@example.com");
const d = user("onboarding-d@example.com");
const session = (id: string, owner: string) =>
`insert into public.chat_sessions(id,user_id,title,theme,model_id,messages,session_type,updated_at) values ('${id}','${owner}','test','general','test-model','[]','consultation',now());`;
fixture.psql(`update public.profiles set credits=0 where id in ('${a}','${c}');
update public.profiles set credits=5 where id='${b}';
${session(sessionA, a)}
${session(sessionB, b)}
${session(sessionC, c)}`);
for (const column of ["onboarding_state", "first_consult_free_used_at", "first_consult_free_request_id"]) {
assert.equal(fixture.psql(`select has_column_privilege('authenticated','public.profiles','${column}','update')`), "f", column);
assert.equal(fixture.psql(`select has_column_privilege('service_role','public.profiles','${column}','select')`), "t", column);
}
assert.equal(fixture.psql("select has_function_privilege('authenticated','public.save_onboarding_state(uuid,jsonb)','execute')"), "f");
assert.equal(fixture.psql("select has_function_privilege('service_role','public.save_onboarding_state(uuid,jsonb)','execute')"), "t");
assert.throws(() => fixture.psql(`set role authenticated; update public.profiles set onboarding_state='{}'::jsonb where id='${a}'`));
const save = (patch: string) => fixture.psql(
`select success::text || ':' || coalesce(error_code,'ok') || ':' || coalesce(state->>'chartVisitedAt','') || ':' || coalesce(state->'hintsSeen'->>0,'') from public.save_onboarding_state('${a}','${patch}'::jsonb)`,
);
assert.equal(save('{"chartVisitedAt":"2026-10-22T00:00:00Z"}'), "true:ok:2026-10-22T00:00:00Z:");
assert.equal(save('{"hintsSeen":["follow-up"]}'), "true:ok:2026-10-22T00:00:00Z:follow-up");
assert.equal(save('{"nope":true}'), "f:invalid_key::");
assert.equal(save('{"hintsSeen":["not-a-hint"]}'), "f:invalid_hint::");
assert.equal(fixture.psql(`select onboarding_state->>'chartVisitedAt' from public.profiles where id='${a}'`), "2026-10-22T00:00:00Z");
assert.equal(fixture.psql(`select save_onboarding_state.success::text from public.save_onboarding_state('${b}','{"hintsSeen":["tab-chart"]}'::jsonb)`), "true");
assert.equal(fixture.psql(`select onboarding_state->>'chartVisitedAt' from public.profiles where id='${a}'`), "2026-10-22T00:00:00Z");
assert.throws(() => fixture.psql(`insert into public.chart_profiles(id,user_id,role,profile,name,relation) values ('${chartChild}','${a}','other','{}','示例乙','cousin')`));
fixture.psql(`insert into public.chart_profiles(id,user_id,role,profile,name) values ('${chartOld}','${a}','other','{}','示例丙')`);
assert.equal(fixture.psql(`select coalesce(relation,'null') from public.chart_profiles where id='${chartOld}'`), "null");
fixture.psql(`update public.chart_profiles set relation='child' where id='${chartOld}'`);
assert.equal(fixture.psql(`select relation from public.chart_profiles where id='${chartOld}'`), "child");
assert.throws(() => fixture.psql(`insert into public.chart_profiles(user_id,role,profile,name,relation) values ('${a}','self','{}','示例甲','partner')`));
fixture.psql(`insert into public.consultation_requests(user_id,request_id,status,response_message) values
('${c}','old-done','completed','{"role":"assistant","text":"done","responseKind":"reading"}'),
('${d}','old-chat','completed','{"role":"assistant","text":"你好","responseKind":"smalltalk"}');`);
assert.equal(fixture.psql("select public.backfill_first_consult_free()"), "1");
assert.equal(fixture.psql("select public.backfill_first_consult_free()"), "0");
assert.equal(fixture.psql(`select (first_consult_free_used_at is null)::text from public.profiles where id='${c}'`), "f");
assert.equal(fixture.psql(`select (first_consult_free_used_at is null)::text from public.profiles where id='${d}'`), "true");
assert.equal(fixture.psql(`select (first_consult_free_used_at is null)::text from public.profiles where id='${a}'`), "true");
const reserve = (owner: string, id: string, sid: string, cost: number) =>
fixture.psql(`select success::text || ':' || coalesce(reason,'ok') from public.reserve_consultation_usage('${owner}','${id}','${sid}','test-model',${cost})`);
assert.equal(reserve(a, "no-price", sessionA, 1), "f:insufficient_credits");
fixture.psql(`insert into public.feature_pricing(feature_key,model_tier,credit_cost,version,status,enabled) values ('chat.standard','standard',3,1,'published',true)`);
assert.equal(reserve(c, "old-account", sessionC, 3), "f:insufficient_credits");
const clients = [
new pg.Client({ connectionString: fixture.connectionUrl("schema_owner", "schema-owner-test-password") }),
new pg.Client({ connectionString: fixture.connectionUrl("schema_owner", "schema-owner-test-password") }),
];
try {
await Promise.all(clients.map((client) => client.connect()));
const raced = await Promise.all([
clients[0]!.query(`select success from public.reserve_consultation_usage('${a}','race-1','${sessionA}','test-model',3)`),
clients[1]!.query(`select success from public.reserve_consultation_usage('${a}','race-2','${sessionA}','test-model',3)`),
]);
const wins = raced.filter((result) => result.rows[0]?.success === true);
assert.equal(wins.length, 1);
} finally {
await Promise.all(clients.map((client) => client.end()));
}
assert.equal(fixture.psql(`select credits::text from public.profiles where id='${a}'`), "0");
assert.equal(fixture.psql(`select count(*) from public.credit_transactions where user_id='${a}' and request_id in ('race-1','race-2')`), "0");
const held = fixture.psql(`select first_consult_free_request_id from public.profiles where id='${a}'`);
assert.match(held, /^race-[12]$/);
assert.equal(fixture.psql(`select (first_consult_free_used_at is null)::text from public.profiles where id='${a}'`), "true");
assert.equal(fixture.psql(`select success::text from public.cancel_consultation_credit('${a}','${held}')`), "true");
assert.equal(fixture.psql(`select coalesce(first_consult_free_request_id,'null') || ':' || (first_consult_free_used_at is null)::text from public.profiles where id='${a}'`), "null:true");
assert.equal(reserve(a, "smalltalk", sessionA, 3), "true:ok");
assert.equal(
fixture.psql(`select success::text from public.complete_consultation_free('${a}','smalltalk','${sessionA}','{"role":"assistant","text":"你好","responseKind":"smalltalk"}','{}')`),
"true",
);
assert.equal(fixture.psql(`select coalesce(first_consult_free_request_id,'null') || ':' || (first_consult_free_used_at is null)::text from public.profiles where id='${a}'`), "null:true");
assert.equal(reserve(a, "standard", sessionA, 3), "true:ok");
assert.equal(
fixture.psql(`select success::text from public.complete_consultation_response('${a}','standard','${sessionA}','{"role":"assistant","text":"a full answer"}','{}')`),
"true",
);
assert.equal(fixture.psql(`select (first_consult_free_used_at is null)::text from public.profiles where id='${a}'`), "f");
assert.equal(fixture.psql(`select credits::text from public.profiles where id='${a}'`), "0");
assert.equal(fixture.psql(`select (metadata->>'billingSource') || ':' || (metadata->>'creditCost') from public.usage_ledger where user_id='${a}' and request_id='standard'`), "first_consult_free:0");
assert.equal(reserve(a, "second", sessionA, 3), "f:insufficient_credits");
assert.equal(reserve(b, "premium-chat", sessionB, 5), "true:ok");
assert.equal(fixture.psql(`select credits::text from public.profiles where id='${b}'`), "3");
assert.equal(
fixture.psql(`select success::text from public.complete_consultation_free('${b}','premium-chat','${sessionB}','{"role":"assistant","text":"你好","responseKind":"smalltalk"}','{}')`),
"true",
);
assert.equal(fixture.psql(`select credits::text || ':' || (first_consult_free_used_at is null)::text from public.profiles where id='${b}'`), "5:true");
assert.equal(reserve(b, "premium-paid", sessionB, 5), "true:ok");
assert.equal(fixture.psql(`select credits::text from public.profiles where id='${b}'`), "3");
assert.equal(fixture.psql(`select amount::text from public.credit_transactions where user_id='${b}' and request_id='premium-paid' and transaction_type='reserve'`), "-2");
assert.equal(
fixture.psql(`select success::text from public.complete_consultation_response('${b}','premium-paid','${sessionB}','{"role":"assistant","text":"a premium answer"}','{}')`),
"true",
);
assert.equal(fixture.psql(`select (first_consult_free_used_at is null)::text from public.profiles where id='${b}'`), "f");
assert.equal(fixture.psql(`select (metadata->>'billingSource') || ':' || (metadata->>'creditCost') from public.usage_ledger where user_id='${b}' and request_id='premium-paid'`), "first_consult_free:2");
} finally {
fixture.stop();
}
});