floor-planner/e2e/optimisation.spec.ts
Andras Schmelczer 8bf3e3b705
Some checks failed
Deploy to Pages / build (push) Failing after 10m45s
Simplify
2026-09-11 23:27:29 +01:00

70 lines
3.3 KiB
TypeScript

import { expect, test } from '@playwright/test';
import { defaultState } from '../src/lib/defaults';
import { planFlooringOptions } from '../src/lib/flooring';
import { mm } from '../src/lib/format';
import { decodeState, encodeState } from '../src/lib/url-state';
test('random optimisation choices show actual totals, select the plan and survive reload', async ({
page,
isMobile,
}) => {
if (isMobile) await page.setViewportSize({ width: 320, height: 844 });
const state = defaultState();
state.project.flooring.pattern = 'random';
const p = state.project;
const options = planFlooringOptions(p.rooms, p.flooring, p.tolerance);
await page.goto(`/${encodeState(state)}`);
const choices = page.getByRole('group', { name: 'Flooring optimisation', exact: true });
const cuts = choices.getByRole('button', { name: /^Minimise cuts/ });
const random = choices.getByRole('button', { name: /^Maximise randomness/ });
await expect(cuts).toHaveAttribute('aria-pressed', 'true');
await expect(cuts).toContainText(
`${options.cuts.cuts} cuts · ${mm(options.cuts.wastePercent)}% waste`,
);
await expect(random).toContainText(
`${options.random.cuts} cuts · ${mm(options.random.wastePercent)}% waste`,
);
expect(options.cuts.cuts).toBeLessThan(options.random.cuts);
const checkbox = page.locator('.stock-cut-group input[type="checkbox"]').first();
await checkbox.check();
expect(decodeState(new URL(page.url()).search).state.project.completedBoards).not.toEqual([]);
await random.click();
await expect(random).toHaveAttribute('aria-pressed', 'true');
await expect(cuts).toHaveAttribute('aria-pressed', 'false');
expect(decodeState(new URL(page.url()).search).state.project.flooring.optimisation).toBe(
'random',
);
expect(decodeState(new URL(page.url()).search).state.project.completedBoards).toEqual([]);
const drawn = page.getByRole('region', { name: 'Floor plan preview' }).locator('.floor-piece');
await expect(drawn).toHaveCount(options.random.pieces.length);
const ids = await drawn.evaluateAll((pieces) =>
pieces.map((piece) => piece.getAttribute('data-piece-id')),
);
expect(ids.sort()).toEqual(options.random.pieces.map((piece) => piece.id).sort());
await page.reload();
await expect(random).toHaveAttribute('aria-pressed', 'true');
expect(decodeState(new URL(page.url()).search).state.project.flooring.optimisation).toBe(
'random',
);
await cuts.click();
await expect(cuts).toHaveAttribute('aria-pressed', 'true');
await expect(drawn).toHaveCount(options.cuts.pieces.length);
expect(await page.evaluate(() => document.documentElement.scrollWidth)).toBeLessThanOrEqual(
page.viewportSize()!.width,
);
await page.getByRole('button', { name: 'Brick', exact: true }).click();
await expect(choices).toHaveCount(0);
});
test('infeasible measurements do not advertise zero-cut or zero-waste options', async ({
page,
}) => {
const state = defaultState();
state.project.flooring.pattern = 'random';
state.project.flooring.minOffset = 700;
await page.goto(`/${encodeState(state)}`);
const choices = page.getByRole('group', { name: 'Flooring optimisation', exact: true });
await expect(choices.getByText('Check measurements', { exact: true })).toHaveCount(2);
await expect(choices).not.toContainText('0 cuts');
await expect(choices).not.toContainText('0% waste');
});