feat: Add timeout period to retry error message (#9123)

This commit is contained in:
Kukhyeon Heo
2020-12-16 15:56:16 +09:00
committed by GitHub
parent 3d1565e3d5
commit cfaf1ad82c
16 changed files with 58 additions and 48 deletions

View File

@@ -26,7 +26,7 @@
"failedTests": [
{
"body": "function () {}",
"error": "Timed out retrying: cy.click() failed because this element is being covered by another element:",
"error": "Timed out retrying after 4000ms: cy.click() failed because this element is being covered by another element:",
"id": "175e807c-ce85-5f94-938c-e2e30b090633",
"instanceId": "d1609552-31b5-50c1-b307-c27c9553ccb8",
"stack": "Error: Uncaught ReferenceError:\n at Object.$Cypress.Utils._.cypressErr (http://localhost:2020/__cypress/static/js/cypress.js:4678:15)\n at Object.$Cypress.Utils._.throwErr (http://localhost:2020/__cypress/static/js/cypress.js:4642:22)\n at Object.$Cypress.Utils._.throwErrByPath (http://localhost:2020/__cypress/static/js/cypress.js:4670:21)",
@@ -53,7 +53,7 @@
},
{
"body": "function () {}",
"error": "Timed out retrying: cy.click() failed because this element is being covered by another element:",
"error": "Timed out retrying after 4000ms: cy.click() failed because this element is being covered by another element:",
"failedFromHookId": "h1",
"id": "ef0d934e-a247-5e60-b801-3c5be5aa8796",
"instanceId": "d1609552-31b5-50c1-b307-c27c9553ccb8",

View File

@@ -1054,7 +1054,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)
expect(err.message).to.eq('Timed out retrying: `cy.trigger()` `eventConstructor` option must be a valid event (e.g. \'MouseEvent\', \'KeyboardEvent\'). You passed: `FooEvent`')
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()
})

View File

@@ -490,7 +490,7 @@ describe('src/cy/commands/assertions', () => {
it('throws when eventually times out', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.eq('Timed out retrying: expected \'<button>\' to have class \'does-not-have-class\'')
expect(err.message).to.eq('Timed out retrying after 50ms: expected \'<button>\' to have class \'does-not-have-class\'')
done()
})

View File

@@ -616,7 +616,7 @@ describe('src/cy/commands/connectors', () => {
}
cy.on('fail', (err) => {
expect(err.message).to.include('Timed out retrying: `cy.invoke()` errored because the property: `foo` returned a `regexp` value instead of a function. `cy.invoke()` can only be used on properties that return callable functions.')
expect(err.message).to.include('Timed out retrying after 100ms: `cy.invoke()` errored because the property: `foo` returned a `regexp` value instead of a function. `cy.invoke()` can only be used on properties that return callable functions.')
expect(err.message).to.include('`cy.invoke()` waited for the specified property `foo` to return a function, but it never did.')
expect(err.message).to.include('If you want to assert on the property\'s value, then switch to use `cy.its()` and add an assertion such as:')
expect(err.message).to.include('`cy.wrap({ foo: \'bar\' }).its(\'foo\').should(\'eq\', \'bar\')`')
@@ -636,7 +636,7 @@ describe('src/cy/commands/connectors', () => {
}
cy.on('fail', (err) => {
expect(err.message).to.include('Timed out retrying: `cy.invoke()` errored because the property: `bar` returned a `string` value instead of a function. `cy.invoke()` can only be used on properties that return callable functions.')
expect(err.message).to.include('Timed out retrying after 100ms: `cy.invoke()` errored because the property: `bar` returned a `string` value instead of a function. `cy.invoke()` can only be used on properties that return callable functions.')
expect(err.message).to.include('`cy.invoke()` waited for the specified property `bar` to return a function, but it never did.')
expect(err.message).to.include('If you want to assert on the property\'s value, then switch to use `cy.its()` and add an assertion such as:')
expect(err.message).to.include('`cy.wrap({ foo: \'bar\' }).its(\'foo\').should(\'eq\', \'bar\')`')
@@ -972,7 +972,7 @@ describe('src/cy/commands/connectors', () => {
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.include('Timed out retrying: `cy.invoke()` errored because the property: `foo` does not exist on your subject.')
expect(err.message).to.include('Timed out retrying after 100ms: `cy.invoke()` errored because the property: `foo` does not exist on your subject.')
expect(err.message).to.include('`cy.invoke()` waited for the specified property `foo` to exist, but it never did.')
expect(err.message).to.include('If you do not expect the property `foo` to exist, then add an assertion such as:')
expect(err.message).to.include('`cy.wrap({ foo: \'bar\' }).its(\'quux\').should(\'not.exist\')`')
@@ -1019,9 +1019,9 @@ describe('src/cy/commands/connectors', () => {
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.eq('Timed out retrying: expected \'foo\' to equal \'bar\'')
expect(err.message).to.eq('Timed out retrying after 100ms: expected \'foo\' to equal \'bar\'')
expect(lastLog.get('error').message).to.eq('Timed out retrying: expected \'foo\' to equal \'bar\'')
expect(lastLog.get('error').message).to.eq('Timed out retrying after 100ms: expected \'foo\' to equal \'bar\'')
done()
})
@@ -1033,7 +1033,7 @@ describe('src/cy/commands/connectors', () => {
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.include('Timed out retrying: `cy.invoke()` errored because your subject is: `undefined`. You cannot invoke any functions such as `foo` on a `undefined` value.')
expect(err.message).to.include('Timed out retrying after 100ms: `cy.invoke()` errored because your subject is: `undefined`. You cannot invoke any functions such as `foo` on a `undefined` value.')
expect(err.message).to.include('If you expect your subject to be `undefined`, then add an assertion such as:')
expect(err.message).to.include('`cy.wrap(undefined).should(\'be.undefined\')`')
expect(err.docsUrl).to.eq('https://on.cypress.io/invoke')
@@ -1049,7 +1049,7 @@ describe('src/cy/commands/connectors', () => {
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.include('Timed out retrying: `cy.invoke()` errored because the property: `foo` is not a function, and instead returned a `undefined` value.')
expect(err.message).to.include('Timed out retrying after 100ms: `cy.invoke()` errored because the property: `foo` is not a function, and instead returned a `undefined` value.')
expect(err.message).to.include('`cy.invoke()` waited for the specified property `foo` to become a callable function, but it never did.')
expect(err.message).to.include('If you expect the property `foo` to be `undefined`, then switch to use `cy.its()` and add an assertion such as:')
expect(err.message).to.include('`cy.wrap({ foo: undefined }).its(\'foo\').should(\'be.undefined\')`')
@@ -1066,7 +1066,7 @@ describe('src/cy/commands/connectors', () => {
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.include('Timed out retrying: `cy.invoke()` errored because the property: `baz` does not exist on your subject.')
expect(err.message).to.include('Timed out retrying after 100ms: `cy.invoke()` errored because the property: `baz` does not exist on your subject.')
expect(lastLog.get('error').message).to.include(err.message)
expect(err.docsUrl).to.eq('https://on.cypress.io/invoke')
@@ -1522,7 +1522,7 @@ describe('src/cy/commands/connectors', () => {
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.include('Timed out retrying: `cy.its()` errored because the property: `foo` does not exist on your subject.')
expect(err.message).to.include('Timed out retrying after 100ms: `cy.its()` errored because the property: `foo` does not exist on your subject.')
expect(err.message).to.include('`cy.its()` waited for the specified property `foo` to exist, but it never did.')
expect(err.message).to.include('If you do not expect the property `foo` to exist, then add an assertion such as:')
expect(err.message).to.include('`cy.wrap({ foo: \'bar\' }).its(\'quux\').should(\'not.exist\')`')
@@ -1539,7 +1539,7 @@ describe('src/cy/commands/connectors', () => {
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.include('Timed out retrying: `cy.its()` errored because the property: `foo` returned a `undefined` value.')
expect(err.message).to.include('Timed out retrying after 100ms: `cy.its()` errored because the property: `foo` returned a `undefined` value.')
expect(err.message).to.include('`cy.its()` waited for the specified property `foo` to become accessible, but it never did.')
expect(err.message).to.include('If you expect the property `foo` to be `undefined`, then add an assertion such as:')
expect(err.message).to.include('`cy.wrap({ foo: undefined }).its(\'foo\').should(\'be.undefined\')`')
@@ -1556,7 +1556,7 @@ describe('src/cy/commands/connectors', () => {
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.include('Timed out retrying: `cy.its()` errored because the property: `foo` returned a `null` value.')
expect(err.message).to.include('Timed out retrying after 100ms: `cy.its()` errored because the property: `foo` returned a `null` value.')
expect(err.message).to.include('`cy.its()` waited for the specified property `foo` to become accessible, but it never did.')
expect(err.message).to.include('If you expect the property `foo` to be `null`, then add an assertion such as:')
expect(err.message).to.include('`cy.wrap({ foo: null }).its(\'foo\').should(\'be.null\')`')
@@ -1573,7 +1573,7 @@ describe('src/cy/commands/connectors', () => {
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.include('Timed out retrying: `cy.its()` errored because the property: `b` does not exist on your subject.')
expect(err.message).to.include('Timed out retrying after 100ms: `cy.its()` errored because the property: `b` does not exist on your subject.')
expect(err.message).to.include('`cy.its()` waited for the specified property `b` to exist, but it never did.')
expect(err.message).to.include('If you do not expect the property `b` to exist, then add an assertion such as:')
expect(err.message).to.include('`cy.wrap({ foo: \'bar\' }).its(\'quux\').should(\'not.exist\')`')
@@ -1590,7 +1590,7 @@ describe('src/cy/commands/connectors', () => {
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.include('Timed out retrying: `cy.its()` errored because the property: `a` returned a `undefined` value.')
expect(err.message).to.include('Timed out retrying after 100ms: `cy.its()` errored because the property: `a` returned a `undefined` value.')
expect(err.message).to.include('`cy.its()` waited for the specified property `a` to become accessible, but it never did.')
expect(err.message).to.include('If you expect the property `a` to be `undefined`, then add an assertion such as:')
expect(err.message).to.include('`cy.wrap({ foo: undefined }).its(\'foo\').should(\'be.undefined\')`')
@@ -1628,7 +1628,7 @@ describe('src/cy/commands/connectors', () => {
it('can handle getter that throws', (done) => {
const spy = cy.spy((err) => {
expect(err.message).to.eq('Timed out retrying: some getter error')
expect(err.message).to.eq('Timed out retrying after 100ms: some getter error')
done()
}).as('onFail')
@@ -1650,7 +1650,7 @@ describe('src/cy/commands/connectors', () => {
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.include('Timed out retrying: `cy.its()` errored because the property: `baz` does not exist on your subject.')
expect(err.message).to.include('Timed out retrying after 100ms: `cy.its()` errored because the property: `baz` does not exist on your subject.')
expect(err.docsUrl).to.eq('https://on.cypress.io/its')
expect(lastLog.get('error').message).to.include(err.message)
expect(lastLog.get('error').message).to.include(err.message)
@@ -1670,7 +1670,7 @@ describe('src/cy/commands/connectors', () => {
[null, undefined].forEach((val) => {
it(`throws on traversed '${val}' subject`, (done) => {
cy.on('fail', (err) => {
expect(err.message).to.include(`Timed out retrying: \`cy.its()\` errored because the property: \`a\` returned a \`${val}\` value. The property: \`b\` does not exist on a \`${val}\` value.`)
expect(err.message).to.include(`Timed out retrying after 100ms: \`cy.its()\` errored because the property: \`a\` returned a \`${val}\` value. The property: \`b\` does not exist on a \`${val}\` value.`)
expect(err.message).to.include('`cy.its()` waited for the specified property `b` to become accessible, but it never did.')
expect(err.message).to.include('If you do not expect the property `b` to exist, then add an assertion such as:')
expect(err.message).to.include(`\`cy.wrap({ foo: ${val} }).its('foo.baz').should('not.exist')\``)
@@ -1684,7 +1684,7 @@ describe('src/cy/commands/connectors', () => {
it(`throws on initial '${val}' subject`, (done) => {
cy.on('fail', (err) => {
expect(err.message).to.include(`Timed out retrying: \`cy.its()\` errored because your subject is: \`${val}\`. You cannot access any properties such as \`foo\` on a \`${val}\` value.`)
expect(err.message).to.include(`Timed out retrying after 100ms: \`cy.its()\` errored because your subject is: \`${val}\`. You cannot access any properties such as \`foo\` on a \`${val}\` value.`)
expect(err.message).to.include(`If you expect your subject to be \`${val}\`, then add an assertion such as:`)
expect(err.message).to.include(`\`cy.wrap(${val}).should('be.${val}')\``)
expect(err.docsUrl).to.eq('https://on.cypress.io/its')
@@ -1767,7 +1767,7 @@ describe('src/cy/commands/connectors', () => {
cy.on('fail', (err) => {
const { lastLog } = this
expect(err.message).to.include('Timed out retrying: expected \'bar\' to equal \'baz\'')
expect(err.message).to.include('Timed out retrying after 200ms: expected \'bar\' to equal \'baz\'')
expect(lastLog.get('error').message).to.include(err.message)
done()

View File

@@ -252,7 +252,7 @@ describe('src/cy/commands/files', () => {
expect(lastLog.get('state')).to.eq('failed')
expect(err.message).to.eq(stripIndent`
Timed out retrying: \`cy.readFile(\"foo.json\")\` failed because the file does not exist at the following path:
Timed out retrying after 50ms: \`cy.readFile(\"foo.json\")\` failed because the file does not exist at the following path:
\`/path/to/foo.json\``)
@@ -274,7 +274,7 @@ describe('src/cy/commands/files', () => {
expect(lastLog.get('error')).to.eq(err)
expect(lastLog.get('state')).to.eq('failed')
expect(err.message).to.eq(stripIndent`\
Timed out retrying: \`cy.readFile(\"foo.json\")\` failed because the file exists when expected not to exist at the following path:
Timed out retrying after 50ms: \`cy.readFile(\"foo.json\")\` failed because the file exists when expected not to exist at the following path:
\`/path/to/foo.json\``)
@@ -297,7 +297,7 @@ describe('src/cy/commands/files', () => {
expect(this.logs.length).to.eq(1)
expect(lastLog.get('error')).to.eq(err)
expect(lastLog.get('state')).to.eq('failed')
expect(err.message).to.eq('Timed out retrying: expected \'foo\' to equal \'contents\'')
expect(err.message).to.eq('Timed out retrying after 50ms: expected \'foo\' to equal \'contents\'')
done()
})

View File

@@ -191,7 +191,7 @@ describe('src/cy/commands/querying - shadow dom', () => {
it('has a custom error message if it cannot find a root', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.equal(`Timed out retrying: Expected the subject to host a shadow root, but never found it.`)
expect(err.message).to.equal(`Timed out retrying after 0ms: Expected the subject to host a shadow root, but never found it.`)
expect(err.docsUrl).to.equal('https://on.cypress.io/shadow')
done()

View File

@@ -66,7 +66,9 @@ const create = (Cypress, state, timeout, clearTimeout, whenStable, finishAsserti
({ error, onFail } = options)
const prependMsg = $errUtils.errByPath('miscellaneous.retry_timed_out').message
const prependMsg = $errUtils.errByPath('miscellaneous.retry_timed_out', {
ms: options._runnableTimeout,
}).message
const retryErrProps = $errUtils.modifyErrMsg(error, prependMsg, (msg1, msg2) => {
return `${msg2}${msg1}`

View File

@@ -820,7 +820,9 @@ module.exports = {
docsUrl: 'https://on.cypress.io/cannot-execute-commands-outside-test',
},
private_custom_command_interface: 'You cannot use the undocumented private command interface: `{{method}}`',
retry_timed_out: 'Timed out retrying: ',
retry_timed_out ({ ms }) {
return `Timed out retrying after ${ms}ms: `
},
},
mocha: {

View File

@@ -67,13 +67,13 @@ describe('errors ui', () => {
verify.it('failure', {
file,
column: 8,
message: 'Timed out retrying: Expected to find element: #does-not-exist, but never found it',
message: 'Timed out retrying after 0ms: Expected to find element: #does-not-exist, but never found it',
})
verify.it('chained failure', {
file,
column: 20,
message: 'Timed out retrying: Expected to find element: #does-not-exist, but never found it',
message: 'Timed out retrying after 0ms: Expected to find element: #does-not-exist, but never found it',
})
})
@@ -95,7 +95,7 @@ describe('errors ui', () => {
verify.it('command failure', {
file,
column: 10,
message: 'Timed out retrying: Expected to find element: #does-not-exist, but never found it',
message: 'Timed out retrying after 0ms: Expected to find element: #does-not-exist, but never found it',
})
})
@@ -117,13 +117,13 @@ describe('errors ui', () => {
verify.it('standard assertion failure', {
file,
column: 6,
message: 'Timed out retrying: expected {} to have property \'foo\'',
message: 'Timed out retrying after 0ms: expected {} to have property \'foo\'',
})
verify.it('after multiple', {
file,
column: 6,
message: 'Timed out retrying: expected \'foo\' to equal \'bar\'',
message: 'Timed out retrying after 0ms: expected \'foo\' to equal \'bar\'',
})
verify.it('after multiple callbacks exception', {
@@ -150,7 +150,7 @@ describe('errors ui', () => {
verify.it('command failure after success', {
file,
column: 8,
message: 'Timed out retrying: Expected to find element: #does-not-exist, but never found it',
message: 'Timed out retrying after 0ms: Expected to find element: #does-not-exist, but never found it',
})
})
@@ -523,7 +523,7 @@ describe('errors ui', () => {
verify.it('command failure', {
file,
column: 6,
message: 'Timed out retrying: Expected to find element: #does-not-exist, but never found it',
message: 'Timed out retrying after 0ms: Expected to find element: #does-not-exist, but never found it',
codeFrameText: `add('failCommand'`,
})
})
@@ -546,7 +546,7 @@ describe('errors ui', () => {
verify.it('command failure', {
file,
column: 8,
message: 'Timed out retrying: Expected to find element: #does-not-exist, but never found it',
message: 'Timed out retrying after 0ms: Expected to find element: #does-not-exist, but never found it',
})
})

View File

@@ -41,7 +41,7 @@ exports['e2e caught and uncaught hooks errors / failing1'] = `
1) s1a
"before each" hook for "t2a":
AssertionError: Timed out retrying: Expected to find element: \`.does-not-exist\`, but never found it.
AssertionError: Timed out retrying after 100ms: Expected to find element: \`.does-not-exist\`, but never found it.
Because this error occurred during a \`before each\` hook we are skipping the remaining tests in the current suite: \`s1a\`
[stack trace lines]

View File

@@ -92,7 +92,7 @@ exports['e2e config applies defaultCommandTimeout globally 1'] = `
1) short defaultCommandTimeout
times out looking for a missing element:
AssertionError: Timed out retrying: Expected to find element: \`#bar\`, but never found it.
AssertionError: Timed out retrying after 1000ms: Expected to find element: \`#bar\`, but never found it.
[stack trace lines]

View File

@@ -24,7 +24,7 @@ exports['e2e issue 173 / failing'] = `
1 failing
1) fails:
AssertionError: Timed out retrying: Expected to find element: \`element_does_not_exist\`, but never found it.
AssertionError: Timed out retrying after 200ms: Expected to find element: \`element_does_not_exist\`, but never found it.
[stack trace lines]

View File

@@ -441,13 +441,13 @@ exports['e2e spec_isolation fails [electron] 1'] = {
],
"state": "failed",
"body": "function() {\n return cy.wrap(true, {\n timeout: 100\n }).should(\"be.false\");\n }",
"displayError": "AssertionError: Timed out retrying: expected true to be false\n [stack trace lines]",
"displayError": "AssertionError: Timed out retrying after 100ms: expected true to be false\n [stack trace lines]",
"attempts": [
{
"state": "failed",
"error": {
"name": "AssertionError",
"message": "Timed out retrying: expected true to be false",
"message": "Timed out retrying after 100ms: expected true to be false",
"stack": "[stack trace lines]",
"codeFrame": {
"line": 3,
@@ -1005,13 +1005,13 @@ exports['e2e spec_isolation fails [chrome] 1'] = {
],
"state": "failed",
"body": "function() {\n return cy.wrap(true, {\n timeout: 100\n }).should(\"be.false\");\n }",
"displayError": "AssertionError: Timed out retrying: expected true to be false\n [stack trace lines]",
"displayError": "AssertionError: Timed out retrying after 100ms: expected true to be false\n [stack trace lines]",
"attempts": [
{
"state": "failed",
"error": {
"name": "AssertionError",
"message": "Timed out retrying: expected true to be false",
"message": "Timed out retrying after 100ms: expected true to be false",
"stack": "[stack trace lines]",
"codeFrame": {
"line": 3,
@@ -1569,13 +1569,13 @@ exports['e2e spec_isolation fails [firefox] 1'] = {
],
"state": "failed",
"body": "function() {\n return cy.wrap(true, {\n timeout: 100\n }).should(\"be.false\");\n }",
"displayError": "AssertionError: Timed out retrying: expected true to be false\n [stack trace lines]",
"displayError": "AssertionError: Timed out retrying after 100ms: expected true to be false\n [stack trace lines]",
"attempts": [
{
"state": "failed",
"error": {
"name": "AssertionError",
"message": "Timed out retrying: expected true to be false",
"message": "Timed out retrying after 100ms: expected true to be false",
"stack": "[stack trace lines]",
"codeFrame": {
"line": 3,

View File

@@ -458,7 +458,7 @@ exports['e2e stdout / displays assertion errors'] = `
2) assertion errors
fails with assertion diff, with retries:
Timed out retrying
Timed out retrying after 4000ms
+ expected - actual
-[]
@@ -473,7 +473,7 @@ exports['e2e stdout / displays assertion errors'] = `
4) assertion errors
fails with dom assertion without diff, with retries:
AssertionError: Timed out retrying: expected '<body>' to have class 'foo'
AssertionError: Timed out retrying after 4000ms: expected '<body>' to have class 'foo'
[stack trace lines]

View File

@@ -98,7 +98,7 @@ https://on.cypress.io/cross-origin-violation
4) web security
fails when doing a CORS request cross-origin:
AssertionError: Timed out retrying: Expected to find content: 'success!' but never did.
AssertionError: Timed out retrying after 500ms: Expected to find content: 'success!' but never did.
[stack trace lines]

View File

@@ -43,6 +43,8 @@ const browserNameVersionRe = /(Browser\:\s+)(Custom |)(Electron|Chrome|Canary|Ch
const availableBrowsersRe = /(Available browsers found on your system are:)([\s\S]+)/g
const crossOriginErrorRe = /(Blocked a frame .* from accessing a cross-origin frame.*|Permission denied.*cross-origin object.*)/gm
const whiteSpaceBetweenNewlines = /\n\s+\n/
const retryDuration = /Timed out retrying after (\d+)ms/g
const escapedRetryDuration = /TORA(\d+)/g
export const STDOUT_DURATION_IN_TABLES_RE = /(\s+?)(\d+ms|\d+:\d+:?\d+)/g
@@ -154,8 +156,12 @@ const normalizeStdout = function (str, options: any = {}) {
.replace(browserNameVersionRe, replaceBrowserName)
// numbers in parenths
.replace(/\s\(\d+([ms]|ms)\)/g, '')
// escape "Timed out retrying" messages
.replace(retryDuration, 'TORA$1')
// 12:35 -> XX:XX
.replace(STDOUT_DURATION_IN_TABLES_RE, replaceDurationInTables)
// restore "Timed out retrying" messages
.replace(escapedRetryDuration, 'Timed out retrying after $1ms')
.replace(/(coffee|js)-\d{3}/g, '$1-456')
// Cypress: 2.1.0 -> Cypress: 1.2.3
.replace(/(Cypress\:\s+)(\d+\.\d+\.\d+)/g, replaceCypressVersion)