Mercurial
diff mrjunejune/test/theme_and_webp_test.js @ 265:056790c4fb0d
add role-aware Epi assistant prompts
Add verified June knowledge, guest/member/admin Copilot profiles, profile-isolated session recovery, animated Epi greetings, and a single authoritative runtime config workflow for inference.
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Fri, 07 Aug 2026 10:50:30 -0700 |
| parents | 04fee26ecce0 |
| children | 41a49c29a28f |
line wrap: on
line diff
--- a/mrjunejune/test/theme_and_webp_test.js Fri Aug 07 07:34:12 2026 -0700 +++ b/mrjunejune/test/theme_and_webp_test.js Fri Aug 07 10:50:30 2026 -0700 @@ -1942,6 +1942,77 @@ /* Conversation URL routing regression tests (Fixes 1–4) */ /* ------------------------------------------------------------------ */ +async function testRoleGreetings(browser) { + const cases = [ + { + name: 'guest', + session: { + kind: 'guest', + csrfToken: 'guest-greeting-csrf', + quota: null, + }, + expected: 'Hi, my name is Epi. June usually calls me Epi-chan.', + }, + { + name: 'invited', + session: { + kind: 'user', + username: 'friend', + role: 'member', + mustChangePassword: false, + csrfToken: 'friend-greeting-csrf', + quota: null, + }, + expected: 'Since June invited you, I can be a little more casual.', + }, + { + name: 'admin', + session: { + kind: 'user', + username: 'june', + role: 'admin', + mustChangePassword: false, + csrfToken: 'admin-greeting-csrf', + quota: null, + }, + expected: 'Hi June! I’m Epi-chan.', + }, + ]; + + for (const testCase of cases) { + const context = await browser.newContext({ serviceWorkers: 'block' }); + const page = await context.newPage(); + await page.route('**/api/auth/session', route => route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify(testCase.session), + })); + await page.route('**/api/conversations**', route => route.fulfill({ + status: 200, + contentType: 'application/json', + body: JSON.stringify({ conversations: [], cursor: null }), + })); + await page.goto(`${baseUrl}/jrpg`, { waitUntil: 'domcontentloaded' }); + const greeting = page.locator('[data-greeting]'); + await greeting.waitFor({ state: 'visible' }); + if (testCase.name === 'guest') { + await page.locator('[data-greeting][data-streaming="true"]').waitFor({ + state: 'visible', + }); + } + await page.waitForFunction(() => { + const item = document.querySelector('[data-greeting]'); + return item && !item.hasAttribute('data-streaming'); + }); + assert.match( + await greeting.locator('p').textContent(), + new RegExp(testCase.expected.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')), + `${testCase.name} receives its role-specific Epi greeting`, + ); + await context.close(); + } +} + async function testConversationRouting(browser) { const CONV_A = 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa'; const CONV_B = 'bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb'; @@ -2199,7 +2270,10 @@ `Fix 1: URL must not have ?conversation after popstate back: ${finalUrl}`, ); assert.equal( - await page.locator('.jrpg-message[data-streaming="true"]').count(), 0, + await page.locator( + '.jrpg-message[data-streaming="true"]:not([data-greeting])', + ).count(), + 0, 'Fix 1: no streaming message must remain after popstate back', ); @@ -2368,7 +2442,7 @@ MRJUNEJUNE_DB_PATH: path.join(tempDirectory, 'site.db'), MRJUNEJUNE_INFERENCE_SIDECAR_PATH: fakeSidecar, MRJUNEJUNE_COPILOT_CLI_PATH: fakeSidecar, - MRJUNEJUNE_ALLOW_ANONYMOUS_INFERENCE: '1', + MRJUNEJUNE_ALLOW_GUEST_INFERENCE: '1', }, stdio: ['ignore', 'pipe', 'pipe'], }); @@ -2389,7 +2463,7 @@ for (const source of [home, dogGame, manifest]) { assert.doesNotMatch(source, /\.png(?:["')]|$)/i); } - assert.match(serviceWorker, /v34-login-modal/); + assert.match(serviceWorker, /v35-role-greeting/); assert.match( await ( await fetch(`${baseUrl}/public/pwa-register.js`) @@ -2458,6 +2532,7 @@ } if (runsSuite('jrpg')) await testJrpgPage(browser); if (runsSuite('routing')) await testConversationRouting(browser); + if (runsSuite('greeting')) await testRoleGreetings(browser); if (runsSuite('hls')) await testHlsPlayer(browser, siteRoot); } finally { if (browser) await browser.close();