diff mrjunejune/test/theme_and_webp_test.js @ 261:b401627fc49e

Add JRPG mock flows and interactive previews Add scripted mock SSE commands, custom event forwarding, animated chat turns, full-height message navigation, and a cyberpunk resume dossier. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <mrjunejune@users.noreply.github.com>
date Wed, 05 Aug 2026 20:38:32 -0700
parents 1f9877b637e9
children 0f45474c1b1a
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 20:38:32 2026 -0700
@@ -476,8 +476,21 @@
     const utility = document.querySelector('.jrpg-utility').getBoundingClientRect();
     const composer = document.querySelector('mjj-jrpg-composer')
       .getBoundingClientRect();
+    const composerField = document.querySelector('.jrpg-composer zen-field')
+      .getBoundingClientRect();
+    const composerFieldStyle = getComputedStyle(
+      document.querySelector('.jrpg-composer zen-field'),
+    );
+    const composerLabel = document.querySelector('.jrpg-composer label')
+      .getBoundingClientRect();
+    const composerTextarea = document.querySelector('#jrpg-message')
+      .getBoundingClientRect();
     const menu = document.querySelector('mjj-jrpg-menu').getBoundingClientRect();
     const character = document.querySelector('[data-character]');
+    const messageScroller = document.querySelector('zen-message-scroller')
+      .getBoundingClientRect();
+    const messageViewport = document.querySelector('.jrpg-message-viewport')
+      .getBoundingClientRect();
     const shell = document.querySelector('.jrpg-shell').getBoundingClientRect();
     const main = document.querySelector('.jrpg-main').getBoundingClientRect();
     const colorProbe = document.createElement('span');
@@ -558,6 +571,27 @@
       characterLoaded: character.complete && character.naturalWidth > 0,
       colors,
       composerBelowScene: composer.top >= scene.bottom,
+      composerTextareaFills: (
+        Math.abs(composerTextarea.left - composerField.left) < 1 &&
+        Math.abs(composerTextarea.right - composerField.right) < 1 &&
+        Math.abs(composerTextarea.bottom - composerField.bottom) < 1 &&
+        composerTextarea.height > 60
+      ),
+      composerTextareaGeometry: {
+        fieldBottom: composerField.bottom,
+        fieldDisplay: composerFieldStyle.display,
+        fieldGridRows: composerFieldStyle.gridTemplateRows,
+        fieldLeft: composerField.left,
+        fieldRight: composerField.right,
+        fieldTop: composerField.top,
+        labelBottom: composerLabel.bottom,
+        labelTop: composerLabel.top,
+        textareaBottom: composerTextarea.bottom,
+        textareaHeight: composerTextarea.height,
+        textareaLeft: composerTextarea.left,
+        textareaRight: composerTextarea.right,
+        textareaTop: composerTextarea.top,
+      },
       fillsViewport: shell.left === 0 &&
         shell.top === 0 &&
         Math.abs(shell.right - innerWidth) < 1 &&
@@ -572,8 +606,14 @@
         font.status === 'loaded'
       ),
       menuRightOfComposer: menu.left >= composer.right,
+      messageViewportFills: (
+        Math.abs(messageViewport.top - messageScroller.top) < 1 &&
+        Math.abs(messageViewport.bottom - messageScroller.bottom) < 1 &&
+        messageViewport.height > 192
+      ),
       noOverflow: document.documentElement.scrollWidth <= innerWidth,
       nonPixelText,
+      questLabelAbsent: !document.body.textContent.includes('QUEST 01'),
       theme: document.documentElement.dataset.zenTheme,
       utilityRightOfScene: utility.left >= scene.right,
     };
@@ -592,12 +632,19 @@
   assert.equal(desktop.colors.submit, desktop.colors.primary);
   assert.equal(desktop.colors.utility, desktop.colors.surface);
   assert.equal(desktop.composerBelowScene, true);
+  assert.equal(
+    desktop.composerTextareaFills,
+    true,
+    JSON.stringify(desktop.composerTextareaGeometry),
+  );
   assert.equal(desktop.fillsViewport, true);
   assert.ok(desktop.fonts.every(font => font === '"Pixel Mplus"'));
   assert.equal(desktop.fontLoaded, true);
   assert.equal(desktop.menuRightOfComposer, true);
+  assert.equal(desktop.messageViewportFills, true);
   assert.equal(desktop.noOverflow, true);
   assert.deepEqual(desktop.nonPixelText, []);
+  assert.equal(desktop.questLabelAbsent, true);
   assert.equal(desktop.theme, 'cyberpunk');
   assert.equal(desktop.utilityRightOfScene, true);
   await page.locator('.jrpg-brand a').focus();
@@ -618,6 +665,27 @@
     await page.locator('meta[name="theme-color"]').first().getAttribute('content'),
     desktop.colors.canvas,
   );
+  assert.equal(await page.locator('[data-work-showcase] a').count(), 6);
+  assert.match(
+    await page.locator('[data-work-showcase]').textContent(),
+    /Copilot Tasks/,
+  );
+  assert.match(
+    await page.locator('[data-work-showcase]').textContent(),
+    /Copilot SuperApp/,
+  );
+  assert.equal(
+    await page.locator('[data-turn-position]').textContent(),
+    'START',
+  );
+  assert.equal(
+    await page.getByRole('button', { name: 'Previous turn' }).isDisabled(),
+    true,
+  );
+  assert.equal(
+    await page.getByRole('button', { name: 'Next turn' }).isDisabled(),
+    true,
+  );
 
   await page.getByRole('button', { name: 'Tools', exact: true }).click();
   assert.equal(
@@ -633,6 +701,7 @@
       .getAttribute('aria-pressed'),
     'true',
   );
+  assert.equal(await page.locator('[data-work-showcase] a').count(), 3);
 
   await page.getByRole('button', { name: /Inspect/ }).click();
   await page.locator('.jrpg-preview-dialog dialog[open]').waitFor();
@@ -643,10 +712,49 @@
   await page.getByRole('button', {
     name: 'Close destination details',
   }).click();
+  await page.locator('.jrpg-preview-dialog dialog').waitFor({ state: 'hidden' });
 
+  await page.getByRole('button', { name: 'Resume', exact: true }).click();
+  await page.getByRole('button', { name: /Inspect/ }).click();
+  await page.locator('[data-resume-content] .sub-header').first().waitFor();
+  const resumeDossier = await page.locator('[data-resume-dossier]').evaluate(
+    dossier => ({
+      fontFamily: getComputedStyle(dossier).fontFamily,
+      text: dossier.textContent,
+    }),
+  );
+  assert.equal(resumeDossier.fontFamily, '"Pixel Mplus"');
+  assert.match(resumeDossier.text, /Copilot Tasks/);
+  assert.match(resumeDossier.text, /Microsoft/);
+  assert.match(resumeDossier.text, /Meta/);
+  assert.equal(
+    await page.locator('[data-resume-content] a[target="_blank"]').count() > 0,
+    true,
+  );
+  await page.getByRole('button', {
+    name: 'Close destination details',
+  }).click();
+
+  await page.evaluate(() => {
+    window.__jrpgStreamEvents = [];
+    document.querySelector('mjj-jrpg-shell').addEventListener(
+      'mjj-jrpg-stream-event',
+      event => window.__jrpgStreamEvents.push(event.detail),
+    );
+  });
   await page.locator('#jrpg-message').fill('Where should I begin?');
   await page.locator('#jrpg-message').press('Enter');
   await page.locator('.jrpg-message[data-speaker="June"]').last().waitFor();
+  const streamingMessage = page.locator(
+    '.jrpg-message[data-speaker="Epi"][data-streaming="true"]',
+  ).last();
+  await streamingMessage.waitFor();
+  await page.locator('[data-cancel-control]').waitFor({ state: 'hidden' });
+  await streamingMessage.waitFor();
+  assert.notEqual(
+    await streamingMessage.locator('p').textContent(),
+    'hello traveler',
+  );
   await page.getByRole('button', { name: 'Blogs', exact: true }).click();
   assert.equal(
     await page.locator('.jrpg-message[data-speaker="June"] p').last()
@@ -658,6 +766,66 @@
       'default' &&
     document.querySelectorAll('.jrpg-message[data-speaker="Epi"]').length > 1
   );
+  assert.equal(
+    await page.locator('.jrpg-message[data-speaker="Epi"] p').last()
+      .textContent(),
+    'hello traveler',
+  );
+  assert.equal(
+    await page.locator(
+      '.jrpg-message[data-speaker="Epi"][data-streaming="true"]',
+    ).count(),
+    0,
+  );
+  assert.deepEqual(
+    await page.evaluate(() => {
+      const event = window.__jrpgStreamEvents.find(
+        item => item.type === 'tool.started',
+      );
+      return {
+        name: event?.data.tool?.name,
+        type: event?.type,
+      };
+    }),
+    {
+      name: 'mock-search',
+      type: 'tool.started',
+    },
+  );
+  assert.equal(
+    await page.locator('[data-turn-position]').textContent(),
+    'TURN 1 / 1',
+  );
+  assert.equal(
+    await page.getByRole('button', { name: 'Previous turn' }).isEnabled(),
+    true,
+  );
+  assert.equal(
+    await page.getByRole('button', { name: 'Next turn' }).isDisabled(),
+    true,
+  );
+  await page.getByRole('button', { name: 'Previous turn' }).click();
+  assert.equal(
+    await page.locator('[data-turn-position]').textContent(),
+    'START',
+  );
+  assert.equal(
+    await page.locator('.jrpg-message[data-speaker="June"]:visible').count(),
+    0,
+  );
+  assert.equal(
+    await page.locator('.jrpg-message[data-speaker="System"]:visible').count(),
+    1,
+  );
+  await page.getByRole('button', { name: 'Next turn' }).click();
+  assert.equal(
+    await page.locator('[data-turn-position]').textContent(),
+    'TURN 1 / 1',
+  );
+  assert.equal(
+    await page.locator('.jrpg-message[data-speaker="June"]:visible').count(),
+    1,
+  );
   assert.equal(await page.locator('#jrpg-message').isEnabled(), true);
 
   await page.waitForFunction(() => navigator.serviceWorker?.controller);
@@ -1041,7 +1209,7 @@
     for (const source of [home, dogGame, manifest]) {
       assert.doesNotMatch(source, /\.png(?:["')]|$)/i);
     }
-    assert.match(serviceWorker, /v10-inference-chat/);
+    assert.match(serviceWorker, /v13-turn-resume/);
     assert.match(
       await (
         await fetch(`${baseUrl}/public/pwa-register.js`)