diff --git a/frontend/src/utils/appStorePreviews.test.ts b/frontend/src/utils/appStorePreviews.test.ts index 03d8721..968af0e 100644 --- a/frontend/src/utils/appStorePreviews.test.ts +++ b/frontend/src/utils/appStorePreviews.test.ts @@ -10,6 +10,10 @@ import { PREVIEWABLE_BUILTIN_APP_IDS, } from '@/utils/appStorePreviews' +function escapeRegExp(value: string): string { + return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') +} + describe('App Store preview catalog', () => { it('contains a real captured screenshot for every built-in store app', () => { const storeAppIds = PHONE_APPS.filter( @@ -56,10 +60,11 @@ describe('App Store preview catalog', () => { ] for (const appId of PREVIEWABLE_BUILTIN_APP_IDS) { + const escapedAppId = escapeRegExp(appId) for (const source of localeSources) { expect(source).toMatch( new RegExp( - `(?:["']${appId}["']\\]?|${appId.replace(/-/g, '\\-')})\\s*[:=]\\s*\\{\\s*first\\s*[:=]`, + `(?:["']${escapedAppId}["']\\]?|${escapedAppId})\\s*[:=]\\s*\\{\\s*first\\s*[:=]`, ), ) } diff --git a/frontend/src/utils/lbPhoneAppBridge.test.ts b/frontend/src/utils/lbPhoneAppBridge.test.ts index c26af99..cab28a5 100644 --- a/frontend/src/utils/lbPhoneAppBridge.test.ts +++ b/frontend/src/utils/lbPhoneAppBridge.test.ts @@ -112,8 +112,16 @@ describe('LB Phone app bridge', () => { expect(document).toContain('https://cfx-nui-snake_app/ui/dist/') expect(document).not.toContain('', + runtimeStart + openingTag.length, + ) + expect(runtimeStart).toBeGreaterThanOrEqual(0) + expect(runtimeEnd).toBeGreaterThan(runtimeStart) + + const runtime = document.slice(runtimeStart + openingTag.length, runtimeEnd) + expect(() => new Function(runtime)).not.toThrow() }) }) diff --git a/frontend/src/utils/notes.test.ts b/frontend/src/utils/notes.test.ts index 3073d85..1de1d31 100644 --- a/frontend/src/utils/notes.test.ts +++ b/frontend/src/utils/notes.test.ts @@ -47,4 +47,12 @@ describe('notes rich text', () => { 'Briefing\nMeet outside.\n• Radio\n• Vest', ) }) + + it('keeps encoded markup as literal preview text', () => { + const body = serializeRichNoteBody( + '

<script>literal</script>

', + ) + + expect(noteBodyToPlainText(body)).toBe('') + }) }) diff --git a/frontend/testserver/index.cjs b/frontend/testserver/index.cjs index 328056d..aea1297 100644 --- a/frontend/testserver/index.cjs +++ b/frontend/testserver/index.cjs @@ -4657,7 +4657,7 @@ app.post('/api/:endpoint', async (request, response, next) => { if (endpoint === 'memos:devCapture') { loggedBody.audioDataUrl = `<${String(request.body.audioDataUrl ?? '').length} characters>` } - console.log(`[NUI] ${endpoint}`, loggedBody) + console.log('[NUI]', endpoint, loggedBody) if (endpoint === 'music:bootstrap') { response.json({ success: true, data: musicBootstrap() }) return diff --git a/frontend/testserver/smoke.cjs b/frontend/testserver/smoke.cjs index ec2c6ee..782f746 100644 --- a/frontend/testserver/smoke.cjs +++ b/frontend/testserver/smoke.cjs @@ -1177,6 +1177,18 @@ async function main() { 'factory reset did not restore a browser-testable setup state', ) + const loggedRequests = [] + const originalConsoleLog = console.log + try { + console.log = (...values) => loggedRequests.push(values) + await post(baseUrl, '%25s', { marker: 'format-string' }) + } finally { + console.log = originalConsoleLog + } + assert.deepEqual(loggedRequests, [ + ['[NUI]', '%s', { marker: 'format-string' }], + ]) + const unknown = await post(baseUrl, 'development:missing-mock', {}) assert.deepEqual(unknown, { error: 'mock_endpoint_missing',