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'); });