Files
memind/page-data-captcha.test.mjs
john 6b0c633a75 feat(page-data): complete Phase 4-5, ops UI, and publish integration
Add visitor roles, row-level scope, owner ops APIs, MySQL policy index,
Turnstile captcha, browser client SDK, publish-panel dataset binding,
acceptance tests, and usage documentation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-08 14:52:49 +08:00

75 lines
2.3 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import {
extractPageDataCaptchaToken,
stripPageDataMetaFields,
verifyPageDataCaptcha,
} from './page-data-captcha.mjs';
import {
buildPageDataPolicyFromPublishInput,
mapPublicationAccessModeToPageData,
} from './page-access-policy.mjs';
test('stripPageDataMetaFields removes captcha and meta keys', () => {
assert.deepEqual(
stripPageDataMetaFields({ name: '张三', turnstile_token: 'abc', updated_by_label: 'x' }),
{ name: '张三' },
);
});
test('verifyPageDataCaptcha skips when secret is not configured', async () => {
const prev = process.env.PAGE_DATA_TURNSTILE_SECRET;
delete process.env.PAGE_DATA_TURNSTILE_SECRET;
try {
const result = await verifyPageDataCaptcha(null, '127.0.0.1');
assert.equal(result.skipped, true);
} finally {
if (prev) process.env.PAGE_DATA_TURNSTILE_SECRET = prev;
}
});
test('verifyPageDataCaptcha rejects missing token when enabled', async () => {
const prev = process.env.PAGE_DATA_TURNSTILE_SECRET;
process.env.PAGE_DATA_TURNSTILE_SECRET = 'test-secret';
try {
await assert.rejects(
() => verifyPageDataCaptcha('', '127.0.0.1'),
(error) => error.code === 'captcha_required',
);
} finally {
if (prev) process.env.PAGE_DATA_TURNSTILE_SECRET = prev;
else delete process.env.PAGE_DATA_TURNSTILE_SECRET;
}
});
test('extractPageDataCaptchaToken reads header and body fields', () => {
assert.equal(
extractPageDataCaptchaToken({ headers: { 'x-page-data-captcha': 'hdr' } }, {}),
'hdr',
);
assert.equal(extractPageDataCaptchaToken({}, { turnstile_token: 'body' }), 'body');
});
test('buildPageDataPolicyFromPublishInput applies defaults by access mode', () => {
const policy = buildPageDataPolicyFromPublishInput({
pageId: 'page-1',
ownerUserId: 'user-1',
accessMode: 'public',
datasetName: 'signups',
registryDataset: {
name: 'signups',
table: 'signups',
columns: {
read: ['id', 'name'],
insert: ['name', 'phone'],
update: ['status'],
soft_delete: ['id'],
},
},
});
assert.equal(policy.accessMode, 'public');
assert.equal(policy.datasets.signups.insert, true);
assert.equal(policy.datasets.signups.read, false);
assert.equal(mapPublicationAccessModeToPageData('private_link'), null);
});