test: follow live title bounds in performance flow
This commit is contained in:
@@ -12,7 +12,6 @@ const chromiumLaunchOptions = Object.freeze({
|
||||
headless: true,
|
||||
args: ['--use-angle=swiftshader', '--enable-unsafe-swiftshader']
|
||||
});
|
||||
const legacyUiScale = 1.5;
|
||||
const budgets = {
|
||||
titleReadyMs: readBudget('PERF_BUDGET_TITLE_READY_MS', 30000),
|
||||
storyReadyFromNewGameMs: readBudget('PERF_BUDGET_STORY_READY_MS', 30000),
|
||||
@@ -28,8 +27,61 @@ const budgets = {
|
||||
largestJsKB: readBudget('PERF_BUDGET_LARGEST_JS_KB', 2500)
|
||||
};
|
||||
|
||||
async function clickLegacyUi(page, x, y, options) {
|
||||
await page.mouse.click(x * legacyUiScale, y * legacyUiScale, options);
|
||||
async function clickTitleNewGame(page) {
|
||||
const clickPoint = await page.evaluate(() => {
|
||||
const scene = window.__HEROS_GAME__?.scene.getScene('TitleScene');
|
||||
const state = scene?.getDebugState?.();
|
||||
const item = state?.focus?.scope === 'main'
|
||||
? state.focus.items.find((candidate) => candidate.id === 'new-game' && candidate.enabled === true)
|
||||
: undefined;
|
||||
const canvas = document.querySelector('canvas');
|
||||
const canvasBounds = canvas?.getBoundingClientRect();
|
||||
if (!scene || !item?.bounds || !canvas || !canvasBounds) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
x: canvasBounds.left + (item.bounds.x + item.bounds.width / 2) * canvasBounds.width / scene.scale.width,
|
||||
y: canvasBounds.top + (item.bounds.y + item.bounds.height / 2) * canvasBounds.height / scene.scale.height,
|
||||
itemBounds: item.bounds,
|
||||
canvasBounds: {
|
||||
x: canvasBounds.x,
|
||||
y: canvasBounds.y,
|
||||
width: canvasBounds.width,
|
||||
height: canvasBounds.height
|
||||
}
|
||||
};
|
||||
});
|
||||
assert(
|
||||
clickPoint &&
|
||||
Number.isFinite(clickPoint.x) &&
|
||||
Number.isFinite(clickPoint.y) &&
|
||||
clickPoint.itemBounds.width > 0 &&
|
||||
clickPoint.itemBounds.height > 0 &&
|
||||
clickPoint.x >= clickPoint.canvasBounds.x &&
|
||||
clickPoint.x <= clickPoint.canvasBounds.x + clickPoint.canvasBounds.width &&
|
||||
clickPoint.y >= clickPoint.canvasBounds.y &&
|
||||
clickPoint.y <= clickPoint.canvasBounds.y + clickPoint.canvasBounds.height,
|
||||
`Expected an enabled title new-game control: ${JSON.stringify(clickPoint)}`
|
||||
);
|
||||
const clickStartedAt = Date.now();
|
||||
await page.mouse.click(clickPoint.x, clickPoint.y);
|
||||
try {
|
||||
await page.waitForFunction(() => {
|
||||
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
|
||||
const title = window.__HEROS_DEBUG__?.title?.();
|
||||
return title?.navigating === true || activeScenes.includes('StoryScene');
|
||||
}, undefined, { timeout: 10000 });
|
||||
} catch (error) {
|
||||
const diagnostic = await page.evaluate(() => ({
|
||||
activeScenes: window.__HEROS_DEBUG__?.activeScenes() ?? [],
|
||||
title: window.__HEROS_DEBUG__?.title?.() ?? null
|
||||
}));
|
||||
throw new Error(
|
||||
`The live title new-game control did not begin navigation: ${JSON.stringify({ clickPoint, diagnostic })}`,
|
||||
{ cause: error }
|
||||
);
|
||||
}
|
||||
return clickStartedAt;
|
||||
}
|
||||
|
||||
async function clickBattleDeploymentStart(page) {
|
||||
@@ -92,8 +144,7 @@ try {
|
||||
const titleMs = Date.now() - titleStartedAt;
|
||||
const titleEntries = await resourceEntries(page);
|
||||
|
||||
const storyStartedAt = Date.now();
|
||||
await clickLegacyUi(page, 962, 240);
|
||||
const storyStartedAt = await clickTitleNewGame(page);
|
||||
await waitForStoryReady(page);
|
||||
await page.waitForLoadState('networkidle', { timeout: 120000 });
|
||||
const storyMs = Date.now() - storyStartedAt;
|
||||
@@ -313,11 +364,23 @@ async function waitForTitle(page) {
|
||||
}
|
||||
|
||||
async function waitForStoryReady(page) {
|
||||
await page.waitForFunction(() => {
|
||||
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
|
||||
const story = window.__HEROS_DEBUG__?.scene('StoryScene')?.getDebugState?.();
|
||||
return activeScenes.includes('StoryScene') && story?.ready === true;
|
||||
}, undefined, { timeout: 120000 });
|
||||
try {
|
||||
await page.waitForFunction(() => {
|
||||
const activeScenes = window.__HEROS_DEBUG__?.activeScenes() ?? [];
|
||||
const story = window.__HEROS_DEBUG__?.scene('StoryScene')?.getDebugState?.();
|
||||
return activeScenes.includes('StoryScene') && story?.ready === true;
|
||||
}, undefined, { timeout: 120000 });
|
||||
} catch (error) {
|
||||
const diagnostic = await page.evaluate(() => ({
|
||||
activeScenes: window.__HEROS_DEBUG__?.activeScenes() ?? [],
|
||||
title: window.__HEROS_DEBUG__?.title?.() ?? null,
|
||||
story: window.__HEROS_DEBUG__?.scene('StoryScene')?.getDebugState?.() ?? null
|
||||
}));
|
||||
throw new Error(
|
||||
`StoryScene did not become ready during performance measurement: ${JSON.stringify(diagnostic)}`,
|
||||
{ cause: error }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function advanceStoryUntilBattle(page, battleId) {
|
||||
|
||||
Reference in New Issue
Block a user