-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Documentation for Cypress.ensure #5054
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
:::caution | ||
|
||
Many of these functions accept an optional `onFail` argument. This is a legacy | ||
feature used to customize the thrown error, and may be removed in a future | ||
release; we recommend against relying on it. If you need more control over the | ||
error thrown, write your own `ensure` function instead. | ||
|
||
::: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO we should just not document this, since the user can just try...catch
to get the same functionality as onFail
, right? Then we can just rip it out when we're done using it internally.
:::caution | |
Many of these functions accept an optional `onFail` argument. This is a legacy | |
feature used to customize the thrown error, and may be removed in a future | |
release; we recommend against relying on it. If you need more control over the | |
error thrown, write your own `ensure` function instead. | |
::: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave a similar suggestion to not document this #5048 (comment). The onFail ties in to how this would be removed up if this callback matched the command onFail behavior, so it's require quite a bit of user-knowledge to handle this correctly. I like @flotwig's suggestion for handling with try-catch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I documented it here is because people's intellisense / TS will show them that there's an additional argument, and they'll see it if they examine the code.
Undocumented arguments are the worst, so I figure a little warning "this exists but don't use it" would be preferable.
Was the response I gave to Emily, and I still feel the same way - if it exists, we should not leave it silently undocumented. I've found myself in this boat several times dealing with other projects, where I see an argument is there, but the documentation is completely silent. What does it do? Why is it there? Your own code uses it, to what purpose?
I think a warning "it exists, but don't use it" is appropriate, as well as not including it in the documented function signatures.
docs/api/cypress-api/ensure.mdx
Outdated
Cypress.ensure.isAttached(subject, name, cy) | ||
Cypress.ensure.isNotDisabled(subject, name) | ||
Cypress.ensure.isNotHiddenByAncestors(subject, name) | ||
Cypress.ensure.isNotReadonly(subject, name) | ||
Cypress.ensure.isScrollable($el, name) | ||
Cypress.ensure.isStrictlyVisible(subject, name) | ||
Cypress.ensure.isVisible(subject, name) | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are most of the referenced as "subject" vs "$el"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
subject
is what they'll see in intellesense, it's how these functions are used in the Cypress repo itself (), and the function signature of a query is (subject: Any) => Any
.
The primary use of these is to call them on a subject
, to ensure the subject matches the conditions, so I think they should be documented that way. $el
is extremely non-descriptive in comparison, and doesn't indicate anything unless you're familiar with our convention that '$' means "A jquery object".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed the one remaining over to subject
so they're all consistent.
docs/api/cypress-api/ensure.mdx
Outdated
Cypress.ensure.isChildCommand(command, args, cy) | ||
|
||
// Type of argument | ||
Cypress.ensure.isType(subject, type, name, cy) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't remember, but do these expect subject to be anything? We don't reference subject must in the docs and I'm thinking it might be helpful to expand above on what a subject might be for users who aren't familiar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We reference 'subject' all over the docs.
https://docs.cypress.io/guides/core-concepts/introduction-to-cypress
How Cypress manages subjects and chains of commands
The very first paragraph of the 'core concepts' guide discusses them.
It's very important to understand the mechanism Cypress uses to chain commands together. It manages a Promise chain on your behalf, with each command yielding a 'subject' to the next command
https://docs.cypress.io/api/cypress-api/custom-commands#Arguments
prevSubject | Boolean, String or Array | false | how to handle the previously yielded subject.
In addition to controlling the command's implicit behavior you can also add declarative subject validations such as:
element: requires the previous subject be a DOM element
document: requires the previous subject be the document
window: requires the previous subject be the window
and all over that page.
docs/api/cypress-api/ensure.mdx
Outdated
Cypress.Commands.addQuery('verifyElementActionable', function (id) { | ||
// Throws an early error if this query is chained directly off `cy`, eg. | ||
// `cy.verifyElementActionable('foo')` would throw an error | ||
Cypress.ensure.isChildCommand(command, args, cy) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you said query's don't have a concept of parent/child commands. Is this a realistic example? Also where is command
, args
, and cy
coming form?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed the example to show where they come from.
Yes it's a realistic example; it's exactly how we use this function in our own code. Queries don't by default have a concept of being child / parent - you can make them have one by using ensure.isChildCommand()
. It's just not baked into the query API the way it's baked into the command API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's just not baked into the query API the way it's baked into the command API.
Gottchya - when you said it didn't have the concept of it, I had understood it as "parent" / "child" truely was no longer a concept vs a difference in how the concept was implemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created isChildCommand()
based on our docs ("must be chained off cy" / "must not be chained off cy"). But the more I work with our command interface, the more I realize it just doesn't make sense: all uses of ensure.isChildCommand
would be better served by a more specific error in the individual command.
We currently use it in two places:
.within()
, which should actually be asserting that the subject is an element or document (.isType()
)..as()
, which should actually be asserting that the subject is not null (or that it's after.intercept()
).
In cypress-io/cypress#25738 (comment), I added it to .should()
- but this is a breaking change, and we've decided to walk it back.
Basically, a generic "this must be a child command" is never the correct error to throw; we want to point users more usefully to what a specific command requires as a subject.
I've opened cypress-io/cypress#25811 to track this code work.
For this PR, I'm thinking I'll just remove the docs around .isChildCommand()
, so that removing it won't be a breaking change (since we won't be documenting it as part of our public interface).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tl;dr - it shouldn't still be a concept, but it leaked into queries through a new implementation. I'll get a paper towel. 😛
Co-authored-by: Zach Bloomquist <[email protected]>
Co-authored-by: Emily Rohrbough <[email protected]>
Cypress.ensure
#4881This part of our API was added in Cypress 12, but never documented properly. Pulled the changes out from #5048 into its own PR.