Check hidden lines behind the Earth and open the picker panel by keyboard

Cesium culls a line the globe hides whole and does not depth-test lines
against the near side of a keyless globe, so the contract check runs the
hidden line round the back of the Earth to a visible end. The wildlife
switch scenario opens VISUAL PRESETS from the keyboard before tabbing to
the engine picker and reports the page state when no switch follows.
This commit is contained in:
German Khokhlov committed 2026-11-09 13:03:13 +04:00
1 parent 68845a4977
commit 69fbf5b38d
2 files changed
+50 -11

No files matched your search

+25 -2
View File
@@ -247,11 +247,21 @@ await strict.run({}, async (b) => {
box: box ? [box.x, box.y, box.width, box.height] : null, box: box ? [box.x, box.y, box.width, box.height] : null,
}; };
}); });
// The picker sits in VISUAL PRESETS, out of the Tab order while that
// panel is collapsed: open it from the keyboard too.
if ((await picker()).panel !== 'true') {
await p.focus('#control-panel-toggle');
await p.keyboard.press('Enter');
}
await p await p
.waitForFunction( .waitForFunction(
() => { () => {
const el = document.querySelector('#globe-engine'); const el = document.querySelector('#globe-engine');
return el && !el.disabled && el.getBoundingClientRect().height > 0; return (
el &&
!el.disabled &&
el.checkVisibility({ visibilityProperty: true })
);
}, },
{ timeout: 30000 }, { timeout: 30000 },
) )
@@ -293,7 +303,20 @@ await strict.run({}, async (b) => {
const tabs = path.length; const tabs = path.length;
const from = await p.$eval('#globe-engine', (el) => el.value); const from = await p.$eval('#globe-engine', (el) => el.value);
await p.keyboard.type(kind[0]); await p.keyboard.type(kind[0]);
await waitForEngine(p, kind); await waitForEngine(p, kind).catch(async (error) => {
const state = await p.evaluate(() => ({
engine: window.__godsEyeView?.engine?.kind ?? null,
picker: document.querySelector('#globe-engine')?.value ?? null,
focus: document.activeElement?.id ?? null,
busy: document.querySelector('#globe-engine')?.disabled ?? null,
frame: Boolean(document.querySelector('.engine-switch-frame')),
loading: document.querySelector('#loading-screen')?.className ?? null,
}));
throw Error(
`no ${kind} globe after typing ${kind[0]}: ${JSON.stringify({ from, tabs: path.length, ...state })}`,
{ cause: error },
);
});
assert.equal( assert.equal(
await p.evaluate(() => performance.timeOrigin), await p.evaluate(() => performance.timeOrigin),
origin, origin,
+25 -9
View File
@@ -795,23 +795,39 @@ export function createContractSuite(
const shownStrength = strength(at(20.5, 9)); const shownStrength = strength(at(20.5, 9));
line.show(false); line.show(false);
await until(() => magentaAt(at(20.5, 9)) === 0, 'the line hidden'); await until(() => magentaAt(at(20.5, 9)) === 0, 'the line hidden');
// 30 km under the ground: only the depth-fail copy shows, dimmed. // Round the back of the Earth along the great circle west of the
const deep = (lon) => at(lon, 11, -30_000); // view centre, out to a visible end past the western horizon. The
hidden.setPositions([deep(19), deep(21)]); // far side, behind the Earth's centre, shows only by its dimmed
// depth-fail copy. Cesium culls a line the globe hides whole, and
// draws in full what lies under the horizon but before the centre.
const west = (degrees) => {
const t = (degrees * Math.PI) / 180;
const [lon0, lat0] = [(20 * Math.PI) / 180, (10 * Math.PI) / 180];
const [x, y, z] = [
Math.cos(lat0) * Math.cos(lon0) * Math.cos(t) +
Math.sin(lon0) * Math.sin(t),
Math.cos(lat0) * Math.sin(lon0) * Math.cos(t) -
Math.cos(lon0) * Math.sin(t),
Math.sin(lat0) * Math.cos(t),
];
return at(
(Math.atan2(y, x) * 180) / Math.PI,
(Math.asin(z) * 180) / Math.PI,
);
};
const deep = () => west(150);
hidden.setPositions([200, 150, 100, 50, 20].map(west));
await until( await until(
() => magentaAt(deep(20)) > 10, () => magentaAt(deep()) > 10,
'the hidden line drawn by its depth-fail copy', 'the hidden line drawn by its depth-fail copy',
); );
const hiddenStrength = strength(deep(20)); const hiddenStrength = strength(deep());
ensure( ensure(
hiddenStrength < shownStrength, hiddenStrength < shownStrength,
`the depth-fail copy (${hiddenStrength}) is not dimmer than the line (${shownStrength})`, `the depth-fail copy (${hiddenStrength}) is not dimmer than the line (${shownStrength})`,
); );
hidden.destroy(); hidden.destroy();
await until( await until(() => magentaAt(deep()) === 0, 'the destroyed line gone');
() => magentaAt(deep(20)) === 0,
'the destroyed line gone',
);
} finally { } finally {
line.destroy(); line.destroy();
hidden.destroy(); hidden.destroy();