@revoloo/cypress6
Version:
Cypress.io end to end testing tool
409 lines (362 loc) • 11.1 kB
JavaScript
const helpers = require('../support/helpers')
const { shouldHaveTestResults, createCypress } = helpers
const { runIsolatedCypress } = createCypress()
const fx_simpleSingleTest = {
suites: { 'suite 1': { tests: [{ name: 'test 1' }] } },
}
const fx_failPass = {
suites: {
'suite 1': {
tests: [
{
name: 'test 1',
fail: true,
},
{ name: 'test 2' },
],
},
},
}
const fx_passFailPassFail = {
suites: {
'suite 1': {
tests: [
'test 1',
{
name: 'test 2',
fail: true,
},
],
},
'suite 2': {
tests: [
'test 1',
{
name: 'test 2',
fail: true,
},
],
},
},
}
describe('src/cypress/runner', () => {
describe('tests finish with correct state', () => {
it('simple 1 test', () => {
runIsolatedCypress(fx_simpleSingleTest)
.then(shouldHaveTestResults(1, 0))
})
it('simple 1 global test', () => {
runIsolatedCypress(() => {
it('foo', () => {
expect(true).is.true
})
})
.then(shouldHaveTestResults(1, 0))
})
it('simple 3 tests', () => {
runIsolatedCypress({
suites: {
'suite 1': { tests: ['test 1', 'test 2', 'test 3'] },
},
})
.then(shouldHaveTestResults(3, 0))
})
it('simple fail', () => {
runIsolatedCypress({
suites: {
'suite 1': {
tests: [
{
name: 'test 1',
fail: true,
},
],
},
},
})
.then(shouldHaveTestResults(0, 1))
.then(() => {
// render exactly one error
cy.get('.runnable-err:contains(AssertionError)').should('have.length', 1)
})
})
it('pass fail pass fail', () => {
runIsolatedCypress(fx_passFailPassFail)
.then(shouldHaveTestResults(2, 2))
})
it('fail pass', () => {
runIsolatedCypress(fx_failPass)
.then(shouldHaveTestResults(1, 1))
})
it('no tests', () => {
runIsolatedCypress({})
.then(shouldHaveTestResults(0, 0))
cy.contains('No tests found.').should('be.visible')
cy.contains('p', 'Cypress could not detect tests in this file.').should('be.visible')
})
it('ends test before nested suite', () => {
runIsolatedCypress({
suites: {
'suite 1': { tests: ['test 1', 'test 2'],
suites: {
'suite 1-1': {
tests: ['test 1'],
},
} },
},
}, {})
.then(shouldHaveTestResults(3, 0))
})
it('simple fail, catch cy.on(fail)', () => {
runIsolatedCypress({
suites: {
'suite 1': {
tests: [
{
name: 'test 1',
fn: () => {
cy.on('fail', () => {
return false
})
expect(false).ok
throw new Error('error in test')
},
eval: true,
},
],
},
},
})
.then(shouldHaveTestResults(1, 0))
})
describe('hook failures', () => {
describe('test failures w/ hooks', () => {
it('test [only]', () => {
runIsolatedCypress({
suites: {
'suite 1': {
hooks: ['before', 'beforeEach', 'afterEach', 'after'],
tests: [
{ name: 'test 1' },
{ name: 'test 2', only: true },
{ name: 'test 3' },
],
},
},
}).then(shouldHaveTestResults(1, 0))
})
it('test [pending]', () => {
runIsolatedCypress(() => {
before(() => {})
it('t1')
it('t2')
it('t3')
after(() => {})
}).then(shouldHaveTestResults(0, 0, 3))
})
it('fail with [before]', () => {
runIsolatedCypress({
suites: {
'suite 1': {
hooks: ['before'],
tests: [
{
name: 'test 1',
fail: true,
},
{ name: 'test 2' },
],
},
},
})
.then(shouldHaveTestResults(1, 1))
})
it('fail with [after]', () => {
runIsolatedCypress({
suites: {
'suite 1': {
hooks: [{ type: 'after' }],
tests: [{ name: 'test 1', fail: true }, 'test 2'],
},
},
})
.then(shouldHaveTestResults(1, 1))
})
it('fail with all hooks', () => {
runIsolatedCypress({
suites: {
'suite 1': {
hooks: ['before', 'beforeEach', 'afterEach', 'after'],
tests: [{ name: 'test 1', fail: true }],
},
},
})
.then(shouldHaveTestResults(0, 1))
})
})
})
})
describe('other specs', () => {
it('simple failing hook spec', () => {
const mochaTests = {
suites: {
'simple failing hook spec': {
suites: {
'beforeEach hooks': {
hooks: [{ type: 'beforeEach', fail: true }],
tests: ['never gets here'],
},
'pending': {
tests: [{ name: 'is pending', pending: true }],
},
'afterEach hooks': {
hooks: [{ type: 'afterEach', fail: true }],
tests: ['fails this', 'does not run this'],
},
'after hooks': {
hooks: [{ type: 'after', fail: true }]
, tests: ['runs this', 'fails on this'],
},
},
},
},
}
runIsolatedCypress(mochaTests)
.then(shouldHaveTestResults(1, 3))
.then(() => {
cy.contains('.test', 'never gets here').should('have.class', 'runnable-failed')
cy.contains('.command', 'beforeEach').should('have.class', 'command-state-failed')
cy.contains('.runnable-err', 'beforeEach').scrollIntoView().should('be.visible')
cy.contains('.test', 'is pending').should('have.class', 'runnable-pending')
cy.contains('.test', 'fails this').should('have.class', 'runnable-failed')
cy.contains('.command', 'afterEach').should('have.class', 'command-state-failed')
cy.contains('.runnable-err', 'afterEach').should('be.visible')
cy.contains('.test', 'does not run this').should('have.class', 'runnable-processing')
cy.contains('.test', 'runs this').should('have.class', 'runnable-passed')
cy.contains('.test', 'fails on this').should('have.class', 'runnable-failed')
cy.contains('.command', 'after').should('have.class', 'command-state-failed')
cy.contains('.runnable-err', 'after').should('be.visible')
})
})
it('async timeout spec', () => {
runIsolatedCypress({
suites: {
'async': {
tests: [
{ name: 'bar fails',
// eslint-disable-next-line
fn (done) {
this.timeout(100)
cy.on('fail', () => {})
// eslint-disable-next-line
foo.bar()
},
eval: true,
},
],
},
},
})
.then(shouldHaveTestResults(0, 1))
})
it('scrolls each command into view', () => {
// HACK to assert on the dom DURING the runIsolatedCypress run
// we expect the last command item to be scrolled into view before
// the test ends
const result = cy.now('get', '.command-number:contains(25):visible').catch((e) => cy.state('reject')(e))
runIsolatedCypress(() => {
describe('s1', () => {
// Passing in done forces the spec to timeout
// eslint-disable-next-line
it('t1', (done) => {
cy.timeout(10)
Cypress._.times(25, () => expect(true).ok)
})
})
})
cy.wrap(result)
})
it('file with empty suites only displays no tests found', () => {
runIsolatedCypress({
suites: {
'suite 1': {
suites: {
'suite 2': {},
},
},
},
}).then(() => {
cy.get('.reporter').contains('No tests found')
})
})
})
describe('runner header', () => {
context('viewport dropdown', () => {
it('shows on click', () => {
runIsolatedCypress({})
cy.get('.viewport-menu').should('not.be.visible')
cy.get('.viewport-info button').click()
cy.get('.viewport-menu').should('be.visible')
cy.percySnapshot()
})
})
context('selector playground', () => {
it('shows on click', () => {
runIsolatedCypress({})
cy.get('.selector-playground').should('not.be.visible')
cy.get('.selector-playground-toggle').click()
cy.get('.selector-playground').should('be.visible')
cy.percySnapshot()
})
it('closes on restart', () => {
runIsolatedCypress({})
cy.get('.selector-playground-toggle').click()
cy.get('.selector-playground').should('be.visible')
cy.get('.restart').click()
cy.get('.selector-playground').should('not.be.visible')
})
})
})
describe('reporter interaction', () => {
// https://github.com/cypress-io/cypress/issues/8621
it('user can stop test execution', (done) => {
runIsolatedCypress(() => {
// eslint-disable-next-line mocha/handle-done-callback
it('test stops while running', (done) => {
cy.timeout(200)
cy.get('.not-exist')
setTimeout(() => {
cy.$$('button.stop', parent.document).click()
}, 100)
})
afterEach(function () {
this.currentTest.err = new Error('ran aftereach')
})
}, {
onBeforeRun ({ autCypress }) {
autCypress.on('test:after:run', (arg) => {
expect(arg.err.message).not.contain('aftereach')
done()
})
},
})
})
it('supports disabling command log reporter with env var NO_COMMAND_LOG', () => {
runIsolatedCypress(() => {
it('foo', () => {
// simulate a page load, ensures reporter state event is properly stubbed
cy.then(() => Cypress.action('cy:collect:run:state'))
cy.visit('/')
// ensures runner doesn't wait for nonexist before:screenshot ack
cy.screenshot({
capture: 'runner',
})
})
},
{
config: { env: { NO_COMMAND_LOG: '1' } },
})
cy.get('.reporter').should('not.exist')
})
})
})