Comments (14)
For me personally, I like to think of the commands I give to Cypress to be instructions I would give to a user, so chaining like this makes a lot of sense to me:
describe('anonymous calculator', () => {
it('can make calculations', () => {
cy.visit('/') // visit this site
.findByText(/^1$/) // then find this element
.click() // then click it
.findByText(/^\+$/) // then find this element
.click() // then click it
.findByText(/^2$/) // then find this element
.click() // then click it
.findByText(/^=$/) // then find this element
.click() // then click it
.findByTestId('total') // then find this element
.should('have.text', '3') // then assert it has this text
})
})
I personally don't think that these queries make sense to scope each other (we already have that with the within
command). The only reason I decided to allow #100 was because I thought it was just to support an additional style of writing these tests, not break the existing style which I think makes more sense.
Thoughts?
from cypress-testing-library.
I'm strongly in favor of this, despite it technically being a breaking change. I would prefer to match semantics of existing Cypress commands over supporting non-idiomatic style of writing tests.
IMHO the above is not idiomatic in Cypress, and isn't nearly as readable as:
cy.visit('/')
cy.findByText(/^1$/).click()
cy.findByText(/^\+$/).click()
cy.findByText(/^2$/).click()
cy.findByText(/^=$/).click()
cy.findByTestId('total').should('have.text', '3')
Cypress already does the work of queuing up commands that aren't chained, so chaining unrelated commands isn't necessary.
Cypress's builtin commands (e.x. contains
which is similar to findByText
) support using the previously yielded subject in chained commands (except get()
and a couple others), so I think it's surprising that @testing-library/cypress
's does not.
Cypress has end()
specifically for yielding null which "resets" to the root element: https://docs.cypress.io/api/commands/end.html#Examples but they also state "Alternatively, you can always start a new chain of commands off of cy."
within
is an option, but it's more verbose when all you want to do is something like cy.findByRole('dialog').findByText('submit')
as you suggested here (and called it stellar!)
from cypress-testing-library.
Hi @tlrobinson,
Somehow I've managed to write non-idiomatic cypress for years and nobody told me 🙃
I just checked their kitchen sink example and boom:
it('.check() - check a checkbox or radio element', () => {
// https://on.cypress.io/check
// By default, .check() will check all
// matching checkbox or radio elements in succession, one after another
cy.get('.action-checkboxes [type="checkbox"]').not('[disabled]')
.check().should('be.checked')
cy.get('.action-radios [type="radio"]').not('[disabled]')
.check().should('be.checked')
// .check() accepts a value argument
cy.get('.action-radios [type="radio"]')
.check('radio1').should('be.checked')
// .check() accepts an array of values
cy.get('.action-multiple-checkboxes [type="checkbox"]')
.check(['checkbox1', 'checkbox2']).should('be.checked')
// Ignore error checking prior to checking
cy.get('.action-checkboxes [disabled]')
.check({ force: true }).should('be.checked')
cy.get('.action-radios [type="radio"]')
.check('radio3', { force: true }).should('be.checked')
})
Yeah, looks like when you want to change the subject of the chain, in this example at least, you should create a new cy
chain.
This is unfortunate for me because I've been doing it differently so long and I've taught thousands of people to do it the way I do. But I think you're right and what you have described is probably better (it just means I have to re-record a bunch of cypress videos on testingjavascript.com 🤦♂️)
Ok, so for this, we're doing some breaking changes in the Testing Library realm in the next few weeks for other projects, so I think we could coordinate this and some other changes at the same time.
I'd love to hear other people's thoughts on this.
from cypress-testing-library.
@NicholasBoll, just commented in #109
I'll look up this issue and see if it is related to #100 and if there is any way to introduce #100 as a non-breaking change
That would be fantastic. Whatever we do, having an easier migration path to the new recommendation would be wonderful.
from cypress-testing-library.
@tlrobinson is right, starting new chains is more idiomatic. I've taught people to think of a chain as a sentence with a complete subject. If I have to start with a new idea, I start a new sentence. I think it is easier to understand when I think of a chain as a complete thought.
cy.get
is the only command that starts from scratch. I've talked with Brian before about this. He prefers the cy.get
for new chains. He didn't go so far as to prevent cy.get
from working while chained from a previous command.
There are get*
commands that are currently just throwing errors if we want to designate those types of queries to always start from the root. cy.get()
looks similar to cy.getByText
... Perhaps that's a compromise? 🤷♂
I try to avoid cy.within
for many of the reasons I avoid with
in JavaScript. It is fine in your test code, but if you have a helper function that implicitly changes root scope, that's hard to debug. It can be nice to not scope multiple times though.
I think it is worthwhile to introduce a breaking change, but we'd have to communicate that. Chaining off previous commands and inheriting the previous element is how all other traversal commands work in Cypress.
This will delay #108, but that's okay.
from cypress-testing-library.
I've verified #100 does indeed cause the issue in #109. I'll dig into why
from cypress-testing-library.
Oh. I know why this is happening.
cy.visit
is returning the Window
and used as the previous subject to the first .findByText()
window.querySelectorAll
is not a function. I've made some changes to how things work inside #108. I'll see if this can be non-breaking. I at least have a test case now
from cypress-testing-library.
Thanks for your work here Nicholas!
I wonder if we could make a codemod to update people's code automatically for them 🤔
from cypress-testing-library.
My thought was to try to run the query scoped to the previous subject. If that fails, try running again unscoped with a warning message.
from cypress-testing-library.
@kentcdodds The idea seems to work! It will first try scoping to the previous subject given by Cypress. If an error is encountered, it will record the error and then try with functionality previous to #100.
from cypress-testing-library.
That's fantastic! That way we can upgrade without the breaking change and update all the documentation to recommend a more idiomatic approach, and people can migrate over time. Then maybe eventually we can remove the old behavior.
from cypress-testing-library.
I've updated #108 with the code. The code in #108 was primed for this type of change, so I tacked it on. The PR is kind of large. I could spend time breaking it down if we prioritize the features listed there. The code changes are interdependent so if I break it up, they would have to be done in a sequence.
from cypress-testing-library.
Amazing. Thank you @NicholasBoll! In a perfect world we'd probably just do the breaking change and move forward, but a lot of people rely on the current behavior so supporting them is important 👍
I'm fine putting it all in one PR. Normally like to have things split up a bit, but I'm not too concerned 🤷♂️
from cypress-testing-library.
🎉 This issue has been resolved in version 5.2.0 🎉
The release is available on:
npm package (@latest dist-tag)
- GitHub release
Your semantic-release bot 📦🚀
from cypress-testing-library.
Related Issues (20)
- Add Cypress 12 as an acceptable peer dependency HOT 2
- Enable to click to input number -webkit-inner-spin-button HOT 1
- Cypress test errors after upgraing to 9.0.0 and using testIsolation: false HOT 10
- findAllByRole and findByRole don't chain correctly HOT 2
- get/query variants don't exist HOT 3
- Testing library throws uncaught error HOT 24
- @testing-library/cypress causes non-cypress tests to fail HOT 1
- any `find*` command fails when is first to run in a test context HOT 6
- Dependency problem on @testing-library/dom between @testing-library/react and cypress-testing-library HOT 1
- Update @testing-library/dom HOT 1
- Conflicting peer dependency with new Cypress release 13.0.0 HOT 2
- should not exist does not work with findByRole
- Configuring testIdAttribute does not work HOT 1
- Doesn't work with Cypress 13.4.0 due to `addQuery` usage HOT 3
- npx cypress open fails on ubuntu 20.03 for missing GLIBCXX_3.4.29 HOT 1
- Unable to install Cypress version 13
- Property 'findByTestId' does not exist on type 'cy & CyEventEmitter' - only in .cy.tsx (component testing) files HOT 1
- Can't resolve 'process/browser.js'
- cy.findByText doesn't work on Cypress 13.6.4 in some situations HOT 2
- `findByRole` with `name` option does not consider element title when element contains text.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cypress-testing-library.