floor-planner/e2e/optimisation.spec.ts
Andras Schmelczer b9485e4097
All checks were successful
Deploy to Pages / build (push) Successful in 26s
landing
2026-09-11 20:34:36 +01:00

68 lines
3.2 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(new URL(page.url()).searchParams.getAll('done')).not.toEqual([]);
await random.click();
await expect(random).toHaveAttribute('aria-pressed', 'true');
await expect(cuts).toHaveAttribute('aria-pressed', 'false');
expect(new URL(page.url()).searchParams.get('flooring.optimisation')).toBe('random');
expect(new URL(page.url()).searchParams.getAll('done')).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');
});