chore: stabilize pipeline and harden infrastructure
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 9s
Build & Deploy / 🧪 QA (push) Failing after 1m43s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 3s
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 9s
Build & Deploy / 🧪 QA (push) Failing after 1m43s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 3s
- Harden E2E smoke tests with increased timeouts and German keyword detection - Implement defensive body parsing in analytics relay to prevent crashes - Refine middleware to bypass i18n logic for Server Actions - Fix date formatting consistency and JsonLd validation
This commit is contained in:
@@ -103,8 +103,10 @@ async function main() {
|
||||
console.log(`\n🧪 Testing Contact Form on: ${contactUrl}`);
|
||||
await page.goto(contactUrl, { waitUntil: 'networkidle0', timeout: 30000 });
|
||||
|
||||
// Ensure React has hydrated completely
|
||||
await page.waitForNetworkIdle({ idleTime: 1000, timeout: 15000 }).catch(() => {});
|
||||
// Ensure React has hydrated completely - CI runners can be slow
|
||||
console.log(` ⏳ Waiting for hydration (5s)...`);
|
||||
await page.evaluate(() => new Promise((resolve) => setTimeout(resolve, 5000)));
|
||||
await page.waitForNetworkIdle({ idleTime: 1000, timeout: 20000 }).catch(() => {});
|
||||
|
||||
// Ensure form is visible and interactive
|
||||
try {
|
||||
@@ -129,18 +131,32 @@ async function main() {
|
||||
// Give state a moment to settle
|
||||
await page.evaluate(() => new Promise((resolve) => setTimeout(resolve, 500)));
|
||||
|
||||
console.log(` Submitting Contact Form...`);
|
||||
|
||||
// Explicitly click submit and wait for navigation/state-change
|
||||
await Promise.all([
|
||||
page.waitForSelector('[role="alert"]', { timeout: 15000 }),
|
||||
page.click('button[type="submit"]'),
|
||||
]);
|
||||
console.log(` ⏳ Waiting for alert selector (30s)...`);
|
||||
try {
|
||||
// Explicitly click submit and wait for navigation/state-change
|
||||
await Promise.all([
|
||||
page.waitForSelector('[role="alert"]', { timeout: 30000 }),
|
||||
page.click('button[type="submit"]'),
|
||||
]);
|
||||
} catch (e) {
|
||||
console.error(`❌ Timeout waiting for [role="alert"]. Dumping page content:`);
|
||||
const bodyHTML = await page.evaluate(() => document.body.innerHTML.slice(0, 1000));
|
||||
console.log(`💻 PAGE BODY (partial): ${bodyHTML}`);
|
||||
throw e;
|
||||
}
|
||||
|
||||
const alertText = await page.$eval('[role="alert"]', (el) => el.textContent);
|
||||
console.log(` Alert text: ${alertText}`);
|
||||
console.log(` 🔔 Alert text: ${alertText}`);
|
||||
|
||||
if (alertText?.includes('Failed') || alertText?.includes('went wrong')) {
|
||||
// Detection robust for both English and German versions
|
||||
const isError =
|
||||
alertText?.toLowerCase().includes('failed') ||
|
||||
alertText?.toLowerCase().includes('wrong') ||
|
||||
alertText?.toLowerCase().includes('fehlgeschlagen') ||
|
||||
alertText?.toLowerCase().includes('schief gelaufen') ||
|
||||
alertText?.toLowerCase().includes('fehler');
|
||||
|
||||
if (isError) {
|
||||
throw new Error(`Form submitted but showed error: ${alertText}`);
|
||||
}
|
||||
|
||||
@@ -156,7 +172,9 @@ async function main() {
|
||||
await page.goto(productUrl, { waitUntil: 'networkidle0', timeout: 30000 });
|
||||
|
||||
// Ensure React has hydrated completely
|
||||
await page.waitForNetworkIdle({ idleTime: 1000, timeout: 15000 }).catch(() => {});
|
||||
console.log(` ⏳ Waiting for hydration (5s)...`);
|
||||
await page.evaluate(() => new Promise((resolve) => setTimeout(resolve, 5000)));
|
||||
await page.waitForNetworkIdle({ idleTime: 1000, timeout: 20000 }).catch(() => {});
|
||||
|
||||
// The product form uses dynamic IDs, so we select by input type in the specific form context
|
||||
try {
|
||||
@@ -179,18 +197,31 @@ async function main() {
|
||||
// Give state a moment to settle
|
||||
await page.evaluate(() => new Promise((resolve) => setTimeout(resolve, 500)));
|
||||
|
||||
console.log(` Submitting Product Quote Form...`);
|
||||
|
||||
// Submit and wait for success state
|
||||
await Promise.all([
|
||||
page.waitForSelector('[role="alert"]', { timeout: 15000 }),
|
||||
page.click('form button[type="submit"]'),
|
||||
]);
|
||||
console.log(` ⏳ Waiting for alert selector (30s)...`);
|
||||
try {
|
||||
// Submit and wait for success state
|
||||
await Promise.all([
|
||||
page.waitForSelector('[role="alert"]', { timeout: 30000 }),
|
||||
page.click('form button[type="submit"]'),
|
||||
]);
|
||||
} catch (e) {
|
||||
console.error(`❌ Timeout waiting for [role="alert"] on Product page. Dumping content:`);
|
||||
const bodyHTML = await page.evaluate(() => document.body.innerHTML.slice(0, 1000));
|
||||
console.log(`💻 PAGE BODY (partial): ${bodyHTML}`);
|
||||
throw e;
|
||||
}
|
||||
|
||||
const alertText = await page.$eval('[role="alert"]', (el) => el.textContent);
|
||||
console.log(` Alert text: ${alertText}`);
|
||||
console.log(` 🔔 Alert text: ${alertText}`);
|
||||
|
||||
if (alertText?.includes('Failed') || alertText?.includes('went wrong')) {
|
||||
const isError =
|
||||
alertText?.toLowerCase().includes('failed') ||
|
||||
alertText?.toLowerCase().includes('wrong') ||
|
||||
alertText?.toLowerCase().includes('fehlgeschlagen') ||
|
||||
alertText?.toLowerCase().includes('schief gelaufen') ||
|
||||
alertText?.toLowerCase().includes('fehler');
|
||||
|
||||
if (isError) {
|
||||
throw new Error(`Form submitted but showed error: ${alertText}`);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user