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();