diff mrjunejune/test/theme_and_webp_test.js @ 260:1f9877b637e9

Add Copilot-powered cyberpunk JRPG chat Integrate the production JRPG chat with Seobeo streaming, Deita persistence, and a Bazel-managed Copilot SDK and LiteLLM inference stack. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <mrjunejune@users.noreply.github.com>
date Wed, 05 Aug 2026 09:19:41 -0700
parents 667156fcd3e3
children b401627fc49e
line wrap: on
line diff
--- a/mrjunejune/test/theme_and_webp_test.js	Wed Aug 05 09:19:41 2026 -0700
+++ b/mrjunejune/test/theme_and_webp_test.js	Wed Aug 05 09:19:41 2026 -0700
@@ -1,6 +1,7 @@
 const assert = require('node:assert/strict');
 const fs = require('node:fs');
 const net = require('node:net');
+const os = require('node:os');
 const path = require('node:path');
 const { spawn } = require('node:child_process');
 
@@ -129,14 +130,68 @@
   }, theme);
   const page = await context.newPage();
   const errors = [];
+  await page.route('**/api/conversations**', async route => {
+    const request = route.request();
+    const url = new URL(request.url());
+    if (request.method() === 'POST' &&
+        url.pathname === '/api/conversations') {
+      await route.fulfill({
+        status: 201,
+        contentType: 'application/json',
+        body: JSON.stringify({
+          id: '11111111-1111-4111-8111-111111111111',
+        }),
+      });
+      return;
+    }
+    if (request.method() === 'POST' && url.pathname.endsWith('/turns')) {
+      await route.fulfill({
+        status: 200,
+        contentType: 'text/event-stream',
+        body: [
+          'event: turn.accepted',
+          'data: {"request_id":"request-1"}',
+          '',
+          'event: assistant.delta',
+          'data: {"request_id":"request-1","delta":"Start with "}',
+          '',
+          'event: assistant.delta',
+          'data: {"request_id":"request-1","delta":"the tools."}',
+          '',
+          'event: assistant.completed',
+          'data: {"request_id":"request-1","content":"Start with the tools."}',
+          '',
+          'event: turn.done',
+          'data: {"request_id":"request-1","failed":false,"aborted":false}',
+          '',
+          '',
+        ].join('\n'),
+      });
+      return;
+    }
+    await route.fulfill({
+      status: 404,
+      contentType: 'application/json',
+      body: JSON.stringify({ error: { message: 'Not found' } }),
+    });
+  });
   page.on('pageerror', error => errors.push(`pageerror: ${error.message}`));
   page.on('console', message => {
-    if (message.type() === 'error') errors.push(`console: ${message.text()}`);
+    if (message.type() === 'error' &&
+        !message.text().startsWith('Failed to load resource:')) {
+      errors.push(`console: ${message.text()}`);
+    }
   });
   page.on('requestfailed', request => {
     errors.push(`requestfailed: ${request.url()} ${request.failure()?.errorText || ''}`);
   });
   page.on('response', response => {
+    if (response.status() === 404 &&
+        response.url().endsWith(
+          '/api/conversations/00000000-0000-4000-8000-000000000000'
+        )) {
+      return;
+    }
     if (response.status() >= 400) {
       errors.push(`response: ${response.status()} ${response.url()}`);
     }
@@ -378,16 +433,31 @@
     colorScheme: 'light',
     viewport: { width: 1280, height: 900 },
   });
+  await context.addInitScript(key => {
+    sessionStorage.setItem(
+      key,
+      '00000000-0000-4000-8000-000000000000',
+    );
+  }, 'mjj-jrpg-conversation-id');
   const page = await context.newPage();
   const errors = [];
   page.on('pageerror', error => errors.push(`pageerror: ${error.message}`));
   page.on('console', message => {
-    if (message.type() === 'error') errors.push(`console: ${message.text()}`);
+    if (message.type() === 'error' &&
+        !message.text().startsWith('Failed to load resource:')) {
+      errors.push(`console: ${message.text()}`);
+    }
   });
   page.on('requestfailed', request => {
     errors.push(`requestfailed: ${request.url()} ${request.failure()?.errorText || ''}`);
   });
   page.on('response', response => {
+    if (response.status() === 404 &&
+        response.url().endsWith(
+          '/api/conversations/00000000-0000-4000-8000-000000000000'
+        )) {
+      return;
+    }
     if (response.status() >= 400) {
       errors.push(`response: ${response.status()} ${response.url()}`);
     }
@@ -435,7 +505,7 @@
       document.querySelector('.jrpg-brand h1'),
       document.querySelector('.jrpg-message p'),
       document.querySelector('#jrpg-message'),
-      document.querySelector('.jrpg-composer button'),
+      document.querySelector('.jrpg-composer button[type="submit"]'),
     ].map(element => getComputedStyle(element).fontFamily);
     const nonPixelText = [document.body, ...document.body.querySelectorAll('*')]
       .filter(element => [...element.childNodes].some(node =>
@@ -447,7 +517,7 @@
       .map(element => element.localName);
     const pageStyle = getComputedStyle(document.body);
     const submitStyle = getComputedStyle(
-      document.querySelector('.jrpg-composer button'),
+      document.querySelector('.jrpg-composer button[type="submit"]'),
     );
     const colors = {
       canvas: probeStyle.backgroundColor,
@@ -537,9 +607,9 @@
     ),
     desktop.colors.focus,
   );
-  await page.locator('.jrpg-composer button').focus();
+  await page.locator('.jrpg-composer button[type="submit"]').focus();
   assert.equal(
-    await page.locator('.jrpg-composer button').evaluate(element =>
+    await page.locator('.jrpg-composer button[type="submit"]').evaluate(element =>
       getComputedStyle(element).outlineColor
     ),
     desktop.colors.focus,
@@ -896,6 +966,13 @@
     'mrjunejune/mrjunejune_server_debug',
   );
   const siteRoot = path.join(runfilesWorkspace, 'mrjunejune/src');
+  const fakeSidecar = path.join(
+    runfilesWorkspace,
+    'mrjunejune/test/inference_bridge_fake_sidecar',
+  );
+  const tempDirectory = fs.mkdtempSync(
+    path.join(os.tmpdir(), 'mrjunejune-theme-test-'),
+  );
   const chromiumPath = path.resolve(process.env.CHROMIUM_PATH);
   const serverLogs = [];
   let server;
@@ -937,7 +1014,14 @@
 
     server = spawn(serverBinary, [], {
       cwd: runfilesWorkspace,
-      env: { ...process.env, MRJUNEJUNE_PORT: port },
+      env: {
+        ...process.env,
+        MRJUNEJUNE_PORT: port,
+        MRJUNEJUNE_DB_PATH: path.join(tempDirectory, 'site.db'),
+        MRJUNEJUNE_INFERENCE_SIDECAR_PATH: fakeSidecar,
+        MRJUNEJUNE_COPILOT_CLI_PATH: fakeSidecar,
+        MRJUNEJUNE_ALLOW_ANONYMOUS_INFERENCE: '1',
+      },
       stdio: ['ignore', 'pipe', 'pipe'],
     });
     server.stdout.on('data', chunk => serverLogs.push(chunk.toString()));
@@ -957,7 +1041,7 @@
     for (const source of [home, dogGame, manifest]) {
       assert.doesNotMatch(source, /\.png(?:["')]|$)/i);
     }
-    assert.match(serviceWorker, /v9-dev-page-split/);
+    assert.match(serviceWorker, /v10-inference-chat/);
     assert.match(
       await (
         await fetch(`${baseUrl}/public/pwa-register.js`)
@@ -1027,6 +1111,7 @@
   } finally {
     if (browser) await browser.close();
     await stopProcess(server);
+    fs.rmSync(tempDirectory, { recursive: true, force: true });
   }
 })().catch(error => {
   console.error(error.stack || error);