Files
tilbudgivern/tests/mobile-orders-readiness.spec.js
2026-07-08 13:06:16 +02:00

122 lines
4.1 KiB
JavaScript

// @ts-check
const { test, expect } = require('@playwright/test');
const BASE_URL = process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:4032';
const order = {
caseNumber: 'MOB-1001',
customerName: 'Test Tømrer Kunde',
projectName: 'Fladtag besigtigelse',
deliveryAddress: 'Testvej 12, 2300 København S',
description: 'Fladtag med afløb og opkanter',
checklistLabel: 'Fladtag',
status: 'active',
statusText: 'Aktiv',
totalHours: 12.5,
materialLinesCount: 4
};
const checklist = {
label: 'Fladtag',
questions: [
{ key: 'slope', label: 'Fald/afvanding kontrolleret', inputType: 'boolean', required: true },
{ key: 'drains', label: 'Afløb/tagnedløb optalt', inputType: 'number', unit: 'stk', required: true },
{ key: 'upstands', label: 'Opkanter og gennembrydninger registreret', inputType: 'boolean' }
]
};
async function mockMobileApis(page) {
await page.route('**/api/mobile/orders?**', async (route) => {
await route.fulfill({
contentType: 'application/json',
body: JSON.stringify({ success: true, orders: [order] })
});
});
await page.route('**/api/mobile/orders/MOB-1001', async (route) => {
await route.fulfill({
contentType: 'application/json',
body: JSON.stringify({
success: true,
order,
checklist,
intakes: [],
attachments: [],
quoteDrafts: [],
history: {
hours: { totalHours: order.totalHours },
materials: [
{ productText: 'SBS overpap', quantity: 100, supplier: 'STARK' }
]
}
})
});
});
await page.route('**/api/mobile/quote-drafts?**', async (route) => {
await route.fulfill({
contentType: 'application/json',
body: JSON.stringify({ success: true, quoteDrafts: [] })
});
});
await page.route('**/api/mobile/orders/MOB-1001/intake', async (route) => {
await route.fulfill({
contentType: 'application/json',
body: JSON.stringify({
success: true,
intake: { id: 77, status: 'ready_for_review' }
})
});
});
await page.route('**/api/mobile/orders/MOB-1001/quote-draft', async (route) => {
await route.fulfill({
contentType: 'application/json',
body: JSON.stringify({
success: true,
quoteDraft: { id: 88, title: 'Mobil kladde MOB-1001', draftLines: [] }
})
});
});
}
test('mobile order readiness blocks incomplete field intake and unlocks review when complete', async ({ page }) => {
await mockMobileApis(page);
await page.addInitScript(() => {
window.localStorage.setItem('accessToken', 'playwright-token');
window.localStorage.setItem('user', JSON.stringify({ username: 'toemrer' }));
window.localStorage.setItem('tilbudgivern_current_view', 'mobile');
});
await page.goto(BASE_URL);
await page.waitForLoadState('networkidle');
await expect(page.getByRole('heading', { name: 'Mobil ordre' })).toBeVisible();
await expect(page.getByRole('button', { name: /Sag MOB-1001/i })).toBeVisible();
await expect(page.getByText('Mangler før desktop-review')).toBeVisible();
const missingList = page.locator('.mobile-readiness-box').filter({ hasText: 'Mangler før desktop-review' });
await expect(missingList.getByRole('listitem')).toHaveText([
'Fald/afvanding kontrolleret',
'Afløb/tagnedløb optalt',
'Areal'
]);
const createDraftButton = page.getByRole('button', { name: 'Lav tilbudskladde' });
await expect(createDraftButton).toBeDisabled();
await page.getByLabel('Fald/afvanding kontrolleret').selectOption('yes');
await page.getByLabel('Afløb/tagnedløb optalt').fill('2');
await page.getByLabel('Areal').fill('96');
await page.getByLabel('Adgangsnoter').fill('Stillads fra indkørsel');
await expect(page.getByText('Mangler før desktop-review')).toBeHidden();
await expect(page.getByText('Godt at få med')).toBeVisible();
await expect(page.getByText('Billeder eller dokumentation')).toBeVisible();
await expect(page.getByText('Adgangsnoter')).toHaveCount(1);
await expect(createDraftButton).toBeEnabled();
await createDraftButton.click();
await expect(page.getByText('Tilbudskladde oprettet til desktop-review')).toBeVisible();
});