annotate mrjunejune/test/theme_and_webp_test.js @ 267:a78f5986011f

discover bundled production runtimes Locate Bazel-packaged Copilot and Python binaries by stable suffix instead of hardcoding an external repository prefix. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Fri, 07 Aug 2026 12:58:55 -0700
parents 056790c4fb0d
children 41a49c29a28f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1 const assert = require('node:assert/strict');
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2 const fs = require('node:fs');
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
3 const net = require('node:net');
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
4 const os = require('node:os');
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
5 const path = require('node:path');
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
6 const { spawn } = require('node:child_process');
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
7
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
8 const RUNFILES = process.env.JS_BINARY__RUNFILES;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
9 const WORKSPACE = process.env.JS_BINARY__WORKSPACE;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
10 let port;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
11 let baseUrl;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
12 const playwrightPath = path.join(
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
13 RUNFILES,
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
14 WORKSPACE,
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
15 'hg-web/e2e/node_modules/playwright-core',
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
16 );
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
17 const { chromium } = require(playwrightPath);
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
18 const browserSuite = process.env.MJJ_BROWSER_SUITE || 'all';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
19 const runsSuite = name => browserSuite === 'all' || browserSuite === name;
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
20
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
21 function stopProcess(child) {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
22 if (!child || child.exitCode !== null) return Promise.resolve();
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
23 child.kill('SIGTERM');
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
24 return new Promise(resolve => {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
25 const timer = setTimeout(() => {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
26 if (child.exitCode === null) child.kill('SIGKILL');
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
27 }, 3000);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
28 child.once('exit', () => {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
29 clearTimeout(timer);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
30 resolve();
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
31 });
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
32 });
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
33 }
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
34
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
35 async function waitForServer(child, logs) {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
36 const deadline = Date.now() + 15000;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
37 while (Date.now() < deadline) {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
38 if (child.exitCode !== null) {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
39 throw new Error(`Server exited with ${child.exitCode}\n${logs.join('')}`);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
40 }
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
41 try {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
42 const response = await fetch(baseUrl);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
43 if (response.ok) return;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
44 } catch {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
45 // Keep waiting for startup.
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
46 }
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
47 await new Promise(resolve => setTimeout(resolve, 100));
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
48 }
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
49 throw new Error(`Server startup timed out\n${logs.join('')}`);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
50 }
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
51
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
52 function listFiles(root) {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
53 const files = [];
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
54 for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
55 const absolute = path.join(root, entry.name);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
56 if (entry.isDirectory()) files.push(...listFiles(absolute));
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
57 else files.push(absolute);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
58 }
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
59 return files;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
60 }
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
61
258
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
62 function primitiveOwnershipViolations(source) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
63 const violations = [];
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
64 const stack = [];
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
65 const voidElements = new Set([
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
66 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
67 'meta', 'param', 'source', 'track', 'wbr',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
68 ]);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
69 const ownerMap = {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
70 button: new Set(['zen-button']),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
71 select: new Set(['zen-field', 'zen-native-select', 'zen-select']),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
72 textarea: new Set(['zen-field', 'zen-textarea']),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
73 };
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
74
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
75 for (const token of source.matchAll(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
76 /<!--[\s\S]*?-->|<\/?([a-zA-Z][\w-]*)\b([^>]*)>/g,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
77 )) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
78 if (!token[1]) continue;
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
79 const name = token[1].toLowerCase();
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
80 if (token[0].startsWith('</')) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
81 while (stack.length) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
82 if (stack.pop() === name) break;
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
83 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
84 continue;
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
85 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
86
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
87 let owners = ownerMap[name];
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
88 if (name === 'input') {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
89 const type = /\btype\s*=\s*["']?([^"'\s>]+)/i.exec(token[2])?.[1]
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
90 ?.toLowerCase() || 'text';
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
91 if (type === 'checkbox') {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
92 owners = new Set(['zen-checkbox', 'zen-field', 'zen-switch']);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
93 } else if (type === 'radio') {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
94 owners = new Set(['zen-field', 'zen-radio-group']);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
95 } else if (type === 'range') {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
96 owners = new Set(['zen-field', 'zen-slider']);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
97 } else if (type === 'date') {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
98 owners = new Set(['zen-calendar', 'zen-date-picker', 'zen-field']);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
99 } else {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
100 owners = new Set([
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
101 'zen-combobox',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
102 'zen-command',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
103 'zen-field',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
104 'zen-input',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
105 'zen-input-group',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
106 'zen-input-otp',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
107 ]);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
108 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
109 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
110 if (owners) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
111 const matchingOwners = stack.filter(ancestor => owners.has(ancestor));
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
112 if (matchingOwners.length !== 1) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
113 violations.push({
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
114 control: name,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
115 owners: matchingOwners,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
116 source: token[0],
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
117 });
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
118 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
119 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
120
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
121 if (!voidElements.has(name) && !token[0].endsWith('/>')) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
122 stack.push(name);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
123 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
124 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
125 return violations;
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
126 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
127
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
128 async function sampleTheme(browser, theme) {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
129 const context = await browser.newContext({ colorScheme: 'dark' });
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
130 await context.addInitScript(value => {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
131 localStorage.setItem('theme-preference', value);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
132 }, theme);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
133 const page = await context.newPage();
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
134 const errors = [];
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
135 await page.route('**/api/conversations**', async route => {
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
136 const request = route.request();
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
137 const url = new URL(request.url());
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
138 if (request.method() === 'POST' &&
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
139 url.pathname === '/api/conversations') {
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
140 await route.fulfill({
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
141 status: 201,
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
142 contentType: 'application/json',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
143 body: JSON.stringify({
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
144 id: '11111111-1111-4111-8111-111111111111',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
145 }),
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
146 });
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
147 return;
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
148 }
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
149 if (request.method() === 'POST' && url.pathname.endsWith('/turns')) {
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
150 await route.fulfill({
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
151 status: 200,
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
152 contentType: 'text/event-stream',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
153 body: [
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
154 'event: turn.accepted',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
155 'data: {"request_id":"request-1"}',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
156 '',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
157 'event: assistant.delta',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
158 'data: {"request_id":"request-1","delta":"Start with "}',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
159 '',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
160 'event: assistant.delta',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
161 'data: {"request_id":"request-1","delta":"the tools."}',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
162 '',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
163 'event: assistant.completed',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
164 'data: {"request_id":"request-1","content":"Start with the tools."}',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
165 '',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
166 'event: turn.done',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
167 'data: {"request_id":"request-1","failed":false,"aborted":false}',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
168 '',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
169 '',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
170 ].join('\n'),
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
171 });
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
172 return;
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
173 }
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
174 await route.fulfill({
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
175 status: 404,
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
176 contentType: 'application/json',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
177 body: JSON.stringify({ error: { message: 'Not found' } }),
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
178 });
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
179 });
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
180 page.on('pageerror', error => errors.push(`pageerror: ${error.message}`));
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
181 page.on('console', message => {
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
182 if (message.type() === 'error' &&
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
183 !message.text().startsWith('Failed to load resource:')) {
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
184 errors.push(`console: ${message.text()}`);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
185 }
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
186 });
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
187 page.on('requestfailed', request => {
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
188 if (request.url().startsWith('blob:') &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
189 request.failure()?.errorText === 'net::ERR_ABORTED') {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
190 return;
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
191 }
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
192 if (request.method() === 'DELETE' &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
193 request.url().includes('/api/download/') &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
194 request.failure()?.errorText === 'net::ERR_ABORTED') {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
195 return;
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
196 }
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
197 if (request.method() === 'POST' &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
198 request.url().endsWith('/api/latex/render') &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
199 request.failure()?.errorText === 'net::ERR_ABORTED') {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
200 return;
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
201 }
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
202 errors.push(`requestfailed: ${request.url()} ${request.failure()?.errorText || ''}`);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
203 });
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
204 page.on('response', response => {
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
205 if (response.status() === 404 &&
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
206 response.url().endsWith(
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
207 '/api/conversations/00000000-0000-4000-8000-000000000000'
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
208 )) {
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
209 return;
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
210 }
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
211 if (response.status() >= 400) {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
212 errors.push(`response: ${response.status()} ${response.url()}`);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
213 }
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
214 });
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
215
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
216 await page.goto(baseUrl, { waitUntil: 'networkidle' });
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
217 await page.waitForFunction(() => {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
218 const canvas = document.querySelector('#background');
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
219 if (!canvas) return false;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
220 const data = canvas.getContext('2d').getImageData(
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
221 0,
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
222 0,
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
223 canvas.width,
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
224 canvas.height,
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
225 ).data;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
226 for (let index = 3; index < data.length; index += 4) {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
227 if (data[index] >= 20) return true;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
228 }
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
229 return false;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
230 });
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
231
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
232 const sample = await page.evaluate(() => {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
233 const canvas = document.querySelector('#background');
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
234 const data = canvas.getContext('2d').getImageData(
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
235 0,
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
236 0,
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
237 canvas.width,
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
238 canvas.height,
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
239 ).data;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
240 let count = 0;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
241 let luminance = 0;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
242 for (let index = 0; index < data.length; index += 4) {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
243 if (data[index + 3] < 20) continue;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
244 count++;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
245 luminance +=
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
246 data[index] * 0.2126 +
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
247 data[index + 1] * 0.7152 +
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
248 data[index + 2] * 0.0722;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
249 }
256
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
250 const channels = value => value.match(/\d+(?:\.\d+)?/g)
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
251 .slice(0, 3)
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
252 .map(Number);
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
253 const colorLuminance = value => {
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
254 const converted = channels(value).map(channel => {
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
255 const normalized = channel / 255;
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
256 return normalized <= 0.04045
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
257 ? normalized / 12.92
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
258 : ((normalized + 0.055) / 1.055) ** 2.4;
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
259 });
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
260 return converted[0] * 0.2126 +
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
261 converted[1] * 0.7152 +
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
262 converted[2] * 0.0722;
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
263 };
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
264 const bodyStyle = getComputedStyle(document.body);
258
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
265 const themeButtonStyle = getComputedStyle(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
266 document.querySelector('#themeToggle'),
256
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
267 );
258
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
268 const foreground = colorLuminance(bodyStyle.color);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
269 const contrastProbe = document.createElement('span');
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
270 contrastProbe.style.background = 'var(--zen-color-surface)';
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
271 document.body.append(contrastProbe);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
272 const background = colorLuminance(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
273 getComputedStyle(contrastProbe).backgroundColor,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
274 );
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
275 contrastProbe.remove();
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
276 return {
258
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
277 backgroundRepeat: bodyStyle.backgroundRepeat,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
278 backgroundSize: bodyStyle.backgroundSize,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
279 bodyCoversViewport: document.body.getBoundingClientRect().height >=
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
280 innerHeight,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
281 componentReady: Boolean(customElements.get('zen-button')),
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
282 count,
256
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
283 fontFamily: getComputedStyle(document.body).fontFamily,
258
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
284 headerPaws: document.querySelectorAll(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
285 'header [data-zen-link-decoration]',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
286 ).length,
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
287 luminance: count ? luminance / count : 0,
256
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
288 textContrast: (Math.max(foreground, background) + 0.05) /
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
289 (Math.min(foreground, background) + 0.05),
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
290 rootTheme: document.documentElement.dataset.zenTheme || 'auto',
258
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
291 enhancedLinks: document.querySelectorAll(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
292 'zen-link[effect="paw"] > a > zen-icon[name="paw"]',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
293 ).length,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
294 links: document.querySelectorAll('a').length,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
295 pawLinks: [...document.querySelectorAll('a')].filter(link =>
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
296 !link.closest('zen-button') &&
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
297 link.dataset.zenLinkEffect !== 'none'
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
298 ).length,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
299 mainBackground: getComputedStyle(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
300 document.querySelector('main'),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
301 ).backgroundColor,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
302 themeButtonBackground: themeButtonStyle.backgroundColor,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
303 themeButtonBorder: themeButtonStyle.borderTopWidth,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
304 themeButtonShadow: themeButtonStyle.boxShadow,
256
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
305 themeLabel: document.querySelector('#themeName')?.textContent,
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
306 };
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
307 });
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
308
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
309 if (errors.length) throw new Error(`${theme}\n${errors.join('\n')}`);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
310 await context.close();
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
311 return sample;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
312 }
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
313
256
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
314 async function testThemeCycle(browser) {
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
315 const context = await browser.newContext({ colorScheme: 'light' });
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
316 const page = await context.newPage();
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
317 await page.goto(baseUrl, { waitUntil: 'networkidle' });
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
318 const expected = ['paper', 'ink', 'playful', 'auto'];
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
319 for (const theme of expected) {
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
320 await page.locator('#themeToggle').click();
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
321 assert.equal(
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
322 await page.evaluate(() =>
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
323 document.documentElement.dataset.zenTheme || 'auto'
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
324 ),
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
325 theme,
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
326 );
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
327 assert.equal(
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
328 await page.evaluate(() => localStorage.getItem('theme-preference')),
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
329 theme,
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
330 );
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
331 }
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
332 await context.close();
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
333 }
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
334
258
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
335 async function testPlainField(browser) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
336 const page = await browser.newPage();
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
337 await page.goto(`${baseUrl}/tools/markdown_to_html`, {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
338 waitUntil: 'networkidle',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
339 });
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
340 await page.waitForFunction(() => customElements.get('zen-field'));
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
341 const state = await page.locator('zen-field[appearance="plain"]').evaluate(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
342 field => {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
343 const label = field.querySelector('label');
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
344 const textarea = field.querySelector('textarea');
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
345 const probe = document.createElement('span');
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
346 probe.style.border = '1px solid var(--accent)';
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
347 document.body.append(probe);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
348 const accent = getComputedStyle(probe).borderColor;
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
349 probe.remove();
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
350 textarea.focus();
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
351 return {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
352 borderColor: getComputedStyle(textarea).borderColor,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
353 display: getComputedStyle(field).display,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
354 labelFor: label.htmlFor,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
355 accent,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
356 textareaId: textarea.id,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
357 };
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
358 },
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
359 );
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
360 assert.deepEqual(state, {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
361 accent: state.borderColor,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
362 borderColor: state.borderColor,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
363 display: 'contents',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
364 labelFor: 'input',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
365 textareaId: 'input',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
366 });
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
367 await page.close();
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
368 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
369
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
370 async function testButtonScale(browser) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
371 const page = await browser.newPage();
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
372 for (const route of [
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
373 '/talk',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
374 '/notes/login',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
375 '/tools/hls_player',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
376 '/tools/latex_editor',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
377 '/tools/markdown_to_html',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
378 '/tools/file_converter',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
379 '/offline.html',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
380 ]) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
381 await page.goto(`${baseUrl}${route}`, { waitUntil: 'networkidle' });
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
382 await page.waitForFunction(() => customElements.get('zen-button'));
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
383 const controls = await page.locator(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
384 'zen-button[size] > :is(button, a):not(#themeToggle)',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
385 ).evaluateAll(elements => elements.map(control => {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
386 const host = control.parentElement;
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
387 const style = getComputedStyle(control);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
388 const hostStyle = getComputedStyle(host);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
389 return {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
390 height: control.getBoundingClientRect().height,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
391 minimum: Number.parseFloat(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
392 hostStyle.getPropertyValue('--zenbu-control-height'),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
393 ) * Number.parseFloat(getComputedStyle(document.documentElement).fontSize),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
394 paddingBlock: style.paddingBlockStart,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
395 paddingVariable: Number.parseFloat(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
396 hostStyle.getPropertyValue('--zenbu-control-padding-block'),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
397 ) * Number.parseFloat(getComputedStyle(document.documentElement).fontSize),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
398 size: host.getAttribute('size'),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
399 };
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
400 }));
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
401 assert.ok(controls.length > 0, route);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
402 for (const control of controls) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
403 assert.match(control.size, /^(?:xs|sm|md|lg|xl)$/);
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
404 assert.ok(control.height >= control.minimum - 1, JSON.stringify(control));
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
405 assert.ok(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
406 Math.abs(Number.parseFloat(control.paddingBlock) -
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
407 control.paddingVariable) < 1,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
408 JSON.stringify(control),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
409 );
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
410 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
411 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
412 await page.close();
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
413 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
414
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
415 async function testDynamicButtonOwnership(browser) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
416 const page = await browser.newPage();
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
417 await page.goto(baseUrl, { waitUntil: 'networkidle' });
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
418 await page.evaluate(() => {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
419 window.dispatchEvent(new Event('beforeinstallprompt', {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
420 cancelable: true,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
421 }));
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
422 });
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
423 const state = await page.locator('#pwa-install-btn').evaluate(button => ({
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
424 ownerCount: button.closest('zen-button') ? 1 : 0,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
425 appearance: button.closest('zen-button')?.getAttribute('appearance'),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
426 size: button.closest('zen-button')?.getAttribute('size'),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
427 }));
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
428 assert.deepEqual(state, {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
429 appearance: 'plain',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
430 ownerCount: 1,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
431 size: 'md',
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
432 });
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
433 await page.close();
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
434 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
435
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
436 async function testResumePrint(browser) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
437 const page = await browser.newPage();
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
438 await page.emulateMedia({ media: 'print' });
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
439 await page.goto(`${baseUrl}/resume`, { waitUntil: 'networkidle' });
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
440 assert.equal(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
441 await page.locator('.info > a[href="/public/resume.pdf"]').isVisible(),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
442 false,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
443 );
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
444 await page.close();
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
445 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
446
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
447 async function testJrpgPage(browser) {
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
448 const context = await browser.newContext({
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
449 colorScheme: 'light',
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
450 viewport: { width: 1280, height: 900 },
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
451 });
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
452 await context.addInitScript(key => {
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
453 sessionStorage.setItem(
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
454 key,
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
455 '00000000-0000-4000-8000-000000000000',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
456 );
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
457 }, 'mjj-jrpg-conversation-id');
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
458 const page = await context.newPage();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
459 const errors = [];
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
460 page.on('pageerror', error => errors.push(`pageerror: ${error.message}`));
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
461 page.on('console', message => {
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
462 if (message.type() === 'error' &&
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
463 !message.text().startsWith('Failed to load resource:')) {
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
464 errors.push(`console: ${message.text()}`);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
465 }
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
466 });
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
467 page.on('requestfailed', request => {
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
468 if (request.url().startsWith('blob:') &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
469 request.failure()?.errorText === 'net::ERR_ABORTED') {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
470 return;
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
471 }
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
472 if (request.method() === 'DELETE' &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
473 request.url().includes('/api/download/') &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
474 request.failure()?.errorText === 'net::ERR_ABORTED') {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
475 return;
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
476 }
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
477 if (request.method() === 'POST' &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
478 request.url().endsWith('/api/latex/render') &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
479 request.failure()?.errorText === 'net::ERR_ABORTED') {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
480 return;
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
481 }
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
482 if (request.url().includes('/api/auth/login') &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
483 request.failure()?.errorText === 'net::ERR_ABORTED') {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
484 return;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
485 }
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
486 errors.push(`requestfailed: ${request.url()} ${request.failure()?.errorText || ''}`);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
487 });
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
488 page.on('response', response => {
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
489 if (response.status() === 404 &&
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
490 response.url().endsWith(
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
491 '/api/conversations/00000000-0000-4000-8000-000000000000'
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
492 )) {
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
493 return;
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
494 }
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
495 if (response.url().includes('/api/auth/login') && response.status() >= 400) {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
496 return; /* expected: login attempt with invalid credentials in modal test */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
497 }
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
498 if (response.status() >= 400) {
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
499 errors.push(`response: ${response.status()} ${response.url()}`);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
500 }
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
501 });
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
502
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
503 await page.goto(`${baseUrl}/jrpg`, { waitUntil: 'networkidle' });
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
504 await page.waitForFunction(() =>
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
505 customElements.get('mjj-jrpg-composer') &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
506 customElements.get('mjj-jrpg-menu') &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
507 customElements.get('mjj-jrpg-chat') &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
508 customElements.get('mjj-jrpg-preview')
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
509 );
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
510 await page.evaluate(() => document.fonts.ready);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
511 const desktop = await page.evaluate(() => {
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
512 const scene = document.querySelector('.jrpg-scene').getBoundingClientRect();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
513 const utility = document.querySelector('.jrpg-utility').getBoundingClientRect();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
514 const composer = document.querySelector('mjj-jrpg-composer')
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
515 .getBoundingClientRect();
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
516 const composerField = document.querySelector('.jrpg-composer zen-field')
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
517 .getBoundingClientRect();
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
518 const composerFieldStyle = getComputedStyle(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
519 document.querySelector('.jrpg-composer zen-field'),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
520 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
521 const composerLabel = document.querySelector('.jrpg-composer label')
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
522 .getBoundingClientRect();
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
523 const composerTextarea = document.querySelector('#jrpg-message')
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
524 .getBoundingClientRect();
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
525 const menu = document.querySelector('mjj-jrpg-menu').getBoundingClientRect();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
526 const character = document.querySelector('[data-character]');
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
527 const characterBox = character.getBoundingClientRect();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
528 const sceneBarStyle = getComputedStyle(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
529 document.querySelector('.jrpg-scene'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
530 '::before',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
531 );
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
532 const messageScroller = document.querySelector('zen-message-scroller')
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
533 .getBoundingClientRect();
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
534 const messageViewport = document.querySelector('.jrpg-message-viewport')
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
535 .getBoundingClientRect();
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
536 const workspace = document.querySelector('.jrpg-workspace')
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
537 .getBoundingClientRect();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
538 const brand = document.querySelector('.jrpg-brand').getBoundingClientRect();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
539 const frameControls = document.querySelector('.jrpg-frame-controls')
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
540 .getBoundingClientRect();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
541 const frameTelemetry = document.querySelector('.jrpg-frame-telemetry')
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
542 .getBoundingClientRect();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
543 const telemetryValues = [
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
544 ...document.querySelectorAll('.jrpg-frame-telemetry > *'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
545 ].map(value => value.getBoundingClientRect());
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
546 const shell = document.querySelector('.jrpg-shell').getBoundingClientRect();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
547 const main = document.querySelector('.jrpg-main').getBoundingClientRect();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
548 const colorProbe = document.createElement('span');
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
549 colorProbe.style.background = 'var(--zenbu-sys-color-surface-page)';
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
550 colorProbe.style.color =
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
551 'var(--zenbu-sys-color-action-primary-background)';
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
552 colorProbe.style.borderColor = 'var(--zenbu-sys-color-focus-outer)';
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
553 const surfaceProbe = document.createElement('span');
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
554 surfaceProbe.style.background =
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
555 'var(--zenbu-sys-color-surface-default)';
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
556 surfaceProbe.style.color = 'var(--zenbu-sys-color-text-primary)';
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
557 surfaceProbe.style.borderColor = 'var(--zenbu-sys-color-border-strong)';
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
558 const sunkenProbe = document.createElement('span');
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
559 sunkenProbe.style.background =
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
560 'var(--zenbu-sys-color-surface-sunken)';
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
561 const panelProbe = document.createElement('span');
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
562 panelProbe.style.background = 'var(--mjj-jrpg-panel-strong)';
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
563 document.body.append(colorProbe, surfaceProbe, sunkenProbe, panelProbe);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
564 const probeStyle = getComputedStyle(colorProbe);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
565 const surfaceProbeStyle = getComputedStyle(surfaceProbe);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
566 const sunkenProbeStyle = getComputedStyle(sunkenProbe);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
567 const panelProbeStyle = getComputedStyle(panelProbe);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
568 const computedFonts = [
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
569 document.body,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
570 document.querySelector('.jrpg-brand h1'),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
571 document.querySelector('.jrpg-message p'),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
572 document.querySelector('#jrpg-message'),
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
573 document.querySelector('.jrpg-composer button[type="submit"]'),
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
574 ].map(element => getComputedStyle(element).fontFamily);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
575 const nonPixelText = [document.body, ...document.body.querySelectorAll('*')]
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
576 .filter(element => [...element.childNodes].some(node =>
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
577 node.nodeType === Node.TEXT_NODE && node.textContent.trim()
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
578 ))
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
579 .filter(element =>
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
580 getComputedStyle(element).fontFamily !== '"Pixel Mplus"'
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
581 )
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
582 .map(element => element.localName);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
583 const pageStyle = getComputedStyle(document.body);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
584 const submitStyle = getComputedStyle(
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
585 document.querySelector('.jrpg-composer button[type="submit"]'),
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
586 );
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
587 const colors = {
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
588 canvas: probeStyle.backgroundColor,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
589 conversation: getComputedStyle(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
590 document.querySelector('mjj-jrpg-chat'),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
591 ).backgroundColor,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
592 conversationBorder: getComputedStyle(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
593 document.querySelector('mjj-jrpg-chat'),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
594 ).borderTopColor,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
595 conversationPanel: panelProbeStyle.backgroundColor,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
596 conversationText: getComputedStyle(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
597 document.querySelector('.jrpg-message p'),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
598 ).color,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
599 focus: probeStyle.borderColor,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
600 frame: surfaceProbeStyle.borderColor,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
601 menu: getComputedStyle(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
602 document.querySelector('mjj-jrpg-menu'),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
603 ).backgroundColor,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
604 page: pageStyle.backgroundColor,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
605 primary: probeStyle.color,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
606 primaryText: getComputedStyle(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
607 document.querySelector('.jrpg-preview-panel h2'),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
608 ).color,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
609 sunken: sunkenProbeStyle.backgroundColor,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
610 surface: surfaceProbeStyle.backgroundColor,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
611 submit: submitStyle.backgroundColor,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
612 text: surfaceProbeStyle.color,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
613 utility: getComputedStyle(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
614 document.querySelector('.jrpg-utility'),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
615 ).backgroundColor,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
616 };
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
617 colorProbe.remove();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
618 surfaceProbe.remove();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
619 sunkenProbe.remove();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
620 panelProbe.remove();
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
621 const closeTo = (value, expected) => Math.abs(value - expected) < 0.01;
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
622 const frameAlignment = [
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
623 closeTo((scene.left - workspace.left) / workspace.width, 0.032),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
624 closeTo((scene.top - workspace.top) / workspace.height, 0.094),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
625 closeTo(scene.width / workspace.width, 0.548),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
626 closeTo(scene.height / workspace.height, 0.57),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
627 closeTo((utility.left - workspace.left) / workspace.width, 0.604),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
628 closeTo(utility.width / workspace.width, 0.365),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
629 closeTo((composer.top - workspace.top) / workspace.height, 0.72),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
630 closeTo(composer.width / workspace.width, 0.682),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
631 closeTo((menu.left - workspace.left) / workspace.width, 0.734),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
632 closeTo(menu.width / workspace.width, 0.234),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
633 ].every(Boolean);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
634 const borderless = [
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
635 '.jrpg-shell',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
636 '.jrpg-scene',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
637 '.jrpg-utility',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
638 'mjj-jrpg-chat',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
639 'mjj-jrpg-composer',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
640 'mjj-jrpg-menu',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
641 '.jrpg-preview-panel',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
642 '.jrpg-message',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
643 '.jrpg-work-showcase a',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
644 '.jrpg-composer textarea',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
645 '.jrpg-composer button[type="submit"]',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
646 'mjj-jrpg-menu button',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
647 ].every(selector => {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
648 const style = getComputedStyle(document.querySelector(selector));
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
649 return style.borderTopWidth === '0px' &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
650 style.borderRightWidth === '0px' &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
651 style.borderBottomWidth === '0px' &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
652 style.borderLeftWidth === '0px';
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
653 });
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
654 return {
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
655 art: getComputedStyle(document.querySelector('.jrpg-workspace'))
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
656 .backgroundImage,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
657 borderless,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
658 brandInSystemSlot:
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
659 closeTo((brand.left - workspace.left) / workspace.width, 0.054) &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
660 closeTo((brand.top - workspace.top) / workspace.height, 0.022) &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
661 document.querySelector('.jrpg-brand').parentElement.classList
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
662 .contains('jrpg-workspace'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
663 brandCoversSystemLabel:
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
664 brand.left <= workspace.left + workspace.width * 0.062 &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
665 brand.right >= workspace.left + workspace.width * 0.102 &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
666 brand.top <= workspace.top + workspace.height * 0.03 &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
667 brand.bottom >= workspace.top + workspace.height * 0.06,
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
668 characterLoaded: character.complete && character.naturalWidth > 0,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
669 colors,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
670 composerBelowScene: composer.top >= scene.bottom,
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
671 composerTextareaFills: (
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
672 Math.abs(composerTextarea.left - composerField.left) < 1 &&
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
673 Math.abs(composerTextarea.right - composerField.right) < 1 &&
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
674 Math.abs(composerTextarea.bottom - composerField.bottom) < 1 &&
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
675 composerTextarea.height > 60
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
676 ),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
677 composerTextareaGeometry: {
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
678 fieldBottom: composerField.bottom,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
679 fieldDisplay: composerFieldStyle.display,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
680 fieldGridRows: composerFieldStyle.gridTemplateRows,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
681 fieldLeft: composerField.left,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
682 fieldRight: composerField.right,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
683 fieldTop: composerField.top,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
684 labelBottom: composerLabel.bottom,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
685 labelTop: composerLabel.top,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
686 textareaBottom: composerTextarea.bottom,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
687 textareaHeight: composerTextarea.height,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
688 textareaLeft: composerTextarea.left,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
689 textareaRight: composerTextarea.right,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
690 textareaTop: composerTextarea.top,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
691 },
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
692 fillsViewport: shell.left === 0 &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
693 shell.top === 0 &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
694 Math.abs(shell.right - innerWidth) < 1 &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
695 Math.abs(shell.bottom - innerHeight) < 1 &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
696 main.left === 0 &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
697 main.top === 0 &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
698 Math.abs(main.right - innerWidth) < 1 &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
699 Math.abs(main.bottom - innerHeight) < 1,
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
700 frameAlignment,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
701 frameChromeAligned:
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
702 closeTo((frameControls.left - workspace.left) / workspace.width, 0.866) &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
703 closeTo((frameTelemetry.left - workspace.left) / workspace.width, 0.085) &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
704 closeTo((frameTelemetry.top - workspace.top) / workspace.height, 0.928),
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
705 fonts: computedFonts,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
706 fontLoaded: [...document.fonts].some(font =>
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
707 font.family.replaceAll('"', '') === 'Pixel Mplus' &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
708 font.status === 'loaded'
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
709 ),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
710 menuRightOfComposer: menu.left >= composer.right,
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
711 messageViewportFills: (
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
712 Math.abs(messageViewport.top - messageScroller.top) < 1 &&
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
713 Math.abs(messageViewport.bottom - messageScroller.bottom) < 1 &&
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
714 messageViewport.height > 192
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
715 ),
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
716 noOverflow: document.documentElement.scrollWidth <= innerWidth,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
717 nonPixelText,
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
718 questLabelAbsent: !document.body.textContent.includes('QUEST 01'),
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
719 previewLabelsRemoved:
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
720 !/CHARACTER RECORD|ITEM INVENTORY|QUEST ARCHIVE/.test(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
721 document.querySelector('.jrpg-preview-panel').textContent,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
722 ),
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
723 statsRemoved:
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
724 !document.querySelector('.jrpg-preview-stats') &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
725 !document.querySelector('[data-preview-type]'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
726 telemetryCovered:
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
727 document.querySelectorAll('.jrpg-frame-telemetry > *').length === 4 &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
728 document.querySelector('[data-frame-network]').textContent
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
729 .includes('ONLINE') &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
730 document.querySelector('[data-frame-uptime]').textContent
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
731 .match(/^\d{2}:\d{2}:\d{2}$/) &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
732 [...document.querySelectorAll('.jrpg-frame-telemetry > *')]
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
733 .every(item => !/TEMP:|USER:|STATUS:|UPTIME:/.test(item.textContent)),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
734 telemetryValuesAligned:
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
735 closeTo(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
736 (telemetryValues[0].left + telemetryValues[0].width / 2 -
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
737 frameTelemetry.left) / frameTelemetry.width,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
738 0.12,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
739 ) &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
740 closeTo(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
741 (telemetryValues[1].left + telemetryValues[1].width / 2 -
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
742 frameTelemetry.left) / frameTelemetry.width,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
743 0.325,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
744 ) &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
745 closeTo(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
746 (telemetryValues[2].left + telemetryValues[2].width / 2 -
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
747 frameTelemetry.left) / frameTelemetry.width,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
748 0.605,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
749 ) &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
750 closeTo(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
751 (telemetryValues[3].left + telemetryValues[3].width / 2 -
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
752 frameTelemetry.left) / frameTelemetry.width,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
753 0.88,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
754 ),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
755 shibaInFrontOfBar:
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
756 sceneBarStyle.backgroundImage.includes('bar-ink.webp') &&
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
757 sceneBarStyle.backgroundSize === 'cover' &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
758 Math.abs(parseFloat(sceneBarStyle.height) - scene.height) < 1 &&
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
759 Number(getComputedStyle(character.parentElement).zIndex) >
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
760 Number(sceneBarStyle.zIndex) &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
761 characterBox.bottom > scene.top + scene.height * 0.65,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
762 terminalScrollbar: (
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
763 getComputedStyle(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
764 document.querySelector('.jrpg-message-viewport'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
765 ).scrollbarWidth === 'thin' &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
766 getComputedStyle(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
767 document.querySelector('.jrpg-message-viewport'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
768 ).scrollbarColor !== 'auto'
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
769 ),
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
770 theme: document.documentElement.dataset.zenTheme,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
771 utilityRightOfScene: utility.left >= scene.right,
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
772 workspaceFillsViewport:
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
773 Math.abs(workspace.left) < 1 &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
774 Math.abs(workspace.top) < 1 &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
775 Math.abs(workspace.right - innerWidth) < 1 &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
776 Math.abs(workspace.bottom - innerHeight) < 1,
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
777 };
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
778 });
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
779 assert.match(desktop.art, /background-frame-2\.webp/);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
780 assert.equal(desktop.borderless, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
781 assert.equal(desktop.brandInSystemSlot, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
782 assert.equal(desktop.brandCoversSystemLabel, true);
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
783 assert.equal(desktop.characterLoaded, true);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
784 assert.equal(desktop.colors.page, desktop.colors.canvas);
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
785 assert.equal(desktop.colors.conversation, 'rgba(0, 0, 0, 0)');
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
786 assert.equal(desktop.colors.conversationText, desktop.colors.text);
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
787 assert.equal(desktop.colors.menu, 'rgba(0, 0, 0, 0)');
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
788 assert.equal(desktop.colors.primaryText, desktop.colors.primary);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
789 assert.equal(desktop.colors.submit, desktop.colors.primary);
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
790 assert.equal(desktop.colors.utility, 'rgba(0, 0, 0, 0)');
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
791 assert.equal(desktop.composerBelowScene, true);
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
792 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
793 desktop.composerTextareaFills,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
794 true,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
795 JSON.stringify(desktop.composerTextareaGeometry),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
796 );
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
797 assert.equal(desktop.fillsViewport, true);
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
798 assert.equal(desktop.frameAlignment, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
799 assert.equal(desktop.frameChromeAligned, true);
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
800 assert.ok(desktop.fonts.every(font => font === '"Pixel Mplus"'));
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
801 assert.equal(desktop.fontLoaded, true);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
802 assert.equal(desktop.menuRightOfComposer, true);
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
803 assert.equal(desktop.messageViewportFills, true);
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
804 assert.equal(desktop.noOverflow, true);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
805 assert.deepEqual(desktop.nonPixelText, []);
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
806 assert.equal(desktop.questLabelAbsent, true);
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
807 assert.equal(desktop.previewLabelsRemoved, true);
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
808 assert.equal(desktop.statsRemoved, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
809 assert.equal(desktop.telemetryCovered, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
810 assert.equal(desktop.telemetryValuesAligned, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
811 assert.equal(desktop.shibaInFrontOfBar, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
812 assert.equal(desktop.terminalScrollbar, true);
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
813 assert.equal(desktop.theme, 'cyberpunk');
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
814 assert.equal(desktop.utilityRightOfScene, true);
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
815 assert.equal(desktop.workspaceFillsViewport, true);
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
816 await page.locator('.jrpg-brand a').focus();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
817 assert.equal(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
818 await page.locator('.jrpg-brand a').evaluate(element =>
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
819 getComputedStyle(element).outlineColor
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
820 ),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
821 desktop.colors.focus,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
822 );
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
823 await page.locator('.jrpg-composer button[type="submit"]').focus();
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
824 assert.equal(
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
825 await page.locator('.jrpg-composer button[type="submit"]').evaluate(element =>
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
826 getComputedStyle(element).outlineColor
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
827 ),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
828 desktop.colors.focus,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
829 );
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
830 assert.equal(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
831 await page.locator('meta[name="theme-color"]').first().getAttribute('content'),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
832 desktop.colors.canvas,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
833 );
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
834 assert.equal(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
835 await page.locator('.jrpg-frame-controls :is(button, a)').count(),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
836 3,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
837 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
838 assert.equal(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
839 await page.locator('.jrpg-frame-controls a').getAttribute('href'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
840 '/',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
841 );
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
842
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
843 // Account slot: guest session shows a login button (modal trigger)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
844 assert.ok(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
845 await page.locator('[data-frame-account]').count() > 0,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
846 'account slot exists in telemetry',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
847 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
848 await page.waitForFunction(() =>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
849 document.querySelector('[data-frame-account]')?.querySelector('button[data-login-open]') !== null
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
850 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
851 const loginBtnState = await page.locator('[data-frame-account] button[data-login-open]').evaluate(btn => ({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
852 text: btn.textContent.trim(),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
853 ownerCount: btn.closest('zen-button') ? 1 : 0,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
854 appearance: btn.closest('zen-button')?.getAttribute('appearance'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
855 size: btn.closest('zen-button')?.getAttribute('size'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
856 }));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
857 assert.match(loginBtnState.text, /LOGIN/i);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
858 assert.equal(loginBtnState.ownerCount, 1, 'login button has zen-button owner');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
859 assert.equal(loginBtnState.appearance, 'plain');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
860 assert.equal(loginBtnState.size, 'xs');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
861
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
862 // Login modal: opens on button click, focuses username, closes on cancel
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
863 await page.locator('[data-frame-account] button[data-login-open]').click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
864 await page.locator('[data-login-dialog]').waitFor({ state: 'visible' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
865 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
866 await page.locator('[data-login-dialog]').getAttribute('aria-modal'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
867 'true',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
868 'login dialog is modal',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
869 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
870 // Username input should receive initial focus
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
871 await page.waitForFunction(() => document.activeElement?.id === 'jrpg-login-username');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
872 // Cancel closes dialog and clears password
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
873 await page.locator('#jrpg-login-password').fill('dummypassword');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
874 await page.locator('[data-login-cancel]').click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
875 await page.locator('[data-login-dialog]').waitFor({ state: 'hidden' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
876 await page.waitForFunction(() => !document.querySelector('#jrpg-login-password')?.value);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
877 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
878 await page.locator('#jrpg-login-password').inputValue(),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
879 '',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
880 'password cleared on close',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
881 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
882
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
883 // Invalid credentials show error message
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
884 await page.locator('[data-frame-account] button[data-login-open]').click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
885 await page.locator('[data-login-dialog]').waitFor({ state: 'visible' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
886 await page.locator('#jrpg-login-username').fill('nosuchuser');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
887 await page.locator('#jrpg-login-password').fill('nosuchpassword123');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
888 let loginErrorShown = false;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
889 const loginResponsePromise = page.waitForResponse(resp =>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
890 resp.url().includes('/api/auth/login')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
891 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
892 await page.locator('[data-login-submit]').click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
893 const loginResp = await loginResponsePromise;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
894 if (loginResp.status() >= 400) {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
895 await page.waitForFunction(() => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
896 const el = document.querySelector('[data-login-error]');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
897 return el && !el.hidden && el.textContent.trim().length > 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
898 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
899 loginErrorShown = true;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
900 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
901 assert.equal(loginErrorShown, true, 'error element shown on bad credentials');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
902 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
903 await page.locator('#jrpg-login-password').inputValue(),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
904 '',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
905 'password cleared after failed login attempt',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
906 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
907 // Close modal via X button (data-zen-close)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
908 await page.getByRole('button', { name: 'Close sign-in dialog' }).click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
909 await page.locator('[data-login-dialog]').waitFor({ state: 'hidden' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
910
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
911 // Archive opens only from the bottom destination menu.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
912 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
913 await page.locator('[data-toggle-archive]').count(),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
914 0,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
915 'redundant chat-heading archive shortcut is removed',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
916 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
917 await page.locator('button[data-preview="conversations"]').click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
918 await page.locator('.jrpg-utility mjj-conversation-archive').waitFor({ state: 'visible' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
919 const archiveGeometry = await page.evaluate(() => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
920 const utility = document.querySelector('.jrpg-utility').getBoundingClientRect();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
921 const archive = document.querySelector(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
922 '.jrpg-utility mjj-conversation-archive',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
923 ).getBoundingClientRect();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
924 return {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
925 archive: {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
926 bottom: archive.bottom,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
927 height: archive.height,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
928 left: archive.left,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
929 right: archive.right,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
930 top: archive.top,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
931 width: archive.width,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
932 },
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
933 fits: archive.left >= utility.left &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
934 archive.top >= utility.top &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
935 archive.right <= utility.right + 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
936 archive.bottom <= utility.bottom + 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
937 archive.width / utility.width > 0.85 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
938 archive.height / utility.height > 0.85,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
939 utility: {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
940 bottom: utility.bottom,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
941 height: utility.height,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
942 left: utility.left,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
943 right: utility.right,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
944 top: utility.top,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
945 width: utility.width,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
946 },
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
947 };
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
948 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
949 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
950 archiveGeometry.fits,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
951 true,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
952 `conversation archive fills the top-right utility aperture: ${JSON.stringify(archiveGeometry)}`,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
953 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
954 // Archive status or empty message should be visible
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
955 await page.waitForFunction(() => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
956 const status = document.querySelector('[data-archive-status]');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
957 return status && !status.hidden;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
958 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
959 // New conversation button exists inside archive
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
960 assert.ok(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
961 await page.locator('[data-archive-new]').isVisible(),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
962 'archive new button visible',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
963 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
964 // Conversations menu button should be pressed
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
965 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
966 await page.locator('button[data-preview="conversations"]').getAttribute('aria-pressed'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
967 'true',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
968 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
969
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
970 // Archive: close via close button, navigates back to resume panel
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
971 await page.locator('[data-archive-close]').click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
972 await page.locator('.jrpg-utility mjj-conversation-archive').waitFor({ state: 'hidden' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
973 // mjj-jrpg-chat must remain visible (always in scene)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
974 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
975 await page.locator('mjj-jrpg-chat').isVisible(),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
976 true,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
977 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
978
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
979 // Quota element is present (may be shown for guest session)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
980 assert.ok(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
981 await page.locator('[data-quota]').count() > 0,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
982 'quota element exists',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
983 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
984
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
985 await page.getByRole('button', { name: 'Minimize interface' }).click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
986 assert.equal(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
987 await page.locator('.jrpg-scene').evaluate(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
988 scene => getComputedStyle(scene).visibility,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
989 ),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
990 'hidden',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
991 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
992 await page.getByRole('button', { name: 'Restore interface' }).click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
993 assert.equal(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
994 await page.locator('.jrpg-scene').evaluate(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
995 scene => getComputedStyle(scene).visibility,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
996 ),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
997 'visible',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
998 );
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
999 assert.equal(await page.locator('[data-work-showcase] a').count(), 8);
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1000 assert.equal(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1001 await page.getByRole('button', { name: /Inspect/ }).count(),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1002 0,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1003 );
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1004 assert.match(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1005 await page.locator('[data-work-showcase]').textContent(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1006 /Copilot Tasks/,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1007 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1008 assert.match(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1009 await page.locator('[data-work-showcase]').textContent(),
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1010 /AIX Harness \/ Copilot/,
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1011 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1012 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1013 await page.locator('[data-turn-position]').textContent(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1014 'START',
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1015 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1016 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1017 await page.getByRole('button', { name: 'Previous turn' }).isDisabled(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1018 true,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1019 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1020 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1021 await page.getByRole('button', { name: 'Next turn' }).isDisabled(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1022 true,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1023 );
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1024
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1025 await page.getByRole('button', { name: 'Tools', exact: true }).click();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1026 assert.equal(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1027 await page.locator('[data-preview-title]').textContent(),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1028 'Tools',
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1029 );
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1030 assert.equal(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1031 await page.locator('[data-preview-link]').getAttribute('href'),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1032 '/tools',
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1033 );
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1034 assert.equal(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1035 await page.getByRole('button', { name: 'Tools', exact: true })
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1036 .getAttribute('aria-pressed'),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1037 'true',
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1038 );
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1039 await page.waitForFunction(() =>
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1040 document.querySelectorAll('[data-latest-tool]').length === 5
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1041 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1042 assert.match(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1043 await page.locator('[data-work-showcase]').textContent(),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1044 /Online LaTeX Editor/,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1045 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1046 assert.match(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1047 await page.locator('[data-work-showcase]').textContent(),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1048 /Personal Notes/,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1049 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1050 await page.locator('[data-latest-tool]').first().click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1051 await page.locator('[data-functional-tool="markdown"]').waitFor();
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1052 assert.equal(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1053 await page.locator('[data-dialog-title]').textContent(),
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1054 'MarkDown to HTML',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1055 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1056 assert.equal(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1057 await page.locator('[data-preview-link]').getAttribute('href'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1058 '/tools/markdown_to_html',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1059 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1060 await page.locator('[data-markdown-source]').fill('# Modal Markdown');
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1061 await page.waitForFunction(() =>
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1062 document.querySelector('[data-markdown-output] h1')?.textContent ===
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1063 'Modal Markdown'
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1064 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1065 assert.equal(await page.locator('.jrpg-tool-pane').count(), 2);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1066 const toolWorkspace = await page.evaluate(() => {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1067 const dialogElement = document.querySelector(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1068 '.jrpg-detail-dialog[data-detail-mode="tools"]',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1069 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1070 const dialog = dialogElement.getBoundingClientRect();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1071 const windows = [...document.querySelectorAll('.jrpg-tool-window')]
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1072 .map(window => window.getBoundingClientRect());
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1073 const windowShadows = [...document.querySelectorAll('.jrpg-tool-window')]
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1074 .map(window => getComputedStyle(window).boxShadow);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1075 const rail = getComputedStyle(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1076 document.querySelector('.jrpg-tool-panes'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1077 '::before',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1078 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1079 return {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1080 dialogHeight: dialogElement.offsetHeight,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1081 dialogWidth: dialogElement.offsetWidth,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1082 fillsViewport: dialogElement.offsetWidth > innerWidth * 0.9 &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1083 dialogElement.offsetHeight > innerHeight * 0.9,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1084 viewportHeight: innerHeight,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1085 viewportWidth: innerWidth,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1086 sideBySide: windows.length === 2 &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1087 windows[0].right < windows[1].left &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1088 Math.abs(windows[0].top - windows[1].top) < 1,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1089 fullPageInHeader: Boolean(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1090 document.querySelector('[data-preview-link]')
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1091 .closest('.jrpg-dialog-heading-actions'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1092 ),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1093 footerHidden: document.querySelector('[data-dialog-actions]').hidden,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1094 metalRail: rail.content !== 'none' &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1095 rail.backgroundImage.includes('bar-ink.webp'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1096 pixelIcons: document.querySelectorAll('.jrpg-tool-window zen-icon').length >= 2 &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1097 [...document.querySelectorAll('.jrpg-tool-window zen-icon svg')]
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1098 .every(icon =>
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1099 getComputedStyle(icon).shapeRendering.toLowerCase() === 'crispedges'
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1100 ),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1101 separateGlows: windowShadows.length === 2 &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1102 windowShadows.every(shadow => shadow !== 'none'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1103 wideWindows: windows.every(window => window.width > dialog.width * 0.35),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1104 };
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1105 });
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1106 assert.equal(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1107 toolWorkspace.fillsViewport,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1108 true,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1109 JSON.stringify(toolWorkspace),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1110 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1111 assert.equal(toolWorkspace.sideBySide, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1112 assert.equal(toolWorkspace.fullPageInHeader, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1113 assert.equal(toolWorkspace.footerHidden, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1114 assert.equal(toolWorkspace.metalRail, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1115 assert.equal(toolWorkspace.pixelIcons, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1116 assert.equal(toolWorkspace.separateGlows, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1117 assert.equal(toolWorkspace.wideWindows, true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1118 await page.getByRole('button', {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1119 name: 'Close destination details',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1120 }).click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1121 await page.locator('.jrpg-preview-dialog dialog').waitFor({ state: 'hidden' });
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1122
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1123 await page.locator('[data-latest-tool]').first().click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1124 await page.locator('[data-functional-tool="markdown"]').waitFor();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1125 await page.getByRole('button', {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1126 name: 'Close destination details',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1127 }).click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1128 await page.locator('.jrpg-preview-dialog dialog').waitFor({ state: 'hidden' });
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1129
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1130 await page.locator('[data-latest-tool]').nth(1).click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1131 await page.locator('[data-functional-tool="converter"]').waitFor();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1132 assert.equal(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1133 await page.locator('[data-converter-input]').count(),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1134 2,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1135 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1136 const converterFixture = path.join(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1137 RUNFILES,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1138 WORKSPACE,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1139 'mrjunejune/test/shiba.webp',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1140 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1141 assert.equal(fs.existsSync(converterFixture), true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1142 await page.locator('[data-converter-input="image"]').setInputFiles(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1143 converterFixture,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1144 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1145 const conversionResponse = page.waitForResponse(response =>
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1146 response.url().endsWith('/api/convert/image-to-webp') &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1147 response.request().method() === 'POST'
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1148 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1149 await page.locator('[data-convert-kind="image"]').click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1150 assert.equal((await conversionResponse).status(), 200);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1151 await page.locator('[data-converter-download="image"]').waitFor();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1152 const cleanupResponse = page.waitForResponse(response =>
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1153 response.url().includes('/api/download/') &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1154 response.request().method() === 'DELETE'
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1155 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1156 await page.getByRole('button', {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1157 name: 'Close destination details',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1158 }).click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1159 assert.equal((await cleanupResponse).status(), 204);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1160 await page.locator('.jrpg-preview-dialog dialog').waitFor({ state: 'hidden' });
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1161
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1162 await page.locator('[data-latest-tool]').nth(1).click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1163 await page.locator('[data-functional-tool="converter"]').waitFor();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1164 await page.locator('[data-converter-input="image"]').setInputFiles(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1165 converterFixture,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1166 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1167 const lateConversionResponse = page.waitForResponse(response =>
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1168 response.url().endsWith('/api/convert/image-to-webp') &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1169 response.request().method() === 'POST'
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1170 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1171 const lateCleanupResponse = page.waitForResponse(response =>
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1172 response.url().includes('/api/download/') &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1173 response.request().method() === 'DELETE'
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1174 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1175 await page.locator('[data-convert-kind="image"]').click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1176 await page.getByRole('button', {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1177 name: 'Close destination details',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1178 }).click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1179 assert.equal((await lateConversionResponse).status(), 200);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1180 assert.equal((await lateCleanupResponse).status(), 204);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1181 await page.locator('.jrpg-preview-dialog dialog').waitFor({ state: 'hidden' });
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1182
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1183 await page.locator('[data-latest-tool]').nth(2).click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1184 await page.locator('[data-functional-tool="hls"]').waitFor();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1185 assert.equal(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1186 await page.locator('[data-preview-link]').getAttribute('href'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1187 '/tools/hls_player',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1188 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1189 await page.locator('[data-hls-sample]').click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1190 await page.waitForFunction(() =>
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1191 ['ready', 'error'].includes(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1192 document.querySelector('[data-hls-status]')?.dataset.state,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1193 )
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1194 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1195 assert.ok(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1196 ['ready', 'error'].includes(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1197 await page.locator('[data-hls-status]').getAttribute('data-state'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1198 ),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1199 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1200 assert.match(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1201 await page.locator('[data-hls-status]').textContent(),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1202 /ready|unsupported|failed/i,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1203 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1204 await page.getByRole('button', {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1205 name: 'Close destination details',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1206 }).click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1207 await page.locator('.jrpg-preview-dialog dialog').waitFor({ state: 'hidden' });
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1208
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1209 await page.locator('[data-latest-tool]').nth(3).click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1210 await page.locator('[data-functional-tool="latex"]').waitFor();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1211 await page.locator('[data-latex-compile]').click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1212 await page.locator('[data-latex-source]').fill(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1213 '\\documentclass{article}\\begin{document}Updated modal PDF\\end{document}',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1214 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1215 assert.equal(await page.locator('[data-latex-download]').isHidden(), true);
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1216 await page.locator('[data-latex-compile]').click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1217 await page.waitForFunction(() =>
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1218 document.querySelector('[data-latex-status]')?.dataset.state === 'ready'
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1219 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1220 assert.match(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1221 await page.locator('[data-latex-preview]').getAttribute('src'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1222 /^blob:/,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1223 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1224 await page.getByRole('button', {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1225 name: 'Close destination details',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1226 }).click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1227 await page.locator('.jrpg-preview-dialog dialog').waitFor({ state: 'hidden' });
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1228
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1229 await page.locator('[data-latest-tool]').nth(4).click();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1230 await page.waitForFunction(() =>
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1231 document.querySelector('[data-tool-content] h1')?.textContent ===
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1232 'Personal Notes'
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1233 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1234 assert.match(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1235 await page.locator('[data-tool-content]').textContent(),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1236 /private browser-based writing workspace/,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1237 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1238 assert.equal(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1239 await page.locator('[data-preview-link]').getAttribute('href'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1240 '/notes',
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1241 );
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1242 await page.getByRole('button', {
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1243 name: 'Close destination details',
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1244 }).click();
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1245 await page.locator('.jrpg-preview-dialog dialog').waitFor({ state: 'hidden' });
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1246
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1247 await page.getByRole('button', { name: 'Resume', exact: true }).click();
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1248 await page.locator('[data-resume-modal]').click();
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1249 await page.locator('[data-resume-content] .sub-header').first().waitFor();
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1250 const resumeDossier = await page.locator('[data-resume-dossier]').evaluate(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1251 dossier => ({
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1252 fontFamily: getComputedStyle(dossier).fontFamily,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1253 text: dossier.textContent,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1254 }),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1255 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1256 assert.equal(resumeDossier.fontFamily, '"Pixel Mplus"');
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1257 assert.match(resumeDossier.text, /Copilot Tasks/);
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1258 assert.match(resumeDossier.text, /Microsoft/);
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1259 assert.match(resumeDossier.text, /Meta/);
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1260 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1261 await page.locator('[data-resume-content] a[target="_blank"]').count() > 0,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1262 true,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1263 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1264 await page.getByRole('button', {
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1265 name: 'Close destination details',
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1266 }).click();
262
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1267 await page.locator('.jrpg-preview-dialog dialog').waitFor({ state: 'hidden' });
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1268
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1269 await page.getByRole('button', { name: 'Blogs', exact: true }).click();
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1270 await page.waitForFunction(() =>
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1271 document.querySelectorAll('[data-latest-blog]').length === 4
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1272 );
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1273 assert.match(
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1274 await page.locator('[data-work-showcase]').textContent(),
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1275 /Websocket Demystified/,
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1276 );
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1277 assert.match(
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1278 await page.locator('[data-work-showcase]').textContent(),
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1279 /Creating Network Library in C/,
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1280 );
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1281 await page.locator('[data-latest-blog]').first().click();
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1282 await page.locator('[data-blog-content] h1').waitFor();
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1283 assert.equal(
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1284 await page.locator('[data-blog-content] h1').textContent(),
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1285 'WebSocket Demystified',
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1286 );
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1287 assert.equal(
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1288 await page.locator('[data-preview-link]').getAttribute('href'),
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1289 '/blog/websocket-demystified',
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1290 );
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1291 assert.equal(
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1292 await page.locator('[data-blog-content]').evaluate(
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1293 article => getComputedStyle(article).fontFamily,
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1294 ),
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1295 '"Pixel Mplus"',
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1296 );
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1297 await page.getByRole('button', {
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1298 name: 'Close destination details',
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1299 }).click();
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1300 await page.locator('.jrpg-preview-dialog dialog').waitFor({ state: 'hidden' });
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1301
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1302 await page.locator('[data-blog-archive]').click();
262
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1303 await page.waitForFunction(() =>
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1304 document.querySelectorAll('[data-blog-entry]').length === 9
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1305 );
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1306 assert.equal(await page.locator('[data-blog-entry]').count(), 9);
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1307 await page.locator('[data-blog-entry]').nth(1).click();
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1308 await page.waitForFunction(() =>
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1309 document.querySelector('[data-blog-content] h1')?.textContent ===
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1310 'Creating Network Library in C'
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1311 );
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1312 assert.equal(
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1313 await page.locator('[data-preview-link]').getAttribute('href'),
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1314 '/blog/my-seobeo-journey',
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1315 );
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1316 await page.getByRole('button', {
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1317 name: 'Close destination details',
0f45474c1b1a Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 261
diff changeset
1318 }).click();
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1319
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1320 await page.evaluate(() => {
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1321 window.__jrpgStreamEvents = [];
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1322 document.querySelector('mjj-jrpg-shell').addEventListener(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1323 'mjj-jrpg-stream-event',
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1324 event => window.__jrpgStreamEvents.push(event.detail),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1325 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1326 });
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1327 await page.locator('#jrpg-message').fill('Where should I begin?');
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1328 await page.locator('#jrpg-message').press('Enter');
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1329 await page.locator('.jrpg-message[data-speaker="June"]').last().waitFor();
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1330 const streamingMessage = page.locator(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1331 '.jrpg-message[data-speaker="Epi"][data-streaming="true"]',
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1332 ).last();
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1333 await streamingMessage.waitFor();
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1334 await page.locator('[data-cancel-control]').waitFor({ state: 'hidden' });
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1335 await streamingMessage.waitFor();
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1336 assert.notEqual(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1337 await streamingMessage.locator('p').textContent(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1338 'hello traveler',
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1339 );
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1340 await page.getByRole('button', { name: 'Blogs', exact: true }).click();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1341 assert.equal(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1342 await page.locator('.jrpg-message[data-speaker="June"] p').last()
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1343 .textContent(),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1344 'Where should I begin?',
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1345 );
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1346 await page.waitForFunction(() =>
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1347 document.querySelector('mjj-jrpg-character')?.getAttribute('state') ===
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1348 'default' &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1349 document.querySelectorAll('.jrpg-message[data-speaker="Epi"]').length > 1
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1350 );
261
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1351 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1352 await page.locator('.jrpg-message[data-speaker="Epi"] p').last()
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1353 .textContent(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1354 'hello traveler',
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1355 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1356 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1357 await page.locator(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1358 '.jrpg-message[data-speaker="Epi"][data-streaming="true"]',
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1359 ).count(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1360 0,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1361 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1362 assert.deepEqual(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1363 await page.evaluate(() => {
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1364 const event = window.__jrpgStreamEvents.find(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1365 item => item.type === 'tool.started',
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1366 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1367 return {
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1368 name: event?.data.tool?.name,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1369 type: event?.type,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1370 };
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1371 }),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1372 {
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1373 name: 'mock-search',
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1374 type: 'tool.started',
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1375 },
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1376 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1377 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1378 await page.locator('[data-turn-position]').textContent(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1379 'TURN 1 / 1',
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1380 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1381 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1382 await page.getByRole('button', { name: 'Previous turn' }).isEnabled(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1383 true,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1384 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1385 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1386 await page.getByRole('button', { name: 'Next turn' }).isDisabled(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1387 true,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1388 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1389 await page.getByRole('button', { name: 'Previous turn' }).click();
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1390 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1391 await page.locator('[data-turn-position]').textContent(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1392 'START',
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1393 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1394 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1395 await page.locator('.jrpg-message[data-speaker="June"]:visible').count(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1396 0,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1397 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1398 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1399 await page.locator('.jrpg-message[data-speaker="System"]:visible').count(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1400 1,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1401 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1402 await page.getByRole('button', { name: 'Next turn' }).click();
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1403 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1404 await page.locator('[data-turn-position]').textContent(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1405 'TURN 1 / 1',
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1406 );
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1407 assert.equal(
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1408 await page.locator('.jrpg-message[data-speaker="June"]:visible').count(),
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1409 1,
b401627fc49e Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 260
diff changeset
1410 );
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1411 assert.equal(await page.locator('#jrpg-message').isEnabled(), true);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1412
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1413 await page.waitForFunction(() => navigator.serviceWorker?.controller);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1414 await page.reload({ waitUntil: 'networkidle' });
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1415 await page.evaluate(() => document.fonts.ready);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1416 const controlledReload = await page.evaluate(() => {
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1417 const shell = document.querySelector('.jrpg-shell').getBoundingClientRect();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1418 return {
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1419 art: getComputedStyle(document.querySelector('.jrpg-workspace'))
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1420 .backgroundImage,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1421 fillsViewport: shell.left === 0 &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1422 shell.top === 0 &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1423 Math.abs(shell.right - innerWidth) < 1 &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1424 Math.abs(shell.bottom - innerHeight) < 1,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1425 fontLoaded: document.fonts.check('16px "Pixel Mplus"'),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1426 fontFamily: getComputedStyle(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1427 document.querySelector('.jrpg-brand h1'),
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1428 ).fontFamily,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1429 theme: document.documentElement.dataset.zenTheme,
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1430 };
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1431 });
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1432 assert.match(controlledReload.art, /background-frame-2\.webp/);
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1433 assert.equal(controlledReload.fillsViewport, true);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1434 assert.equal(controlledReload.fontLoaded, true);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1435 assert.equal(controlledReload.fontFamily, '"Pixel Mplus"');
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1436 assert.equal(controlledReload.theme, 'cyberpunk');
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1437 assert.deepEqual(errors, []);
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1438 await context.close();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1439
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1440 const mobileContext = await browser.newContext({
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1441 colorScheme: 'light',
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1442 viewport: { width: 360, height: 640 },
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1443 });
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1444 const mobilePage = await mobileContext.newPage();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1445 await mobilePage.goto(`${baseUrl}/jrpg`, { waitUntil: 'networkidle' });
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1446 await mobilePage.waitForFunction(() =>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1447 customElements.get('mjj-jrpg-composer') &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1448 customElements.get('mjj-jrpg-menu')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1449 );
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1450 const mobile = await mobilePage.evaluate(() => {
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1451 const workspace = document.querySelector('.jrpg-workspace')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1452 .getBoundingClientRect();
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1453 const scene = document.querySelector('.jrpg-scene').getBoundingClientRect();
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1454 const utility = document.querySelector('.jrpg-utility').getBoundingClientRect();
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1455 const composer = document.querySelector('mjj-jrpg-composer')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1456 .getBoundingClientRect();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1457 const menu = document.querySelector('mjj-jrpg-menu').getBoundingClientRect();
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1458 const shell = document.querySelector('.jrpg-shell').getBoundingClientRect();
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1459 const hamburger = document.querySelector('[data-mobile-menu-toggle]');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1460 const hamburgerBox = hamburger?.getBoundingClientRect();
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1461 const menuButtons = [...document.querySelectorAll(
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1462 'mjj-jrpg-menu button[data-preview]',
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1463 )];
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1464 const telemetryItems = [
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1465 ...document.querySelectorAll('.jrpg-frame-telemetry > *'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1466 ];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1467 const closeTo = (value, expected, tol = 0.025) =>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1468 Math.abs(value - expected) < tol;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1469 const wsW = workspace.width;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1470 const wsH = workspace.height;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1471 const mobileArt = getComputedStyle(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1472 document.querySelector('.jrpg-workspace'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1473 ).backgroundImage;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1474 const mobileArtIsCorrect = mobileArt.includes('background-frame-mobile.webp');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1475 const aperturesTolerance = [
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1476 closeTo((scene.left - workspace.left) / wsW, 0.045),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1477 closeTo((scene.top - workspace.top) / wsH, 0.075),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1478 closeTo(scene.width / wsW, 0.91),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1479 closeTo(scene.height / wsH, 0.455),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1480 closeTo((utility.left - workspace.left) / wsW, 0.045),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1481 closeTo((utility.top - workspace.top) / wsH, 0.547),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1482 closeTo(utility.width / wsW, 0.91),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1483 closeTo(utility.height / wsH, 0.171),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1484 closeTo((composer.left - workspace.left) / wsW, 0.045),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1485 closeTo((composer.top - workspace.top) / wsH, 0.728),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1486 closeTo(composer.width / wsW, 0.603),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1487 closeTo(composer.height / wsH, 0.192),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1488 closeTo((menu.left - workspace.left) / wsW, 0.665),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1489 closeTo((menu.top - workspace.top) / wsH, 0.728),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1490 closeTo(menu.width / wsW, 0.29),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1491 closeTo(menu.height / wsH, 0.192),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1492 ].every(Boolean);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1493 const hamburgerPresent = hamburger !== null &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1494 hamburger.getAttribute('aria-expanded') === 'true' &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1495 hamburgerBox !== null &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1496 hamburgerBox.width > 0 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1497 hamburgerBox.height > 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1498 const telemetryCount = telemetryItems.length === 4;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1499 const composerVisible = composer.width > 0 && composer.height > 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1500 const menuVisible = menu.width > 0 && menu.height > 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1501 const conversationsButton = document.querySelector(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1502 'button[data-preview="conversations"]',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1503 );
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1504 return {
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1505 aperturesTolerance,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1506 conversationsButtonVisible: conversationsButton !== null &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1507 conversationsButton.offsetParent !== null,
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1508 buttonsFit: menuButtons.every(button =>
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1509 button.getBoundingClientRect().right <= innerWidth + 1
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1510 ),
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1511 composerVisible,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1512 fillsViewport: shell.left === 0 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1513 shell.top === 0 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1514 Math.abs(shell.right - innerWidth) < 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1515 Math.abs(shell.bottom - innerHeight) < 1,
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1516 fillsWidth: shell.left === 0 &&
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1517 Math.abs(shell.right - innerWidth) < 1,
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1518 hamburgerPresent,
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1519 initialScroll: scrollY,
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1520 mobileArtIsCorrect,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1521 menuVisible,
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1522 noOverflow: document.documentElement.scrollWidth <= innerWidth,
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1523 telemetryCount,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1524 utilityBelowScene: utility.top >= scene.bottom - 1,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1525 workspaceFills: Math.abs(workspace.left) < 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1526 Math.abs(workspace.top) < 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1527 Math.abs(workspace.right - innerWidth) < 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1528 Math.abs(workspace.bottom - innerHeight) < 1,
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1529 };
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1530 });
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1531 assert.equal(mobile.aperturesTolerance, true, 'mobile apertures within tolerance at 360x640');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1532 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1533 mobile.conversationsButtonVisible,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1534 true,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1535 'Conversations destination visible on mobile',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1536 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1537 assert.equal(mobile.buttonsFit, true, 'menu buttons fit within viewport width');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1538 assert.equal(mobile.composerVisible, true, 'composer visible');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1539 assert.equal(mobile.fillsViewport, true, 'shell fills viewport');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1540 assert.equal(mobile.fillsWidth, true, 'shell fills width');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1541 assert.equal(mobile.hamburgerPresent, true, 'hamburger button present and has aria-expanded=true');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1542 assert.equal(mobile.initialScroll, 0, 'no initial scroll');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1543 assert.equal(mobile.mobileArtIsCorrect, true, 'mobile background URL is background-frame-mobile.webp');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1544 assert.equal(mobile.menuVisible, true, 'menu visible');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1545 assert.equal(mobile.noOverflow, true, 'no horizontal overflow at 360x640');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1546 assert.equal(mobile.telemetryCount, true, 'four telemetry items present');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1547 assert.equal(mobile.utilityBelowScene, true, 'utility aperture below scene');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1548 assert.equal(mobile.workspaceFills, true, 'workspace fills full viewport');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1549
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1550 // Test hamburger disclosure behavior.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1551 await mobilePage.locator('[data-mobile-menu-toggle]').click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1552 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1553 await mobilePage.locator('[data-mobile-menu-toggle]')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1554 .getAttribute('aria-expanded'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1555 'false',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1556 'hamburger collapses the destination menu',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1557 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1558 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1559 await mobilePage.locator('mjj-jrpg-menu')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1560 .getAttribute('data-mobile-menu-collapsed'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1561 '',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1562 'menu exposes its collapsed state',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1563 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1564 // Second click expands.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1565 await mobilePage.locator('[data-mobile-menu-toggle]').click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1566 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1567 await mobilePage.locator('[data-mobile-menu-toggle]')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1568 .getAttribute('aria-expanded'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1569 'true',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1570 'hamburger expands the destination menu',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1571 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1572 // Hamburger keyboard accessible
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1573 assert.ok(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1574 await mobilePage.locator('[data-mobile-menu-toggle]').evaluate(el =>
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1575 el.tabIndex >= 0 || el.tabIndex === -1
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1576 ),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1577 'hamburger button is in document',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1578 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1579 await mobileContext.close();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1580
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1581 // Test at 390x844
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1582 const mobile390Context = await browser.newContext({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1583 colorScheme: 'light',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1584 viewport: { width: 390, height: 844 },
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1585 });
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1586 const mobile390Page = await mobile390Context.newPage();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1587 await mobile390Page.goto(`${baseUrl}/jrpg`, { waitUntil: 'networkidle' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1588 const mobile390 = await mobile390Page.evaluate(() => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1589 const workspace = document.querySelector('.jrpg-workspace')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1590 .getBoundingClientRect();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1591 const shell = document.querySelector('.jrpg-shell').getBoundingClientRect();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1592 const mobileArt = getComputedStyle(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1593 document.querySelector('.jrpg-workspace'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1594 ).backgroundImage;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1595 return {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1596 fillsViewport: shell.left === 0 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1597 shell.top === 0 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1598 Math.abs(shell.right - innerWidth) < 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1599 Math.abs(shell.bottom - innerHeight) < 1,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1600 mobileArtIsCorrect: mobileArt.includes('background-frame-mobile.webp'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1601 noOverflow: document.documentElement.scrollWidth <= innerWidth,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1602 workspaceFills: Math.abs(workspace.left) < 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1603 Math.abs(workspace.top) < 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1604 Math.abs(workspace.right - innerWidth) < 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1605 Math.abs(workspace.bottom - innerHeight) < 1,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1606 };
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1607 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1608 assert.equal(mobile390.fillsViewport, true, 'fills viewport at 390x844');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1609 assert.equal(mobile390.mobileArtIsCorrect, true, 'mobile art at 390x844');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1610 assert.equal(mobile390.noOverflow, true, 'no overflow at 390x844');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1611 assert.equal(mobile390.workspaceFills, true, 'workspace fills at 390x844');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1612 await mobile390Context.close();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1613
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1614 // Test at 320x568 (narrow)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1615 const mobile320Context = await browser.newContext({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1616 colorScheme: 'light',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1617 viewport: { width: 320, height: 568 },
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1618 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1619 const mobile320Page = await mobile320Context.newPage();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1620 await mobile320Page.goto(`${baseUrl}/jrpg`, { waitUntil: 'networkidle' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1621 const mobile320 = await mobile320Page.evaluate(() => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1622 const workspace = document.querySelector('.jrpg-workspace')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1623 .getBoundingClientRect();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1624 const shell = document.querySelector('.jrpg-shell').getBoundingClientRect();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1625 const composer = document.querySelector('mjj-jrpg-composer')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1626 .getBoundingClientRect();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1627 const menu = document.querySelector('mjj-jrpg-menu').getBoundingClientRect();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1628 const mobileArt = getComputedStyle(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1629 document.querySelector('.jrpg-workspace'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1630 ).backgroundImage;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1631 return {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1632 composerPresent: composer.width > 0 && composer.height > 0,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1633 fillsViewport: shell.left === 0 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1634 shell.top === 0 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1635 Math.abs(shell.right - innerWidth) < 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1636 Math.abs(shell.bottom - innerHeight) < 1,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1637 menuPresent: menu.width > 0 && menu.height > 0,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1638 mobileArtIsCorrect: mobileArt.includes('background-frame-mobile.webp'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1639 noOverflow: document.documentElement.scrollWidth <= innerWidth,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1640 workspaceFills: Math.abs(workspace.left) < 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1641 Math.abs(workspace.top) < 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1642 Math.abs(workspace.right - innerWidth) < 1 &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1643 Math.abs(workspace.bottom - innerHeight) < 1,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1644 };
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1645 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1646 assert.equal(mobile320.composerPresent, true, 'composer present at 320x568');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1647 assert.equal(mobile320.fillsViewport, true, 'fills viewport at 320x568');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1648 assert.equal(mobile320.menuPresent, true, 'menu present at 320x568');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1649 assert.equal(mobile320.mobileArtIsCorrect, true, 'mobile art at 320x568');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1650 assert.equal(mobile320.noOverflow, true, 'no overflow at 320x568');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1651 assert.equal(mobile320.workspaceFills, true, 'workspace fills at 320x568');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1652 await mobile320Context.close();
263
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1653
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1654 const shortContext = await browser.newContext({
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1655 colorScheme: 'dark',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1656 viewport: { width: 900, height: 500 },
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1657 });
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1658 const shortPage = await shortContext.newPage();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1659 await shortPage.goto(`${baseUrl}/jrpg`, { waitUntil: 'networkidle' });
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1660 const shortLayout = await shortPage.evaluate(() => {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1661 const scene = document.querySelector('.jrpg-scene').getBoundingClientRect();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1662 const character = document.querySelector('mjj-jrpg-character')
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1663 .getBoundingClientRect();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1664 const chat = document.querySelector('mjj-jrpg-chat')
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1665 .getBoundingClientRect();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1666 return {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1667 characterInside: character.left >= scene.left &&
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1668 character.right <= scene.right,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1669 chatInside: chat.left >= scene.left && chat.right <= scene.right,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1670 noSceneOverflow: document.querySelector('.jrpg-scene').scrollWidth <=
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1671 document.querySelector('.jrpg-scene').clientWidth,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1672 };
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1673 });
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1674 assert.deepEqual(shortLayout, {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1675 characterInside: true,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1676 chatInside: true,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1677 noSceneOverflow: true,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1678 });
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1679 await shortContext.close();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1680
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1681 const forcedColorsContext = await browser.newContext({
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1682 forcedColors: 'active',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1683 viewport: { width: 1280, height: 900 },
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1684 });
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1685 const forcedColorsPage = await forcedColorsContext.newPage();
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1686 await forcedColorsPage.goto(`${baseUrl}/jrpg`, { waitUntil: 'networkidle' });
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1687 assert.deepEqual(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1688 await forcedColorsPage.evaluate(() => ({
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1689 sceneBar: getComputedStyle(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1690 document.querySelector('.jrpg-scene'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1691 '::before',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1692 ).backgroundImage,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1693 workspace: getComputedStyle(
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1694 document.querySelector('.jrpg-workspace'),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1695 ).backgroundImage,
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1696 })),
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1697 {
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1698 sceneBar: 'none',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1699 workspace: 'none',
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1700 },
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1701 );
ee04e4e69fed Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 262
diff changeset
1702 await forcedColorsContext.close();
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1703 }
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
1704
242
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1705 async function testHlsPlayer(browser, siteRoot) {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1706 const page = await browser.newPage();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1707 const errors = [];
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1708 const mediaRequests = [];
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1709 let testingExpectedFailure = false;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1710 let testingExpectedReload = false;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1711 page.on('pageerror', error => errors.push(`pageerror: ${error.message}`));
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1712 page.on('console', message => {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1713 if (message.type() !== 'error') return;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1714 if (testingExpectedFailure &&
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1715 message.text().startsWith('Failed to load resource:')) return;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1716 errors.push(`console: ${message.text()}`);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1717 });
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1718 page.on('requestfailed', request => {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1719 if (testingExpectedReload &&
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1720 request.failure()?.errorText === 'net::ERR_ABORTED') return;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1721 errors.push(`requestfailed: ${request.url()} ${request.failure()?.errorText || ''}`);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1722 });
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1723 page.on('request', request => {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1724 if (/\.(?:m3u8|m4s|mp4)(?:\?|$)/.test(request.url())) {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1725 mediaRequests.push(request.url());
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1726 }
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1727 });
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1728
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1729 const playlistResponse = await fetch(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1730 `${baseUrl}/public/hls-sample/master.m3u8`,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1731 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1732 assert.equal(playlistResponse.status, 200);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1733 assert.match(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1734 playlistResponse.headers.get('content-type') || '',
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1735 /^application\/vnd\.apple\.mpegurl/,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1736 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1737 assert.match(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1738 await playlistResponse.text(),
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1739 /#EXT-X-STREAM-INF:.*CODECS="vp09\.00\.10\.08,opus"/,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1740 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1741
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1742 const variantResponse = await fetch(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1743 `${baseUrl}/public/hls-sample/vp9-stream.m3u8`,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1744 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1745 assert.equal(variantResponse.status, 200);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1746 assert.match(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1747 await variantResponse.text(),
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1748 /#EXT-X-MAP:URI="vp9-init\.mp4"/,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1749 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1750
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1751 const segmentResponse = await fetch(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1752 `${baseUrl}/public/hls-sample/vp9-segment000.m4s`,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1753 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1754 assert.equal(segmentResponse.status, 200);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1755 assert.match(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1756 segmentResponse.headers.get('content-type') || '',
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1757 /^video\/iso\.segment/,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1758 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1759 const transportStreamResponse = await fetch(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1760 `${baseUrl}/public/hls-sample/h264-ts-segment000.ts`,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1761 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1762 assert.equal(transportStreamResponse.status, 200);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1763 assert.match(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1764 transportStreamResponse.headers.get('content-type') || '',
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1765 /^video\/mp2t/,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1766 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1767 assert.ok((await transportStreamResponse.arrayBuffer()).byteLength > 0);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1768
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1769 await page.goto(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1770 `${baseUrl}/tools/hls_player?url=${encodeURIComponent('/public/hls-sample/master.m3u8')}`,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1771 {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1772 waitUntil: 'networkidle',
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1773 },
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1774 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1775 await page.getByRole('button', { name: 'Sample', exact: true }).waitFor();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1776 assert.equal(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1777 await page.locator('#hlsUrl').evaluate(input => input.defaultValue),
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1778 '/public/hls-sample/h264-ts-stream.m3u8',
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1779 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1780 await page.waitForFunction(() => {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1781 const status = document.querySelector('#hlsStatus');
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1782 return status?.dataset.state === 'ready' ||
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1783 status?.dataset.state === 'error';
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1784 }, null, { timeout: 15000 });
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1785 const terminalState = await page.locator('#hlsStatus').getAttribute('data-state');
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1786 if (terminalState !== 'ready') {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1787 throw new Error(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1788 `HLS player failed: ${await page.locator('#hlsStatus').textContent()}\n${errors.join('\n')}`,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1789 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1790 }
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1791 assert.match(await page.locator('#hlsStatus').textContent(), /Stream ready/);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1792 assert.equal(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1793 await page.locator('[data-detail="mode"]').textContent(),
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1794 'hls.js',
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1795 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1796 assert.match(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1797 await page.locator('[data-detail="segments"]').textContent(),
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1798 /Managed by hls\.js|adaptive levels/,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1799 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1800 await page.waitForFunction(() => {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1801 const video = document.querySelector('#hlsVideo');
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1802 return video.readyState >= HTMLMediaElement.HAVE_METADATA &&
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1803 Number.isFinite(video.duration) &&
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1804 video.duration >= 14;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1805 });
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1806 const firstFrame = await page.locator('#hlsVideo').evaluate(video => {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1807 const canvas = document.createElement('canvas');
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1808 canvas.width = video.videoWidth;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1809 canvas.height = video.videoHeight;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1810 const context = canvas.getContext('2d');
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1811 context.drawImage(video, 0, 0);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1812 const pixels = context.getImageData(0, 0, canvas.width, canvas.height).data;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1813 let total = 0;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1814 for (let index = 0; index < pixels.length; index += 4) {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1815 total += pixels[index] + pixels[index + 1] + pixels[index + 2];
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1816 }
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1817 return total / (canvas.width * canvas.height * 3);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1818 });
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1819 assert.ok(firstFrame > 10, `Initial HLS frame is black: ${firstFrame}`);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1820 await page.locator('#hlsVideo').evaluate(video => video.play());
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1821 await page.waitForFunction(() => document.querySelector('#hlsVideo').currentTime > 0.2);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1822 await page.locator('#hlsVideo').evaluate(video => video.pause());
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1823 assert.ok(mediaRequests.some(url => url.endsWith('/hls-sample/master.m3u8')));
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1824 assert.ok(mediaRequests.some(url => url.endsWith('-stream.m3u8')));
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1825 assert.ok(mediaRequests.some(url => url.endsWith('-init.mp4')));
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1826 assert.ok(mediaRequests.some(url => /-segment\d+\.m4s$/.test(url)));
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1827
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1828 await page.evaluate(() => {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1829 window.hlsPlayer.hls.trigger(window.Hls.Events.ERROR, {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1830 fatal: true,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1831 type: window.Hls.ErrorTypes.MEDIA_ERROR,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1832 details: 'testRuntimeFailure',
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1833 error: new Error('runtime segment failed'),
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1834 });
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1835 });
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1836 await page.locator('#hlsStatus[data-state="error"]').waitFor();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1837 assert.match(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1838 await page.locator('#hlsStatus').textContent(),
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1839 /runtime segment failed/,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1840 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1841 await page.locator('#hlsUrl').fill('/public/hls-sample/master.m3u8');
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1842 await page.getByRole('button', { name: 'Load', exact: true }).click();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1843 await page.locator('#hlsStatus[data-state="ready"]').waitFor();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1844
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1845 let delayedSegment = true;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1846 await page.route('**/hls-sample/vp9-segment000.m4s', async route => {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1847 if (delayedSegment) {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1848 delayedSegment = false;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1849 await new Promise(resolve => setTimeout(resolve, 250));
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1850 }
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1851 await route.continue();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1852 });
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1853 testingExpectedReload = true;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1854 await page.locator('#hlsUrl').fill('/public/hls-sample/master.m3u8');
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1855 await page.getByRole('button', { name: 'Load', exact: true }).click();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1856 await page.waitForTimeout(25);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1857 await page.getByRole('button', { name: 'Load', exact: true }).click();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1858 await page.locator('#hlsStatus[data-state="ready"]').waitFor();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1859 testingExpectedReload = false;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1860 assert.match(await page.locator('#hlsStatus').textContent(), /Stream ready/);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1861
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1862 await page.evaluate(() => {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1863 window.__hlsObjectUrls = { created: [], revoked: [] };
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1864 const createObjectURL = URL.createObjectURL.bind(URL);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1865 const revokeObjectURL = URL.revokeObjectURL.bind(URL);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1866 URL.createObjectURL = value => {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1867 const url = createObjectURL(value);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1868 window.__hlsObjectUrls.created.push(url);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1869 return url;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1870 };
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1871 URL.revokeObjectURL = url => {
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1872 window.__hlsObjectUrls.revoked.push(url);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1873 revokeObjectURL(url);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1874 };
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1875 });
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1876 const localFiles = listFiles(path.join(siteRoot, 'public/hls-sample'));
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1877 await page.locator('#hlsFiles').setInputFiles(localFiles);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1878 await page.waitForFunction(() =>
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1879 document.querySelector('#hlsUrl')?.value.startsWith('Local: ')
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1880 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1881 await page.locator('#hlsStatus[data-state="ready"]').waitFor();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1882 assert.match(await page.locator('#hlsUrl').inputValue(), /^Local: /);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1883 assert.equal(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1884 await page.locator('[data-detail="mode"]').textContent(),
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1885 'hls.js',
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1886 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1887 await page.locator('#hlsVideo').evaluate(video => video.play());
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1888 await page.waitForFunction(() => document.querySelector('#hlsVideo').currentTime > 0.3);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1889 await page.locator('#hlsVideo').evaluate(video => video.pause());
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1890 const incompleteLocalFiles = localFiles.filter(file =>
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1891 file.endsWith('master.m3u8') ||
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1892 file.endsWith('vp9-stream.m3u8')
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1893 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1894 await page.locator('#hlsFiles').setInputFiles(incompleteLocalFiles);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1895 await page.locator('#hlsStatus[data-state="error"]').waitFor();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1896 assert.match(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1897 await page.locator('#hlsStatus').textContent(),
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1898 /Local HLS file is missing/,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1899 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1900 const objectUrlCounts = await page.evaluate(() => ({
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1901 created: window.__hlsObjectUrls.created.length,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1902 revoked: window.__hlsObjectUrls.revoked.length,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1903 }));
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1904 assert.ok(objectUrlCounts.created > 10, JSON.stringify(objectUrlCounts));
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1905 assert.ok(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1906 objectUrlCounts.revoked >= objectUrlCounts.created,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1907 JSON.stringify(objectUrlCounts),
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1908 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1909
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1910 await page.route('**/invalid.m3u8', route => route.fulfill({
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1911 status: 404,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1912 body: 'not found',
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1913 }));
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1914 testingExpectedFailure = true;
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1915 await page.locator('#hlsUrl').fill(`${baseUrl}/invalid.m3u8`);
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1916 await page.getByRole('button', { name: 'Load', exact: true }).click();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1917 await page.locator('#hlsStatus[data-state="error"]').waitFor();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1918 assert.match(
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1919 await page.locator('#hlsStatus').textContent(),
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1920 /404|manifestLoadError|Playlist request failed/,
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1921 );
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1922
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1923 if (errors.length) throw new Error(errors.join('\n'));
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1924 await page.close();
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1925 }
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
1926
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1927 function findFreePort() {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1928 return new Promise((resolve, reject) => {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1929 const socket = net.createServer();
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1930 socket.once('error', reject);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1931 socket.listen(0, '127.0.0.1', () => {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1932 const address = socket.address();
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1933 socket.close(error => {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1934 if (error) reject(error);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1935 else resolve(String(address.port));
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1936 });
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1937 });
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1938 });
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1939 }
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1940
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1941 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1942 /* Conversation URL routing regression tests (Fixes 1–4) */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1943 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
1944
265
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1945 async function testRoleGreetings(browser) {
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1946 const cases = [
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1947 {
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1948 name: 'guest',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1949 session: {
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1950 kind: 'guest',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1951 csrfToken: 'guest-greeting-csrf',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1952 quota: null,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1953 },
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1954 expected: 'Hi, my name is Epi. June usually calls me Epi-chan.',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1955 },
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1956 {
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1957 name: 'invited',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1958 session: {
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1959 kind: 'user',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1960 username: 'friend',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1961 role: 'member',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1962 mustChangePassword: false,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1963 csrfToken: 'friend-greeting-csrf',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1964 quota: null,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1965 },
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1966 expected: 'Since June invited you, I can be a little more casual.',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1967 },
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1968 {
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1969 name: 'admin',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1970 session: {
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1971 kind: 'user',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1972 username: 'june',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1973 role: 'admin',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1974 mustChangePassword: false,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1975 csrfToken: 'admin-greeting-csrf',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1976 quota: null,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1977 },
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1978 expected: 'Hi June! I’m Epi-chan.',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1979 },
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1980 ];
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1981
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1982 for (const testCase of cases) {
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1983 const context = await browser.newContext({ serviceWorkers: 'block' });
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1984 const page = await context.newPage();
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1985 await page.route('**/api/auth/session', route => route.fulfill({
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1986 status: 200,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1987 contentType: 'application/json',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1988 body: JSON.stringify(testCase.session),
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1989 }));
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1990 await page.route('**/api/conversations**', route => route.fulfill({
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1991 status: 200,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1992 contentType: 'application/json',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1993 body: JSON.stringify({ conversations: [], cursor: null }),
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1994 }));
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1995 await page.goto(`${baseUrl}/jrpg`, { waitUntil: 'domcontentloaded' });
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1996 const greeting = page.locator('[data-greeting]');
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1997 await greeting.waitFor({ state: 'visible' });
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1998 if (testCase.name === 'guest') {
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
1999 await page.locator('[data-greeting][data-streaming="true"]').waitFor({
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2000 state: 'visible',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2001 });
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2002 }
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2003 await page.waitForFunction(() => {
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2004 const item = document.querySelector('[data-greeting]');
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2005 return item && !item.hasAttribute('data-streaming');
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2006 });
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2007 assert.match(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2008 await greeting.locator('p').textContent(),
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2009 new RegExp(testCase.expected.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')),
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2010 `${testCase.name} receives its role-specific Epi greeting`,
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2011 );
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2012 await context.close();
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2013 }
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2014 }
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2015
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2016 async function testConversationRouting(browser) {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2017 const CONV_A = 'aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2018 const CONV_B = 'bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2019 const GUEST_SESSION = {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2020 kind: 'guest', csrfToken: 'test-csrf',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2021 quota: {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2022 turnsLimit: 10, turnsUsed: 0, turnsRemaining: 10,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2023 outputTokensLimit: 10000, outputTokensUsed: 0,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2024 outputTokensReserved: 0, outputTokensRemaining: 10000,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2025 resetsAt: Math.floor(Date.now() / 1000) + 86400,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2026 },
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2027 };
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2028
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2029 /* ---- Fix 3: malformed ?conversation param must not fall back to sessionStorage ---- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2030 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2031 const storedId = 'cccccccc-cccc-4ccc-8ccc-cccccccccccc';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2032 const context = await browser.newContext({ serviceWorkers: 'block' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2033 await context.addInitScript(id => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2034 sessionStorage.setItem('mjj-jrpg-conversation-id', id);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2035 }, storedId);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2036 const page = await context.newPage();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2037 const storedIdFetched = [];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2038 await page.route('**/api/auth/session', route => route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2039 status: 200, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2040 body: JSON.stringify(GUEST_SESSION),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2041 }));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2042 await page.route('**/api/conversations**', route => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2043 const url = new URL(route.request().url());
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2044 if (url.pathname.endsWith(`/${storedId}`)) {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2045 storedIdFetched.push(route.request().url());
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2046 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2047 if (url.pathname === '/api/conversations') {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2048 return route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2049 status: 200, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2050 body: JSON.stringify({ conversations: [], cursor: null }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2051 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2052 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2053 return route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2054 status: 404, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2055 body: JSON.stringify({ error: { message: 'Not found' } }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2056 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2057 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2058 await page.route('**/api/conversations/claim', route => route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2059 status: 503,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2060 contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2061 body: JSON.stringify({ error: { message: 'Service unavailable' } }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2062 }));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2063 await page.goto(`${baseUrl}/jrpg?conversation=not-a-valid-uuid`, {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2064 waitUntil: 'networkidle',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2065 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2066 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2067 storedIdFetched.length, 0,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2068 'Fix 3: malformed ?conversation param must not trigger sessionStorage fallback',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2069 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2070 await context.close();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2071 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2072
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2073 /* ---- Fix 4: legacy claim: key retained on 5xx, button re-renders and re-fires ---- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2074 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2075 const legacyStoredId = 'dddddddd-dddd-4ddd-8ddd-dddddddddddd';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2076 const context = await browser.newContext({ serviceWorkers: 'block' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2077 /* Seed CONVERSATION_STORAGE_KEY so init migrates it to CONVERSATION_LEGACY_KEY */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2078 await context.addInitScript(id => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2079 sessionStorage.setItem('mjj-jrpg-conversation-id', id);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2080 }, legacyStoredId);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2081 const page = await context.newPage();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2082 const pageErrors = [];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2083 page.on('pageerror', e => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2084 if (!e.message.startsWith('Failed to load resource:')) {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2085 pageErrors.push(`pageerror: ${e.message}`);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2086 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2087 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2088 await page.route('**/api/auth/session', route => route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2089 status: 200, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2090 body: JSON.stringify({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2091 kind: 'user', username: 'tester', role: 'member',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2092 csrfToken: 'test-csrf', quota: null,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2093 }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2094 }));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2095 await page.route('**/api/conversations**', route => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2096 const url = new URL(route.request().url());
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2097 const req = route.request();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2098 if (url.pathname === '/api/conversations' && req.method() === 'GET') {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2099 return route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2100 status: 200, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2101 body: JSON.stringify({ conversations: [], cursor: null }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2102 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2103 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2104 if (url.pathname === `/api/conversations/${legacyStoredId}` && req.method() === 'GET') {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2105 return route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2106 status: 404, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2107 body: JSON.stringify({ error: { message: 'Not found' } }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2108 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2109 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2110 if (url.pathname === '/api/conversations/claim' && req.method() === 'POST') {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2111 return route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2112 status: 503, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2113 body: JSON.stringify({ error: { message: 'Service unavailable' } }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2114 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2115 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2116 return route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2117 status: 404, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2118 body: JSON.stringify({ error: { message: 'Not found' } }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2119 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2120 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2121 await page.route('**/api/conversations/claim', route => route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2122 status: 503,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2123 contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2124 body: JSON.stringify({ error: { message: 'Service unavailable' } }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2125 }));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2126 await page.goto(`${baseUrl}/jrpg`, { waitUntil: 'networkidle' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2127
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2128 /* Open archive panel so the legacy claim status is visible */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2129 await page.locator('button[data-preview="conversations"]').click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2130 await page.locator('mjj-conversation-archive').waitFor({ state: 'visible' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2131
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2132 /* Init should have called showLegacyClaim() — wait for the button */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2133 await page.waitForFunction(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2134 () => document.querySelector('[data-archive-claim]') !== null,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2135 null, { timeout: 5000 },
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2136 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2137
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2138 /* First claim attempt — returns 503 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2139 const firstClaimResponse = page.waitForResponse(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2140 response => response.url().includes('/api/conversations/claim'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2141 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2142 await page.locator('[data-archive-claim]').click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2143 const firstClaimStatus = (await firstClaimResponse).status();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2144 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2145 firstClaimStatus,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2146 503,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2147 `claim fixture returns the mocked service failure, got ${firstClaimStatus}`,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2148 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2149
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2150 /* Wait for the retry state to appear: showLegacyClaim re-rendered with error msg */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2151 await page.waitForFunction(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2152 () => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2153 const status = document.querySelector('[data-archive-status]');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2154 return status && !status.hidden && status.textContent.includes('Claim failed');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2155 },
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2156 null, { timeout: 5000 },
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2157 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2158
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2159 /* Key must be retained in sessionStorage on 5xx */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2160 const keyAfterFail = await page.evaluate(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2161 () => sessionStorage.getItem('mjj-jrpg-legacy-claim'),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2162 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2163 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2164 keyAfterFail, legacyStoredId,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2165 'Fix 4: CONVERSATION_LEGACY_KEY must be retained after 5xx failure',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2166 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2167
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2168 /* Button must be present and enabled for retry */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2169 await page.locator('[data-archive-claim]').waitFor({ state: 'visible' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2170
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2171 /* Tag the current button so we can detect when it's replaced by a second re-render */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2172 await page.locator('[data-archive-claim]').evaluate(btn => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2173 btn.dataset.claimGen = '1';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2174 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2175
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2176 /* Second click: must dispatch event again — proves no {once:true} on button */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2177 await page.locator('[data-archive-claim]').click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2178
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2179 /* Wait for the button to be replaced (showLegacyClaim called again = handler ran) */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2180 await page.waitForFunction(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2181 () => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2182 const btn = document.querySelector('[data-archive-claim]');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2183 return btn !== null && btn.dataset.claimGen !== '1';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2184 },
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2185 null, { timeout: 5000 },
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2186 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2187
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2188 assert.deepEqual(pageErrors, [], 'no page errors in legacy claim test');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2189 await context.close();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2190 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2191
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2192 /* ---- Fix 1: popstate during active stream converges URL and UI ---- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2193 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2194 let releaseStream = () => {};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2195 const streamGate = new Promise(resolve => { releaseStream = resolve; });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2196
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2197 const context = await browser.newContext();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2198 const page = await context.newPage();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2199 const pageErrors = [];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2200 page.on('pageerror', e => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2201 if (!e.message.startsWith('Failed to load resource:')) {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2202 pageErrors.push(`pageerror: ${e.message}`);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2203 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2204 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2205 /* Suppress expected abort-network errors from the held-then-aborted stream */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2206 page.on('requestfailed', request => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2207 if (request.failure()?.errorText === 'net::ERR_ABORTED') return;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2208 pageErrors.push(`requestfailed: ${request.url()} ${request.failure()?.errorText || ''}`);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2209 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2210
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2211 await page.route('**/api/auth/session', route => route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2212 status: 200, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2213 body: JSON.stringify(GUEST_SESSION),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2214 }));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2215 await page.route('**/api/conversations**', async route => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2216 const url = new URL(route.request().url());
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2217 const req = route.request();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2218 if (url.pathname === '/api/conversations' && req.method() === 'GET') {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2219 return route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2220 status: 200, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2221 body: JSON.stringify({ conversations: [], cursor: null }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2222 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2223 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2224 if (url.pathname === '/api/conversations' && req.method() === 'POST') {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2225 return route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2226 status: 201, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2227 body: JSON.stringify({ id: CONV_A }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2228 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2229 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2230 if (url.pathname.endsWith('/turns') && req.method() === 'POST') {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2231 /* Hold the SSE stream until the test releases it */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2232 await streamGate;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2233 try { await route.abort(); } catch { /* request may already be aborted */ }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2234 return;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2235 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2236 return route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2237 status: 404, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2238 body: JSON.stringify({ error: { message: 'Not found' } }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2239 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2240 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2241
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2242 await page.goto(`${baseUrl}/jrpg`, { waitUntil: 'networkidle' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2243 await page.waitForFunction(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2244 () => !document.querySelector('mjj-jrpg-composer textarea')?.disabled,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2245 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2246
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2247 /* Submit — creates conversation via pushState and starts stream */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2248 await page.locator('#jrpg-message').fill('routing race test');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2249 await page.locator('#jrpg-message').press('Enter');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2250
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2251 /* Stream is now active */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2252 await page.locator('[data-cancel-control]').waitFor({ state: 'visible' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2253
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2254 const urlDuringStream = page.url();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2255 assert.ok(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2256 urlDuringStream.includes('conversation='),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2257 `Fix 1: URL must have ?conversation during stream: ${urlDuringStream}`,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2258 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2259
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2260 /* Navigate back while stream is active — URL already changes here */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2261 await page.goBack();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2262
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2263 /* Stream abort + pending-popstate application: cancel control disappears */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2264 await page.locator('[data-cancel-control]').waitFor({ state: 'hidden' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2265
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2266 /* URL and UI must converge to the pre-stream state */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2267 const finalUrl = page.url();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2268 assert.ok(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2269 !finalUrl.includes('conversation='),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2270 `Fix 1: URL must not have ?conversation after popstate back: ${finalUrl}`,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2271 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2272 assert.equal(
265
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2273 await page.locator(
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2274 '.jrpg-message[data-streaming="true"]:not([data-greeting])',
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2275 ).count(),
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2276 0,
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2277 'Fix 1: no streaming message must remain after popstate back',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2278 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2279
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2280 releaseStream(); /* clean up the held route */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2281 assert.deepEqual(pageErrors, [], 'no page errors in popstate-during-stream test');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2282 await context.close();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2283 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2284
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2285 /* ---- Fix 2: openSeq incremented on no-conv popstate, invalidates pending open ---- */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2286 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2287 let resolveConvBFetch = () => {};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2288 const convBFetchGate = new Promise(resolve => { resolveConvBFetch = resolve; });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2289
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2290 const context = await browser.newContext();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2291 const page = await context.newPage();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2292 const pageErrors = [];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2293 page.on('pageerror', e => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2294 if (!e.message.startsWith('Failed to load resource:')) {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2295 pageErrors.push(`pageerror: ${e.message}`);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2296 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2297 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2298
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2299 await page.route('**/api/auth/session', route => route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2300 status: 200, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2301 body: JSON.stringify(GUEST_SESSION),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2302 }));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2303 await page.route('**/api/conversations**', async route => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2304 const url = new URL(route.request().url());
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2305 const req = route.request();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2306 /* Empty archive: no auto-open, no gate deadlock */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2307 if (url.pathname === '/api/conversations' && req.method() === 'GET') {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2308 return route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2309 status: 200, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2310 body: JSON.stringify({ conversations: [], cursor: null }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2311 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2312 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2313 /* The archive-open click will trigger this; hold it with the gate */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2314 if (url.pathname === `/api/conversations/${CONV_B}` && req.method() === 'GET') {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2315 await convBFetchGate;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2316 return route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2317 status: 200, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2318 body: JSON.stringify({ id: CONV_B, title: 'Conv B', turns: [] }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2319 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2320 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2321 return route.fulfill({
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2322 status: 404, contentType: 'application/json',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2323 body: JSON.stringify({ error: { message: 'Not found' } }),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2324 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2325 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2326
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2327 /* Empty archive so init completes without auto-opening any conversation */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2328 await page.goto(`${baseUrl}/jrpg`, { waitUntil: 'networkidle' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2329
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2330 /* Open archive panel — this pushes a history entry (conversations panel) */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2331 await page.locator('button[data-preview="conversations"]').click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2332 await page.locator('mjj-conversation-archive').waitFor({ state: 'visible' });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2333
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2334 /* Inject Conv B into the archive list without triggering an API fetch */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2335 await page.evaluate(id => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2336 document.querySelector('mjj-conversation-archive')
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2337 ?.addConversation({ id, title: 'Conv B', turn_count: 0 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2338 }, CONV_B);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2339
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2340 await page.waitForFunction(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2341 id => [...document.querySelectorAll('[data-conv-item]')]
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2342 .some(item => item._convId === id),
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2343 CONV_B,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2344 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2345
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2346 /* Click Conv B — archive-open fires, fetch held by convBFetchGate */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2347 await page.evaluate(id => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2348 for (const item of document.querySelectorAll('[data-conv-item]')) {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2349 if (item._convId === id) {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2350 item.querySelector('[data-conv-open]')?.click();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2351 break;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2352 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2353 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2354 }, CONV_B);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2355
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2356 /* Brief pause so archive-open can increment openSeq and start the fetch */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2357 await page.waitForTimeout(80);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2358
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2359 /* Navigate back — popstate fires with no-conv state, openSeq is incremented */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2360 await page.goBack();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2361 await page.waitForTimeout(80);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2362
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2363 /* Release the held fetch — the archive-open handler should ignore it */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2364 resolveConvBFetch();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2365 await page.waitForTimeout(300);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2366
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2367 /* currentConversationId must remain null (no aria-current item) */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2368 const currentAriaItem = await page.evaluate(() => {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2369 const btn = document.querySelector('[data-conv-open][aria-current="true"]');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2370 return btn ? (btn.closest('[data-conv-item]')?._convId ?? null) : null;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2371 });
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2372 assert.equal(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2373 currentAriaItem, null,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2374 'Fix 2: pending archive-open must not overwrite no-conv popstate',
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2375 );
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2376
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2377 assert.deepEqual(pageErrors, [], 'no page errors in openSeq test');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2378 await context.close();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2379 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2380 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2381
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2382 (async () => {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2383 assert.ok(RUNFILES);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2384 assert.ok(WORKSPACE);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2385 const runfilesWorkspace = path.join(RUNFILES, WORKSPACE);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2386 const serverBinary = path.join(
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2387 runfilesWorkspace,
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
2388 'mrjunejune/mrjunejune_server_debug',
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2389 );
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2390 const siteRoot = path.join(runfilesWorkspace, 'mrjunejune/src');
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2391 const fakeSidecar = path.join(
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2392 runfilesWorkspace,
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2393 'mrjunejune/test/inference_bridge_fake_sidecar',
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2394 );
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2395 const tempDirectory = fs.mkdtempSync(
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2396 path.join(os.tmpdir(), 'mrjunejune-theme-test-'),
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2397 );
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2398 const chromiumPath = path.resolve(process.env.CHROMIUM_PATH);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2399 const serverLogs = [];
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2400 let server;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2401 let browser;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2402
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2403 try {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2404 port = await findFreePort();
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2405 baseUrl = `http://127.0.0.1:${port}`;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2406 const pngFiles = listFiles(siteRoot).filter(file => file.endsWith('.png'));
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2407 assert.deepEqual(pngFiles, [], `PNG files leaked into runfiles: ${pngFiles}`);
258
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2408 for (const file of listFiles(siteRoot).filter(file =>
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2409 file.endsWith('.html')
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2410 )) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2411 const source = fs.readFileSync(file, 'utf8');
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2412 for (const primitive of source.matchAll(/<zen-button\b([^>]*)>/g)) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2413 assert.match(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2414 primitive[1],
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2415 /\bsize=["'](?:xs|sm|md|lg|xl)["']/,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2416 `${path.relative(siteRoot, file)} has an unsized zen-button`,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2417 );
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2418 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2419 assert.deepEqual(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2420 primitiveOwnershipViolations(source),
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2421 [],
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2422 `${path.relative(siteRoot, file)} violates primitive ownership`,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2423 );
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2424 }
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2425 for (const file of listFiles(siteRoot).filter(file =>
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2426 /\.(?:css|html|js)$/.test(file) &&
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2427 !file.includes(`${path.sep}public${path.sep}design-system${path.sep}`)
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2428 )) {
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2429 const source = fs.readFileSync(file, 'utf8');
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2430 assert.doesNotMatch(
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2431 source,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2432 /var\(\s*--zen-/,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2433 `${path.relative(siteRoot, file)} consumes a deprecated token`,
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2434 );
60a876c4587a [ui] Add semantic primitive ownership
MrJuneJune <me@mrjunejune.com>
parents: 256
diff changeset
2435 }
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2436
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2437 server = spawn(serverBinary, [], {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2438 cwd: runfilesWorkspace,
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2439 env: {
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2440 ...process.env,
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2441 MRJUNEJUNE_PORT: port,
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2442 MRJUNEJUNE_DB_PATH: path.join(tempDirectory, 'site.db'),
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2443 MRJUNEJUNE_INFERENCE_SIDECAR_PATH: fakeSidecar,
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2444 MRJUNEJUNE_COPILOT_CLI_PATH: fakeSidecar,
265
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2445 MRJUNEJUNE_ALLOW_GUEST_INFERENCE: '1',
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2446 },
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2447 stdio: ['ignore', 'pipe', 'pipe'],
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2448 });
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2449 server.stdout.on('data', chunk => serverLogs.push(chunk.toString()));
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2450 server.stderr.on('data', chunk => serverLogs.push(chunk.toString()));
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2451 await waitForServer(server, serverLogs);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2452
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2453 const home = await (await fetch(baseUrl)).text();
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2454 const dogGame = await (
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2455 await fetch(`${baseUrl}/public/dog-game.js`)
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2456 ).text();
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2457 const manifest = await (
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2458 await fetch(`${baseUrl}/public/manifest.json`)
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2459 ).text();
242
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
2460 const serviceWorker = await (
256
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
2461 await fetch(`${baseUrl}/sw.js`)
242
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
2462 ).text();
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2463 for (const source of [home, dogGame, manifest]) {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2464 assert.doesNotMatch(source, /\.png(?:["')]|$)/i);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2465 }
265
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2466 assert.match(serviceWorker, /v35-role-greeting/);
256
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
2467 assert.match(
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
2468 await (
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
2469 await fetch(`${baseUrl}/public/pwa-register.js`)
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
2470 ).text(),
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
2471 /register\('\/sw\.js', \{ scope: '\/' \}\)/,
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
2472 );
242
543df0fe7168 [tools] Add full HLS player support
MrJuneJune <me@mrjunejune.com>
parents: 241
diff changeset
2473 assert.ok(serviceWorker.includes("startsWith('/tools/hls_player')"));
259
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
2474 assert.ok(serviceWorker.includes("url.hostname === 'localhost'"));
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
2475 assert.ok(serviceWorker.includes("url.hostname === '127.0.0.1'"));
667156fcd3e3 Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents: 258
diff changeset
2476 assert.ok(!serviceWorker.includes("startsWith('/jrpg')"));
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2477
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2478 for (const asset of [
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2479 'sprite_shiba0.webp',
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2480 'dog-treat.webp',
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2481 'start-large.webp',
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2482 'icon-192.webp',
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2483 'vscode.webp',
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2484 ]) {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2485 const response = await fetch(`${baseUrl}/public/${asset}`);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2486 assert.equal(response.status, 200, asset);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2487 assert.ok((await response.arrayBuffer()).byteLength > 0, asset);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2488 }
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2489
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2490 browser = await chromium.launch({
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2491 executablePath: chromiumPath,
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2492 headless: true,
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2493 args: ['--no-sandbox'],
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2494 });
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2495 if (runsSuite('core')) {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2496 const paper = await sampleTheme(browser, 'paper');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2497 const ink = await sampleTheme(browser, 'ink');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2498 const playful = await sampleTheme(browser, 'playful');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2499 const automatic = await sampleTheme(browser, 'auto');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2500 assert.equal(paper.rootTheme, 'paper');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2501 assert.equal(ink.rootTheme, 'ink');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2502 assert.equal(playful.rootTheme, 'playful');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2503 assert.equal(automatic.rootTheme, 'auto');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2504 assert.equal(paper.themeLabel, 'Paper');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2505 assert.equal(ink.themeLabel, 'Ink');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2506 assert.equal(playful.themeLabel, 'Playful');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2507 assert.equal(automatic.themeLabel, 'Auto');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2508 for (const sample of [paper, ink, playful, automatic]) {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2509 assert.ok(sample.count > 0);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2510 assert.equal(sample.backgroundRepeat, 'no-repeat');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2511 assert.equal(sample.backgroundSize, 'cover');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2512 assert.equal(sample.bodyCoversViewport, true);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2513 assert.equal(sample.componentReady, true);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2514 assert.ok(sample.links > 0);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2515 assert.equal(sample.enhancedLinks, sample.pawLinks);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2516 assert.match(sample.fontFamily, /More/);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2517 assert.equal(sample.headerPaws, 0);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2518 assert.ok(sample.textContrast >= 4.5, JSON.stringify(sample));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2519 assert.equal(sample.mainBackground, 'rgba(0, 0, 0, 0)');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2520 assert.equal(sample.themeButtonBackground, 'rgba(0, 0, 0, 0)');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2521 assert.equal(sample.themeButtonBorder, '0px');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2522 assert.equal(sample.themeButtonShadow, 'none');
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2523 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2524 assert.ok(paper.luminance < 175, JSON.stringify(paper));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2525 assert.ok(playful.luminance < 175, JSON.stringify(playful));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2526 assert.ok(ink.luminance > 200, JSON.stringify(ink));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2527 await testThemeCycle(browser);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2528 await testPlainField(browser);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2529 await testButtonScale(browser);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2530 await testDynamicButtonOwnership(browser);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2531 await testResumePrint(browser);
256
30c2196d03d4 [site] Integrate Zenbu themes and components
MrJuneJune <me@mrjunejune.com>
parents: 242
diff changeset
2532 }
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2533 if (runsSuite('jrpg')) await testJrpgPage(browser);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2534 if (runsSuite('routing')) await testConversationRouting(browser);
265
056790c4fb0d add role-aware Epi assistant prompts
MrJuneJune <me@mrjunejune.com>
parents: 264
diff changeset
2535 if (runsSuite('greeting')) await testRoleGreetings(browser);
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 263
diff changeset
2536 if (runsSuite('hls')) await testHlsPlayer(browser, siteRoot);
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2537 } finally {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2538 if (browser) await browser.close();
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2539 await stopProcess(server);
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents: 259
diff changeset
2540 fs.rmSync(tempDirectory, { recursive: true, force: true });
241
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2541 }
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2542 })().catch(error => {
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2543 console.error(error.stack || error);
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2544 process.exitCode = 1;
9c2eec61a152 [assets] Generate site images as WebP with Bazel
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2545 });