Download app/tests/mascot-transparency.mjs from Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP: direct link, hf CLI and curl.
- Browser
- Download file 6.05 kB
-
https://huggingface.co/spaces/Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP/resolve/main/app/tests/mascot-transparency.mjs
- Command line
-
hf download hf://spaces/Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP/app/tests/mascot-transparency.mjs
-
curl -L -o mascot-transparency.mjs https://huggingface.co/spaces/Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP/resolve/main/app/tests/mascot-transparency.mjs
6.05 kB
| import { chromium, webkit } from 'playwright'; | |
| import fs from 'node:fs/promises'; | |
| import assert from 'node:assert/strict'; | |
| const url = process.argv[2] ?? 'http://127.0.0.1:4173/'; | |
| const label = process.argv[3] ?? 'mascot-transparency'; | |
| const result = { url, checks: [], errors: [] }; | |
| const webkitRoot = process.env.WEBKIT_MINIBROWSER_ROOT; | |
| const points = [[.04,.04], [.5,.04], [.96,.5], [.05,.85], [.5,.97], [.75,.7]]; | |
| for (const engine of ['chromium', 'webkit']) { | |
| const browser = engine === 'chromium' | |
| ? await chromium.launch({ executablePath: '/usr/bin/chromium', headless: true }) | |
| : await webkit.launch({ headless: true, ...(webkitRoot ? { | |
| executablePath: webkitRoot + '/bin/MiniBrowser', env: { ...process.env, | |
| WEBKIT_EXEC_PATH: webkitRoot + '/bin', WEBKIT_INJECTED_BUNDLE_PATH: webkitRoot + '/lib', | |
| WEBKIT_INSPECTOR_RESOURCES_PATH: webkitRoot + '/share', | |
| LD_LIBRARY_PATH: webkitRoot + '/lib:' + webkitRoot + '/sys/lib:' + (process.env.WEBKIT_EXTRA_LIBS ?? ''), | |
| }, | |
| } : {}) }); | |
| try { | |
| for (const [width, height, scale] of [[1440,1000,1], [390,844,2]]) { | |
| const context = await browser.newContext({ viewport: { width, height }, deviceScaleFactor: scale }); | |
| const page = await context.newPage(); | |
| page.on('pageerror', e => result.errors.push(e.message)); | |
| const figure = page.locator('.mascot-cat'); | |
| const ready = async () => { | |
| await page.waitForFunction(() => window.browserPi?.terminal); | |
| await page.evaluate(() => window.browserPi.ready); | |
| await figure.waitFor({ state: 'visible' }); | |
| }; | |
| async function check(name) { | |
| const rect = await figure.boundingBox(); | |
| const actual = await page.screenshot(); | |
| // Compare the real backdrop at identical coordinates with the cat hidden. | |
| await figure.evaluate(el => { el.style.visibility = 'hidden'; }); | |
| const backdrop = await page.screenshot(); | |
| await figure.evaluate(el => { el.style.visibility = ''; }); | |
| const pixels = await page.evaluate(async ({ actual, backdrop, rect, scale, points }) => { | |
| async function read(data) { | |
| const img = new Image(); img.src = 'data:image/png;base64,' + data; await img.decode(); | |
| const canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; | |
| const ctx = canvas.getContext('2d'); ctx.drawImage(img,0,0); | |
| return points.map(([x,y]) => [...ctx.getImageData(Math.floor((rect.x+x*rect.width)*scale), Math.floor((rect.y+y*rect.height)*scale),1,1).data]); | |
| } | |
| const outside = { actual: await read(actual), backdrop: await read(backdrop) }; | |
| points = [[.45,.3], [.235,.18], [.32,.42]]; | |
| return { ...outside, cat: await read(actual) }; | |
| }, { actual: actual.toString('base64'), backdrop: backdrop.toString('base64'), rect, scale, points }); | |
| assert.deepEqual(pixels.actual,pixels.backdrop, `${engine} ${width} ${name}: opaque pixels outside silhouette`); | |
| const [fur, ear, eye] = pixels.cat; | |
| assert(fur[0] > 200 && fur[1] > 200 && fur[2] > 170, 'Cream fur must remain visible'); | |
| assert(ear[0] > 200 && ear[0] > ear[1] + 20, 'Pink inner ear must remain visible'); | |
| assert(eye.slice(0,3).every(v => v < 20), 'Black eye must be preserved, not color-keyed away'); | |
| await fs.writeFile(`../validation/${label}-${engine}-${width}-${name}.png`, actual); | |
| result.checks.push({ engine, width, height, scale, name, passed: true }); | |
| } | |
| await page.goto(url); await ready(); | |
| // Pause timers before the first automatic hop so screenshots cannot hide a first-paint defect. | |
| await page.clock.install(); await page.clock.pauseAt(new Date()); | |
| await check('cold-load'); | |
| assert.equal(await figure.evaluate(el => getComputedStyle(el).mixBlendMode), 'normal'); | |
| await figure.click(); | |
| const hopping = await figure.evaluate(el => { | |
| const a = el.getAnimations().find(a => a.id === 'mascot-bump'); | |
| if (!a) return false; a.pause(); a.currentTime = 170; return true; | |
| }); | |
| assert(hopping, 'Click must still animate the cat'); | |
| await check('mid-hop'); | |
| await figure.evaluate(el => el.getAnimations().forEach(a => a.finish())); | |
| await check('after-hop'); | |
| await page.emulateMedia({ reducedMotion: 'reduce' }); | |
| await page.clock.resume(); | |
| await page.reload(); await ready(); | |
| await check('reduced-motion-reload'); | |
| assert.equal(await figure.evaluate(el => el.getAnimations().length), 0); | |
| // A contrasting background proves actual clipping, not a dark-color cover-up. | |
| await page.addStyleTag({ content: '.mascot-cat { background: repeating-conic-gradient(#f57bc5 0 25%, #53d4ce 0 50%) 0 / 16px 16px !important; }' }); | |
| const rect = await figure.boundingBox(); | |
| const screenshot = await page.screenshot(); | |
| const colors = await page.evaluate(async ({ data, rect, scale, points }) => { | |
| const img=new Image();img.src='data:image/png;base64,'+data;await img.decode(); | |
| const canvas=document.createElement('canvas');canvas.width=img.width;canvas.height=img.height; | |
| const ctx=canvas.getContext('2d');ctx.drawImage(img,0,0); | |
| return points.map(([x,y])=>[...ctx.getImageData(Math.floor((rect.x+x*rect.width)*scale),Math.floor((rect.y+y*rect.height)*scale),1,1).data]); | |
| }, { data:screenshot.toString('base64'),rect,scale,points }); | |
| for (const pixel of colors) assert(pixel[0] > 50 && pixel[1] > 100 && pixel[2] > 150, JSON.stringify(pixel)); | |
| result.checks.push({engine,width,name:'patterned-backdrop',passed:true}); | |
| await fs.writeFile(`../validation/${label}-${engine}-${width}-patterned-backdrop.png`,screenshot); | |
| await context.close(); | |
| } | |
| } finally { await browser.close(); } | |
| } | |
| assert.deepEqual(result.errors, []); | |
| result.passed = true; | |
| await fs.writeFile(`../validation/${label}.json`,JSON.stringify(result,null,2)+'\n'); | |
| console.log(JSON.stringify(result)); | |