comparison mrjunejune/test/theme_and_webp_test.js @ 256:30c2196d03d4

[site] Integrate Zenbu themes and components Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Tue, 04 Aug 2026 16:49:01 -0700
parents 543df0fe7168
children 60a876c4587a
comparison
equal deleted inserted replaced
255:5ec271d612ae 256:30c2196d03d4
108 luminance += 108 luminance +=
109 data[index] * 0.2126 + 109 data[index] * 0.2126 +
110 data[index + 1] * 0.7152 + 110 data[index + 1] * 0.7152 +
111 data[index + 2] * 0.0722; 111 data[index + 2] * 0.0722;
112 } 112 }
113 const channels = value => value.match(/\d+(?:\.\d+)?/g)
114 .slice(0, 3)
115 .map(Number);
116 const colorLuminance = value => {
117 const converted = channels(value).map(channel => {
118 const normalized = channel / 255;
119 return normalized <= 0.04045
120 ? normalized / 12.92
121 : ((normalized + 0.055) / 1.055) ** 2.4;
122 });
123 return converted[0] * 0.2126 +
124 converted[1] * 0.7152 +
125 converted[2] * 0.0722;
126 };
127 const bodyStyle = getComputedStyle(document.body);
128 const foreground = colorLuminance(bodyStyle.color);
129 const background = colorLuminance(
130 getComputedStyle(document.querySelector('main')).backgroundColor,
131 );
113 return { 132 return {
133 cardCount: document.querySelectorAll('.site-link-grid zen-card').length,
134 componentReady: Boolean(customElements.get('zen-card')),
114 count, 135 count,
136 fontFamily: getComputedStyle(document.body).fontFamily,
115 luminance: count ? luminance / count : 0, 137 luminance: count ? luminance / count : 0,
116 rootClass: document.documentElement.className, 138 textContrast: (Math.max(foreground, background) + 0.05) /
139 (Math.min(foreground, background) + 0.05),
140 rootTheme: document.documentElement.dataset.zenTheme || 'auto',
141 themeLabel: document.querySelector('#themeName')?.textContent,
117 }; 142 };
118 }); 143 });
119 144
120 if (errors.length) throw new Error(`${theme}\n${errors.join('\n')}`); 145 if (errors.length) throw new Error(`${theme}\n${errors.join('\n')}`);
121 await context.close(); 146 await context.close();
122 return sample; 147 return sample;
148 }
149
150 async function testThemeCycle(browser) {
151 const context = await browser.newContext({ colorScheme: 'light' });
152 const page = await context.newPage();
153 await page.goto(baseUrl, { waitUntil: 'networkidle' });
154 const expected = ['paper', 'ink', 'playful', 'auto'];
155 for (const theme of expected) {
156 await page.locator('#themeToggle').click();
157 assert.equal(
158 await page.evaluate(() =>
159 document.documentElement.dataset.zenTheme || 'auto'
160 ),
161 theme,
162 );
163 assert.equal(
164 await page.evaluate(() => localStorage.getItem('theme-preference')),
165 theme,
166 );
167 }
168 await context.close();
123 } 169 }
124 170
125 async function testHlsPlayer(browser, siteRoot) { 171 async function testHlsPlayer(browser, siteRoot) {
126 const page = await browser.newPage(); 172 const page = await browser.newPage();
127 const errors = []; 173 const errors = [];
393 ).text(); 439 ).text();
394 const manifest = await ( 440 const manifest = await (
395 await fetch(`${baseUrl}/public/manifest.json`) 441 await fetch(`${baseUrl}/public/manifest.json`)
396 ).text(); 442 ).text();
397 const serviceWorker = await ( 443 const serviceWorker = await (
398 await fetch(`${baseUrl}/public/sw.js`) 444 await fetch(`${baseUrl}/sw.js`)
399 ).text(); 445 ).text();
400 for (const source of [home, dogGame, manifest]) { 446 for (const source of [home, dogGame, manifest]) {
401 assert.doesNotMatch(source, /\.png(?:["')]|$)/i); 447 assert.doesNotMatch(source, /\.png(?:["')]|$)/i);
402 } 448 }
403 assert.match(serviceWorker, /v4-hlsjs/); 449 assert.match(serviceWorker, /v5-zenbu-themes/);
450 assert.match(
451 await (
452 await fetch(`${baseUrl}/public/pwa-register.js`)
453 ).text(),
454 /register\('\/sw\.js', \{ scope: '\/' \}\)/,
455 );
404 assert.ok(serviceWorker.includes("startsWith('/tools/hls_player')")); 456 assert.ok(serviceWorker.includes("startsWith('/tools/hls_player')"));
405 457
406 for (const asset of [ 458 for (const asset of [
407 'sprite_shiba0.webp', 459 'sprite_shiba0.webp',
408 'dog-treat.webp', 460 'dog-treat.webp',
418 browser = await chromium.launch({ 470 browser = await chromium.launch({
419 executablePath: chromiumPath, 471 executablePath: chromiumPath,
420 headless: true, 472 headless: true,
421 args: ['--no-sandbox'], 473 args: ['--no-sandbox'],
422 }); 474 });
423 const light = await sampleTheme(browser, 'light'); 475 const paper = await sampleTheme(browser, 'paper');
424 const dark = await sampleTheme(browser, 'dark'); 476 const ink = await sampleTheme(browser, 'ink');
425 assert.ok(light.count > 0); 477 const playful = await sampleTheme(browser, 'playful');
426 assert.ok(dark.count > 0); 478 const automatic = await sampleTheme(browser, 'auto');
427 assert.ok(light.luminance < 175, JSON.stringify(light)); 479 assert.equal(paper.rootTheme, 'paper');
428 assert.ok(dark.luminance > 200, JSON.stringify(dark)); 480 assert.equal(ink.rootTheme, 'ink');
481 assert.equal(playful.rootTheme, 'playful');
482 assert.equal(automatic.rootTheme, 'auto');
483 assert.equal(paper.themeLabel, 'Paper');
484 assert.equal(ink.themeLabel, 'Ink');
485 assert.equal(playful.themeLabel, 'Playful');
486 assert.equal(automatic.themeLabel, 'Auto');
487 for (const sample of [paper, ink, playful, automatic]) {
488 assert.ok(sample.count > 0);
489 assert.equal(sample.componentReady, true);
490 assert.equal(sample.cardCount, 4);
491 assert.match(sample.fontFamily, /More/);
492 assert.ok(sample.textContrast >= 4.5, JSON.stringify(sample));
493 }
494 assert.ok(paper.luminance < 175, JSON.stringify(paper));
495 assert.ok(playful.luminance < 175, JSON.stringify(playful));
496 assert.ok(ink.luminance > 200, JSON.stringify(ink));
497 await testThemeCycle(browser);
429 await testHlsPlayer(browser, siteRoot); 498 await testHlsPlayer(browser, siteRoot);
430 } finally { 499 } finally {
431 if (browser) await browser.close(); 500 if (browser) await browser.close();
432 await stopProcess(server); 501 await stopProcess(server);
433 } 502 }