Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ module.exports = defineConfig({
openMode: false,
runMode: true,
},
setupNodeEvents(on, _config) {
setupNodeEvents(on, config) {
// Check for Cypress build marker
const markerPath = path.resolve(__dirname, 'tmp/.cypress-build-marker');
if (!fs.existsSync(markerPath)) {
Expand All @@ -51,14 +51,29 @@ module.exports = defineConfig({
throw new Error('Webpack was not built with CYPRESS=true. See console for details');
}

// Capture DB state once before entire test run
on('before:run', async () => {
await fetch('http://localhost:3000/__e2e__/command', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'db_state', options: 'capture' })
});
});
// In open mode (cypress open), the process stays alive between spec runs so
// manually-created UI data would be wiped when a test calls cy.appDbState('restore').
// Capture before each spec so the snapshot always reflects the current DB state.
// In run mode (both CI and local cypress:run), the process exits after the run so
// a single upfront capture via before:run is sufficient.
const captureDbState = async () => {
try {
await fetch('http://localhost:3000/__e2e__/command', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'db_state', options: 'capture' }),
});
} catch (err) {
console.error('[DB] Failed to capture DB state:', err.message);
}
};

if (config.isInteractive) {
// open mode (cypress open) — capture per-spec to pick up any manual UI changes
on('before:spec', () => captureDbState());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need an else for when it's not CI and not interactive (open)?

Or easier, would swap it and do if interactive, use before:spec, else, before:run?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. My bad

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's all good. Looks good to me!

} else {
on('before:run', () => captureDbState());
}

on('after:spec', (spec, results) => {
// Delete the video on CI if the spec passed and no tests retried
Expand Down
4 changes: 3 additions & 1 deletion cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@
// });

// Use cy.appDbState('restore') in afterEach to clean up test data.
// Note, db_state is automatically captured once before the suite via before:run.
// In CI db_state is captured once via before:run (before the entire run).
// In open mode (local dev) it is captured via before:spec (before each spec file),
// so any data created manually in the UI between spec runs is preserved.
Cypress.Commands.add('appDbState', function (options) {
return cy.app('db_state', options);
});
Loading