191 lines
7.3 KiB
JavaScript
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);
|
|
});
|