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

Revert changes to query*s and add deprecation warning #117

Closed
kentcdodds opened this issue Feb 4, 2020 · 14 comments · Fixed by #125
Closed

Revert changes to query*s and add deprecation warning #117

kentcdodds opened this issue Feb 4, 2020 · 14 comments · Fixed by #125
Assignees
Labels
bug Something isn't working released

Comments

@kentcdodds
Copy link
Member

As noted in #108, we accidentally broke the query* queries. We should restore those to the original behavior and add a deprecation warning. Let's try to make it subtle enough to not be really annoying, but present enough to be noticed :)

@kentcdodds kentcdodds added the bug Something isn't working label Feb 4, 2020
@NicholasBoll
Copy link
Contributor

I don't mind taking this on since I broke it. I can finish that today.

@kentcdodds
Copy link
Member Author

Thanks @NicholasBoll!

@NicholasBoll NicholasBoll self-assigned this Feb 4, 2020
@NicholasBoll
Copy link
Contributor

@andycarrell Could you update #117 with some reproduction steps? I've been trying to reproduce the problem and haven't been able to. I'm positive I was able to reproduce before, but I must be missing something. I've tried the following with many versions of this library:

    cy.queryByText('Eventually not exists').then($el => {
      cy.wrap($el).should('not.exist')
    })

The button with "Eventually not exists" is in the index.html of this document and gets removed by a timer after 500ms. I've also tried with your custom command: retryUntilDoesNotExist().

According to the list of releases:

You mentioned you bumped from 5.1.1 to 5.2.0.

From what I can tell there are 3 differences between #100 and #108 (main differences between 5.1.1 and 5.2.0):

From what your issue was, I'm guessing the 2nd is causing your issue. If the 3rd was causing issues, using find* + .should('not.exist') would also fail. I'm not sure how the first could cause an issue. Technically #100 uses query* queries from @testing-library/dom and #108 uses get* queries from @testing-library/dom to get errors. Perhaps there is a subtle difference there? get* queries are used to get more useful error messages and run a retry loop until an error is no longer thrown (eventually finds the element)

I guess there is another subtle difference. #108 allows timeout overrides for retry loops where #100 did not. Perhaps there's a issue there?

It would really help to narrow down what previous functionality is required. I could simply revert any changes to the query* queries, but I'm not sure what tests to run so the original functionality isn't changed again.

@andycarrell
Copy link

Ah that's subtly different to what we have:

Cypress.Commands.add(
	"retryUntilDoesNotExist",
	{ prevSubject: true },
	subject => {
		cy.wrap(subject).should("not.exist");
	},
);

// in the test:
cy.queryByText('Eventually not exists').retryUntilDoesNotExist();

Can you try that?

I can try reproduce this if I get some time in the next couple of days, is there an example repo with Cypress && testing library already setup?

@NicholasBoll
Copy link
Contributor

I couldn't find an issue reproduction repository. You could fork this one. query* specs are in the cypress/integration/query_spec.js file. The page that is run against is in the cypress/fixtures/index.html file. The "Eventual not exists" button is in there with a scrip tag that removes it from the DOM after 500ms. I think that's a really good starting point.

I do have the custom command you provided (added to the cypress/support/index.js file, but it seems to behave the same way and it seems to work. I must be missing something.

I'd like to fix the issue, but I'd also like to have a test that proves it works/doesn't work. When I said the behavior was unspecified, I meant by a test.

@ktsosno
Copy link

ktsosno commented Feb 5, 2020

Hi - possibly related here. It looks like the getBy* commands were removed from the type definitions but are still supported calls. We swapped to queryBy* in the interim.

Docs:
https://testing-library.com/docs/dom-testing-library/api-queries

Types:
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/testing-library__cypress/index.d.ts

I know it's possible someone else mismatched these types given the nature of DefinitelyTyped, but figured you'd like to know if there aren't plans to deprecate getBy calls.

@NicholasBoll
Copy link
Contributor

@ktsosno AFAIK, they are only removed from the Cypress version, not others. There are adapters for DOM, React, Vue, etc.

The docs for Cypress Testing Library are here: https://testing-library.com/docs/cypress-testing-library/intro

There is a note about the lack of get* queries. At runtime, they throw an error warning to use a different query type.

@ktsosno
Copy link

ktsosno commented Feb 5, 2020

Perfect, thanks @NicholasBoll!

@NicholasBoll
Copy link
Contributor

@andycarrell Are you able to give a example repo to reproduce? I'm unsure of what functionality to revert back to: 5.0.1 or 5.1.0 (5.1.2 should be the same as 5.0.1).

@andycarrell
Copy link

Hi @NicholasBoll - sorry for the delay, I haven't had time to look further into this until now.

I've managed to recreate the pass/fail scenario, (passes on v5.1.2, fails on master). More specifically, it was the case of using retryUntilDoesNotExist on an element that already doesn't exist. I think this is a legitimate use case, since the test is specifying that the element is eventually gone, not whether it is gone at the moment the assertion is called.

I'm not sure where the root cause of this being a breaking change, some part of the interaction between queryByText and cy.wrap ?

Here's the test :)

  it('queryByText - reproduction', () => {
    const text = 'Supercalifragilistic'

    cy.queryByText('Eventually not exists').then($el => {
      cy.wrap($el).should('not.exist')
    })
    cy.queryByText(`Currently does not exist - ${text}`).then($el => {
      cy.wrap($el).should('not.exist')
    })
  })

Additionally, I'm not even sure if it's worth reverting this change, if it just going to be slated for the next major version - I'm not even sure of the wider impact currently, and reverting it would just delay the pain to the next major version update.
I think the case presented is a legitimate and useful case for queryBy* still returning null and it's a bit punishing that the original change (v5.2) removes this 👐

@NicholasBoll
Copy link
Contributor

That must be what I was missing. It seems to be working with eventually not existing, but failing on does not exist now. I can reproduce again! Thank you!

There is a risk that reverting the change will break those relying on how 5.2 works now... :(

@andycarrell
Copy link

There is a risk that reverting the change will break those relying on how 5.2 works now... :(

Yeh for sure @NicholasBoll - and any later versions :(

Personally, we've updated our failing tests, and are now on v5.3.0, so the outcome of this shouldn't affect our usage.

@NicholasBoll
Copy link
Contributor

I know why this is happening now. I changed query* to use verifyUpcomingAssertions which will put an implicit should('exist') after the command. That works if you follow the command with an assertion - the explicit assertion changes the implicit one. If you disconnect the chain with a .then and a .wrap, the implicit assertion is in place and it doesn't get to the .wrap. That's true for built-in Cypress commands as well.

 // always worked
cy.queryByText('Never Exists').should('not.exist')

// Broke on the `queryByText` command since using `verifyUpcomingAssertions`
cy.queryByText('Never Exists').then(val => {
  cy.wrap(val).should('not.exist')
})

The reason the wrap worked before is because query used to return null and not fail like other commands that return DOM. This functionality might have been intentional since find* commands didn't always retry properly. (I think that happened in 5.0).

I'm very sorry for the inconvenience. I'm glad the Cypress Testing Library find* commands work more like native Cypress commands. It makes it more natural to use in the Cypress context.

I'll leave this issue open a bit more. Perhaps it is still safer to revert the query* line of queries. There's a higher chance the upgrade breaks people that haven't updated yet. Your code should be fine. The code can warn about the deprecation of query* and suggest an upgrade path

NicholasBoll added a commit to NicholasBoll/cypress-testing-library that referenced this issue Mar 5, 2020
NicholasBoll added a commit to NicholasBoll/cypress-testing-library that referenced this issue Mar 5, 2020
NicholasBoll added a commit to NicholasBoll/cypress-testing-library that referenced this issue Mar 5, 2020
kentcdodds pushed a commit that referenced this issue Mar 12, 2020
* fix: Revert to previous query* API

Closes #117
@kentcdodds
Copy link
Member Author

🎉 This issue has been resolved in version 5.3.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working released
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants