-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
TypeScript type definitions #1040
Comments
I like everything about it. I have not used Is it possible to split the work into multiple smaller pull requests?
|
Definitely. Right now I'm changing everything together, but I'm happy to break it up (was thinking about doing that more incrementally). At the moment I'm working a bit on the type definitions using
I'm going to assume the kitchen sink is correct for now, so probably the docs would need to be updated. |
Some things we documented in anticipation of making these changes.
There is a technical difference between
|
Here are a bunch of random notes for improvements to various commands and inconsistencies with the docs.
|
|
Thanks @brian-mann. I'll update. |
@brian-mann Is this a supported use-case (in the kitchen sink, but not the docs): // Specify the route to listen to method 'POST'
cy.route('POST', '/comments').as('postComment');
cy.wait('@postComment');
// get the route - notice the use of `cy.get`?
cy.get('@postComment').then(function(xhr) {
expect(xhr.requestBody).to.include('email');
expect(xhr.requestHeaders).to.have.property('Content-Type');
expect(xhr.responseBody).to.have.property('name', 'Using POST in cy.route()');
}); That is pretty difficult to type since an alias could be anything. The docs say cy.route('POST', '/comments').as('postComment');
cy.wait('@postComment').then(function(xhr) {
expect(xhr.requestBody).to.include('email');
expect(xhr.requestHeaders).to.have.property('Content-Type');
expect(xhr.responseBody).to.have.property('name', 'Using POST in cy.route()');
}); |
Using the An alias could be: a route, an element, or a primitive / regular object. https://docs.cypress.io/guides/core-concepts/variables-and-aliases.html#What-You’ll-Learn That shows some additional use cases. You can alias a fixture and then use Getting an aliased element has special semantics - it either yields you the element, or if its stale, it'll go query for it agian. Getting an aliased route also has special semantics - it yields you the associated XHR http request + response data based on the index (or latest one) you've asked for. This case is not super well documented but there are tests for it and it technically works. |
So yes, it will be hard to type. It could literally be anything |
Aliases are very powerful, but they can't be typed since by nature they mutate // allowing a chain to be assigned to a variable
const foo = cy.wrap('foo');
foo.then(subject => {
subject; // $ExpectType string
});
// just chaining
cy.wrap('foo').then(subject = {
subject: // $ExpectType string
}); I don't know enough about the implementation, but I think the first one could be possible. It would probably need some metadata but would be no problem to type. An option might be to separate some special use cases into different getters. Ex: I will have to leave it up to generic overrides: cy.wrap('foo').as('foo');
cy.get<string>('@foo').should('eq', 'foo'); By default, For comparison, |
I will be closing this issue, since we have TypeScript definitions now. I know there is some discussion in this thread for improvements. If there are features/enhancements regarding TypeScript in the comments that are left to be completed, please open them in a new issue. |
This is more of a discussion about the strategy for Cypress having type definitions. @bahmutov mentioned the long term goal is for Cypress to be written in TypeScript.
I had a few proposals for how the types should be structured to maximize type safety and minimize explicit type casting. These changes would start to shape the architecture of the eventual TypeScript code. I don't want to step on toes, but I want types to be correct.
Here are the proposals my type definitions have:
Cypress.$
,Cypress._
, etc.Chainable
into 3 separate interfaces:ParentCommand
,Command<Subject>
andCommandElement<Subject>
. There is also aCommandAs<Subject>
forcy.route
return type. AlsoTerminal
which only has.then
. Those names aren't set in stone, but shouldn't be changed once they are created. This makes it socy.clearCookies().clearCookies()
orcy.wrap({ foo: 'bar' }).trigger('mouseover')
are type errors and auto completion won't even suggest invalid chains.ParentCommand
: Commands that are initiated straight fromcy.
- starts a chainCommand<Subject>
: Commands for any subject type.Subject
becomes the type for.then
.CommandElement<Subject = JQuery>
: Commands for chained commands that are meant to work with JQuery-wrapped elements. As far as I can tell, all elements are JQuery-wrapped elements.What we get with these type definitions:
Additionally (an totally optional), I added chai suggestions for
.should
and.and
using an interface where happy-path string values are defined per command type. This is only for convenience and doesn't actually change or dictate anything. Ex:Gleb's todo list:
Chainer
interface into different interfaces #1137The text was updated successfully, but these errors were encountered: