test(e2e): pin NEXT TURN full-width and no-overlap with the active-tasks strip (#52)
This commit is contained in:
@@ -1046,3 +1046,47 @@ test('NEXT TURN with an empty queue is a free skip — +1 turn, the strip stays
|
||||
expect(after.turn).toBe(T + 1);
|
||||
expect(after.tasks.length).toBe(0);
|
||||
});
|
||||
|
||||
test('NEXT TURN button is full-width in the right pane and not covered by the task strip (#52)', async ({ page }) => {
|
||||
await drainQueue(page);
|
||||
const world = (await (await page.request.get('/api/world')).json()) as WorldStateQ;
|
||||
const currentId = world.systems.find((s) => s.current)!.id;
|
||||
const edge = world.edges.find(([a, b]) => a === currentId || b === currentId)!;
|
||||
const targetId = edge[0] === currentId ? edge[1] : edge[0];
|
||||
const { crew } = (await (await page.request.get('/api/crew')).json()) as { crew: CrewDto[]; tasks: QueueTaskDto[] };
|
||||
expect(crew.length).toBeGreaterThanOrEqual(2);
|
||||
|
||||
// Queue a one-person JUMP and deliberately do not tick it (the #44 jump scenarios' pattern,
|
||||
// the in-transit 409 one leaves it that way on purpose): the strip renders from the shell's
|
||||
// system snapshot — the same queue — so a non-empty queue keeps ACTIVE TASKS visible all test.
|
||||
const res = await page.request.post('/api/jump', { data: { systemId: targetId, leadCrewId: crew[0].id, helperCrewIds: [] } });
|
||||
expect(res.status()).toBe(200);
|
||||
const queued = (await res.json()) as WorldStateQ;
|
||||
expect(queued.tasks.find((t) => t.type === 'JUMP')!.status).toBe('ACTIVE');
|
||||
|
||||
await page.goto('/');
|
||||
await expect(page.getByText('ACTIVE TASKS', { exact: true })).toBeVisible(); // the strip is up
|
||||
|
||||
// Two rects intersect when their x AND y ranges overlap (touching edges do not count).
|
||||
type Box = { x: number; y: number; width: number; height: number };
|
||||
const intersects = (a: Box, b: Box) => a.x < b.x + b.width && b.x < a.x + a.width && a.y < b.y + b.height && b.y < a.y + a.height;
|
||||
|
||||
const buttonBox = await page.getByRole('button', { name: 'NEXT TURN' }).boundingBox();
|
||||
expect(buttonBox).not.toBeNull();
|
||||
// The strip's root div is the parent of its 'ACTIVE TASKS' label (components/task-strip.tsx).
|
||||
const stripBox = await page.getByText('ACTIVE TASKS', { exact: true }).locator('xpath=..').boundingBox();
|
||||
expect(stripBox).not.toBeNull();
|
||||
// The CARGO HOLD panel: the Panel root is the h3 heading's grandparent div (components/ui/panel.tsx).
|
||||
const panelBox = await page.getByRole('heading', { name: 'CARGO HOLD // INVENTORY' }).locator('xpath=ancestor::div[2]').boundingBox();
|
||||
expect(panelBox).not.toBeNull();
|
||||
|
||||
// (a) The button spans the right pane's content width — >= 280 on its own, and within ±8px of
|
||||
// the CARGO HOLD panel, a sibling full-width element in the same pane column.
|
||||
expect(buttonBox!.width).toBeGreaterThanOrEqual(280);
|
||||
expect(Math.abs(buttonBox!.width - panelBox!.width)).toBeLessThanOrEqual(8);
|
||||
|
||||
// (b) The button's box does not intersect the active-tasks strip's box.
|
||||
expect(intersects(buttonBox!, stripBox!)).toBe(false);
|
||||
|
||||
await drainQueue(page); // leave the queue clean for the next scenario
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user