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

How to test disappearance? #13

Closed
pr0da opened this issue Jul 19, 2018 · 13 comments
Closed

How to test disappearance? #13

pr0da opened this issue Jul 19, 2018 · 13 comments
Labels
help wanted Extra attention is needed needs discussion We're not sure what to do about this and need to discuss it further.

Comments

@pr0da
Copy link

pr0da commented Jul 19, 2018

  • cypress-testing-library version: 2.2.0
  • node version: 9.4.0
  • yarn version: 1.7.0

Relevant code or config

// I have a table with users, and I want to test user deletion
cy.getByTestId(`user-id-${userId}`).within(() => {
  cy.getByText('Remove').click();
});
cy.getByTestId(`user-id-${userId}`).should('not.exist');

What you did:
I've tried to use cypress-testing-library custom commands with should('not.exist') expectation.

What happened:
The expectation failed, because cypress does not wait until the row/element disappeared.

On the other hand the following works as expected:

cy.getByTestId(`user-id-${invitee.userId}`).within(() => {
  cy.getByText('Remove').click();
});
cy.get(`[data-testid="user-id-${invitee.userId}"`).should('not.exist');

What would be the proper way to test element disappearance with custom commands?

@kentcdodds
Copy link
Member

I actually don't know how to do this I'm afraid :-( If you could dig in a little bit and come up with a good solution that would be appreciated! Thank you!

@kentcdodds kentcdodds added help wanted Extra attention is needed needs discussion We're not sure what to do about this and need to discuss it further. labels Jul 19, 2018
@DJTB
Copy link

DJTB commented Oct 3, 2018

Not an ideal solution, but you can work around it using cypress .wait(n)

it('remove member', () => {
  cy.getByTestId(`remove-member-${username}`)
    .click()
    .wait(1000)
    .queryByTestId(`member-${username}`)
    .should('not.exist');
});

@kentcdodds
Copy link
Member

Actually I've done this since and the queryBy* queries work fine without the wait for me. You can even add a timeout if it disappears quickly to make the command and assertion execute faster.

@DJTB
Copy link

DJTB commented Oct 4, 2018

Hmm, for me it resolves instantly with the still existing element if there's no wait, even with a timeout since the element exists when queryByTestId starts. (Removal is subject to server response, so it's always going to occur after the query runs).

@kentcdodds
Copy link
Member

Ah, right, that makes sense. My situation was slightly different. I think a wait is required here... I wonder how it would work with a normal get command... 🤔

@DJTB
Copy link

DJTB commented Oct 4, 2018

Solution might be a config flag that inverts the behaviour.
Not a great name, but hypothetically { invert: true }
Waits until query cannot find the specified element, then immediately returns undefined?
If the element still exists when timeout is exceeded, it would return the element.

Definitely needs a clearer config flag than invert though...

@kentcdodds
Copy link
Member

I feel like this is a problem that Cypress should solve honestly.

@pr0da
Copy link
Author

pr0da commented Oct 4, 2018

Sorry for the radio silence. I figured out that the following works as expected:

cy.getByTestId(`user-id-${userId}`).then(
  $el => cy.wrap($el).should('not.exist')
);

So we ended up overwriting cypress-testing-library commands by wrapping up subject:

['getByTestId', 'getByLabelText', 'getByText'].forEach(name => {
  Cypress.Commands.overwrite(name, (original, ...rest) =>
    original(...rest).then(subject => cy.wrap(subject, { log: false }))
  );
});

My plan was to investigate this further and eventually open a pr with a fix but it won`t happen at least for one month.

I hope this is helpful at least.

@Pallinder
Copy link

I'm encountering the same issue.
Im waiting for a loading indicator to get removed from a button, relying on cy.get('loading-indicator') works. Relying on either query or getByTestId resolves straight away and fails.
The command is

cy.get('loading-indicator').should('not.exist') // works
cy.getByTestId('loading-indicator').should('not.exist') // does not work
cy.queryByTestId('loading-indicator').should('not.exist') // does not work

@kentcdodds
Copy link
Member

Remember that get accepts a query string. I think you should try: get('[data-testid="loading-indicator"]')

@digitaldrummerj
Copy link

@DJTB could you use a combo of cy.route and cy.wait? I know for loading of data before testing a page I had to setup a cy.route('GET', '/api/').as('myapi'), call cy.visit('/') and and then call cy.wait('@myapi') to wait for the API call to finish before running tests.

@alexkrolick
Copy link
Contributor

#30 should fix this

@krvajal
Copy link

krvajal commented Jan 31, 2019

I am having a similar problem. In my case, I have a button that changes its text like this
"SAVE" => "SAVING" [duration unknown] => "SAVE"
or (error case)
"SAVE" => "SAVING" [duration unknown] => "COULD NOT SAVE"

The "SAVING" state can take some time to change. Is there a way to detect when the "SAVING" text is gone and then assert that the text changed to "SAVE"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed needs discussion We're not sure what to do about this and need to discuss it further.
Projects
None yet
Development

No branches or pull requests

7 participants