From 925fc659b37facf80acfbf10466eed40d6cb8647 Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Tue, 9 Nov 2021 16:46:59 +0000 Subject: [PATCH 1/3] chore: patch `winston` to suppress `padLevels` warning (#18824) --- patches/winston+2.4.4.patch | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 patches/winston+2.4.4.patch diff --git a/patches/winston+2.4.4.patch b/patches/winston+2.4.4.patch new file mode 100644 index 000000000000..a62afd1ee724 --- /dev/null +++ b/patches/winston+2.4.4.patch @@ -0,0 +1,16 @@ +diff --git a/node_modules/winston/lib/winston/common.js b/node_modules/winston/lib/winston/common.js +index 8ed9973..ecc59f8 100644 +--- a/node_modules/winston/lib/winston/common.js ++++ b/node_modules/winston/lib/winston/common.js +@@ -32,7 +32,10 @@ exports.setLevels = function (target, past, current, isDefault) { + } + + target.levels = current || config.npm.levels; +- if (target.padLevels) { ++ // Check if `padLevels` exists to suppress a warning about accessing ++ // a non-existing property on `exports`. ++ // @see https://github.com/winstonjs/winston/issues/1882 ++ if (target.hasOwnProperty('padLevels') && target.padLevels) { + target.levelLength = exports.longestElement(Object.keys(target.levels)); + } + From e66734d514e12655accab1dd6d047958583ea3d1 Mon Sep 17 00:00:00 2001 From: Chris Breiding Date: Tue, 9 Nov 2021 15:30:28 -0500 Subject: [PATCH 2/3] chore: Bind this correctly when setting response headers with cy.route() (#18859) --- .../cypress/integration/commands/xhr_spec.js | 27 +++++++++++++++++++ packages/driver/src/cypress/server.ts | 3 +-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/packages/driver/cypress/integration/commands/xhr_spec.js b/packages/driver/cypress/integration/commands/xhr_spec.js index 8f0061d6c1b8..2c785e73dd80 100644 --- a/packages/driver/cypress/integration/commands/xhr_spec.js +++ b/packages/driver/cypress/integration/commands/xhr_spec.js @@ -1659,6 +1659,33 @@ describe('src/cy/commands/xhr', () => { }) }) + // https://github.com/cypress-io/cypress/issues/18858 + it('can stub headers', (done) => { + cy + .route({ + url: '/foo', + response: '', + headers: { + 'some-header': 'header-value', + }, + }).as('getFoo') + .window().then((win) => { + win.$.ajax({ + url: '/foo', + error (_a, _b, err) { + done(`Errored but should not have: ${err.stack}`) + }, + }) + + return null + }) + .wait('@getFoo') + .then((xhr) => { + expect(xhr.response.headers['some-header']).to.equal('header-value') + done() + }) + }) + // https://github.com/cypress-io/cypress/issues/2372 it('warns if a percent-encoded URL is used', () => { cy.spy(Cypress.utils, 'warning') diff --git a/packages/driver/src/cypress/server.ts b/packages/driver/src/cypress/server.ts index 16ed777a71a0..e039d1d55b7f 100644 --- a/packages/driver/src/cypress/server.ts +++ b/packages/driver/src/cypress/server.ts @@ -200,8 +200,7 @@ export class Server { this.setHeader(xhr, 'response', route.response, responser) this.setHeader(xhr, 'matched', `${route.url}`) this.setHeader(xhr, 'delay', route.delay) - - return this.setHeader(xhr, 'headers', route.headers, this.transformHeaders) + this.setHeader(xhr, 'headers', route.headers, this.transformHeaders.bind(this)) } route (attrs = {}) { From a5cf5c0982c04bb955df051bb0390556c7c9a5ea Mon Sep 17 00:00:00 2001 From: Emily Rohrbough Date: Tue, 9 Nov 2021 15:16:18 -0600 Subject: [PATCH 3/3] chore(driver): fix integration test retry configuration (#18643) Co-authored-by: Matt Henkes Co-authored-by: Zach Bloomquist --- .../commands/actions/check_spec.js | 19 +-- .../commands/actions/clear_spec.js | 9 +- .../commands/actions/click_spec.js | 18 +-- .../commands/actions/focus_spec.js | 13 +- .../commands/actions/select_spec.js | 7 +- .../commands/actions/submit_spec.js | 10 +- .../commands/actions/trigger_spec.js | 11 +- .../commands/actions/type_errors_spec.js | 35 ++--- .../integration/commands/agents_spec.js | 8 +- .../integration/commands/aliasing_spec.js | 5 +- .../integration/commands/angular_spec.js | 3 +- .../integration/commands/assertions_spec.js | 105 +++++++------- .../integration/commands/connectors_spec.js | 19 +-- .../integration/commands/cookies_spec.js | 35 ++--- .../cypress/integration/commands/exec_spec.js | 13 +- .../integration/commands/files_spec.js | 25 ++-- .../integration/commands/fixtures_spec.js | 9 +- .../integration/commands/location_spec.js | 7 +- .../cypress/integration/commands/misc_spec.js | 7 +- .../integration/commands/navigation_spec.js | 128 ++++++++++-------- .../integration/commands/popups_spec.js | 6 +- .../integration/commands/querying_spec.js | 19 +-- .../integration/commands/request_spec.js | 33 ++--- .../integration/commands/screenshot_spec.js | 5 +- .../cypress/integration/commands/task_spec.js | 15 +- .../integration/commands/traversals_spec.js | 3 +- .../integration/commands/waiting_spec.js | 3 +- .../integration/commands/window_spec.js | 27 ++-- .../cypress/integration/commands/xhr_spec.js | 11 +- .../cypress/integration/e2e/redirects_spec.js | 25 ++-- .../integration/e2e/return_value_spec.js | 10 +- packages/driver/cypress/support/defaults.js | 5 +- packages/driver/cypress/support/utils.js | 6 + packages/driver/package.json | 3 +- packages/driver/src/cypress/mocha.ts | 7 + 35 files changed, 361 insertions(+), 303 deletions(-) diff --git a/packages/driver/cypress/integration/commands/actions/check_spec.js b/packages/driver/cypress/integration/commands/actions/check_spec.js index a60c9cd10957..554e8656b361 100644 --- a/packages/driver/cypress/integration/commands/actions/check_spec.js +++ b/packages/driver/cypress/integration/commands/actions/check_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../../support/utils') const { _, Promise, $ } = Cypress describe('src/cy/commands/actions/check', () => { @@ -469,7 +470,7 @@ describe('src/cy/commands/actions/check', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(chk.length + 1) + assertLogLength(this.logs, chk.length + 1) expect(lastLog.get('error')).to.eq(err) expect(err.message).to.include('`cy.check()` failed because this element is not visible') @@ -501,7 +502,7 @@ describe('src/cy/commands/actions/check', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(chk.length + 1) + assertLogLength(this.logs, chk.length + 1) expect(lastLog.get('error')).to.eq(err) expect(err.message).to.include('`cy.check()` failed because this element is not visible') @@ -515,7 +516,7 @@ describe('src/cy/commands/actions/check', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -530,7 +531,7 @@ describe('src/cy/commands/actions/check', () => { $('span on button').css({ position: 'absolute', left: checkbox.offset().left, top: checkbox.offset().top, padding: 5, display: 'inline-block', backgroundColor: 'yellow' }).prependTo($('body')) cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.include('`cy.check()` failed because this element') expect(err.message).to.include('is being covered by another element') @@ -559,7 +560,7 @@ describe('src/cy/commands/actions/check', () => { it('does not log an additional log on failure', function (done) { cy.on('fail', () => { - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) done() }) @@ -1016,7 +1017,7 @@ describe('src/cy/commands/actions/check', () => { const { lastLog } = this const len = (chk.length * 2) + 6 - expect(this.logs.length).to.eq(len) + assertLogLength(this.logs, len) expect(lastLog.get('error')).to.eq(err) expect(err.message).to.include('`cy.uncheck()` failed because this element is not visible') @@ -1032,7 +1033,7 @@ describe('src/cy/commands/actions/check', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -1068,7 +1069,7 @@ describe('src/cy/commands/actions/check', () => { $('span on button').css({ position: 'absolute', left: checkbox.offset().left, top: checkbox.offset().top, padding: 5, display: 'inline-block', backgroundColor: 'yellow' }).prependTo($('body')) cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.include('`cy.uncheck()` failed because this element') expect(err.message).to.include('is being covered by another element') @@ -1122,7 +1123,7 @@ describe('src/cy/commands/actions/check', () => { it('does not log an additional log on failure', function (done) { cy.on('fail', () => { - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) done() }) diff --git a/packages/driver/cypress/integration/commands/actions/clear_spec.js b/packages/driver/cypress/integration/commands/actions/clear_spec.js index 5dfab1bb74ae..e751a6469a4a 100644 --- a/packages/driver/cypress/integration/commands/actions/clear_spec.js +++ b/packages/driver/cypress/integration/commands/actions/clear_spec.js @@ -1,5 +1,6 @@ const { _, $ } = Cypress const { + assertLogLength, attachKeyListeners, shouldBeCalledOnce, shouldNotBeCalled, @@ -286,7 +287,7 @@ describe('src/cy/commands/actions/type - #clear', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) expect(lastLog.get('error')).to.eq(err) expect(err.message).to.include('`cy.clear()` failed because it requires a valid clearable element.') expect(err.message).to.include('The element cleared was:') @@ -381,7 +382,7 @@ describe('src/cy/commands/actions/type - #clear', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -408,7 +409,7 @@ describe('src/cy/commands/actions/type - #clear', () => { .prependTo(cy.$$('body')) cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.include('`cy.clear()` failed because this element') expect(err.message).to.include('is being covered by another element') @@ -442,7 +443,7 @@ describe('src/cy/commands/actions/type - #clear', () => { }) cy.on('fail', () => { - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) done() }) diff --git a/packages/driver/cypress/integration/commands/actions/click_spec.js b/packages/driver/cypress/integration/commands/actions/click_spec.js index e8e0bc7b54f3..b20fad3739a1 100644 --- a/packages/driver/cypress/integration/commands/actions/click_spec.js +++ b/packages/driver/cypress/integration/commands/actions/click_spec.js @@ -1,5 +1,7 @@ const { _, $, Promise } = Cypress -const { getCommandLogWithText, +const { + assertLogLength, + getCommandLogWithText, findReactInstance, withMutableReporterState, clickCommandLog, @@ -2163,7 +2165,7 @@ describe('src/cy/commands/actions/click', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -2356,7 +2358,7 @@ describe('src/cy/commands/actions/click', () => { it('throws when attempting to click a ` element. Use `cy.select()` command instead to change the value.') expect(err.docsUrl).to.eq('https://on.cypress.io/select') @@ -2368,7 +2370,7 @@ describe('src/cy/commands/actions/click', () => { it('throws when provided invalid position', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('Invalid position argument: `foo`. Position may only be topLeft, top, topRight, left, center, right, bottomLeft, bottom, bottomRight.') done() @@ -2416,7 +2418,7 @@ describe('src/cy/commands/actions/click', () => { it('does not log an additional log on failure', function (done) { cy.on('fail', () => { - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) done() }) @@ -3293,7 +3295,7 @@ describe('src/cy/commands/actions/click', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -3731,7 +3733,7 @@ describe('src/cy/commands/actions/click', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -3747,7 +3749,7 @@ describe('src/cy/commands/actions/click', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(4) + assertLogLength(this.logs, 4) expect(lastLog.get('error')).to.eq(err) expect(err.message).to.include('`cy.rightclick()` failed because this element is not visible') diff --git a/packages/driver/cypress/integration/commands/actions/focus_spec.js b/packages/driver/cypress/integration/commands/actions/focus_spec.js index b70d7a313782..57b31a7deb93 100644 --- a/packages/driver/cypress/integration/commands/actions/focus_spec.js +++ b/packages/driver/cypress/integration/commands/actions/focus_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../../support/utils') const { _, $ } = Cypress const getActiveElement = () => { @@ -297,7 +298,7 @@ describe('src/cy/commands/actions/focus', () => { cy .get('input:first').focus() .get('button:first').focus().then(function () { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) }) }) @@ -384,7 +385,7 @@ describe('src/cy/commands/actions/focus', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -467,7 +468,7 @@ describe('src/cy/commands/actions/focus', () => { it('does not log an additional log on failure', function (done) { cy.on('fail', () => { - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) done() }) @@ -738,7 +739,7 @@ describe('src/cy/commands/actions/focus', () => { it('logs 1 blur event', () => { cy.get('input:first').focus().blur().then(function () { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) }) }) @@ -866,7 +867,7 @@ describe('src/cy/commands/actions/focus', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -893,7 +894,7 @@ describe('src/cy/commands/actions/focus', () => { it('does not log an additional log on failure', function (done) { cy.on('fail', () => { - expect(this.logs.length).to.eq(4) + assertLogLength(this.logs, 4) done() }) diff --git a/packages/driver/cypress/integration/commands/actions/select_spec.js b/packages/driver/cypress/integration/commands/actions/select_spec.js index 52fa2efe98b9..4ba66c479258 100644 --- a/packages/driver/cypress/integration/commands/actions/select_spec.js +++ b/packages/driver/cypress/integration/commands/actions/select_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../../support/utils') const { _, $ } = Cypress describe('src/cy/commands/actions/select', () => { @@ -586,7 +587,7 @@ describe('src/cy/commands/actions/select', () => { it('does not log an additional log on failure', function (done) { cy.on('fail', () => { - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) done() }) @@ -597,7 +598,7 @@ describe('src/cy/commands/actions/select', () => { it('only logs once on failure', function (done) { cy.on('fail', (err) => { // 2 logs, 1 for cy.get, 1 for cy.select - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) done() }) @@ -702,7 +703,7 @@ describe('src/cy/commands/actions/select', () => { }) cy.get('#select-maps').select('de_dust2').then(function () { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(types.length).to.eq(1) }) }) diff --git a/packages/driver/cypress/integration/commands/actions/submit_spec.js b/packages/driver/cypress/integration/commands/actions/submit_spec.js index d379edbeb8d5..61f210a6a954 100644 --- a/packages/driver/cypress/integration/commands/actions/submit_spec.js +++ b/packages/driver/cypress/integration/commands/actions/submit_spec.js @@ -1,5 +1,5 @@ -const { _, $ } = Cypress -const { Promise } = Cypress +const { assertLogLength } = require('../../../support/utils') +const { _, $, Promise } = Cypress describe('src/cy/commands/actions/submit', () => { before(() => { @@ -242,7 +242,7 @@ describe('src/cy/commands/actions/submit', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(lastLog.get('error')).to.eq(err) expect(err.message).to.include('`cy.submit()` can only be called on a `
`. Your subject contains a: ``') expect(err.docsUrl).to.eq('https://on.cypress.io/submit') @@ -293,7 +293,7 @@ describe('src/cy/commands/actions/submit', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -328,7 +328,7 @@ describe('src/cy/commands/actions/submit', () => { }) cy.on('fail', () => { - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) done() }) diff --git a/packages/driver/cypress/integration/commands/actions/trigger_spec.js b/packages/driver/cypress/integration/commands/actions/trigger_spec.js index 98e483876923..0bde9d654f4f 100644 --- a/packages/driver/cypress/integration/commands/actions/trigger_spec.js +++ b/packages/driver/cypress/integration/commands/actions/trigger_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../../support/utils') const { _, $ } = Cypress describe('src/cy/commands/actions/trigger', () => { @@ -1060,7 +1061,7 @@ describe('src/cy/commands/actions/trigger', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(lastLog.get('error')).to.eq(err) done() @@ -1075,7 +1076,7 @@ describe('src/cy/commands/actions/trigger', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(lastLog.get('error')).to.eq(err) expect(err.message).to.include('`cy.trigger()` failed because this element is not visible') @@ -1114,7 +1115,7 @@ describe('src/cy/commands/actions/trigger', () => { it('throws when provided invalid position', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('Invalid position argument: `foo`. Position may only be topLeft, top, topRight, left, center, right, bottomLeft, bottom, bottomRight.') done() @@ -1125,7 +1126,7 @@ describe('src/cy/commands/actions/trigger', () => { it('throws when provided invalid event type', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('Timed out retrying after 100ms: `cy.trigger()` `eventConstructor` option must be a valid event (e.g. \'MouseEvent\', \'KeyboardEvent\'). You passed: `FooEvent`') done() @@ -1175,7 +1176,7 @@ describe('src/cy/commands/actions/trigger', () => { it('does not log an additional log on failure', function (done) { cy.on('fail', () => { - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) done() }) diff --git a/packages/driver/cypress/integration/commands/actions/type_errors_spec.js b/packages/driver/cypress/integration/commands/actions/type_errors_spec.js index 9422d35b3cdf..b5c864ee7a4e 100644 --- a/packages/driver/cypress/integration/commands/actions/type_errors_spec.js +++ b/packages/driver/cypress/integration/commands/actions/type_errors_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../../support/utils') const { _, $ } = Cypress describe('src/cy/commands/actions/type - #type errors', () => { @@ -100,7 +101,7 @@ describe('src/cy/commands/actions/type - #type errors', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(lastLog.get('error')).to.eq(err) expect(err.message).to.include('`cy.type()` failed because this element is not visible') @@ -130,7 +131,7 @@ describe('src/cy/commands/actions/type - #type errors', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -156,7 +157,7 @@ describe('src/cy/commands/actions/type - #type errors', () => { .prependTo(cy.$$('body')) cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.include('`cy.type()` failed because this element') expect(err.message).to.include('is being covered by another element') @@ -168,7 +169,7 @@ describe('src/cy/commands/actions/type - #type errors', () => { it('throws when special characters dont exist', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) const allChars = _.keys(Cypress.Keyboard.getKeymap()).join(', ') @@ -186,7 +187,7 @@ If you want to skip parsing special character sequences and type the text exactl it('throws when attempting to type tab', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('`{tab}` isn\'t a supported character sequence.') done() @@ -197,7 +198,7 @@ If you want to skip parsing special character sequences and type the text exactl it('throws on an empty string', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('`cy.type()` cannot accept an empty string. You need to actually type something.') expect(err.docsUrl).to.eq('https://on.cypress.io/type') done() @@ -262,7 +263,7 @@ If you want to skip parsing special character sequences and type the text exactl }) cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq(`\`cy.type()\` can only accept a string or number. You passed in: \`${val}\``) expect(err.docsUrl).to.eq('https://on.cypress.io/type') done() @@ -312,7 +313,7 @@ If you want to skip parsing special character sequences and type the text exactl it('does not log an additional log on failure', function (done) { cy.on('fail', () => { - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) done() }) @@ -323,7 +324,7 @@ If you want to skip parsing special character sequences and type the text exactl context('[type=date]', () => { it('throws when chars is not a string', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('Typing into a `date` input with `cy.type()` requires a valid date with the format `YYYY-MM-DD`. You passed: `1989`') expect(err.docsUrl).to.eq('https://on.cypress.io/type') done() @@ -334,7 +335,7 @@ If you want to skip parsing special character sequences and type the text exactl it('throws when chars is invalid format', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('Typing into a `date` input with `cy.type()` requires a valid date with the format `YYYY-MM-DD`. You passed: `01-01-1989`') expect(err.docsUrl).to.eq('https://on.cypress.io/type') done() @@ -345,7 +346,7 @@ If you want to skip parsing special character sequences and type the text exactl it('throws when chars is non-existent date', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('Typing into a `date` input with `cy.type()` requires a valid date with the format `YYYY-MM-DD`. You passed: `1989-04-31`') expect(err.docsUrl).to.eq('https://on.cypress.io/type') done() @@ -359,7 +360,7 @@ If you want to skip parsing special character sequences and type the text exactl context('[type=month]', () => { it('throws when chars is not a string', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('Typing into a `month` input with `cy.type()` requires a valid month with the format `YYYY-MM`. You passed: `6`') expect(err.docsUrl).to.eq('https://on.cypress.io/type') done() @@ -370,7 +371,7 @@ If you want to skip parsing special character sequences and type the text exactl it('throws when chars is invalid format', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('Typing into a `month` input with `cy.type()` requires a valid month with the format `YYYY-MM`. You passed: `01/2000`') expect(err.docsUrl).to.eq('https://on.cypress.io/type') done() @@ -381,7 +382,7 @@ If you want to skip parsing special character sequences and type the text exactl it('throws when chars is invalid month', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('Typing into a `month` input with `cy.type()` requires a valid month with the format `YYYY-MM`. You passed: `1989-13`') expect(err.docsUrl).to.eq('https://on.cypress.io/type') done() @@ -408,7 +409,7 @@ If you want to skip parsing special character sequences and type the text exactl context('[type=week]', () => { it('throws when chars is not a string', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('Typing into a `week` input with `cy.type()` requires a valid week with the format `YYYY-Www`, where `W` is the literal character `W` and `ww` is the week number (00-53). You passed: `23`') expect(err.docsUrl).to.eq('https://on.cypress.io/type') done() @@ -419,7 +420,7 @@ If you want to skip parsing special character sequences and type the text exactl it('throws when chars is invalid format', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('Typing into a `week` input with `cy.type()` requires a valid week with the format `YYYY-Www`, where `W` is the literal character `W` and `ww` is the week number (00-53). You passed: `2005/W18`') expect(err.docsUrl).to.eq('https://on.cypress.io/type') done() @@ -430,7 +431,7 @@ If you want to skip parsing special character sequences and type the text exactl it('throws when chars is invalid week', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('Typing into a `week` input with `cy.type()` requires a valid week with the format `YYYY-Www`, where `W` is the literal character `W` and `ww` is the week number (00-53). You passed: `1995-W60`') expect(err.docsUrl).to.eq('https://on.cypress.io/type') done() diff --git a/packages/driver/cypress/integration/commands/agents_spec.js b/packages/driver/cypress/integration/commands/agents_spec.js index d5558bbcbe03..c15347b8a7db 100644 --- a/packages/driver/cypress/integration/commands/agents_spec.js +++ b/packages/driver/cypress/integration/commands/agents_spec.js @@ -1,3 +1,5 @@ +const { assertLogLength } = require('../../support/utils') + const { _ } = Cypress describe('src/cy/commands/agents', () => { @@ -176,10 +178,10 @@ describe('src/cy/commands/agents', () => { describe('logging', () => { it('creates new log instrument with sub-count', function () { - expect(this.agentLogs.length).to.eq(2) + assertLogLength(this.agentLogs, 2) expect(this.agentLogs[1].get('name')).to.eq('stub-1.1') this.stub.withArgs('bar') - expect(this.agentLogs.length).to.eq(3) + assertLogLength(this.agentLogs, 3) expect(this.agentLogs[2].get('name')).to.eq('stub-1.2') }) @@ -187,7 +189,7 @@ describe('src/cy/commands/agents', () => { it('only logs once', function () { this.obj.foo('foo') - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) }) it('includes count in name', function () { diff --git a/packages/driver/cypress/integration/commands/aliasing_spec.js b/packages/driver/cypress/integration/commands/aliasing_spec.js index d746a0c70341..e51684afcceb 100644 --- a/packages/driver/cypress/integration/commands/aliasing_spec.js +++ b/packages/driver/cypress/integration/commands/aliasing_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { _, $ } = Cypress describe('src/cy/commands/aliasing', () => { @@ -291,7 +292,7 @@ describe('src/cy/commands/aliasing', () => { cy.foo().as('foo').then(function () { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('alias')).to.eq('foo') expect(lastLog.get('aliasType')).to.eq('dom') }) @@ -305,7 +306,7 @@ describe('src/cy/commands/aliasing', () => { .then(function () { // 1 log from visit // 1 log from route - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(this.logs[0].get('name')).to.eq('visit') expect(this.logs[0].get('alias')).not.to.be.ok diff --git a/packages/driver/cypress/integration/commands/angular_spec.js b/packages/driver/cypress/integration/commands/angular_spec.js index 5118e9c49621..9e620c1d8856 100644 --- a/packages/driver/cypress/integration/commands/angular_spec.js +++ b/packages/driver/cypress/integration/commands/angular_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { _, $ } = Cypress describe('src/cy/commands/angular', () => { @@ -198,7 +199,7 @@ describe('src/cy/commands/angular', () => { .ng('repeater', 'foo in foos').should('have.length', 2) .url().should('include', ':') .then(() => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(this.logs[0].get('state')).to.eq('passed') expect(this.logs[1].get('state')).to.eq('passed') }) diff --git a/packages/driver/cypress/integration/commands/assertions_spec.js b/packages/driver/cypress/integration/commands/assertions_spec.js index 1135fbb6c836..6a82bd22522f 100644 --- a/packages/driver/cypress/integration/commands/assertions_spec.js +++ b/packages/driver/cypress/integration/commands/assertions_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { $, _ } = Cypress describe('src/cy/commands/assertions', () => { @@ -163,7 +164,7 @@ describe('src/cy/commands/assertions', () => { expect(o).to.have.property('foo').and.eq('bar') }).then(function () { // wrap + have property + and eq - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) }) }) @@ -186,7 +187,7 @@ describe('src/cy/commands/assertions', () => { }).then(function () { cy.$$('body').removeClass('foo').removeAttr('id') - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) // the messages should have been updated to reflect // the current state of the element @@ -219,7 +220,7 @@ describe('src/cy/commands/assertions', () => { expect(types).to.deep.eq(['parent', 'child', 'child']) - expect(this.logs.length).to.eq(4) + assertLogLength(this.logs, 4) }) }) @@ -238,7 +239,7 @@ describe('src/cy/commands/assertions', () => { expect(subject).not.to.contain('c') }) .then(function () { - expect(this.logs.length).to.eq(8) + assertLogLength(this.logs, 8) this.logs.slice(1).forEach((log) => { expect(log.get('name')).to.eq('assert') @@ -332,7 +333,7 @@ describe('src/cy/commands/assertions', () => { it('does not log extra commands on fail and properly fails command + assertions', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(6) + assertLogLength(this.logs, 6) expect(this.logs[3].get('name')).to.eq('get') expect(this.logs[3].get('state')).to.eq('failed') @@ -352,7 +353,7 @@ describe('src/cy/commands/assertions', () => { it('finishes failed assertions and does not log extra commands when cy.contains fails', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(this.logs[0].get('name')).to.eq('contains') expect(this.logs[0].get('state')).to.eq('failed') @@ -528,7 +529,7 @@ describe('src/cy/commands/assertions', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(lastLog.get('name')).to.eq('should') expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') @@ -604,7 +605,7 @@ describe('src/cy/commands/assertions', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) expect(err.message).to.eq('You must provide a valid number to a `length` assertion. You passed: `foo`') expect(lastLog.get('name')).to.eq('should') expect(lastLog.get('error')).to.eq(err) @@ -623,7 +624,7 @@ describe('src/cy/commands/assertions', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('name')).to.eq('should') expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') @@ -641,7 +642,7 @@ describe('src/cy/commands/assertions', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('`match` requires its argument be a `RegExp`. You passed: `foo`') expect(lastLog.get('name')).to.eq('should') expect(lastLog.get('error')).to.eq(err) @@ -658,7 +659,7 @@ describe('src/cy/commands/assertions', () => { it('does not log ensureElExistence errors', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) done() }) @@ -668,7 +669,7 @@ describe('src/cy/commands/assertions', () => { it('throws if used as a parent command', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.include('looks like you are trying to call a child command before running a parent command') done() @@ -1511,7 +1512,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$div).to.have.data('foo').and.match(/bar/) // 6,7 expect(this.$div).not.to.have.data('baz') // 8 - expect(this.logs.length).to.eq(8) + assertLogLength(this.logs, 8) }) // https://github.com/cypress-io/cypress/issues/7314 @@ -1524,7 +1525,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.be.ok expect(err.message).to.include('> data') expect(err.message).to.include('> {}') @@ -1549,7 +1550,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$div).to.have.class('bar') // 2 expect(this.$div).not.to.have.class('baz') // 3 - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) const l1 = this.logs[0] const l3 = this.logs[2] @@ -1573,7 +1574,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected \'foo\' to have class \'bar\'', ) @@ -1628,7 +1629,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$div3).to.have.id('foo') // 4 - expect(this.logs.length).to.eq(4) + assertLogLength(this.logs, 4) const l1 = this.logs[0] const l2 = this.logs[1] @@ -1652,7 +1653,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected [] to have id \'foo\'', ) @@ -1678,7 +1679,7 @@ describe('src/cy/commands/assertions', () => { it('html, not html, contain html', function () { expect(this.$div).to.have.html('') // 1 expect(this.$div).not.to.have.html('foo') // 2 - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) const l1 = this.logs[0] const l2 = this.logs[1] @@ -1724,7 +1725,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected null to have HTML \'foo\'', ) @@ -1759,7 +1760,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$div).to.have.text('foo') // 1 expect(this.$div).not.to.have.text('bar') // 2 - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) const l1 = this.logs[0] const l2 = this.logs[1] @@ -1821,7 +1822,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected undefined to have text \'foo\'', ) @@ -1848,7 +1849,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$input).to.have.value('foo') // 1 expect(this.$input).not.to.have.value('bar') // 2 - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) const l1 = this.logs[0] const l2 = this.logs[1] @@ -1923,7 +1924,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected {} to have value \'foo\'', ) @@ -1989,7 +1990,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$div).to.have.descendants('button') // 1 expect(this.$div).not.to.have.descendants('input') // 2 - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2005,7 +2006,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected {} to have descendants \'foo\'', ) @@ -2043,7 +2044,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$div).to.be.visible // 1 expect(this.$div2).not.to.be.visible // 2 - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2069,7 +2070,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected {} to be \'visible\'', ) @@ -2107,7 +2108,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$div).to.be.hidden // 1 expect(this.$div2).not.to.be.hidden // 2 - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2132,7 +2133,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected {} to be \'hidden\'', ) @@ -2164,7 +2165,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$option).to.be.selected // 1 expect(this.$option2).not.to.be.selected // 2 - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2180,7 +2181,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected {} to be \'selected\'', ) @@ -2212,7 +2213,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$input).to.be.checked // 1 expect(this.$input2).not.to.be.checked // 2 - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2228,7 +2229,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected {} to be \'checked\'', ) @@ -2260,7 +2261,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$input).to.be.enabled // 1 expect(this.$input2).not.to.be.enabled // 2 - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2276,7 +2277,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected {} to be \'enabled\'', ) @@ -2308,7 +2309,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$input).to.be.disabled // 1 expect(this.$input2).not.to.be.disabled // 2 - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2324,7 +2325,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected {} to be \'disabled\'', ) @@ -2345,7 +2346,7 @@ describe('src/cy/commands/assertions', () => { expect({}).to.exist expect('foo').to.exist - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2383,7 +2384,7 @@ describe('src/cy/commands/assertions', () => { expect({}).to.be.empty expect('').to.be.empty - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2409,7 +2410,7 @@ describe('src/cy/commands/assertions', () => { expect(this.div.get(0)).to.be.empty // 3 expect(this.div2.get(0)).not.to.be.empty // 4 - expect(this.logs.length).to.eq(4) + assertLogLength(this.logs, 4) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2465,7 +2466,7 @@ describe('src/cy/commands/assertions', () => { this.div2.focus() expect(this.div2).to.be.focused - expect(this.logs.length).to.eq(10) + assertLogLength(this.logs, 10) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2510,7 +2511,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.contain( 'expected {} to be \'focused\'', ) @@ -2548,7 +2549,7 @@ describe('src/cy/commands/assertions', () => { it('passes thru non DOM', function () { expect('foo').to.match(/f/) - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) const l1 = this.logs[0] @@ -2564,7 +2565,7 @@ describe('src/cy/commands/assertions', () => { expect(this.div.get(0)).to.match('div') // 3 expect(this.div.get(0)).not.to.match('button') // 4 - expect(this.logs.length).to.eq(4) + assertLogLength(this.logs, 4) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2595,7 +2596,7 @@ describe('src/cy/commands/assertions', () => { expect({ foo: 'bar', baz: 'quux' }).to.contain({ foo: 'bar' }) // 2, 3 expect('foo').to.contain('fo') // 4 - expect(this.logs.length).to.eq(4) + assertLogLength(this.logs, 4) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2649,7 +2650,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$a).not.to.have.attr('href', 'https://google.com') // 10 } catch (error) {} // eslint-disable-line no-empty - expect(this.logs.length).to.eq(10) + assertLogLength(this.logs, 10) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2713,7 +2714,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected {} to have attribute \'foo\'', ) @@ -2760,7 +2761,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$a).not.to.have.prop('href', href) // 10 } catch (error) {} // eslint-disable-line no-empty - expect(this.logs.length).to.eq(10) + assertLogLength(this.logs, 10) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2829,7 +2830,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected {} to have property \'foo\'', ) @@ -2863,7 +2864,7 @@ describe('src/cy/commands/assertions', () => { expect(this.$div).not.to.have.css('display', 'none') // 6 } catch (error) {} // eslint-disable-line no-empty - expect(this.logs.length).to.eq(6) + assertLogLength(this.logs, 6) const l1 = this.logs[0] const l2 = this.logs[1] @@ -2899,7 +2900,7 @@ describe('src/cy/commands/assertions', () => { it('throws when obj is not DOM', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error').message).to.eq( 'expected {} to have CSS property \'foo\'', ) diff --git a/packages/driver/cypress/integration/commands/connectors_spec.js b/packages/driver/cypress/integration/commands/connectors_spec.js index 52308e49443a..5968da419f53 100644 --- a/packages/driver/cypress/integration/commands/connectors_spec.js +++ b/packages/driver/cypress/integration/commands/connectors_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { _, Promise, $ } = Cypress describe('src/cy/commands/connectors', () => { @@ -240,7 +241,7 @@ describe('src/cy/commands/connectors', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(err.message).to.include('`cy.then()` timed out after waiting `150ms`.') @@ -256,7 +257,7 @@ describe('src/cy/commands/connectors', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(err.message).to.include('`cy.then()` failed because you are mixing up async and sync code.') @@ -276,7 +277,7 @@ describe('src/cy/commands/connectors', () => { cy.on('fail', () => { listeners.push(cy.listeners('command:enqueued').length) - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(listeners).to.deep.eq([1, 0]) done() @@ -404,7 +405,7 @@ describe('src/cy/commands/connectors', () => { } cy.on('fail', () => { - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) done() }) @@ -1000,7 +1001,7 @@ describe('src/cy/commands/connectors', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -1956,7 +1957,7 @@ describe('src/cy/commands/connectors', () => { it('can time out', function (done) { cy.on('fail', (err) => { // get + each - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.include('`cy.each()` timed out after waiting `100ms`.\n\nYour callback function returned a promise that never resolved.') expect(err.docsUrl).to.include('https://on.cypress.io/each') @@ -1977,7 +1978,7 @@ describe('src/cy/commands/connectors', () => { cy.on('fail', (err) => { // get + each - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.include('`cy.each()` must be passed a callback function.') expect(err.docsUrl).to.eq('https://on.cypress.io/each') @@ -1990,7 +1991,7 @@ describe('src/cy/commands/connectors', () => { it('throws when not passed a number', function (done) { cy.on('fail', (err) => { // get + each - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.include('`cy.each()` can only operate on an array like subject. Your subject was: `100`') expect(err.docsUrl).to.eq('https://on.cypress.io/each') @@ -2003,7 +2004,7 @@ describe('src/cy/commands/connectors', () => { it('throws when not passed an array like structure', function (done) { cy.on('fail', (err) => { // get + each - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.include('`cy.each()` can only operate on an array like subject. Your subject was: `{}`') expect(err.docsUrl).to.eq('https://on.cypress.io/each') diff --git a/packages/driver/cypress/integration/commands/cookies_spec.js b/packages/driver/cypress/integration/commands/cookies_spec.js index ce7661fa47bf..50df439a1aeb 100644 --- a/packages/driver/cypress/integration/commands/cookies_spec.js +++ b/packages/driver/cypress/integration/commands/cookies_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { stripIndent } = require('common-tags') const { Promise } = Cypress @@ -134,7 +135,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', () => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.contain(`\`cy.getCookies()\` had an unexpected error reading cookies from ${Cypress.browser.displayName}.`) expect(lastLog.get('error').message).to.contain('some err message') @@ -150,7 +151,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(lastLog.get('name')).to.eq('getCookies') @@ -305,7 +306,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.contain(`\`cy.getCookie()\` had an unexpected error reading the requested cookie from ${Cypress.browser.displayName}.`) expect(lastLog.get('error').message).to.contain('some err message') @@ -322,7 +323,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(lastLog.get('name')).to.eq('getCookie') @@ -340,7 +341,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.eq('`cy.getCookie()` must be passed a string argument for name.') expect(lastLog.get('error').docsUrl).to.eq('https://on.cypress.io/getcookie') expect(lastLog.get('error')).to.eq(err) @@ -571,7 +572,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.include('some err message') expect(lastLog.get('error').name).to.eq('CypressError') @@ -587,7 +588,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(lastLog.get('name')).to.eq('setCookie') @@ -605,7 +606,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.eq('`cy.setCookie()` must be passed two string arguments for `name` and `value`.') expect(lastLog.get('error').docsUrl).to.eq('https://on.cypress.io/setcookie') expect(lastLog.get('error')).to.eq(err) @@ -620,7 +621,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.eq('`cy.setCookie()` must be passed two string arguments for `name` and `value`.') expect(lastLog.get('error').docsUrl).to.eq('https://on.cypress.io/setcookie') expect(lastLog.get('error')).to.eq(err) @@ -635,7 +636,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.eq(stripIndent` If a \`sameSite\` value is supplied to \`cy.setCookie()\`, it must be a string from the following list: > no_restriction, lax, strict @@ -655,7 +656,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.eq(stripIndent` Only cookies with the \`secure\` flag set to \`true\` can use \`sameSite: 'None'\`. @@ -820,7 +821,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.contain(`\`cy.clearCookie()\` had an unexpected error clearing the requested cookie in ${Cypress.browser.displayName}.`) expect(lastLog.get('error').message).to.contain('some err message') @@ -836,7 +837,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(lastLog.get('name')).to.eq('clearCookie') @@ -854,7 +855,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.eq('`cy.clearCookie()` must be passed a string argument for name.') expect(lastLog.get('error').docsUrl).to.eq('https://on.cypress.io/clearcookie') expect(lastLog.get('error')).to.eq(err) @@ -1088,7 +1089,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.contain(`\`cy.clearCookies()\` had an unexpected error clearing cookies in ${Cypress.browser.displayName}.`) expect(lastLog.get('error').message).to.contain('some err message') expect(lastLog.get('error')).to.eq(err) @@ -1106,7 +1107,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(lastLog.get('name')).to.eq('clearCookies') @@ -1135,7 +1136,7 @@ describe('src/cy/commands/cookies', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.contain(`\`cy.clearCookies()\` had an unexpected error clearing cookies in ${Cypress.browser.displayName}.`) expect(lastLog.get('error').message).to.contain('some err message') expect(lastLog.get('error')).to.eq(err) diff --git a/packages/driver/cypress/integration/commands/exec_spec.js b/packages/driver/cypress/integration/commands/exec_spec.js index e0dc8d438bb2..0d20f786161f 100644 --- a/packages/driver/cypress/integration/commands/exec_spec.js +++ b/packages/driver/cypress/integration/commands/exec_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { _, Promise } = Cypress describe('src/cy/commands/exec', () => { @@ -142,7 +143,7 @@ describe('src/cy/commands/exec', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.exec()` must be passed a non-empty string as its 1st argument. You passed: \'\'.') @@ -158,7 +159,7 @@ describe('src/cy/commands/exec', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.exec()` must be passed a non-empty string as its 1st argument. You passed: \'3\'.') @@ -174,7 +175,7 @@ describe('src/cy/commands/exec', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.exec()` must be passed a non-empty string as its 1st argument. You passed: \'\'.') @@ -192,7 +193,7 @@ describe('src/cy/commands/exec', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') @@ -211,7 +212,7 @@ describe('src/cy/commands/exec', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.exec(\'ls\')` timed out after waiting `50ms`.') @@ -229,7 +230,7 @@ describe('src/cy/commands/exec', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') diff --git a/packages/driver/cypress/integration/commands/files_spec.js b/packages/driver/cypress/integration/commands/files_spec.js index 6bb71b68eb68..e5ee3834b114 100644 --- a/packages/driver/cypress/integration/commands/files_spec.js +++ b/packages/driver/cypress/integration/commands/files_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { stripIndent } = require('common-tags') const { _ } = Cypress @@ -175,7 +176,7 @@ describe('src/cy/commands/files', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.readFile()` must be passed a non-empty string as its 1st argument. You passed: `undefined`.') @@ -191,7 +192,7 @@ describe('src/cy/commands/files', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.readFile()` must be passed a non-empty string as its 1st argument. You passed: `2`.') @@ -207,7 +208,7 @@ describe('src/cy/commands/files', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.readFile()` must be passed a non-empty string as its 1st argument. You passed: ``.') @@ -231,7 +232,7 @@ describe('src/cy/commands/files', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq(stripIndent`\ @@ -263,7 +264,7 @@ describe('src/cy/commands/files', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') @@ -286,7 +287,7 @@ describe('src/cy/commands/files', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq(stripIndent`\ @@ -310,7 +311,7 @@ describe('src/cy/commands/files', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('Timed out retrying after 50ms: expected \'foo\' to equal \'contents\'') @@ -511,7 +512,7 @@ describe('src/cy/commands/files', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.writeFile()` must be passed a non-empty string as its 1st argument. You passed: `undefined`.') @@ -527,7 +528,7 @@ describe('src/cy/commands/files', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.writeFile()` must be passed a non-empty string as its 1st argument. You passed: `2`.') @@ -543,7 +544,7 @@ describe('src/cy/commands/files', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.writeFile()` must be passed a non-empty string, an object, or an array as its 2nd argument. You passed: `undefined`.') @@ -558,7 +559,7 @@ describe('src/cy/commands/files', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.writeFile()` must be passed a non-empty string, an object, or an array as its 2nd argument. You passed: `2`.') @@ -581,7 +582,7 @@ describe('src/cy/commands/files', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq(stripIndent` diff --git a/packages/driver/cypress/integration/commands/fixtures_spec.js b/packages/driver/cypress/integration/commands/fixtures_spec.js index 9f084878f7ef..f7570ad252a8 100644 --- a/packages/driver/cypress/integration/commands/fixtures_spec.js +++ b/packages/driver/cypress/integration/commands/fixtures_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { Promise } = Cypress describe('src/cy/commands/fixtures', () => { @@ -106,7 +107,7 @@ describe('src/cy/commands/fixtures', () => { cy.on('fail', () => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.eq('`cy.fixture()` is not valid because you have configured `fixturesFolder` to `false`.') expect(lastLog.get('error').docsUrl).to.eq('https://on.cypress.io/fixture') expect(lastLog.get('state')).to.eq('failed') @@ -122,7 +123,7 @@ describe('src/cy/commands/fixtures', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(lastLog.get('name')).to.eq('fixture') @@ -141,7 +142,7 @@ describe('src/cy/commands/fixtures', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(lastLog.get('name')).to.eq('fixture') @@ -162,7 +163,7 @@ describe('src/cy/commands/fixtures', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(lastLog.get('name')).to.eq('fixture') diff --git a/packages/driver/cypress/integration/commands/location_spec.js b/packages/driver/cypress/integration/commands/location_spec.js index 46a907378aea..9c92cbe6144f 100644 --- a/packages/driver/cypress/integration/commands/location_spec.js +++ b/packages/driver/cypress/integration/commands/location_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { _ } = Cypress describe('src/cy/commands/location', () => { @@ -99,7 +100,7 @@ describe('src/cy/commands/location', () => { it('does not log an additional log on failure', function (done) { cy.on('fail', () => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) done() }) @@ -249,7 +250,7 @@ describe('src/cy/commands/location', () => { it('does not log an additional log on failure', function (done) { cy.on('fail', () => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) done() }) @@ -441,7 +442,7 @@ describe('src/cy/commands/location', () => { }) cy.on('fail', () => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) done() }) diff --git a/packages/driver/cypress/integration/commands/misc_spec.js b/packages/driver/cypress/integration/commands/misc_spec.js index df39f277a808..eaf41954a429 100644 --- a/packages/driver/cypress/integration/commands/misc_spec.js +++ b/packages/driver/cypress/integration/commands/misc_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { _, $, dom } = Cypress describe('src/cy/commands/misc', () => { @@ -268,7 +269,7 @@ describe('src/cy/commands/misc', () => { Cypress.config('defaultCommandTimeout', 100) cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.include('`cy.wrap()` timed out waiting `100ms` to complete.') expect(err.message).to.include('You called `cy.wrap()` with a promise that never resolved.') expect(err.message).to.include('To increase the timeout, use `{ timeout: number }`') @@ -287,7 +288,7 @@ describe('src/cy/commands/misc', () => { it('throws when exceeding custom timeout', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.include('`cy.wrap()` timed out waiting `100ms` to complete.') expect(err.message).to.include('You called `cy.wrap()` with a promise that never resolved.') expect(err.message).to.include('To increase the timeout, use `{ timeout: number }`') @@ -306,7 +307,7 @@ describe('src/cy/commands/misc', () => { it('logs once when promise parameter is rejected', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.include('custom error') expect(this.lastLog.get('error')).to.eq(err) done() diff --git a/packages/driver/cypress/integration/commands/navigation_spec.js b/packages/driver/cypress/integration/commands/navigation_spec.js index 70656959d95c..cca1cabdc816 100644 --- a/packages/driver/cypress/integration/commands/navigation_spec.js +++ b/packages/driver/cypress/integration/commands/navigation_spec.js @@ -1,7 +1,7 @@ const Cookie = require('js-cookie') const { stripIndent } = require('common-tags') -const helpers = require('../../support/helpers') +const { assertLogLength } = require('../../support/utils') const { _, Promise, $ } = Cypress describe('src/cy/commands/navigation', () => { @@ -85,7 +85,7 @@ describe('src/cy/commands/navigation', () => { }) // TODO: fix this - it.skip('(FLAKY) sets timeout to Cypress.config(pageLoadTimeout)', { + it('sets timeout to Cypress.config(pageLoadTimeout)', { pageLoadTimeout: 4567, }, () => { const timeout = cy.spy(Promise.prototype, 'timeout') @@ -141,7 +141,7 @@ describe('src/cy/commands/navigation', () => { defaultCommandTimeout: 200, }, function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) done() }) @@ -303,7 +303,7 @@ describe('src/cy/commands/navigation', () => { }) // TODO: fix this - it.skip('(FLAKY) sets timeout to Cypress.config(pageLoadTimeout)', { + it('sets timeout to Cypress.config(pageLoadTimeout)', { pageLoadTimeout: 4567, }, () => { const timeout = cy.spy(Promise.prototype, 'timeout') @@ -456,7 +456,7 @@ describe('src/cy/commands/navigation', () => { it('only logs once on error', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('error')).to.eq(err) done() @@ -546,7 +546,7 @@ describe('src/cy/commands/navigation', () => { context('#visit', () => { // TODO: fix this - it.skip('(FLAKY) sets timeout to Cypress.config(pageLoadTimeout)', { + it('sets timeout to Cypress.config(pageLoadTimeout)', { pageLoadTimeout: 4567, }, () => { const timeout = cy.spy(Promise.prototype, 'timeout') @@ -1251,7 +1251,7 @@ describe('src/cy/commands/navigation', () => { .rejects(new Error) cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) done() }) @@ -1263,7 +1263,7 @@ describe('src/cy/commands/navigation', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.include('Your page did not fire its `load` event within `20ms`.') expect(lastLog.get('error')).to.eq(err) @@ -1392,7 +1392,7 @@ describe('src/cy/commands/navigation', () => { expect(err.message).to.include('The new URL is considered a different origin because the following parts of the URL are different:') expect(err.message).to.include('> port') expect(err.docsUrl).to.eq('https://on.cypress.io/cannot-visit-different-origin-domain') - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(lastLog.get('error')).to.eq(err) done() @@ -1411,7 +1411,7 @@ describe('src/cy/commands/navigation', () => { expect(err.message).to.include('The new URL is considered a different origin because the following parts of the URL are different:') expect(err.message).to.include('> protocol') expect(err.docsUrl).to.eq('https://on.cypress.io/cannot-visit-different-origin-domain') - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(lastLog.get('error')).to.eq(err) done() @@ -1429,7 +1429,7 @@ describe('src/cy/commands/navigation', () => { expect(err.message).to.include('The new URL is considered a different origin because the following parts of the URL are different:') expect(err.message).to.include('> superdomain') expect(err.docsUrl).to.eq('https://on.cypress.io/cannot-visit-different-origin-domain') - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(lastLog.get('error')).to.eq(err) done() @@ -1469,7 +1469,7 @@ describe('src/cy/commands/navigation', () => { expect(err.message).to.include('`cy.visit()` failed because you are attempting to visit a URL that is of a different origin.') expect(err.docsUrl).to.eq('https://on.cypress.io/cannot-visit-different-origin-domain') - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(lastLog.get('error')).to.eq(err) done() @@ -1480,7 +1480,7 @@ describe('src/cy/commands/navigation', () => { .visit('http://126.0.0.1:3500/fixtures/generic.html') }) - it('does not call resolve:url when throws attemping to visit a 2nd domain', (done) => { + it('does not call resolve:url when throws attempting to visit a 2nd domain', (done) => { const backend = cy.spy(Cypress, 'backend') cy.on('fail', (err) => { @@ -1527,7 +1527,7 @@ describe('src/cy/commands/navigation', () => { expect(err1.url).to.include('/foo.html') expect(emit).to.be.calledWith('visit:failed', err1) - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -1574,7 +1574,7 @@ describe('src/cy/commands/navigation', () => { > 404: Not Found`) expect(emit).to.be.calledWithMatch('visit:failed', obj) - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -1627,7 +1627,7 @@ describe('src/cy/commands/navigation', () => { - 301: http://localhost:3500/bar/`) expect(emit).to.be.calledWithMatch('visit:failed', obj) - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -1673,7 +1673,7 @@ describe('src/cy/commands/navigation', () => { If you do not want status codes to cause failures pass the option: \`failOnStatusCode: false\``) expect(emit).to.be.calledWithMatch('visit:failed', obj) - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -1727,7 +1727,7 @@ describe('src/cy/commands/navigation', () => { If you do not want status codes to cause failures pass the option: \`failOnStatusCode: false\``) expect(emit).to.be.calledWithMatch('visit:failed', obj) - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -1769,7 +1769,7 @@ describe('src/cy/commands/navigation', () => { \`cy.request()\` will automatically get and set cookies and enable you to parse responses.`) - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -1818,7 +1818,7 @@ describe('src/cy/commands/navigation', () => { \`cy.request()\` will automatically get and set cookies and enable you to parse responses.`) expect(emit).to.be.calledWithMatch('visit:failed', obj) - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -1845,7 +1845,7 @@ describe('src/cy/commands/navigation', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq(stripIndent`\ @@ -1971,12 +1971,10 @@ describe('src/cy/commands/navigation', () => { }) describe('errors', () => { - helpers.registerCypressConfigBackupRestore() - beforeEach(function () { this.logs = [] - cy.on('log:added', (attrs, log) => { + cy.on('log:added', (_attrs, log) => { this.lastLog = log this.logs.push(log) }) @@ -1984,42 +1982,57 @@ describe('src/cy/commands/navigation', () => { return null }) - it('can time out', function (done) { - let thenCalled = false + describe('can time out', () => { + let pageLoadTimeout - cy.on('fail', (err) => { - const { lastLog } = this + before(() => { + pageLoadTimeout = Cypress.config().pageLoadTimeout + }) - // visit, window, page loading - expect(this.logs.length).to.eq(3) - expect(err.message).to.include('Your page did not fire its `load` event within `50ms`.') - expect(lastLog.get('name')).to.eq('page load') - expect(lastLog.get('error')).to.eq(err) + after(() => { + Cypress.config('pageLoadTimeout', pageLoadTimeout) + }) - return Promise - .delay(100) - .then(() => { - expect(cy.state('onPageLoadErr')).to.be.null - expect(cy.isStopped()).to.be.true // make sure we ran our cleanup routine - expect(thenCalled).to.be.false + it('times out', function (done) { + let thenCalled = false - done() - }) - }) + cy.on('fail', (err, test) => { + if (test._currentRetry < 1) { + const { lastLog } = this - cy - .visit('/fixtures/jquery.html') - .window().then((win) => { - Cypress.config('pageLoadTimeout', 50) + // visit, window, page loading + assertLogLength(this.logs, 3) - const $a = win.$('jquery') - .appendTo(win.document.body) + expect(lastLog.get('name')).to.eq('page load') + expect(lastLog.get('error')).to.eq(err) + } - causeSynchronousBeforeUnload($a) + expect(err.message).to.include('Your page did not fire its `load` event within `50ms`.') - return null - }).wrap(null).then(() => { - thenCalled = true + return Promise + .delay(100) + .then(() => { + expect(cy.state('onPageLoadErr')).to.be.null + expect(cy.isStopped()).to.be.true // make sure we ran our cleanup routine + expect(thenCalled).to.be.false + + done() + }) + }) + + cy + .visit('/fixtures/jquery.html') + .window().then((win) => { + Cypress.config('pageLoadTimeout', 50) + const $a = win.$('jquery') + .appendTo(win.document.body) + + causeSynchronousBeforeUnload($a) + + return null + }).wrap(null).then(() => { + thenCalled = true + }) }) }) @@ -2086,8 +2099,7 @@ describe('src/cy/commands/navigation', () => { } }) - cy - .visit('/fixtures/jquery.html') + cy.visit('/fixtures/jquery.html') // make get timeout after only 200ms .get('#does-not-exist', { timeout: 200 }).should('have.class', 'foo') @@ -2097,7 +2109,7 @@ describe('src/cy/commands/navigation', () => { cy.once('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.include('Cypress detected a cross origin error happened on page load') expect(err.docsUrl).to.eq('https://on.cypress.io/cross-origin-violation') expect(lastLog.get('name')).to.eq('page load') @@ -2368,7 +2380,7 @@ describe('src/cy/commands/navigation', () => { .visit('/fixtures/generic.html') .get('#dimensions').click() .then(function () { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('message')).to.eq( 'http://localhost:3500/fixtures/dimensions.html', @@ -2487,7 +2499,7 @@ describe('src/cy/commands/navigation', () => { }) }) }).then(function () { - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) expect(this.logs[0].get('message')).to.eq( 'http://localhost:3500/fixtures/generic.html#hashchange', @@ -2614,7 +2626,7 @@ describe('src/cy/commands/navigation', () => { cy .get('#click-me').find('input[type=submit]').click() .then(function () { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('message')).to.eq( '--submitting form--', diff --git a/packages/driver/cypress/integration/commands/popups_spec.js b/packages/driver/cypress/integration/commands/popups_spec.js index 584d309d298d..03bd8df6e6fd 100644 --- a/packages/driver/cypress/integration/commands/popups_spec.js +++ b/packages/driver/cypress/integration/commands/popups_spec.js @@ -1,3 +1,5 @@ +const { assertLogLength } = require('../../support/utils') + describe('src/cy/commands/popups', () => { context('alert', () => { beforeEach(function () { @@ -19,7 +21,7 @@ describe('src/cy/commands/popups', () => { win.alert('fooooo') }) .then(function () { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('name')).to.eq('alert') expect(this.logs[0].get('message')).to.eq('fooooo') @@ -52,7 +54,7 @@ describe('src/cy/commands/popups', () => { cy.window().then((win) => { win.confirm('Delete hard drive?') }).then(function () { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(this.logs[0].get('name')).to.eq('confirm') expect(this.logs[0].get('message')).to.eq('Delete hard drive?') diff --git a/packages/driver/cypress/integration/commands/querying_spec.js b/packages/driver/cypress/integration/commands/querying_spec.js index 777da0a46c98..4a3168a0077c 100644 --- a/packages/driver/cypress/integration/commands/querying_spec.js +++ b/packages/driver/cypress/integration/commands/querying_spec.js @@ -1,5 +1,6 @@ -const { _, $ } = Cypress -const { Promise } = Cypress +const { assertLogLength } = require('../../support/utils') + +const { _, $, Promise } = Cypress describe('src/cy/commands/querying', () => { beforeEach(() => { @@ -214,7 +215,7 @@ describe('src/cy/commands/querying', () => { it('does not log an additional log on failure', function (done) { cy.on('fail', () => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) done() }) @@ -386,7 +387,7 @@ describe('src/cy/commands/querying', () => { it('can silence logging', () => { cy.get('div:first').within({ log: false }, () => {}).then(function () { - expect(this.logs.length).to.eq(0) + assertLogLength(this.logs, 0) }) }) @@ -437,7 +438,7 @@ describe('src/cy/commands/querying', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) done() @@ -1334,7 +1335,7 @@ describe('src/cy/commands/querying', () => { it('throws once when incorrect sizzle selector', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) done() }) @@ -2101,7 +2102,7 @@ space cy.get('#complex-contains').contains('nested contains').then(function ($label) { const names = _.map(this.logs, (log) => log.get('name')) - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(names).to.deep.eq(['get', 'contains']) }) @@ -2214,7 +2215,7 @@ space it('logs once on error', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) done() }) @@ -2300,7 +2301,7 @@ space it('throws when assertion is have.length > 1', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.eq('`cy.contains()` cannot be passed a `length` option because it will only ever return 1 element.') expect(err.docsUrl).to.eq('https://on.cypress.io/contains') diff --git a/packages/driver/cypress/integration/commands/request_spec.js b/packages/driver/cypress/integration/commands/request_spec.js index b466141e3613..ee0b9dff2668 100644 --- a/packages/driver/cypress/integration/commands/request_spec.js +++ b/packages/driver/cypress/integration/commands/request_spec.js @@ -1,4 +1,5 @@ const { stripIndent } = require('common-tags') +const { assertLogLength } = require('../../support/utils') const { _, Promise } = Cypress const RESPONSE_TIMEOUT = 22222 @@ -807,7 +808,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.request()` requires a `url`. You did not provide a `url`.') @@ -827,7 +828,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.request()` must be provided a fully qualified `url` - one that begins with `http`. By default `cy.request()` will use either the current window\'s origin or the `baseUrl` in `cypress.json`. Neither of those values were present.') @@ -848,7 +849,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.request()` must be provided a fully qualified `url` - one that begins with `http`. By default `cy.request()` will use either the current window\'s origin or the `baseUrl` in `cypress.json` (currently disabled by --config-file=false). Neither of those values were present.') @@ -868,7 +869,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.request()` must be provided a fully qualified `url` - one that begins with `http`. By default `cy.request()` will use either the current window\'s origin or the `baseUrl` in `foo.json`. Neither of those values were present.') @@ -883,7 +884,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.request()` requires the `url` to be a string.') @@ -901,7 +902,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.request()` must be passed an object literal for the `auth` option.') @@ -920,7 +921,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.request()` requires the `headers` option to be an object literal.') @@ -939,7 +940,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.request()` was called with an invalid method: `FOO`. Method can be: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, or any other method supported by Node\'s HTTP parser.') @@ -958,7 +959,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.request()` requires the `gzip` option to be a boolean.') @@ -977,7 +978,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.request()` was called with invalid encoding: `binaryX`. Encoding can be: `utf8`, `utf16le`, `latin1`, `base64`, `hex`, `ascii`, `binary`, `latin1`, `ucs2`, `utf16le`, or any other encoding supported by Node\'s Buffer encoding.') @@ -996,7 +997,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.request()` requires the `form` option to be a boolean.\n\nIf you\'re trying to send a `x-www-form-urlencoded` request then pass either a string or object literal to the `body` property.') @@ -1049,7 +1050,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.docsUrl).to.eq('https://on.cypress.io/request') @@ -1134,7 +1135,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq(stripIndent`\ @@ -1168,7 +1169,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.docsUrl).to.eq('https://on.cypress.io/request') @@ -1230,7 +1231,7 @@ describe('src/cy/commands/request', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') @@ -1351,7 +1352,7 @@ describe('src/cy/commands/request', () => { lastLog, } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.docsUrl).to.eq('https://on.cypress.io/request') diff --git a/packages/driver/cypress/integration/commands/screenshot_spec.js b/packages/driver/cypress/integration/commands/screenshot_spec.js index 0f3de799fb01..0045c2a7b24a 100644 --- a/packages/driver/cypress/integration/commands/screenshot_spec.js +++ b/packages/driver/cypress/integration/commands/screenshot_spec.js @@ -1,4 +1,5 @@ const $ = require('jquery') +const { assertLogLength } = require('../../support/utils') const { _, Promise, Screenshot } = Cypress @@ -1050,7 +1051,7 @@ describe('src/cy/commands/screenshot', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).to.eq(error.message) expect(lastLog.get('error').name).to.eq(error.name) expect(lastLog.get('error').stack).to.eq(error.stack) @@ -1068,7 +1069,7 @@ describe('src/cy/commands/screenshot', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(lastLog.get('name')).to.eq('screenshot') diff --git a/packages/driver/cypress/integration/commands/task_spec.js b/packages/driver/cypress/integration/commands/task_spec.js index b7a57ccf85af..62c2e4d1498f 100644 --- a/packages/driver/cypress/integration/commands/task_spec.js +++ b/packages/driver/cypress/integration/commands/task_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { _, Promise } = Cypress describe('src/cy/commands/task', () => { @@ -138,7 +139,7 @@ describe('src/cy/commands/task', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.task()` must be passed a non-empty string as its 1st argument. You passed: ``.') @@ -154,7 +155,7 @@ describe('src/cy/commands/task', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.task()` must be passed a non-empty string as its 1st argument. You passed: `3`.') @@ -170,7 +171,7 @@ describe('src/cy/commands/task', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.task()` must be passed a non-empty string as its 1st argument. You passed: ``.') @@ -188,7 +189,7 @@ describe('src/cy/commands/task', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') @@ -205,7 +206,7 @@ describe('src/cy/commands/task', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') @@ -223,7 +224,7 @@ describe('src/cy/commands/task', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') expect(err.message).to.eq('`cy.task(\'foo\')` timed out after waiting `50ms`.') @@ -241,7 +242,7 @@ describe('src/cy/commands/task', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('state')).to.eq('failed') diff --git a/packages/driver/cypress/integration/commands/traversals_spec.js b/packages/driver/cypress/integration/commands/traversals_spec.js index 405857217d4c..5f2f08b9402d 100644 --- a/packages/driver/cypress/integration/commands/traversals_spec.js +++ b/packages/driver/cypress/integration/commands/traversals_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { _, $, dom } = Cypress const helpers = require('../../support/helpers') @@ -333,7 +334,7 @@ describe('src/cy/commands/traversals', () => { it('throws once when incorrect sizzle selector', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) done() }) diff --git a/packages/driver/cypress/integration/commands/waiting_spec.js b/packages/driver/cypress/integration/commands/waiting_spec.js index 6d32cbb531a3..73ab6976121b 100644 --- a/packages/driver/cypress/integration/commands/waiting_spec.js +++ b/packages/driver/cypress/integration/commands/waiting_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { _, Promise } = Cypress let reqQueue = [] @@ -1000,7 +1001,7 @@ describe('src/cy/commands/waiting', () => { it('only logs once', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.eq('`cy.wait()` could not find a registered alias for: `@foo`.\nYou have not aliased anything yet.') done() diff --git a/packages/driver/cypress/integration/commands/window_spec.js b/packages/driver/cypress/integration/commands/window_spec.js index 39b9859e938d..27665aa2344e 100644 --- a/packages/driver/cypress/integration/commands/window_spec.js +++ b/packages/driver/cypress/integration/commands/window_spec.js @@ -1,3 +1,4 @@ +const { assertLogLength } = require('../../support/utils') const { _, $ } = Cypress describe('src/cy/commands/window', () => { @@ -70,7 +71,7 @@ describe('src/cy/commands/window', () => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.include(lastLog.get('error').message) expect(lastLog.get('name')).to.eq('window') expect(lastLog.get('state')).to.eq('failed') @@ -85,7 +86,7 @@ describe('src/cy/commands/window', () => { this.remoteWindow.foo = 'foo' cy.on('fail', () => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) done() }) @@ -140,7 +141,7 @@ describe('src/cy/commands/window', () => { .get('body') .get('@win').then(function (win) { // window + get + get - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) expect(win).to.eq(this.win) @@ -247,7 +248,7 @@ describe('src/cy/commands/window', () => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.include(lastLog.get('error').message) expect(lastLog.get('name')).to.eq('document') expect(lastLog.get('state')).to.eq('failed') @@ -262,7 +263,7 @@ describe('src/cy/commands/window', () => { this.remoteDocument.foo = 'foo' cy.on('fail', () => { - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) done() }) @@ -324,7 +325,7 @@ describe('src/cy/commands/window', () => { .get('body') .get('@doc').then(function (doc) { // docdow + get + get - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) expect(doc).to.eq(this.doc) @@ -474,7 +475,7 @@ describe('src/cy/commands/window', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.include(lastLog.get('error').message) done() @@ -846,7 +847,7 @@ describe('src/cy/commands/window', () => { it('throws when passed invalid preset', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.match(/^`cy.viewport\(\)` could not find a preset for: `foo`. Available presets are: /) expect(err.docsUrl).to.eq('https://on.cypress.io/viewport') @@ -858,7 +859,7 @@ describe('src/cy/commands/window', () => { it('throws when passed a string as height', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.eq('`cy.viewport()` can only accept a string preset or a `width` and `height` as numbers.') expect(err.docsUrl).to.eq('https://on.cypress.io/viewport') @@ -870,7 +871,7 @@ describe('src/cy/commands/window', () => { it('throws when passed negative numbers', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.eq('`cy.viewport()` `width` and `height` must be at least 0px.') expect(err.docsUrl).to.eq('https://on.cypress.io/viewport') @@ -890,7 +891,7 @@ describe('src/cy/commands/window', () => { it('throws when passed an empty string as width', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.eq('`cy.viewport()` cannot be passed an empty string.') expect(err.docsUrl).to.eq('https://on.cypress.io/viewport') @@ -902,7 +903,7 @@ describe('src/cy/commands/window', () => { it('throws when passed an invalid orientation on a preset', function (done) { cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.eq('`cy.viewport()` can only accept `landscape` or `portrait` as valid orientations. Your orientation was: `foobar`') expect(err.docsUrl).to.eq('https://on.cypress.io/viewport') @@ -921,7 +922,7 @@ describe('src/cy/commands/window', () => { }) cy.on('fail', (err) => { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(err.message).to.eq('`cy.viewport()` can only accept a string preset or a `width` and `height` as numbers.') expect(err.docsUrl).to.eq('https://on.cypress.io/viewport') diff --git a/packages/driver/cypress/integration/commands/xhr_spec.js b/packages/driver/cypress/integration/commands/xhr_spec.js index 2c785e73dd80..6aa0b8155c29 100644 --- a/packages/driver/cypress/integration/commands/xhr_spec.js +++ b/packages/driver/cypress/integration/commands/xhr_spec.js @@ -1,4 +1,5 @@ const { stripIndent } = require('common-tags') +const { assertLogLength } = require('../../support/utils') const { _, $, Promise } = Cypress describe('src/cy/commands/xhr', () => { @@ -1037,7 +1038,7 @@ describe('src/cy/commands/xhr', () => { if (!lastLog || lastLog.get('name') !== 'request') return try { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('error').message).contain('foo is not defined') done() @@ -1071,7 +1072,7 @@ describe('src/cy/commands/xhr', () => { if (!lastLog || lastLog.get('name') !== 'request') return try { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('name')).to.eq('request') expect(e.message).to.include(lastLog.get('error').message) done() @@ -2024,7 +2025,7 @@ describe('src/cy/commands/xhr', () => { const { lastLog } = this // route + window + xhr log === 3 - expect(this.logs.length).to.eq(3) + assertLogLength(this.logs, 3) expect(lastLog.get('name')).to.eq('xhr') expect(err.message).to.include(lastLog.get('error').message) @@ -2064,7 +2065,7 @@ describe('src/cy/commands/xhr', () => { const { lastLog } = this expect(err.message).to.eq('some error') - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('name')).to.eq('route') expect(lastLog.get('error')).to.eq(err) expect(lastLog.get('message')).to.eq('/foo/, fixture:bar') @@ -2115,7 +2116,7 @@ describe('src/cy/commands/xhr', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(2) + assertLogLength(this.logs, 2) expect(err.message).to.eq('`cy.route()` could not find a registered alias for: `@bar`.\nAvailable aliases are: `foo`.') expect(lastLog.get('name')).to.eq('route') expect(lastLog.get('error')).to.eq(err) diff --git a/packages/driver/cypress/integration/e2e/redirects_spec.js b/packages/driver/cypress/integration/e2e/redirects_spec.js index 2648abd66df3..21d0e06b177d 100644 --- a/packages/driver/cypress/integration/e2e/redirects_spec.js +++ b/packages/driver/cypress/integration/e2e/redirects_spec.js @@ -1,3 +1,5 @@ +const { assertLogLength } = require('../../support/utils') + describe('redirection', () => { beforeEach(function () { this.logs = [] @@ -15,13 +17,14 @@ describe('redirection', () => { .visit('/fixtures/meta-redirect-timeout.html') .contains('timeout') .then(function () { - // visit, contains, page load, new url - expect(this.logs.length).to.eq(4) + // visit, contains, page load, new url + const receivedLogs = this.logs.reduce((prev, curr, index) => `${prev}, ${index}: ${curr.get('name')}`, '') + + assertLogLength(this.logs, 4, `received more logs than expected: ${receivedLogs}`) expect(this.logs[0].get('name')).to.eq('visit') expect(this.logs[1].get('name')).to.eq('contains') expect(this.logs[2].get('name')).to.eq('page load') - expect(this.logs[3].get('name')).to.eq('new url') }) }) @@ -31,13 +34,14 @@ describe('redirection', () => { .visit('/fixtures/meta-redirect.html') .get('a:first') .then(function () { - // visit, get, page load, new url - expect(this.logs.length).to.eq(4) + // visit, get, page load, new url + const receivedLogs = this.logs.reduce((prev, curr, index) => `${prev}, ${index}: ${curr.get('name')}`, '') + + assertLogLength(this.logs, 4, `received more logs than expected: ${receivedLogs}`) expect(this.logs[0].get('name')).to.eq('visit') expect(this.logs[1].get('name')).to.eq('get') expect(this.logs[2].get('name')).to.eq('page load') - expect(this.logs[3].get('name')).to.eq('new url') }) }) @@ -50,13 +54,12 @@ describe('redirection', () => { .visit('/fixtures/js-redirect-timeout.html') .contains('timeout') .then(function () { - // visit, contains, page load, new url - expect(this.logs.length).to.eq(4) + // visit, contains, page load, new url + assertLogLength(this.logs, 4) expect(this.logs[0].get('name')).to.eq('visit') expect(this.logs[1].get('name')).to.eq('contains') expect(this.logs[2].get('name')).to.eq('page load') - expect(this.logs[3].get('name')).to.eq('new url') }) }) @@ -66,8 +69,8 @@ describe('redirection', () => { .visit('/fixtures/js-redirect.html') .get('a:first') .then(function () { - // visit, get, page load, new url - expect(this.logs.length).to.eq(4) + // visit, get, page load, new url + assertLogLength(this.logs, 4) expect(this.logs[0].get('name')).to.eq('visit') expect(this.logs[1].get('name')).to.eq('get') diff --git a/packages/driver/cypress/integration/e2e/return_value_spec.js b/packages/driver/cypress/integration/e2e/return_value_spec.js index a1a55a5b492d..d9280c031acd 100644 --- a/packages/driver/cypress/integration/e2e/return_value_spec.js +++ b/packages/driver/cypress/integration/e2e/return_value_spec.js @@ -1,3 +1,5 @@ +const { assertLogLength } = require('../../support/utils') + describe('return values', () => { beforeEach(function () { this.logs = [] @@ -13,7 +15,7 @@ describe('return values', () => { it('can return undefined and invoke cy commands', (done) => { cy.wrap(null).then(function () { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) done() }) @@ -60,7 +62,7 @@ describe('return values', () => { it('can return undefined when invoking cy commands in custom command', (done) => { Cypress.Commands.add('foo', () => { cy.wrap(null).then(function () { - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) done() }) @@ -74,7 +76,7 @@ describe('return values', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('name')).to.eq('foo') expect(lastLog.get('error')).to.eq(err) expect(err.message).to.include('> `cy.foo()`') @@ -98,7 +100,7 @@ describe('return values', () => { cy.on('fail', (err) => { const { lastLog } = this - expect(this.logs.length).to.eq(1) + assertLogLength(this.logs, 1) expect(lastLog.get('name')).to.eq('foo') expect(lastLog.get('error')).to.eq(err) expect(err.message).to.include('> `cy.foo()`') diff --git a/packages/driver/cypress/support/defaults.js b/packages/driver/cypress/support/defaults.js index 7fdac3420dbe..e4bac5f20ad2 100644 --- a/packages/driver/cypress/support/defaults.js +++ b/packages/driver/cypress/support/defaults.js @@ -1,8 +1,7 @@ const { $ } = Cypress -let isActuallyInteractive +const isActuallyInteractive = Cypress.config('isInteractive') -isActuallyInteractive = Cypress.config('isInteractive') if (!isActuallyInteractive) { // we want to only enable retries in runMode // and because we set `isInteractive` above @@ -11,8 +10,6 @@ if (!isActuallyInteractive) { } beforeEach(() => { - isActuallyInteractive = Cypress.config('isInteractive') - // always set that we're interactive so we // get consistent passes and failures when running // from CI and when running in GUI mode diff --git a/packages/driver/cypress/support/utils.js b/packages/driver/cypress/support/utils.js index 8a741a8b74e6..c358c3d657c8 100644 --- a/packages/driver/cypress/support/utils.js +++ b/packages/driver/cypress/support/utils.js @@ -66,6 +66,12 @@ export const shouldBeCalledWithCount = (num) => (stub) => wrapped(stub).should(' export const shouldNotBeCalled = (stub) => wrapped(stub).should('not.be.called') +export const assertLogLength = (logs, expectedLength) => { + const receivedLogs = logs.map((x, index) => `\n\n${index} - ${x.get('name')}: ${x.get('message')}`).join('\n') + + expect(logs.length).to.eq(expectedLength, `received ${logs.length} logs when we expected ${expectedLength}: [${receivedLogs}]`) +} + export const attachListeners = (listenerArr) => { return (els) => { _.each(els, (el, elName) => { diff --git a/packages/driver/package.json b/packages/driver/package.json index 265068e64c0b..df5da2ff910e 100644 --- a/packages/driver/package.json +++ b/packages/driver/package.json @@ -7,7 +7,8 @@ "cypress:open": "node ../../scripts/cypress open", "cypress:run": "node ../../scripts/cypress run", "postinstall": "patch-package", - "start": "node -e 'console.log(require(`chalk`).red(`\nError:\n\tRunning \\`yarn start\\` is no longer needed for driver/cypress tests.\n\tWe now automatically spawn the server in the pluginsFile.\n\tChanges to the server will be watched and reloaded automatically.`))'" + "start": "node -e 'console.log(require(`chalk`).red(`\nError:\n\tRunning \\`yarn start\\` is no longer needed for driver/cypress tests.\n\tWe now automatically spawn the server in the pluginsFile.\n\tChanges to the server will be watched and reloaded automatically.`))'", + "test-integration": "yarn cypress:run" }, "dependencies": {}, "devDependencies": { diff --git a/packages/driver/src/cypress/mocha.ts b/packages/driver/src/cypress/mocha.ts index 9450c2f1a885..f6bd59aee47d 100644 --- a/packages/driver/src/cypress/mocha.ts +++ b/packages/driver/src/cypress/mocha.ts @@ -416,6 +416,13 @@ const patchRunnableResetTimeout = () => { } this.timer = setTimeout(() => { + if (runnable.state === 'passed') { + // this timeout can be reached at the same time that a + // user does an asynchronous `done`, so double-check + // that the test has not already passed before timing out + return + } + const err = $errUtils.errByPath(getErrPath(), { ms }) runnable.callback(err)