Skip to content

Commit c804cbb

Browse files
committed
fix(cypress): enhance logging in test lifecycle hooks and improve error handling
1 parent cb3ab69 commit c804cbb

File tree

4 files changed

+52
-22
lines changed

4 files changed

+52
-22
lines changed

cypress/e2e/common/spec_utils.js

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,38 @@ export function after(taskResult, backend) {
1616
export function beforeEach(taskResult, backend) {
1717
const spec = Cypress.mocha.getRunner().suite.ctx.currentTest.parent.title;
1818
const testName = Cypress.mocha.getRunner().suite.ctx.currentTest.title;
19-
20-
console.log(`[${new Date().toISOString()}] [beforeEach] Starting for backend: ${backend}`);
21-
console.log(`[${new Date().toISOString()}] [beforeEach] mockResponses:`, taskResult.data.mockResponses);
22-
19+
20+
cy.task('log', `[beforeEach] backend=${backend} spec="${spec}" test="${testName}"`);
21+
cy.task('log', `[beforeEach] mockResponses=${String(taskResult.data.mockResponses)}`);
22+
2323
cy.task('setupBackendTest', {
2424
backend,
2525
...taskResult.data,
2626
spec,
2727
testName,
28+
}).then(() => {
29+
cy.task('log', '[beforeEach] setupBackendTest completed');
2830
});
2931

3032
if (taskResult.data.mockResponses) {
3133
const fixture = `${spec}__${testName}.json`;
32-
console.log('loading fixture:', fixture);
33-
cy.stubFetch({ fixture });
34+
cy.task('log', `[beforeEach] Loading fixture: "${fixture}"`);
35+
cy.stubFetch({ fixture }).then(() => {
36+
cy.task('log', '[beforeEach] stubFetch completed');
37+
});
38+
} else {
39+
cy.task('log', '[beforeEach] Skipping fixture load - mockResponses is false/undefined');
3440
}
3541

3642
// cy.clock(0, ['Date']) was hanging git-gateway tests after page load
3743
// Hypothesis: freezing time to 0 breaks app initialization during cy.visit()
3844
// Temporary fix: skip cy.clock for git-gateway, use default clock for others
3945
if (backend !== 'git-gateway') {
40-
console.log(`[${new Date().toISOString()}] [beforeEach] Setting clock to epoch 0 for non-git-gateway`);
46+
cy.task('log', '[beforeEach] Setting clock to epoch 0 for non-git-gateway');
4147
return cy.clock(0, ['Date']);
4248
}
43-
44-
console.log(`[${new Date().toISOString()}] [beforeEach] Skipped clock for git-gateway`);
49+
50+
cy.task('log', '[beforeEach] Skipped clock for git-gateway');
4551
}
4652

4753
export function afterEach(taskResult, backend) {
@@ -59,12 +65,24 @@ export function afterEach(taskResult, backend) {
5965
const {
6066
suite: {
6167
ctx: {
62-
currentTest: { state, _retries: retries, _currentRetry: currentRetry },
68+
currentTest: { state, _retries: retries, _currentRetry: currentRetry, err },
6369
},
6470
},
6571
} = Cypress.mocha.getRunner();
72+
73+
cy.task(
74+
'log',
75+
`[afterEach] backend=${backend} test="${testName}" state=${state} retry=${currentRetry}/${retries}`,
76+
);
77+
if (state === 'failed' && err?.message) {
78+
cy.task('log', `[afterEach] failure: ${err.message}`);
79+
}
80+
6681
if (state === 'failed' && retries === currentRetry) {
67-
Cypress.runner.stop();
82+
// Avoid deadlock in headless CI: runner.stop can leave recorded parallel runs hanging.
83+
if (Cypress.config('isInteractive')) {
84+
Cypress.runner.stop();
85+
}
6886
}
6987
}
7088
}

cypress/plugins/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ const { copyBackendFiles, switchVersion, updateConfig } = require('../utils/conf
4141
module.exports = async (on, config) => {
4242
// `on` is used to hook into various events Cypress emits
4343
on('task', {
44+
log(message) {
45+
console.log(message);
46+
return null;
47+
},
4448
async setupBackend({ backend, options }) {
4549
console.log('Preparing environment for backend', backend);
4650
await copyBackendFiles(backend);

cypress/support/e2e.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ addMatchImageSnapshotCommand({
2323
capture: 'viewport',
2424
});
2525

26-
Cypress.on('uncaught:exception', () => false);
26+
Cypress.on('uncaught:exception', (err) => {
27+
console.error('[UNCAUGHT EXCEPTION]', err.message);
28+
console.error('[UNCAUGHT EXCEPTION] Stack:', err.stack);
29+
return false; // Prevent Cypress from failing the test
30+
});
2731

2832
import './commands';
2933

cypress/utils/steps.js

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ const {
99
} = require('./constants');
1010

1111
function login(user) {
12-
console.log(`[${new Date().toISOString()}] [login] Starting with user:`, user ? 'yes' : 'no', user?.netlifySiteURL ? 'has site URL' : 'no site URL');
12+
cy.task(
13+
'log',
14+
`[login] start user=${user ? 'yes' : 'no'} netlifySiteURL=${user?.netlifySiteURL ? 'yes' : 'no'}`,
15+
);
1316
cy.viewport(1200, 1200);
1417
if (user) {
15-
console.log(`[${new Date().toISOString()}] [login] About to cy.visit('/')`);
18+
cy.task('log', '[login] about to visit /');
1619
cy.visit('/', {
1720
onBeforeLoad: () => {
1821
// https://github.com/cypress-io/cypress/issues/1208
@@ -21,26 +24,27 @@ function login(user) {
2124
if (user.netlifySiteURL) {
2225
window.localStorage.setItem('netlifySiteURL', user.netlifySiteURL);
2326
}
24-
console.log(`[${new Date().toISOString()}] [login] onBeforeLoad complete, localStorage set`);
2527
},
28+
}).then(() => {
29+
cy.task('log', '[login] visit completed');
2630
});
27-
console.log(`[${new Date().toISOString()}] [login] cy.visit('/') queued`);
2831
if (user.netlifySiteURL && user.email && user.password) {
29-
console.log(`[${new Date().toISOString()}] [login] About to fill login form`);
30-
cy.get('input[name="email"]').clear();
32+
cy.task('log', '[login] filling login form');
33+
cy.get('input[name="email"]', { timeout: 10000 }).clear();
3134
cy.get('input[name="email"]').type(user.email);
3235
cy.get('input[name="password"]').clear();
3336
cy.get('input[name="password"]').type(user.password);
3437
cy.contains('button', 'Login').click();
35-
console.log(`[${new Date().toISOString()}] [login] Login button clicked`);
38+
cy.task('log', '[login] login button clicked');
3639
}
3740
} else {
3841
cy.visit('/');
3942
cy.contains('button', 'Login').click();
4043
}
41-
console.log(`[${new Date().toISOString()}] [login] About to wait for "New Post" link`);
42-
cy.contains('a', 'New Post');
43-
console.log(`[${new Date().toISOString()}] [login] "New Post" link found - login complete`);
44+
cy.task('log', '[login] waiting for New Post link');
45+
cy.contains('a', 'New Post', { timeout: 60000 }).then(() => {
46+
cy.task('log', '[login] New Post link found');
47+
});
4448
}
4549

4650
function assertNotification(message) {

0 commit comments

Comments
 (0)