Files
tilbudgivern/tests/production-verification.spec.js
alexpolo1 26d3452d59 Add comprehensive tests for API verification, frontend integration, and PDF generation
- Implemented a new test suite for production API verification using curl, ensuring all critical endpoints respond correctly and return valid JSON.
- Added frontend integration tests to check for critical errors in the UI and verify key UI elements are present and functional.
- Created test data for quotes and project calculations to facilitate testing.
- Developed a script to check offers in the Ordrestyring system, including detailed task descriptions.
- Added tests for generating PDFs from quote data, ensuring the output is valid and contains expected information.
- Implemented a test script for the Røsevangen project, integrating with the Ordrestyring API and verifying database entries.
2025-11-07 08:02:07 +00:00

231 lines
7.9 KiB
JavaScript

const { test, expect } = require('@playwright/test');
// Production URL
const BASE_URL = 'https://tilbudsgiveren.alw.dk';
test.describe('Tilbudgivern Production Verification', () => {
test('Frontend loads successfully', async ({ page }) => {
await page.goto(BASE_URL);
// Should load without errors
await expect(page).toHaveTitle(/Tilbudgivern/i);
// Should show main interface elements
await expect(page.locator('body')).toBeVisible();
// No critical JavaScript errors
const errors = [];
page.on('pageerror', error => errors.push(error.message));
await page.waitForTimeout(3000); // Wait for JS to load
expect(errors.filter(e => e.includes('Cannot read properties of undefined'))).toHaveLength(0);
});
test('SmartPackages API works correctly', async ({ request }) => {
const response = await request.get(`${BASE_URL}/api/smart-packages?limit=5`, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
});
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.success).toBe(true);
expect(data.packages).toBeDefined();
expect(Array.isArray(data.packages)).toBe(true);
expect(data.packages.length).toBeGreaterThan(0);
// Verify package structure
const packageItem = data.packages[0];
expect(packageItem).toHaveProperty('id');
expect(packageItem).toHaveProperty('name');
expect(packageItem).toHaveProperty('category');
expect(packageItem).toHaveProperty('difficulty_level');
});
test('Categories API works correctly', async ({ request }) => {
const response = await request.get(`${BASE_URL}/api/smart-packages/categories`);
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.success).toBe(true);
expect(data.categories).toBeDefined();
expect(Array.isArray(data.categories)).toBe(true);
expect(data.categories.length).toBeGreaterThan(0);
// Should contain expected categories
expect(data.categories).toContain('Tagarbejde');
});
test('Materials API works correctly', async ({ request }) => {
const response = await request.get(`${BASE_URL}/api/materials?limit=5`);
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.success).toBe(true);
expect(data.materials).toBeDefined();
expect(Array.isArray(data.materials)).toBe(true);
expect(data.materials.length).toBeGreaterThan(0);
// Verify material structure
const material = data.materials[0];
expect(material).toHaveProperty('id');
expect(material).toHaveProperty('name');
expect(material).toHaveProperty('category');
expect(material).toHaveProperty('unit');
});
test('Employees API works correctly - Calendar Fix Verification', async ({ request }) => {
const response = await request.get(`${BASE_URL}/api/planning/employees`);
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.success).toBe(true);
expect(data.employees).toBeDefined();
expect(Array.isArray(data.employees)).toBe(true);
// Critical fix verification: Should have active employees (not 0)
expect(data.count).toBeGreaterThan(0);
expect(data.employees.length).toBeGreaterThan(0);
expect(data.totalEmployees).toBeGreaterThan(0);
// Verify employee structure
if (data.employees.length > 0) {
const employee = data.employees[0];
expect(employee).toHaveProperty('id');
expect(employee).toHaveProperty('first_name');
expect(employee).toHaveProperty('last_name');
expect(employee).toHaveProperty('employee_type_title');
}
console.log(`✅ Employee Fix Verified: ${data.count} active employees out of ${data.totalEmployees} total`);
});
test('Planning Calendar API works correctly', async ({ request }) => {
const response = await request.get(`${BASE_URL}/api/planning/calendar`);
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.success).toBe(true);
expect(data.data).toBeDefined();
expect(Array.isArray(data.data)).toBe(true);
// Should have calendar events
expect(data.data.length).toBeGreaterThan(0);
// Verify calendar event structure
const event = data.data[0];
expect(event).toHaveProperty('employee_id');
expect(event).toHaveProperty('start_time');
expect(event).toHaveProperty('first_name');
expect(event).toHaveProperty('last_name');
console.log(`✅ Calendar API Verified: ${data.data.length} calendar events loaded`);
});
test('Enhanced Roof Types API works correctly', async ({ request }) => {
const response = await request.get(`${BASE_URL}/api/enhanced/roof-types`);
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.success).toBe(true);
expect(data.roofTypes).toBeDefined();
expect(Array.isArray(data.roofTypes)).toBe(true);
expect(data.roofTypes.length).toBeGreaterThan(0);
// Verify clean labels (no complexity suffix)
const roofType = data.roofTypes[0];
expect(roofType).toHaveProperty('value');
expect(roofType).toHaveProperty('label');
expect(roofType.label).not.toMatch(/\(kompleksitet/i); // No complexity suffix
console.log(`✅ Roof Types Verified: ${data.roofTypes.length} clean roof type labels`);
});
test('Health endpoint responds correctly', async ({ request }) => {
const response = await request.get(`${BASE_URL}/api/health`);
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.status).toBe('ok');
expect(data.timestamp).toBeDefined();
});
test('Frontend UI Elements - Key Features Present', async ({ page }) => {
await page.goto(BASE_URL);
await page.waitForLoadState('networkidle');
// Wait for React app to fully load
await page.waitForTimeout(5000);
// Check for key UI elements (this may need adjustment based on actual UI)
const pageContent = await page.content();
// Should not show critical errors
expect(pageContent).not.toContain('Ingen materialer fundet');
expect(pageContent).not.toContain('Smart Package Management Service ikke initialiseret');
expect(pageContent).not.toContain('Failed to load categories');
console.log('✅ Frontend UI loaded without critical errors');
});
test('No 500/503 errors in recent requests', async ({ page }) => {
const responses = [];
page.on('response', response => {
responses.push({
url: response.url(),
status: response.status()
});
});
await page.goto(BASE_URL);
await page.waitForLoadState('networkidle');
await page.waitForTimeout(5000);
// Check for any 500/503 errors
const serverErrors = responses.filter(r => r.status >= 500);
if (serverErrors.length > 0) {
console.log('❌ Server errors found:', serverErrors);
}
expect(serverErrors).toHaveLength(0);
console.log(`✅ No server errors found in ${responses.length} requests`);
});
});
test.describe('API Performance Tests', () => {
test('All critical APIs respond within acceptable time', async ({ request }) => {
const endpoints = [
'/api/health',
'/api/smart-packages?limit=5',
'/api/smart-packages/categories',
'/api/materials?limit=5',
'/api/planning/employees',
'/api/enhanced/roof-types'
];
for (const endpoint of endpoints) {
const start = Date.now();
const response = await request.get(`${BASE_URL}${endpoint}`);
const duration = Date.now() - start;
expect(response.status()).toBe(200);
expect(duration).toBeLessThan(10000); // Should respond within 10 seconds
console.log(`${endpoint}: ${response.status()} in ${duration}ms`);
}
});
});