Files
tilbudgivern/tests/status-flow-validation.js

191 lines
7.3 KiB
JavaScript

const { chromium } = require('@playwright/test');
const fs = require('fs');
const path = require('path');
const BASE_URL = process.env.PLAYWRIGHT_BASE_URL || 'http://127.0.0.1:4132';
const ARTIFACTS_DIR = path.join(__dirname, 'artifacts', 'status-flow');
const LOGIN_USERNAME = 'toemrer';
const LOGIN_PASSWORD = process.env.AUTH_PASSWORD;
async function ensureArtifactsDir() {
fs.mkdirSync(ARTIFACTS_DIR, { recursive: true });
}
async function login(page) {
await page.goto(BASE_URL, { waitUntil: 'networkidle', timeout: 30000 });
const onLogin = await page.getByRole('heading', { name: /Log ind/i }).isVisible({ timeout: 5000 }).catch(() => false);
if (!onLogin) {
return;
}
await page.locator('input[type="text"]').first().fill(LOGIN_USERNAME);
await page.locator('input[type="password"]').first().fill(LOGIN_PASSWORD);
await page.getByRole('button', { name: /Log ind/i }).click();
await page.waitForLoadState('networkidle', { timeout: 20000 }).catch(() => {});
await page.waitForTimeout(1500);
}
async function getProjectSnapshot(page, projectName) {
return await page.evaluate(async ({ projectName }) => {
const token = localStorage.getItem('accessToken');
const response = await fetch('/api/customer-projects/projects', {
headers: token ? { Authorization: `Bearer ${token}` } : {}
});
const data = await response.json();
const project = (data.projects || []).find((item) => item.project_name === projectName);
return project ? {
id: project.id,
status: project.project_status,
customer_name: project.customer_name
} : null;
}, { projectName });
}
async function waitForProjectSnapshot(page, projectName, maxAttempts = 10) {
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
const snapshot = await getProjectSnapshot(page, projectName);
if (snapshot) {
return snapshot;
}
await page.waitForTimeout(1000);
}
return null;
}
async function fillGeometry(page) {
const widthInput = page.locator('input[placeholder="10"]').first();
const lengthInput = page.locator('input[placeholder="15"]').first();
await widthInput.waitFor({ state: 'visible', timeout: 10000 });
await widthInput.fill('10');
await lengthInput.fill('12');
const saveBtn = page.getByRole('button', { name: /Gem Nu|Gem Geometri/i }).first();
await saveBtn.click();
await page.waitForTimeout(6000);
}
async function completeSmartPackage(page) {
const continueBtn = page.getByRole('button', { name: /Fortsæt til Smart Pakke/i }).first();
if (await continueBtn.isVisible({ timeout: 5000 }).catch(() => false)) {
await continueBtn.click();
} else {
await page.locator('.step').filter({ hasText: /Smart Pakke/i }).first().click();
}
await page.waitForTimeout(3000);
const packageOptions = page.locator('.package-option');
const packageCount = await packageOptions.count();
if (packageCount === 0) {
throw new Error('Ingen smart pakker fundet i UI');
}
await packageOptions.first().click();
await page.waitForTimeout(2500);
const saveSmartPackageBtn = page.getByRole('button', { name: /Gem Smart Pakke/i }).first();
if (await saveSmartPackageBtn.isVisible({ timeout: 5000 }).catch(() => false)) {
await saveSmartPackageBtn.click();
await page.waitForTimeout(1500);
}
}
async function goToFinalReview(page) {
const nextBtn = page.getByRole('button', { name: /Næste.*Final Review/i }).first();
if (await nextBtn.isVisible({ timeout: 5000 }).catch(() => false)) {
await nextBtn.click();
} else {
await page.locator('.step').filter({ hasText: /Final Review/i }).first().click();
}
await page.waitForTimeout(5000);
}
async function main() {
await ensureArtifactsDir();
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage({ viewport: { width: 1440, height: 1400 } });
const projectName = `Status Flow ${Date.now()}`;
try {
await login(page);
console.log('STEP login', JSON.stringify({ url: page.url() }));
const newProjectBtn = page.getByRole('button', { name: /Nyt Projekt/i });
if (await newProjectBtn.isVisible({ timeout: 10000 }).catch(() => false)) {
await newProjectBtn.click();
await page.waitForTimeout(500);
}
await page.locator('#field-projectName').fill(projectName);
await page.locator('#field-customerName').fill('Status Flow Testkunde');
await page.locator('#field-customerEmail').fill('statusflow@example.com');
await page.locator('#field-projectDescription').fill('Test af persisted statusflow for tømrer med tagmål og smart pakke.');
await page.getByRole('button', { name: /Gem Projekt/i }).click();
await page.waitForTimeout(4000);
await page.screenshot({ path: path.join(ARTIFACTS_DIR, '01-after-create.png'), fullPage: true });
let snapshot = await waitForProjectSnapshot(page, projectName);
console.log('STEP after_create', JSON.stringify(snapshot));
await fillGeometry(page);
await page.screenshot({ path: path.join(ARTIFACTS_DIR, '02-after-geometry.png'), fullPage: true });
snapshot = await waitForProjectSnapshot(page, projectName);
console.log('STEP after_geometry', JSON.stringify(snapshot));
await completeSmartPackage(page);
await page.screenshot({ path: path.join(ARTIFACTS_DIR, '03-after-smart-package.png'), fullPage: true });
snapshot = await waitForProjectSnapshot(page, projectName);
console.log('STEP after_smart_package', JSON.stringify(snapshot));
await goToFinalReview(page);
await page.screenshot({ path: path.join(ARTIFACTS_DIR, '04-final-review.png'), fullPage: true });
snapshot = await waitForProjectSnapshot(page, projectName);
console.log('STEP after_review', JSON.stringify({
snapshot,
hasReadyButton: await page.getByRole('button', { name: /Klar til Ordrestyring/i }).isVisible().catch(() => false),
hasSendButton: await page.getByRole('button', { name: /Send til Ordrestyring/i }).isVisible().catch(() => false)
}));
const readyBtn = page.getByRole('button', { name: /Klar til Ordrestyring/i }).first();
if (await readyBtn.isVisible({ timeout: 5000 }).catch(() => false)) {
await readyBtn.click();
await page.waitForTimeout(3000);
}
await page.screenshot({ path: path.join(ARTIFACTS_DIR, '05-after-ready.png'), fullPage: true });
snapshot = await waitForProjectSnapshot(page, projectName);
console.log('STEP after_ready', JSON.stringify(snapshot));
const sendBtn = page.getByRole('button', { name: /Send til Ordrestyring/i }).first();
let sendResult = 'button_not_found';
if (await sendBtn.isVisible({ timeout: 5000 }).catch(() => false)) {
await sendBtn.click();
await page.waitForTimeout(15000);
const bodyText = await page.locator('body').textContent();
if (bodyText.includes('Tilbud sendt til ordrestyring')) {
sendResult = 'success';
} else if (bodyText.includes('Fejl ved indsendelse')) {
sendResult = 'error';
} else {
sendResult = 'unknown';
}
}
await page.screenshot({ path: path.join(ARTIFACTS_DIR, '06-after-send.png'), fullPage: true });
snapshot = await waitForProjectSnapshot(page, projectName);
console.log('STEP after_send', JSON.stringify({ snapshot, sendResult }));
} finally {
await browser.close();
}
}
main().catch((error) => {
console.error('STATUS_FLOW_ERROR', error);
process.exit(1);
});