Files
juzi/h5/test/tone-overlay-browser.mjs

27 lines
2.8 KiB
JavaScript

// Solid-color canvas fixtures verify actual blended pixels, not only CSS flags.
import assert from 'node:assert/strict';import {execSync}from'node:child_process';import{pathToFileURL}from'node:url';
const{chromium}=await import(pathToFileURL(execSync('npm root -g',{encoding:'utf8'}).trim()+'/playwright/index.mjs').href);
const browser=await chromium.launch();
try{
const page=await browser.newPage({viewport:{width:375,height:726}});const errors=[];let mode='map';
page.on('pageerror',e=>errors.push(e.message));
await page.route('**/*',r=>{assert.equal(r.request().method(),'GET');return r.continue();});
await page.route('**/assets/mock/report-fixture.js',r=>r.fulfill({contentType:'text/javascript',body:`
function solid(color){var c=document.createElement('canvas');c.width=100;c.height=100;var x=c.getContext('2d');x.fillStyle=color;x.fillRect(0,0,100,100);return c.toDataURL('image/png');}
window.MOCK_FIXTURE={result:{score_info:{melanin_score:90,water_score:80,dark_circle_score:50,wrinkle_score:65},melasma:{value:1},freckle:{value:0},face_maps:${mode==='map'?"{brown_area:solid('#000')}" : '{}'}},side:{},photos:[solid('rgb(200,100,50)')]};
`}));
const base=process.env.H5_BASE_URL||'http://127.0.0.1:8080/';
const pixel=async()=>page.locator('#viz-tone').evaluate(async i=>{await i.decode();const c=document.createElement('canvas');c.width=i.naturalWidth;c.height=i.naturalHeight;const x=c.getContext('2d');x.drawImage(i,0,0);return [...x.getImageData(c.width/2,c.height/2,1,1).data].slice(0,3);});
await page.goto(base+'?mock=1&screen=report');
await page.waitForFunction(()=>{const i=document.querySelector('#viz-tone');return !i.hidden&&i.naturalWidth&&i.dataset.overlayAlpha==='0.3'});
const actual=await pixel();[140,70,35].forEach((v,i)=>assert(Math.abs(actual[i]-v)<=4,actual+' != 30% overlay'));
assert.equal(await page.locator('#viz-tone').evaluate(i=>getComputedStyle(i).opacity),'1','face image not globally faded');
assert.equal(await page.locator('#tone-detections').count(),0,'no detection status overlay');
assert.equal(await page.locator('#tone-map-note').count(),0,'no technical caption below color copy');
assert(!(await page.locator('#tx-tone').textContent()).includes('占肤色项20%'));
mode='missing';await page.reload();await page.waitForFunction(()=>{const i=document.querySelector('#viz-tone');return !i.hidden&&i.naturalWidth});
const plain=await pixel();[200,100,50].forEach((v,i)=>assert(Math.abs(plain[i]-v)<=4));
assert.equal(await page.locator('#tone-map-note').count(),0,'missing map does not add technical caption');
assert.deepEqual(errors,[]);console.log('PASS tone overlay: actual 30% pixel blending, original photo opaque, true flags/no invented boxes, missing map photo fallback, new dark-circle copy, no writes');
}finally{await browser.close()}