Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow hiding assertion logs for .should() and .and() except on failure #7693

Open
ncknuna opened this issue Jun 13, 2020 · 36 comments
Open

Allow hiding assertion logs for .should() and .and() except on failure #7693

ncknuna opened this issue Jun 13, 2020 · 36 comments
Labels
E2E Issue related to end-to-end testing pkg/driver This is due to an issue in the packages/driver directory type: enhancement Requested enhancement of existing feature

Comments

@ncknuna
Copy link

ncknuna commented Jun 13, 2020

Current behavior:

There is no way to hide logs when making assertions, for example, with should.

Desired behavior:

There is a way to hide passing assertions while still reporting failing assertions. Ideally these successful assertions could also be turned back on when running under a different log level.

This came up because I wanted a "safer" version of the get command, which would by default assert that there is only 1 element found (unless an explicit length option was passed) and that the element is visible (unless an explicit noVisibleCheck option was passed), since I've seen tests fail or falsely succeed because of overbroad selectors or when an element was present in the DOM but not visible. Cypress tests run fast enough that doing this shouldn't add significantly to the test run time.

However, when I do this, I end up with a ton of extra logs for each get, which clutters the test output. I'd like a way to disable these logs by default, unless the assertions fail.

Test code to reproduce

https://github.com/ncknuna/cypress-test-tiny/blob/master/cypress/support/commands.js#L45

Versions

Cypress 4.8.0
OSX 10.15.5
Chrome 83.0.4103.61

@jennifer-shehane
Copy link
Member

.should() and .and() doesn't currently accept a log option (or any options) as an argument. So turning off these assertions within the Command Log is not currently possible. This would have to be coded in somehow which would likely be a bit more difficult than other commands given the API signature of .should().

@cypress-bot cypress-bot bot added the stage: proposal 💡 No work has been done of this issue label Jun 15, 2020
@jennifer-shehane jennifer-shehane changed the title Allow hiding assertion logs except on failure Allow hiding assertion logs for .should() and .and() except on failure Jun 15, 2020
@jennifer-shehane jennifer-shehane added type: enhancement Requested enhancement of existing feature pkg/driver This is due to an issue in the packages/driver directory labels Jun 15, 2020
@ncknuna
Copy link
Author

ncknuna commented Jun 15, 2020

Got it, that makes sense! Thanks for accepting it as an valid potential enhancement :)

@bmitchinson
Copy link

Would like to +1 this, i'm asserting that 3 strings are contained in a file (represented as a string), and the entire contents of the file are printed, 3 times over.

@johnnymetz
Copy link

+1

@JasonFairchild
Copy link

+1
I want to assert that a local storage token exists before I get it to send as an auth header before any cy.request. Cypress will often look for it quicker than it is set, so an assertion seems like the best way, but then it can lead to many weird assertions in the log.

@northkevin
Copy link

+1

I like to check that a cookie exists before each outgoing api request & suppressing this assertion would clean up test logs quite nicely 👍

@nickdavis2001
Copy link

nickdavis2001 commented Apr 8, 2021

+1. The use case this would solve for us is for example:

  cy.request(myUrl).then((response) => {
                expect(response.headers['content-type']).to.contain('application/pdf');
                expect(response.body).to.have.length.gt(500);
            });

This is checking that the response is a reasonably sized pdf. This currently prints out the whole pdf in the log. :( I'm open to other ideas of how to do this if there's a better way. :)

@richardscarrott
Copy link

richardscarrott commented Apr 23, 2021

@ncknuna I found this issue when attempting to define the exact same thing as I found myself constantly checking have.length and is.visible.

I'm now using this:

type VGetOptions = { length: number; visible: boolean } & Parameters<
  typeof cy.get
>[1];

Cypress.Commands.add(
  'vget',
  (
    selector: string,
    { length, visible, ...rest }: VGetOptions = { visible: true, length: 1 }
  ): Cypress.Chainable<JQuery<HTMLElement>> =>
    cy
      .get(selector, rest)
      .should('have.length', length)
      .and(visible ? 'be.visible' : 'not.be.visible')
);

// ...
cy.vget('.foo'); // most common scenario
cy.vget('.foos', { length: 10 });
cy.vget('.bar', { visible: false });
cy.vget('.bars', { visible: false, length: 5 });

But yes, It would be great if passing assertions could optionally be removed from the command log.

@Threnos
Copy link

Threnos commented May 20, 2021

I'm using retry-ability to wait for SSE connection to establish. In this case I have no need for --assert expected true to be true in command log, unless it failed. Thus, having ability to hide assertion will free up space from not critical information.

const eventSource = new FetchEventSource(`http://localhost/sse/subscribe`)
cy.wrap(eventSource, { log: false }).should(eventSource => expect(eventSource.isOpen).to.be.true)

A little background for why it is done like this: for connecting to SSE we use @microsoft/fetch-event-source package. Unfortunately, because of the way it handles connection, chrome cannot properly read events and data. Which makes cy.intercept() helpless in this case.

@pcj
Copy link

pcj commented May 27, 2021

I would like this feature as well, to only log assertions that fail.

As a workaround for assertions that are easily checked up front, you can use a somewhat redundant approach like:

            let actual = ctx.maybeGet(key);
            // if we always perform the 'expect', cypress log becomes very busy.
            // detect the failure condition and repeat with chai assertion so it 
            // surfaces in the log and fails the test
            if (!actual) {
                expect(actual, `${this.id}:unreadactBody:${key}`).to.not.be.empty;
            }

@AFM-Horizon
Copy link

I'll add my name to the list - this would be great

@uday-nitjsr
Copy link

Hard +1 on this.
I was adding log options to reduce the noise in our logs, only to find i cant add it for should 😰

@carla-at-wiris
Copy link

It would be very usefull

@stychu

This comment has been minimized.

@mduft
Copy link

mduft commented Sep 21, 2021

We're checking for downloads of ZIP files, using the cypress examples as a basis, which has an assertion for the files length to be at least 300 bytes which floods the log - does not look that nice..

@zdebski
Copy link

zdebski commented Sep 22, 2021

@jennifer-shehane is there any news about this enhancement?

@DanaGoyette
Copy link

I'm using a function like this, that keeps running into "element is detached", so I had to add assertions, but they're a whole lot of clutter. I'd like to be able to hide the interim assertions if they pass.

export function getTableVal(row: string, column: 'left' | 'center' | 'right' = 'center') {
  return cy.get(`[data-row=${row}]`).should('exist').find(`[data-column=${column}]`).should('exist').find(`[data-testid=value]`)
}

image

@PierreTurnbull
Copy link

I'd love this too.

@CoryDanielson
Copy link
Contributor

@DanaGoyette, you can combine your selectors into a single get.

  return cy.get(`[data-row=${row}] [data-column=${column}] [data-testid=value]`);

@DanaGoyette
Copy link

DanaGoyette commented Nov 17, 2021

@DanaGoyette, you can combine your selectors into a single get.

  return cy.get(`[data-row=${row}] [data-column=${column}] [data-testid=value]`);

I've tried that, and the result is that I get tests failing with "component became detached from the DOM" quite often. Using the separate selectors seems to fix that. Also, the log tends to show line breaks at the dashes, which is ugly, instead of breaking at the logical place of the space between selectors.

What I get:

[data-test-row=phone] [data-test-
column=center] [data-
testid=value]

What I'd want:

[data-test-row=phone]
 [data-test-column=center]
 [data-testid=value]

The chained .get/.find makes the logs neater, except for the assertions in between.

@MoKhajavi75
Copy link

+1

Would be great to check password input values!

@laurentRank
Copy link

+1
Coupling this with Gherkin, I'm trying to get all my assertions to have specific messages when passed.
automatic assertions in .should() and .and() are currently polluting the output logs.

@jmicu
Copy link

jmicu commented Mar 4, 2022

+1. I have a custom command with several expects that clutter the log when they pass.

@sarahTheTester
Copy link

sarahTheTester commented Apr 13, 2022

As a work around, "native" chai expect() will not generate a Cypress log.

  • add chai package to the project
  • at top of spec import {expect} from 'chai'
  • use .should() with callback, e.g: .should($els => expect($els.length).to.eq(2))

If assertion fails, the error appears in the log in the normal way.

Anybody see any cons for this method?

@cypress-bot cypress-bot bot added stage: backlog and removed stage: proposal 💡 No work has been done of this issue labels Apr 28, 2022
@pkoral
Copy link

pkoral commented Jun 22, 2022

+1

@esudaley
Copy link

esudaley commented Jul 31, 2022

Aside from the issue of log clutter, when performing some large validations, I noticed that using expect() takes far longer than a plain JS conditional, which I assume is due to the logging behavior.

Here's a sample I prepared to reproduce the behavior.

describe('Compare Chai expect() to JS conditional', () => {
    let sampleString = "expect vs conditional"
    
    it('Check equality using expect()', () => {
        for (let i=0; i < 4000; i++){
            expect(sampleString).to.equal(sampleString)
        }
    })

    it('Check equality using JS to trigger expect()', () => {
        for (let i=0; i < 4000; i++){
            if(sampleString !== sampleString)
                expect(sampleString).to.equal(sampleString)
        }
    })
})

Using expect() took ~30 seconds, whereas the conditional took about 0.02 seconds.

For the time being, is there anything lacking in simply using a plain conditional to trigger expect() when the assertion should fail?

@Lagluck07
Copy link

Lagluck07 commented Aug 3, 2022

Hi all,

I just found on web a solution to hide all the "xhr" logs. So I´ve just included the "..command-name-assert" (class for the <"Li"> selector that displays the assert logs). I know that´s not the best way to do that, but it works (sorry for the poor english rs):

//Put the code below in the support/index.js file, create a hideXHR config (just in case u want to disable) and add in //style.innerHTML all the classes (LI lines) u want hide.
// Hide all fetch/XHR requests in Cy console, toggle via cypress.json

if (Cypress.config('hideXHR')) {
const app = window.top
if (!app.document.head.querySelector('[data-hide-command-log-request]')) {
const style = app.document.createElement('style')
style.innerHTML =
'.command-name-page-load, .command-name-new-url, .command-name-request, .command-name-xhr, .command-name-assert { display: none }'
style.setAttribute('data-hide-command-log-request', '')
app.document.head.appendChild(style)
}
}

@udayivaturi
Copy link

+1

@leila-c908
Copy link

+1.

@THEtheChad
Copy link

If you use the function signature form of .should, you can eliminate the logging clutter.

.should($subject => { if( {condition ) throw new Error('This is whack yo!'); })

Cypress.Commands.add('waitOnLoad', () => {

    cy.get(".fa-spinner", { log: false })
        .should($subject => {
            if (!$subject.length) throw new Error("Should exist.");
        })
        .then($el =>
            Cypress.log({
                name: "waitOnLoad",
                displayName: "waitOnLoad",
                message: "",
                $el
            })
        );

    cy.get(".fa-spinner", { log: false }).should($subject => {
        if ($subject.length) throw new Error("Should not exist.");
    });
})

@lacma2011
Copy link

+1

@goska-malaga
Copy link

allowing hiding assertion logs would be a good option, just like you can hide every other log { log: false }, case to show the log on failure could be additional option
when you run E2E test and you need to wait until loader is not visible - what other option do you have except for should('not.be.visible')? even worse is if the loader show up and then disappear so first I have to wait for it to be visible and then not.to.exist - so those are 2 assertions that I have hard time to avoid
and it is not the assertion that is a goal of the test, it is just an intermediate step
I want the final test assertions to be logged and being clear from looking at log what actually was asserted in the test

@ameduza
Copy link

ameduza commented Aug 29, 2023

+1
Still looking for that enhancement - also want to hide successful assertion or just always hide to reduce Cypress log. In my case it might be just huge

@datashard
Copy link

+1

I'd also love this enhancement, it'd make it a lot nicer for plugin developers (like me), especially if you use any form of .should

@aKzenT
Copy link

aKzenT commented Nov 10, 2023

it sucks that there is still no solution to this issue after more than 3 years. In our case we want to assert on the contents of a file, which results in the whole file being printed out on the log... :-(

@ParTee71
Copy link

+1 Would be great to have

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
E2E Issue related to end-to-end testing pkg/driver This is due to an issue in the packages/driver directory type: enhancement Requested enhancement of existing feature
Projects
None yet
Development

No branches or pull requests