chore(e2e): implement asset-resilience with cache-busting retries
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 7s
Build & Deploy / 🧪 QA (push) Successful in 1m5s
Build & Deploy / 🏗️ Build (push) Successful in 2m23s
Build & Deploy / 🚀 Deploy (push) Successful in 16s
Build & Deploy / 🧪 Post-Deploy Verification (push) Failing after 3m48s
Build & Deploy / 🔔 Notify (push) Successful in 3s
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 7s
Build & Deploy / 🧪 QA (push) Successful in 1m5s
Build & Deploy / 🏗️ Build (push) Successful in 2m23s
Build & Deploy / 🚀 Deploy (push) Successful in 16s
Build & Deploy / 🧪 Post-Deploy Verification (push) Failing after 3m48s
Build & Deploy / 🔔 Notify (push) Successful in 3s
This commit is contained in:
@@ -80,11 +80,48 @@ async function main() {
|
||||
|
||||
const page = await browser.newPage();
|
||||
|
||||
page.on('console', (msg) => console.log('💻 BROWSER CONSOLE:', msg.text()));
|
||||
page.on('pageerror', (error) => console.error('💻 BROWSER ERROR:', error.message));
|
||||
page.on('requestfailed', (request) => {
|
||||
console.error('💻 BROWSER REQUEST FAILED:', request.url(), request.failure()?.errorText);
|
||||
let chunkErrorsDetected = false;
|
||||
page.on('console', (msg) => {
|
||||
const text = msg.text();
|
||||
console.log('💻 BROWSER CONSOLE:', text);
|
||||
if (text.includes('ChunkLoadError') || text.includes('failed to load chunk')) {
|
||||
chunkErrorsDetected = true;
|
||||
}
|
||||
});
|
||||
page.on('pageerror', (error) => {
|
||||
console.error('💻 BROWSER ERROR:', error.message);
|
||||
if (error.message.includes('ChunkLoadError')) {
|
||||
chunkErrorsDetected = true;
|
||||
}
|
||||
});
|
||||
page.on('requestfailed', (request) => {
|
||||
const url = request.url();
|
||||
const failure = request.failure()?.errorText;
|
||||
console.error('💻 BROWSER REQUEST FAILED:', url, failure);
|
||||
if (url.endsWith('.js') && (failure === 'net::ERR_ABORTED' || failure?.includes('404'))) {
|
||||
chunkErrorsDetected = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Helper for resilient navigation with cache-busting fallback
|
||||
const navigateWithRetry = async (url: string, label: string) => {
|
||||
chunkErrorsDetected = false;
|
||||
console.log(`\n🧪 Testing ${label} on: ${url}`);
|
||||
|
||||
// First attempt
|
||||
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
|
||||
await delay(2000); // Allow initial JS execution
|
||||
|
||||
if (chunkErrorsDetected) {
|
||||
const cbUrl = `${url}${url.includes('?') ? '&' : '?'}cb=${Date.now()}`;
|
||||
console.warn(` ⚠️ Assets failed to load (Varnish staleness suspected). Retrying with cache-buster: ${cbUrl}`);
|
||||
chunkErrorsDetected = false;
|
||||
await page.goto(cbUrl, { waitUntil: 'domcontentloaded', timeout: 30000 });
|
||||
}
|
||||
|
||||
// Wait for network to settle slightly
|
||||
await page.waitForNetworkIdle({ idleTime: 500, timeout: 10000 }).catch(() => {});
|
||||
};
|
||||
|
||||
// 3. Authenticate through Gatekeeper login form
|
||||
try {
|
||||
@@ -123,13 +160,11 @@ async function main() {
|
||||
|
||||
// 4. Test Contact Form
|
||||
try {
|
||||
console.log(`\n🧪 Testing Contact Form on: ${contactUrl}`);
|
||||
await page.goto(contactUrl, { waitUntil: 'networkidle0', timeout: 30000 });
|
||||
await navigateWithRetry(contactUrl, 'Contact Form');
|
||||
|
||||
// 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(() => {});
|
||||
await delay(5000);
|
||||
|
||||
// Ensure form is visible and interactive
|
||||
try {
|
||||
@@ -191,13 +226,11 @@ async function main() {
|
||||
|
||||
// 4. Test Product Quote Form
|
||||
try {
|
||||
console.log(`\n🧪 Testing Product Quote Form on: ${productUrl}`);
|
||||
await page.goto(productUrl, { waitUntil: 'networkidle0', timeout: 30000 });
|
||||
await navigateWithRetry(productUrl, 'Product Quote Form');
|
||||
|
||||
// Ensure React has hydrated completely
|
||||
console.log(` ⏳ Waiting for hydration (5s)...`);
|
||||
await page.evaluate(() => new Promise((resolve) => setTimeout(resolve, 5000)));
|
||||
await page.waitForNetworkIdle({ idleTime: 1000, timeout: 20000 }).catch(() => {});
|
||||
await delay(5000);
|
||||
|
||||
// The product form uses dynamic IDs, so we select by input type in the specific form context
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user