forked from wangziqi/gongxue-base
150 lines
6.1 KiB
JavaScript
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');
|