fix(ci): accept hydrated markers hidden by responsive layouts
creative workspace review checks / verify-deployed-canvas (pull_request) Successful in 3m24s
creative workspace review checks / verify (pull_request) Successful in 25m23s

This commit is contained in:
2026-11-02 16:32:37 +08:00
parent 7f397fd3a2
commit 38a71e04ca
2 changed files with 11 additions and 3 deletions
@@ -51,9 +51,11 @@ export async function visitBrowserDocument(page, url, reload = false) {
const remaining = timeout - (Date.now() - started);
if (remaining <= 0) throw new Error('Document hydration budget exhausted: ' + url);
try {
// Responsive layouts may hide the toggle. Its mounted ready marker
// proves hydration; each caller still checks the controls it needs.
// A cancelled script may be a preload duplicate. Hydration is the
// authority; recover only when cancellation actually blocks startup.
await page.locator('button[data-theme-ready="true"]').first().waitFor({timeout: failures.length ? Math.min(5000, remaining) : remaining});
await page.locator('button[data-theme-ready="true"]').first().waitFor({state: 'attached', timeout: failures.length ? Math.min(5000, remaining) : remaining});
} catch (error) {
if (failures.length) throw new Error('Document bootstrap script request failed: ' + failures.join('; '), {cause: error});
throw error;
@@ -49,7 +49,7 @@ test('recovery cannot extend the total navigation budget', async () => {
assert.equal(calls, 1);
});
function browserFixture(failBootstrap = false, failHydration = false, blockedOnce = false) {
function browserFixture(failBootstrap = false, failHydration = false, blockedOnce = false, readyVisible = true) {
const listeners = new Map(), calls = [];
const page = {
on(event, fn) { if (!listeners.has(event)) listeners.set(event, new Set()); listeners.get(event).add(fn); },
@@ -61,7 +61,7 @@ function browserFixture(failBootstrap = false, failHydration = false, blockedOnc
if (failBootstrap && calls.length === 1) for (const fn of listeners.get('requestfailed') || []) fn(request);
return response(200);
},
locator() { return {first: () => ({waitFor: async () => { calls.push('hydrated'); if (failHydration || (blockedOnce && calls.length === 2)) throw Error('Hydration timeout'); }})}; },
locator() { return {first: () => ({waitFor: async options => { calls.push('hydrated'); if (!readyVisible && options.state !== 'attached') throw Error('Ready marker is hidden by responsive CSS'); if (failHydration || (blockedOnce && calls.length === 2)) throw Error('Hydration timeout'); }})}; },
};
return {page, calls, listeners};
}
@@ -87,3 +87,9 @@ test('cancelled script does not reject an already hydrated document', async () =
await visitBrowserDocument(page, '/account');
assert.deepEqual(calls, ['domcontentloaded', 'hydrated']);
});
test('hydrated pages are ready even when responsive CSS hides the marker', async () => {
const {page, calls} = browserFixture(false, false, false, false);
await visitBrowserDocument(page, '/graphic');
assert.deepEqual(calls, ['domcontentloaded', 'hydrated']);
});