Skip Before Each Hook

How a Cypress test can control the beforeEach hook behavior.

Imagine that we have a Cypress project with end-to-end tests and a support file. The support file has the beforeEach hooks common to all spec files.

cypress/support/e2e.js
1
2
3
beforeEach(function () {
cy.log('**beforeEach**')
})

Every e2e spec file is affected by the e2e support file, since it loads and runs before every spec. Let's say we have 2 tests in the spec.cy.js file:

cypress/e2e/spec.cy.js
1
2
3
4
5
6
7
8
9
10
it('runs a normal test', () => {
expect(1).to.equal(1)
})

it(
'avoids beforeEach hook in the support file',
() => {
expect(1).to.equal(1)
},
)

We can see the beforeEach hook execute before both tests.

The beforeEach hook runs before both tests

Here is our challenge: can we somehow skip or modify the beforeEach hook from the test? Can we skip it? In this blog, I will show how you can skip the hook by using the test config object. You can similarly control all aspects of the test.

🎁 You can find the source code shown in this blog post in the repo bahmutov/control-before-each-example.

The test config

Let's pick how a test can control its behavior. I will use the test config object. Let's say the test can signal that it wants the beforeEach hook skipped by setting a property:

cypress/e2e/spec.cy.js
1
2
3
4
5
6
7
it(
'avoids beforeEach hook in the support file',
{ skipBeforeEach: true },
() => {
expect(1).to.equal(1)
},
)

How can the code inside the beforeEach hook "know" about this configuration value skipBeforeEach? Let's inspect what we have in the test context object.

cypress/support/e2e.js
1
2
3
4
beforeEach(function () {
console.log(this.currentTest)
cy.log('**beforeEach**')
})

There is a lot stored in the currenTest object, but the last property _testConfig looks promising.

The test configuration object

Let's expand it. Oh my, what a find!

The test configuration in the unverified test config object

So the beforeEach hook code can find the test configuration values inside the this.currentTest._testConfig.unverifiedTestConfig object. If the test does not have any custom config properties, the object is empty. Let's control the hook's behavior.

cypress/support/e2e.js
1
2
3
4
5
6
7
beforeEach(function () {
if (this.currentTest._testConfig.unverifiedTestConfig.skipBeforeEach) {
cy.log('skipping beforeEach hook')
return
}
cy.log('**beforeEach**')
})

Skipping the beforeEach hook in the second test

Tip: you can go hardcore and overwrite the global beforeEach function to skip it automatically, but I have not found a way.

See also