From d65ee3045e1ad08acfa3159fa75bcfb811f77738 Mon Sep 17 00:00:00 2001 From: sainthkh Date: Wed, 13 Nov 2019 00:20:15 +0900 Subject: [PATCH] Fix formatting in Command Log test results. (#5619) * Preserve number strings. * Fixed warning caused by exception. * Fixed excessive quotation marks. And added related tests to show this. * Show keys properly. * Minor fixes: arrowify, use backtick. * Added tests. * Fixed confusing asterisks. --- packages/driver/src/cy/chai.js | 42 +++++-- .../integration/commands/assertions_spec.js | 104 ++++++++++++++++++ 2 files changed, 134 insertions(+), 12 deletions(-) diff --git a/packages/driver/src/cy/chai.js b/packages/driver/src/cy/chai.js index ea018736522a..e5bcdfbd36c8 100644 --- a/packages/driver/src/cy/chai.js +++ b/packages/driver/src/cy/chai.js @@ -9,20 +9,21 @@ const $dom = require('../dom') const $utils = require('../cypress/utils') const $chaiJquery = require('../cypress/chai_jquery') -// all words between single quotes which are at -// the end of the string -const allPropertyWordsBetweenSingleQuotes = /('.*?')$/g - -// grab all words between single quotes except -// when the single quote word is the LAST word -const allButLastWordsBetweenSingleQuotes = /('.*?')(.+)/g +// all words between single quotes +const allPropertyWordsBetweenSingleQuotes = /('.*?')/g const allBetweenFourStars = /\*\*.*\*\*/ +const allNumberStrings = /'([0-9]+)'/g +const allEmptyStrings = /''/g const allSingleQuotes = /'/g const allEscapedSingleQuotes = /\\'/g const allQuoteMarkers = /__quote__/g const allWordsBetweenCurlyBraces = /(#{.+?})/g const allQuadStars = /\*\*\*\*/g +const leadingWhitespaces = /\*\*'\s*/g +const trailingWhitespaces = /\s*'\*\*/g +const whitespace = /\s/g +const valueHasLeadingOrTrailingWhitespaces = /\*\*'\s+|\s+'\*\*/g let assertProto = null let matchProto = null @@ -78,17 +79,32 @@ chai.use((chai, u) => { existProto = Object.getOwnPropertyDescriptor(chai.Assertion.prototype, 'exist').get; ({ getMessage } = chaiUtils) - // remove any single quotes between our **, preserving escaped quotes - // and if an empty string, put the quotes back + // remove any single quotes between our **, + // except escaped quotes, empty strings and number strings. const removeOrKeepSingleQuotesBetweenStars = (message) => { return message.replace(allBetweenFourStars, (match) => { + if (valueHasLeadingOrTrailingWhitespaces.test(match)) { + // Above we used \s+, but below we use \s*. + // It's because of the strings like ' love' that have empty spaces on one side only. + match = match + .replace(leadingWhitespaces, (match) => { + return match.replace(`**'`, '**__quote__') + .replace(whitespace, ' ') + }) + .replace(trailingWhitespaces, (match) => { + return match.replace(`'**`, '__quote__**') + .replace(whitespace, ' ') + }) + } + return match .replace(allEscapedSingleQuotes, '__quote__') // preserve escaped quotes + .replace(allNumberStrings, '__quote__$1__quote__') // preserve number strings (e.g. '42') + .replace(allEmptyStrings, '__quote____quote__') // preserve empty strings (e.g. '') .replace(allSingleQuotes, '') .replace(allQuoteMarkers, '\'') // put escaped quotes back - .replace(allQuadStars, '**\'\'**') }) - } // fix empty strings that end up as **** + } const replaceArgMessages = (args, str) => { return _.reduce(args, (memo, value, index) => { @@ -96,8 +112,10 @@ chai.use((chai, u) => { value = value .replace(allWordsBetweenCurlyBraces, '**$1**') .replace(allEscapedSingleQuotes, '__quote__') - .replace(allButLastWordsBetweenSingleQuotes, '**$1**$2') .replace(allPropertyWordsBetweenSingleQuotes, '**$1**') + // when a value has ** in it, **** are sometimes created after the process above. + // remove them with this. + .replace(allQuadStars, '**') memo.push(value) } else { diff --git a/packages/driver/test/cypress/integration/commands/assertions_spec.js b/packages/driver/test/cypress/integration/commands/assertions_spec.js index c34d5c63a6e1..3153dcb1f75d 100644 --- a/packages/driver/test/cypress/integration/commands/assertions_spec.js +++ b/packages/driver/test/cypress/integration/commands/assertions_spec.js @@ -976,6 +976,110 @@ describe('src/cy/commands/assertions', () => { }) }) + context('format quotation marks', () => { + const expectMarkdown = (test, message, done) => { + cy.then(() => { + test() + }) + + cy.on('log:added', (attrs, log) => { + if (attrs.name === 'assert') { + cy.removeAllListeners('log:added') + + expect(log.get('message')).to.eq(message) + + done() + } + }) + } + + it('preserves quotation marks in number strings', (done) => { + expectMarkdown(() => { + try { + expect(25).to.eq('25') + } catch (error) {} /* eslint-disable-line no-empty */ + }, + `expected **25** to equal **'25'**`, + done) + }) + + it('preserves quotation marks in empty string', (done) => { + expectMarkdown(() => { + try { + expect(42).to.eq('') + } catch (error) {} /* eslint-disable-line no-empty */ + }, + `expected **42** to equal **''**`, + done) + }) + + it('preserves quotation marks if escaped', (done) => { + expectMarkdown( + () => expect(`\'cypress\'`).to.eq(`\'cypress\'`), + // ****'cypress'**** -> ** for emphasizing result string + ** for emphasizing the entire result. + `expected **'cypress'** to equal ****'cypress'****`, + done + ) + }) + + it('removes quotation marks in DOM elements', (done) => { + expectMarkdown( + () => { + cy.get('body').then(($body) => { + expect($body).to.contain('div') + }) + }, + `expected **** to contain **div**`, + done + ) + }) + + it('removes quotation marks in strings', (done) => { + expectMarkdown(() => expect('cypress').to.eq('cypress'), `expected **cypress** to equal **cypress**`, done) + }) + + it('removes quotation marks in objects', (done) => { + expectMarkdown( + () => expect({ foo: 'bar' }).to.deep.eq({ foo: 'bar' }), + `expected **{ foo: bar }** to deeply equal **{ foo: bar }**`, + done + ) + }) + + it('formats keys properly for "have.all.keys"', (done) => { + const person = { + name: 'Joe', + age: 20, + } + + expectMarkdown( + () => expect(person).to.have.all.keys('name', 'age'), + `expected **{ name: Joe, age: 20 }** to have keys **name**, and **age**`, + done + ) + }) + + describe('formats strings with spaces', (done) => { + const tester = (message, done) => { + const nbspedMsg = message + .replace(/^\s+/, (match) => { + return match.replace(/\s/g, ' ') + }) + .replace(/\s+$/, (match) => { + return match.replace(/\s/g, ' ') + }) + + expectMarkdown(() => expect(message).to.eq(message), `expected **'${nbspedMsg}'** to equal **'${nbspedMsg}'**`, done) + } + + [' 37:46 ', ' test ', ' love'].forEach((v) => { + it(v, (done) => { + tester(v, done) + }) + }) + }) + }) + context('chai overrides', () => { beforeEach(function () { this.$body = cy.$$('body')