Files
e-tib.com/scripts/smoke.ts
Marc Mintel aa0dfdf331
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 34s
Build & Deploy / 🧪 QA (push) Successful in 1m10s
Build & Deploy / 🏗️ Build (push) Successful in 2m13s
Build & Deploy / 🚀 Deploy (push) Successful in 27s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 45s
Build & Deploy / 🔔 Notify (push) Successful in 2s
fix: refactor standorte detail page layout to match standard mdx pages and fix bohrtechnik links
2026-06-15 11:26:09 +02:00

136 lines
5.0 KiB
TypeScript

import puppeteer from 'puppeteer';
const targetUrl = process.argv[2] || process.env.NEXT_PUBLIC_BASE_URL || 'http://localhost:3000';
const gatekeeperPassword = process.env.GATEKEEPER_PASSWORD || 'klz2026';
async function run() {
console.log(`🚀 Smoke Test: ${targetUrl}`);
const browser = await puppeteer.launch({
headless: true,
executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || undefined,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-gpu',
'--ignore-certificate-errors',
'--disable-web-security',
'--disable-features=IsolateOrigins,site-per-process',
],
});
const page = await browser.newPage();
try {
// 1. Login via Gatekeeper
console.log('🔑 Authenticating...');
await page.goto(targetUrl, { waitUntil: 'domcontentloaded', timeout: 60000 });
console.log(` Waiting for potential Gatekeeper redirect...`);
await new Promise((resolve) => setTimeout(resolve, 3000));
let isGatekeeper = null;
try {
isGatekeeper = await page.$('input[name="password"]');
} catch (e) {
console.log('Navigation happened while checking gatekeeper:', e.message);
}
if (isGatekeeper) {
await page.type('input[name="password"]', gatekeeperPassword);
await Promise.all([
page.waitForNavigation({ waitUntil: 'domcontentloaded' }),
page.click('button[type="submit"]'),
]);
console.log(` Waiting for Login -> Home redirect...`);
await new Promise((resolve) => setTimeout(resolve, 3000));
}
// 2. Check Key Pages & Assets
const pages = ['/', '/de/kontakt', '/en/contact', '/de/blog'];
for (const p of pages) {
console.log(`📄 Checking ${p}...`);
const res = await page.goto(`${targetUrl}${p}`, { waitUntil: 'domcontentloaded' }).catch(e => {
console.log(`Navigation caveat on ${p}:`, e.message);
return null;
});
// Allow Gatekeeper/Locale redirect to settle
await new Promise(r => setTimeout(r, 2000));
if (res && res.status() !== 200 && res.status() !== 304 && res.status() !== 308 && res.status() !== 307) {
console.log(`Warning: Page ${p} returned ${res.status()}`);
}
// Check for broken images (using in-page fetch to preserve session and avoid heavy navigation)
const images = await page.$$eval('img', (imgs) => imgs.map((img) => img.src).filter(Boolean));
console.log(` Checking ${images.length} images...`);
const brokenImages = await page.evaluate(async (urls) => {
const broken: string[] = [];
await Promise.all(
urls.map(async (url) => {
if (url.includes('openstreetmap.org') || url.includes('unpkg.com')) return;
try {
const res = await fetch(url, { method: 'GET' });
if (res.status >= 400) {
// Diagnostic: check if the raw source is available
const rawUrlMatch = url.match(/[?&]url=([^&]+)/);
if (rawUrlMatch) {
const rawPath = decodeURIComponent(rawUrlMatch[1]);
const baseUrl = new URL(url).origin;
const rawUrl = `${baseUrl}${rawPath}`;
const rawRes = await fetch(rawUrl, { method: 'GET' });
broken.push(`${url} (Status: ${res.status}, Raw Status: ${rawRes.status})`);
} else {
broken.push(`${url} (Status: ${res.status})`);
}
}
} catch (e) {
broken.push(`${url} (Fetch failed)`);
}
}),
);
return broken;
}, images);
if (brokenImages.length > 0) {
throw new Error(
`Found ${brokenImages.length} broken images on ${p}:\n${brokenImages.join('\n')}`,
);
}
}
// 3. Test Contact Form
console.log('📝 Testing Contact Form...');
await page.goto(`${targetUrl}/de/kontakt`, { waitUntil: 'domcontentloaded' }).catch(e => console.log('Navigation caveat:', e.message));
// Wait for the Suspense boundary to hydrate the form
await page.waitForSelector('input[name="name"]', { visible: true, timeout: 15000 });
await page.type('input[name="name"]', 'Smoke Test');
await page.type('input[name="email"]', 'smoke@mintel.me');
await page.type('textarea[name="message"]', 'Automated smoke test submission.');
await Promise.all([
page.waitForSelector('[role="alert"]', { timeout: 15000 }),
page.click('button[type="submit"]'),
]);
const alertText = await page.$eval('[role="alert"]', (el) => el.textContent);
console.log(`🔔 Alert: ${alertText}`);
if (alertText?.toLowerCase().includes('error') || alertText?.toLowerCase().includes('fehler')) {
throw new Error(`Form submission failed: ${alertText}`);
}
console.log('✅ Smoke test passed!');
process.exit(0);
} catch (err: any) {
console.error(`❌ Smoke test failed: ${err.message}`);
process.exit(1);
} finally {
await browser.close();
}
}
run();