1
votes

I have a simple Cypress test:

    describe('My First Test', () => {
      it('Go to login page', () => {
        cy.visit('http://localhost:3000')
        cy.contains('Log in').click()
      })

      it('Login with local account', () => {
        cy.get('input[type=email]').type('[email protected]')
        cy.get('input[type=password]').type('asd123')
        cy.contains('Log in').type('{enter}')
      })
    })

The first assertion checks if there's a element with the text Log in, then clicks it. Second assertion tries to log in.

I've changed the text in the Log in button to Assertion Failed. So now the first assertion fails, but it still runs the second assertion even though I'm not redirected to the login page.

Is there a way to cancel a running spec when a assertion fails?

2
these are 2 different tests. It is just an alias of test,if you want it to fail, merge them into one test source: jestjs.io/docs/api#testname-fn-timeout - mosaad
The above comment is the correct answer. The describe construct groups together tests. But each test should stand alone. - Robert Moskal

2 Answers

0
votes

You can add an afterEach() and write this:

afterEach(function() {
  if (this.currentTest.state === 'failed') {
    Cypress.runner.stop()
  }
});

Or

You can use the plugin cypress-fail-fast and configure it at the Test level:

describe("All tests", {
  failFast: {
    enabled: false, // Children tests and describes will inherit this configuration
  },
}, () => {
  it("sanity test", {
    failFast: {
      enabled: true, // Overwrite configuration defined in parents
    },
  }, () => {
    // Will skip the rest of tests if this one fails
    expect(true).to.be.true;
  });

  it("second test",() => {
    // Will continue executing tests if this one fails
    expect(true).to.be.true;
  });
});

or, globally for all specsby writing in cypress.json:

{
  "env":
  {
    "FAIL_FAST_ENABLED": true
  }
}
0
votes

You can also use

afterEach(() => {
  if (cy.state('test').state === 'failed') {
    Cypress.runner.stop()
  }
})

but there is a problem with this, none of your after() hooks will run, including plugins like code-coverage.

A better solution is to dynamically skip following tests, similar to this answer How to add test case grouping in Cypress

beforeEach(function() {
  const suite = cy.state('test').parent
  if (suite.tests.some(test => test.state === 'failed')) {
    this.skip()
  }
})

This is my simplified test

describe('all tests', () => {

  describe('fail fast', () => {

    beforeEach(function() {               // move up to apply to all tests
      const suite = cy.state('test').parent;
      if (suite.tests.some(test => test.state === 'failed')) {
        console.log(`skipping test "${cy.state('test').title}"`)
        this.skip()
      }
    })

    after(() => {
      console.log('after')               // runs
    })

    it('fails', () => {
      expect(true).to.eq(false)          // fails
    })

    it('next', () => {
      expect(true).to.eq(true)           // skipped
    })
  })

  describe('no fail fast', () => {
    it('no skip', () => {
      expect(true).to.eq(true)           // runs
    })
  })
})