Files
gongxue-base/scripts/tenant-student-capacity-contract-test.js
2026-07-12 19:26:57 +08:00

150 lines
6.1 KiB
JavaScript

import assert from 'node:assert/strict';
import fs from 'node:fs';
import path from 'node:path';
import {
CAPACITY_NAMESPACE,
DEFAULT_STUDENT_COUNT,
MAX_STUDENT_COUNT,
buildStudentListQuery,
containsSearchPattern,
parseCapacityOptions,
safeTarget,
} from './tenant-student-capacity.js';
const repoRoot = process.cwd();
const harnessPath = path.join(repoRoot, 'scripts', 'tenant-student-capacity.js');
const apiPath = path.join(repoRoot, 'apps', 'api', 'src', 'features', 'tenant-admin', 'classes.ts');
const migrationPath = path.join(
repoRoot,
'supabase',
'migrations',
'202607120011_tenant_student_search_pagination.sql',
);
const runbookPath = path.join(repoRoot, 'docs', 'refactor', 'tenant-student-capacity-runbook.md');
const harness = fs.readFileSync(harnessPath, 'utf8');
const api = fs.readFileSync(apiPath, 'utf8');
const migration = fs.readFileSync(migrationPath, 'utf8');
const runbook = fs.readFileSync(runbookPath, 'utf8');
const packageJson = JSON.parse(fs.readFileSync(path.join(repoRoot, 'package.json'), 'utf8'));
const defaults = parseCapacityOptions([], {});
assert.equal(defaults.mode, 'plan');
assert.equal(defaults.count, DEFAULT_STUDENT_COUNT);
assert.equal(DEFAULT_STUDENT_COUNT, MAX_STUDENT_COUNT);
assert.equal(defaults.databaseUrl, '');
assert.throws(() => parseCapacityOptions(['--mode=seed'], {}), /DATABASE_URL is required/);
assert.throws(
() => parseCapacityOptions(['--count=100001'], {}),
/count must be between 10 and 100000/,
);
assert.throws(
() => parseCapacityOptions(['--tenant-slug=master'], {}),
/tenant slug must match capacity-test-/,
);
assert.equal(containsSearchPattern('a_b%c\\d'), '%a\\_b\\%c\\\\d%');
assert.throws(
() => safeTarget('postgresql://postgres:secret@127.0.0.1:5432/postgres'),
/local port 5432 is reserved for tikupro-pg/,
);
assert.throws(
() => safeTarget('postgresql://postgres:secret@tikupro-pg:5432/postgres'),
/tikupro-pg targets are forbidden/,
);
assert.deepEqual(safeTarget('postgresql://postgres:secret@127.0.0.1:55432/postgres'), {
host: '127.0.0.1',
port: '55432',
database: 'postgres',
user: 'postgres',
});
assert.match(harness, /assertDestructiveTestDatabase\s*\(/);
assert.match(harness, /pg_try_advisory_lock/);
assert.match(harness, /generate_series\(\$4::integer, \$5::integer\)/);
assert.match(harness, /on conflict \(legacy_id\)/i);
assert.match(harness, /on conflict \(tenant_id, user_id, role\)/i);
assert.match(harness, /on conflict \(tenant_id, user_id\)/i);
assert.match(harness, /raw_profile #>> '\{capacityHarness,namespace\}'/);
assert.match(harness, /metadata #>> '\{capacityHarness,namespace\}'/);
assert.match(harness, /auth_user_id is not null/);
assert.match(harness, /tm\.tenant_id <> \$3/);
assert.match(harness, /dedicated tenant contains unmanaged memberships/);
assert.match(harness, /EXPLAIN \(ANALYZE, BUFFERS, FORMAT JSON\)/i);
assert.match(harness, /MAX_STUDENT_COUNT = 100_000/);
assert.match(harness, /timingsMs/);
const databaseModeStart = harness.indexOf('async function runDatabaseMode(options)');
const databaseModeEnd = harness.indexOf('\nexport async function main', databaseModeStart);
const databaseMode = harness.slice(databaseModeStart, databaseModeEnd);
assert.ok(databaseModeStart >= 0 && databaseModeEnd > databaseModeStart);
assert.ok(
databaseMode.indexOf('assertDestructiveTestDatabase({') < databaseMode.indexOf('seedFixture(client, options)'),
'the destructive database guard must execute before fixture writes',
);
for (const shape of [{}, { cursor: true }, { keyword: true }]) {
const benchmarkSql = buildStudentListQuery(shape).sql;
for (const fragment of [
'with student_page as materialized',
'join public.platform_users u on u.id = tm.user_id',
'left join public.student_profiles sp on sp.tenant_id = tm.tenant_id and sp.user_id = tm.user_id',
'join student_page page on page.tenant_id = tcm.tenant_id and page.user_id = tcm.user_id',
'order by tm.created_at desc, tm.id desc',
]) {
assert.ok(benchmarkSql.includes(fragment), `benchmark SQL must contain ${fragment}`);
assert.ok(api.includes(fragment), `API SQL must contain ${fragment}`);
}
}
const identityExpressionFragments = [
"coalesce(u.username, '') || ' '",
"coalesce(u.name, '') || ' '",
"coalesce(u.phone, '') || ' '",
"coalesce(u.email::text, '')",
];
for (const fragment of identityExpressionFragments) {
assert.ok(buildStudentListQuery({ keyword: true }).sql.includes(fragment));
assert.ok(api.includes(fragment));
assert.ok(migration.includes(fragment.replaceAll('u.', '')));
}
assert.match(migration, /create extension if not exists pg_trgm with schema extensions/i);
assert.match(
migration,
/idx_memberships_student_keyset_page[\s\S]*\(tenant_id, status, created_at desc, id desc\)[\s\S]*where role = 'student'/i,
);
assert.match(
migration,
/idx_platform_users_identity_search_trgm[\s\S]*using gin[\s\S]*gin_trgm_ops/i,
);
assert.equal(CAPACITY_NAMESPACE, 'tiku.student-capacity.v1');
for (const scriptName of [
'perf:tenant-students:plan',
'perf:tenant-students:run',
'perf:tenant-students:evidence',
'perf:tenant-students:benchmark',
'perf:tenant-students:cleanup',
'test:tenant-students:capacity:contract',
'test:tenant-students:capacity:smoke',
]) {
assert.ok(packageJson.scripts?.[scriptName], `missing package script ${scriptName}`);
}
assert.match(packageJson.scripts['test:tenant-students:capacity:smoke'], /--count=250/);
assert.match(
packageJson.scripts['test:tenant-students:capacity:smoke'],
/--tenant-slug=capacity-test-students-smoke/,
);
assert.match(packageJson.scripts['test:tenant-students:capacity:smoke'], /SMOKE_SEED_LOCAL_OR_CI_ONLY/);
assert.ok(packageJson.scripts['test:readiness'].includes('tenant-student-capacity-contract-test.js'));
assert.match(runbook, /capacity-test-/);
assert.match(runbook, /tikupro-pg/i);
assert.match(runbook, /SMOKE_SEED_LOCAL_OR_CI_ONLY/);
assert.match(runbook, /100000/);
assert.match(runbook, /perf:tenant-students:evidence/);
assert.match(runbook, /cleanupVerified=true/);
assert.match(runbook, /cleanup/i);
assert.match(runbook, /not a production SLA/i);
console.log('[PASS] tenant student capacity harness contract');