UNPKG

@revoloo/cypress6

Version:

Cypress.io end to end testing tool

310 lines (248 loc) 9.23 kB
import { EventEmitter } from 'events' import { itHandlesFileOpening } from '../support/utils' import Err from '../../src/errors/err-model' import { RootRunnable } from '../../src/runnables/runnables-store' describe('test errors', () => { let commandErr: Partial<Err> let setError: Function let runnablesWithErr: RootRunnable let runner: EventEmitter beforeEach(() => { cy.fixture('runnables_error').then((_runnablesWithErr) => runnablesWithErr = _runnablesWithErr) cy.fixture('command_error').then((_commandErr) => commandErr = _commandErr) runner = new EventEmitter() cy.visit('/').then((win) => { setError = (err: Error) => { // @ts-ignore runnablesWithErr.suites[0].tests[0].err = err cy.get('.reporter').then(() => { runner.emit('runnables:ready', runnablesWithErr) runner.emit('reporter:start', {}) }) } win.render({ runner, spec: { name: 'foo.js', relative: 'relative/path/to/foo.js', absolute: '/absolute/path/to/foo.js', }, }) }) }) describe('print to console', () => { beforeEach(() => { setError(commandErr) }) it('clicking prints to console', () => { cy.spy(runner, 'emit') cy.get('.runnable-err-print').click().should(() => { expect(runner.emit).to.be.calledWith('runner:console:error') // @ts-ignore const err = runner.emit.withArgs('runner:console:error').lastCall.args[1].err expect(err.message).to.equal(commandErr.message) expect(err.stack).to.equal(commandErr.stack) }) }) it('shows popup confirming output was printed', () => { cy.get('.runnable-err-print').click() cy.contains('Printed output to your console') }) it('does not collapse test when clicking', () => { cy.get('.runnable-err-print').click() cy.get('.command-wrapper').should('be.visible') }) it('does not expand or collapse stack trace when clicking', () => { cy.get('.runnable-err-print').click() cy.get('.runnable-err-stack-trace').should('not.be.visible') cy.contains('View stack trace').click() cy.get('.runnable-err-stack-trace').should('be.visible') cy.get('.runnable-err-print').click() cy.get('.runnable-err-stack-trace').should('be.visible') }) }) describe('stack trace', () => { beforeEach(() => { setError(commandErr) }) it('hides stack trace by default', () => { cy.get('.runnable-err-stack-trace').should('not.be.visible') }) it('opens stack trace on click', () => { cy.contains('View stack trace').click() cy.get('.runnable-err-stack-trace').should('be.visible') cy.percySnapshot() }) it('pairs down stack line whitespace', () => { cy.contains('View stack trace').click() cy.get('.runnable-err-stack-trace').within(() => { cy.get('.err-stack-line') .should('have.length', 10) .first().should('have.text', 'at foo.bar (my/app.js:2:7)') cy.get('.err-stack-line') .eq(1).should('have.text', ' at baz.qux (cypress/integration/foo_spec.js:5:2)') cy.get('.err-stack-line') .eq(2).should('have.text', ' at space (cypress/integration/a b.js:34:99)') cy.get('.err-stack-line') .eq(3).should('have.text', 'At previous event:') cy.get('.err-stack-line') .eq(4).should('have.text', ' at bar.baz (http://localhost:1234/me/dev/my/app.js:8:11)') cy.get('.err-stack-line') .eq(5).should('have.text', ' at callFn (cypress://../driver/src/cypress/runner.js:9:12)') }) }) it('does not include message in stack trace', () => { cy.contains('View stack trace').click() cy.get('.runnable-err-stack-trace') .invoke('text') .should('not.include', 'Some Error') .should('not.include', 'Message line below blank line') }) it('turns files into links', () => { cy.contains('View stack trace').click() cy.get('.runnable-err-stack-trace .runnable-err-file-path') .should('have.length', 3) .first() .should('have.text', 'my/app.js:2:7') cy.get('.runnable-err-stack-trace .runnable-err-file-path').eq(1) .should('have.text', 'cypress/integration/foo_spec.js:5:2') cy.get('.runnable-err-stack-trace .runnable-err-file-path').eq(2) .should('have.text', 'cypress/integration/a b.js:34:99') }) it('does not turn cypress:// files into links', () => { cy.contains('View stack trace').click() cy.contains('cypress://').find('a').should('not.exist') }) it('does not turn cypress_runner.js files into links', () => { cy.contains('View stack trace').click() cy.contains('cypress_runner.js').find('a').should('not.exist') }) it('does not turn lines without absoluteFile into links', () => { cy.contains('View stack trace').click() cy.contains('.err-stack-line', 'http://localhost:1234/me/dev/my/app.js:8:11') .find('a').should('not.exist') }) it('does not turn anything after "From Node.js Internals" into links', () => { cy.contains('View stack trace').click() cy.contains('events.js').find('a').should('not.exist') cy.contains('node/internals.js').find('a').should('not.exist') }) it('does not collapse test when clicking', () => { cy.contains('View stack trace').click() cy.get('.command-wrapper').should('be.visible') }) it('displays tooltip on hover', () => { cy.contains('View stack trace').click() cy.get('.runnable-err-stack-trace a').first().trigger('mouseover') cy.get('.cy-tooltip').first().should('have.text', 'Open in IDE') }) itHandlesFileOpening({ getRunner: () => runner, selector: '.runnable-err-stack-trace a', file: { file: '/me/dev/my/app.js', line: 2, column: 7, }, stackTrace: true, }) }) describe('command error', () => { it('shows error name', () => { setError(commandErr) cy.get('.runnable-err-name').should('contain', commandErr.name) }) it('renders and escapes markdown', () => { setError(commandErr) cy.get('.runnable-err-message') // renders `foo` as <code>foo</code> .contains('code', 'foo') .then((content) => { expect(content).not.to.contain('`foo`') }) // renders /`bar/` as `bar` cy.get('.runnable-err-message') .should('contain', '`bar`') // renders **baz** as <strong>baz</strong> cy.get('.runnable-err-message') .contains('strong', 'baz') .then((content) => { expect(content).not.to.contain('**baz**') }) // renders *fizz* as <em>fizz</em> cy.get('.runnable-err-message') .contains('em', 'fizz') .then((content) => { expect(content).not.to.contain('*fizz*') }) // ensure the page is loaded before taking snapshot cy.get('.focus-tests-text').should('be.visible') cy.percySnapshot() }) // NOTE: still needs to be implemented it.skip('renders and escapes markdown with leading/trailing whitespace', () => { cy.get('.runnable-err-message') // https://github.com/cypress-io/cypress/issues/1360 // renders ** buzz ** as <strong> buzz </strong> .contains('code', 'foo') .and('not.contain', '`foo`') }) }) describe('code frames', () => { beforeEach(() => { setError(commandErr) }) it('shows code frame when included on error', () => { cy .get('.test-err-code-frame') .should('be.visible') // ensure the page is loaded before taking snapshot cy.get('.focus-tests-text').should('be.visible') cy.percySnapshot() }) it('does not show code frame when not included on error', () => { commandErr.codeFrame = undefined cy .get('.test-err-code-frame') .should('not.exist') }) it('use correct language class', () => { cy .get('.test-err-code-frame pre') .should('have.class', 'language-javascript') }) it('falls back to text language class', () => { // @ts-ignore commandErr.codeFrame.language = null cy .get('.test-err-code-frame pre') .should('have.class', 'language-text') }) it('displays tooltip on hover', () => { cy.get('.test-err-code-frame a').first().trigger('mouseover') cy.get('.cy-tooltip').first().should('have.text', 'Open in IDE') }) itHandlesFileOpening({ getRunner: () => runner, selector: '.test-err-code-frame a', file: { file: '/me/dev/my/app.js', line: 2, column: 7, }, }) }) describe('studio error', () => { beforeEach(() => { setError(runnablesWithErr) }) it('is not visible by default', () => { cy.get('.studio-err-wrapper').should('not.be.visible') }) it('is visible when studio is active', () => { runner.emit('reporter:start', { studioActive: true }) cy.get('.studio-err-wrapper').should('be.visible') cy.percySnapshot() }) }) })