Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: it.skip no longer causes hooks to be assigned to the wrong test #8113

Merged
merged 9 commits into from
Aug 4, 2020
4 changes: 2 additions & 2 deletions packages/driver/src/cypress/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ const hookFailed = (hook, err, hookName, getTest, getTestFromHookOrFindTest) =>
// NOTE: sometimes mocha will fail a hook without having emitted on('hook')
// event, so this hook might not have currentTest set correctly
// in which case we need to lookup the test
const test = getTest() || getTestFromHookOrFindTest(hook)
const test = getTestFromHookOrFindTest(hook)
panzarino marked this conversation as resolved.
Show resolved Hide resolved

test.err = err
test.state = 'failed'
Expand Down Expand Up @@ -622,7 +622,7 @@ const _runnerListeners = (_runner, Cypress, _emissions, getTestById, getTest, se
// hooks do not have their own id, their
// commands need to grouped with the test
// and we can only associate them by this id
const test = getTest() || getTestFromHookOrFindTest(hook)
const test = getTestFromHookOrFindTest(hook)

if (!test) {
// we couldn't find a test to run with this hook
Expand Down
31 changes: 31 additions & 0 deletions packages/runner/cypress/fixtures/hooks/only_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
describe('test wrapper', () => {
it('test 1', () => {
cy.log('testBody 1')
})

describe('nested suite 1', () => {
beforeEach(() => {
cy.log('beforeEachHook 1')
})

it.only('test 2', () => {
cy.log('testBody 2')
})
})

describe('nested suite 2', () => {
beforeEach(() => {
cy.log('beforeEachHook 2')
})

it('test 3', () => {
cy.log('testBody 3')
})
})

describe('nested suite 3', () => {
it.only('test 4', () => {
cy.log('testBody 4')
})
})
})
15 changes: 15 additions & 0 deletions packages/runner/cypress/fixtures/hooks/skip_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
describe('outer suite', () => {
it.skip('test 1', () => {
cy.log('testBody 1')
})

describe('inner suite', () => {
before(() => {
cy.log('beforeHook 1')
})

it('test 2', () => {
cy.log('testBody 2')
})
})
})
148 changes: 100 additions & 48 deletions packages/runner/cypress/integration/reporter.hooks.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,67 +4,119 @@ const { createCypress } = helpers
const { runIsolatedCypress } = createCypress()

describe('hooks', function () {
beforeEach(function () {
this.editor = {}

return runIsolatedCypress(`cypress/fixtures/hook_spec.js`, {
onBeforeRun: ({ win }) => {
this.win = win

win.runnerWs.emit.withArgs('get:user:editor')
.yields({
preferredOpener: this.editor,
})
},
describe('displays hooks', function () {
beforeEach(function () {
return runIsolatedCypress(`cypress/fixtures/hooks/basic_spec.js`)
})
})

it('displays commands under correct hook', function () {
cy.contains('tests 1').click()
it('displays commands under correct hook', function () {
cy.contains('tests 1').click()

cy.contains('before all').closest('.collapsible').should('contain', 'beforeHook 1')
cy.contains('before each').closest('.collapsible').should('contain', 'beforeEachHook 1')
cy.contains('test body').closest('.collapsible').should('contain', 'testBody 1')
cy.contains('after each').closest('.collapsible').should('contain', 'afterEachHook 1')
})
cy.contains('before all').closest('.collapsible').should('contain', 'beforeHook 1')
cy.contains('before each').closest('.collapsible').should('contain', 'beforeEachHook 1')
cy.contains('test body').closest('.collapsible').should('contain', 'testBody 1')
cy.contains('after each').closest('.collapsible').should('contain', 'afterEachHook 1')
})

it('displays hooks without number when only one of type', function () {
cy.contains('tests 1').click()
it('displays hooks without number when only one of type', function () {
cy.contains('tests 1').click()

cy.contains('before all').should('not.contain', '(1)')
cy.contains('before each').should('not.contain', '(1)')
cy.contains('after each').should('not.contain', '(1)')
cy.contains('before all').should('not.contain', '(1)')
cy.contains('before each').should('not.contain', '(1)')
cy.contains('after each').should('not.contain', '(1)')
})

it('displays hooks separately with number when more than one of type', function () {
cy.contains('tests 2').click()

cy.contains('before all (1)').closest('.collapsible').should('contain', 'beforeHook 2')
cy.contains('before all (2)').closest('.collapsible').should('contain', 'beforeHook 3')
cy.contains('before each (1)').closest('.collapsible').should('contain', 'beforeEachHook 1')
cy.contains('before each (2)').closest('.collapsible').should('contain', 'beforeEachHook 2')
cy.contains('test body').closest('.collapsible').should('contain', 'testBody 2')
cy.contains('after each (1)').closest('.collapsible').should('contain', 'afterEachHook 2')
cy.contains('after each (2)').closest('.collapsible').should('contain', 'afterEachHook 1')
cy.contains('after all (1)').closest('.collapsible').should('contain', 'afterHook 2')
cy.contains('after all (2)').closest('.collapsible').should('contain', 'afterHook 1')
})
})

it('displays hooks separately with number when more than one of type', function () {
cy.contains('tests 2').click()

cy.contains('before all (1)').closest('.collapsible').should('contain', 'beforeHook 2')
cy.contains('before all (2)').closest('.collapsible').should('contain', 'beforeHook 3')
cy.contains('before each (1)').closest('.collapsible').should('contain', 'beforeEachHook 1')
cy.contains('before each (2)').closest('.collapsible').should('contain', 'beforeEachHook 2')
cy.contains('test body').closest('.collapsible').should('contain', 'testBody 2')
cy.contains('after each (1)').closest('.collapsible').should('contain', 'afterEachHook 2')
cy.contains('after each (2)').closest('.collapsible').should('contain', 'afterEachHook 1')
cy.contains('after all (1)').closest('.collapsible').should('contain', 'afterHook 2')
cy.contains('after all (2)').closest('.collapsible').should('contain', 'afterHook 1')
describe('open in IDE', function () {
beforeEach(function () {
this.editor = {}

return runIsolatedCypress(`cypress/fixtures/hooks/basic_spec.js`, {
onBeforeRun: ({ win }) => {
this.win = win

win.runnerWs.emit.withArgs('get:user:editor')
.yields({
preferredOpener: this.editor,
})
},
})
})

it('creates open in IDE button', function () {
cy.contains('tests 1').click()

cy.get('.hook-open-in-ide').should('have.length', 4)
})

it('properly opens file in IDE at hook', function () {
cy.contains('tests 1').click()

cy.contains('Open in IDE').invoke('show').click().then(function () {
expect(this.win.runnerWs.emit.withArgs('open:file').lastCall.args[1].file).to.include('basic_spec.js')
// chrome sets the column to right before "before("
// while firefox sets it right after "before("
expect(this.win.runnerWs.emit.withArgs('open:file').lastCall.args[1].column).to.be.eq(Cypress.browser.family === 'firefox' ? 10 : 3)
expect(this.win.runnerWs.emit.withArgs('open:file').lastCall.args[1].line).to.be.eq(2)
})
})
})

it('creates open in IDE button', function () {
cy.contains('tests 1').click()
describe('skipped tests', function () {
beforeEach(function () {
return runIsolatedCypress(`cypress/fixtures/hooks/skip_spec.js`)
})

it('does not display commands from skipped tests', function () {
cy.contains('test 1').click()

cy.contains('test 1').parents('.collapsible').first().should('not.contain', 'testBody 1')
})

// https://github.com/cypress-io/cypress/issues/8086
it('displays before hook when following it.skip', function () {
cy.contains('test 2').click()

cy.get('.hook-open-in-ide').should('have.length', 4)
cy.contains('test 2').parents('.collapsible').first().should('contain', 'before all')
})
})

it('properly opens file in IDE at hook', function () {
cy.contains('tests 1').click()
describe('only tests', function () {
beforeEach(function () {
return runIsolatedCypress(`cypress/fixtures/hooks/only_spec.js`)
})

it('only displays tests with .only', function () {
cy.contains('test wrapper').parents('.collapsible').first().should(($suite) => {
expect($suite).not.to.contain('test 1')
expect($suite).to.contain('nested suite 1')
expect($suite).to.contain('test 2')
expect($suite).not.to.contain('nested suite 2')
expect($suite).not.to.contain('test 3')
expect($suite).to.contain('nested suite 3')
expect($suite).to.contain('test 4')
})

cy.contains('test 2').click()

cy.contains('Open in IDE').invoke('show').click().then(function () {
expect(this.win.runnerWs.emit.withArgs('open:file').lastCall.args[1].file).to.include('hook_spec.js')
// chrome sets the column to right before "before("
// while firefox sets it right after "before("
expect(this.win.runnerWs.emit.withArgs('open:file').lastCall.args[1].column).to.be.eq(Cypress.browser.family === 'firefox' ? 10 : 3)
expect(this.win.runnerWs.emit.withArgs('open:file').lastCall.args[1].line).to.be.eq(2)
cy.contains('test 2').parents('.collapsible').first().should(($test) => {
expect($test).to.contain('before each')
expect($test).to.contain('test body')
})
})
})
})