Verify release canvas pixels
This commit is contained in:
@@ -38,6 +38,7 @@ try {
|
||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||
await waitForTitle(page);
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-title-first-run.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'title first run');
|
||||
|
||||
const emptySave = await readCampaignSave(page);
|
||||
assert(!emptySave.current && !emptySave.slot1, `Expected first run without campaign save: ${JSON.stringify(emptySave)}`);
|
||||
@@ -45,8 +46,10 @@ try {
|
||||
await page.mouse.click(962, 240);
|
||||
await waitForStoryReady(page);
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-new-game-story.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'new game story');
|
||||
await advanceUntilBattle(page, 'first-battle-zhuo-commandery');
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-first-battle.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'first battle');
|
||||
|
||||
const firstBattleProbe = await page.evaluate(() => {
|
||||
const scene = window.__HEROS_GAME__?.scene.getScene('BattleScene');
|
||||
@@ -76,6 +79,7 @@ try {
|
||||
await page.evaluate(() => window.__HEROS_DEBUG__?.forceBattleOutcome('victory'));
|
||||
await waitForBattleOutcome(page, 'victory');
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-first-battle-result.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'first battle result');
|
||||
|
||||
const resultProbe = await page.evaluate(() => {
|
||||
const scene = window.__HEROS_GAME__?.scene.getScene('BattleScene');
|
||||
@@ -97,6 +101,7 @@ try {
|
||||
await page.mouse.click(738, 642);
|
||||
await waitForCampAfterBattleResult(page);
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-first-camp.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'first camp');
|
||||
|
||||
const firstCampProbe = await page.evaluate(() => {
|
||||
const scene = window.__HEROS_GAME__?.scene.getScene('CampScene');
|
||||
@@ -128,6 +133,7 @@ try {
|
||||
await page.mouse.click(962, 310);
|
||||
await waitForCamp(page);
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-mid-campaign-continue.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'mid campaign camp');
|
||||
|
||||
const midCampState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||
assert(midCampState?.campaign?.step === 'fifty-eighth-camp', `Expected mid-campaign save to continue into camp: ${JSON.stringify(midCampState)}`);
|
||||
@@ -150,6 +156,7 @@ try {
|
||||
const finalCampState = await page.evaluate(() => window.__HEROS_DEBUG__?.camp());
|
||||
assert(finalCampState?.campaign?.step === 'sixty-sixth-camp', `Expected final camp save to continue: ${JSON.stringify(finalCampState)}`);
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-final-camp.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'final camp');
|
||||
|
||||
await page.mouse.click(1160, 38);
|
||||
const finalTransitionScenes = await waitForStoryOrEnding(page);
|
||||
@@ -159,6 +166,7 @@ try {
|
||||
}
|
||||
await waitForEnding(page);
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-ending.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'ending');
|
||||
|
||||
const endingState = await page.evaluate(() => window.__HEROS_DEBUG__?.scene('EndingScene')?.getDebugState?.());
|
||||
assert(endingState?.campaignStep === 'ending-complete', `Expected ending-complete state: ${JSON.stringify(endingState)}`);
|
||||
@@ -169,6 +177,7 @@ try {
|
||||
await page.mouse.click(962, 310);
|
||||
await waitForEnding(page);
|
||||
await page.screenshot({ path: `${screenshotDir}/rc-ending-continue.png`, fullPage: true });
|
||||
await assertCanvasPainted(page, 'ending continue');
|
||||
|
||||
const endingContinueState = await page.evaluate(() => ({
|
||||
activeScenes: window.__HEROS_DEBUG__?.activeScenes() ?? [],
|
||||
@@ -337,6 +346,50 @@ async function waitForEnding(page) {
|
||||
}, undefined, { timeout: 90000 });
|
||||
}
|
||||
|
||||
async function assertCanvasPainted(page, context) {
|
||||
const probe = await page.evaluate(() => {
|
||||
const canvas = document.querySelector('canvas');
|
||||
if (!canvas) {
|
||||
return { readable: false, missing: true, sampleCount: 0, nonTransparentRatio: 0, distinctColorBuckets: 0 };
|
||||
}
|
||||
|
||||
const canvasContext = canvas.getContext('2d', { willReadFrequently: true });
|
||||
if (!canvasContext) {
|
||||
return { readable: false, missing: false, sampleCount: 0, nonTransparentRatio: 0, distinctColorBuckets: 0 };
|
||||
}
|
||||
|
||||
const stepX = Math.max(1, Math.floor(canvas.width / 64));
|
||||
const stepY = Math.max(1, Math.floor(canvas.height / 64));
|
||||
const colorBuckets = new Set();
|
||||
let sampleCount = 0;
|
||||
let nonTransparentCount = 0;
|
||||
|
||||
for (let y = Math.floor(stepY / 2); y < canvas.height; y += stepY) {
|
||||
for (let x = Math.floor(stepX / 2); x < canvas.width; x += stepX) {
|
||||
const [r, g, b, a] = canvasContext.getImageData(x, y, 1, 1).data;
|
||||
sampleCount += 1;
|
||||
if (a > 8) {
|
||||
nonTransparentCount += 1;
|
||||
}
|
||||
colorBuckets.add(`${r >> 4},${g >> 4},${b >> 4},${a >> 5}`);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
readable: true,
|
||||
missing: false,
|
||||
sampleCount,
|
||||
nonTransparentRatio: sampleCount > 0 ? nonTransparentCount / sampleCount : 0,
|
||||
distinctColorBuckets: colorBuckets.size
|
||||
};
|
||||
});
|
||||
|
||||
assert(probe.readable === true, `Expected readable canvas pixels during ${context}: ${JSON.stringify(probe)}`);
|
||||
assert(probe.sampleCount >= 500, `Expected enough canvas pixel samples during ${context}: ${JSON.stringify(probe)}`);
|
||||
assert(probe.nonTransparentRatio > 0.5, `Expected non-empty canvas pixels during ${context}: ${JSON.stringify(probe)}`);
|
||||
assert(probe.distinctColorBuckets >= 12, `Expected visually varied canvas pixels during ${context}: ${JSON.stringify(probe)}`);
|
||||
}
|
||||
|
||||
async function readCampaignSave(page) {
|
||||
return page.evaluate(() => {
|
||||
const read = (key) => {
|
||||
|
||||
Reference in New Issue
Block a user