forked from wangziqi/gongxue-base
32 lines
1.3 KiB
JavaScript
32 lines
1.3 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
|
|
const {
|
|
containsSearchPattern,
|
|
decodeTenantStudentsCursor,
|
|
encodeTenantStudentsCursor,
|
|
} = await import('../apps/api/src/features/tenant-admin/student-cursor.ts');
|
|
|
|
const cursor = {
|
|
createdAt: '2026-07-12T03:04:05.678Z',
|
|
membershipId: '11111111-1111-4111-8111-111111111111',
|
|
};
|
|
const encoded = encodeTenantStudentsCursor(cursor);
|
|
assert.deepEqual(decodeTenantStudentsCursor(encoded), cursor, 'student cursor should round-trip');
|
|
assert.equal(decodeTenantStudentsCursor(''), null, 'empty cursor should start from the first page');
|
|
assert.equal(containsSearchPattern('100%_ready\\now'), '%100\\%\\_ready\\\\now%', 'student search should escape LIKE metacharacters');
|
|
|
|
for (const invalid of [
|
|
'not-a-valid-cursor',
|
|
Buffer.from(JSON.stringify({ version: 2, ...cursor })).toString('base64url'),
|
|
Buffer.from(JSON.stringify({ version: 1, createdAt: 'not-a-date', membershipId: cursor.membershipId })).toString('base64url'),
|
|
Buffer.from(JSON.stringify({ version: 1, createdAt: cursor.createdAt, membershipId: 'not-a-uuid' })).toString('base64url'),
|
|
]) {
|
|
assert.throws(
|
|
() => decodeTenantStudentsCursor(invalid),
|
|
error => error?.code === 'INVALID_STUDENT_CURSOR' && error?.statusCode === 400,
|
|
'malformed student cursors must fail closed',
|
|
);
|
|
}
|
|
|
|
console.log('[PASS] tenant student cursor contract');
|