cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
46.66k stars 3.16k forks source link

feat: Add Typescript support for Aliases #8762

Open pocketcolin opened 3 years ago

pocketcolin commented 3 years ago

Current behavior

Aliases are not Typescript friendly. When using aliases to share values between hooks/tests, the alias value is automatically typed as any because TS has no way of following the chained .as method through to its new value on this. This results in needing to revert to using the let method to share context if one wants TS to keep track of the variables.

Desired behavior

I think there are a few different options here. Ideally, it would be great if the alias method, .as, could determine the type of the passed in value and somehow let TS know that this property now exists on this. I'm not sure how one would do that, so if that is not possible then I think we might need a way of passing a variable to .as that is used instead of this and gives us more control over its type. As a final option, if Cypress could expose or make typeable (maybe as a type param for describe?) this, then we could just append our custom variables manually.

All that said, I'm very open to suggestions for other ways of approaching making Aliases TS friendly.

jennifer-shehane commented 3 years ago

We’re open to a PR to fix the typings for alias references.

pocketcolin commented 3 years ago

Hey Jennifer, any thoughts on which of the three approaches I suggested would be preferable? If you agree that the first option is ideal, do you have thoughts on how I might approach that?

markhus-aurelius commented 3 years ago

Not a silver bullet, but this gives me types for my .as() aliases. Though it's not automatic like you want.

If I had an interface Entity for example.

declare module "mocha" {
  export interface Context {
    entities: Entity[];
  }
}

cy.fixture('entity').as('entities');

this.entities now will be typed as Entity[] in my it() blocks

yossisp commented 3 years ago

@markhus-aurelius your solution didn't work for me but this did (I'm using cypress version ^6.8.0 from npm):

declare namespace Mocha {
    interface CustomData {
        data: string
    }
    export interface Suite {
        customData: CustomData
    }
}

According to VS Code intellisence the this (e.g. cy.get(this.customData)) is of type Mocha.Suite.

DetachHead commented 3 years ago

I've given this a go using assertion functions, though I think it's held back by https://github.com/microsoft/TypeScript/issues/43786

borecz commented 3 years ago

Any updates on this? It would be very useful to have it

itai-codefresh commented 3 years ago

need this as well

jankaifer commented 2 years ago

I've given this a go using assertion functions, though I think it's held back by microsoft/TypeScript#43786

This won't work on aliases that are used across multiple contexts. Like those defined in beforeEach and those accessed in it.

And since we cannot really guarantee type-safety, we could at least provide reasonable DX. We could type this as Record<string, typeof cy.get("@alias")>(this is just pseudotype).

johndatserakis commented 2 years ago

I stumbled across this thread when trying to solve my issue of wanting my alias value to have the proper typing.

The below (pseudo-code) left me with a JQuery<HTMLElement> type that wasn't very useful.

interface Item {
  id: string;
}
type Items = Item[];

const items = [{ id: '123' }]
const [firstItem] = items;
cy.wrap(firstItem).as('firstItem');

// Then later
cy.get('@firstItem').then((firstItem) => {}); // type of `firstItem` is `JQuery<HTMLElement>`

To use the proper typing in my aliased variable, I just passed a Generic type parameter to the get:

cy.get<Item>('@firstItem').then((firstItem) => {}); // type of `firstItem` is `Item`

This may not be exactly what you're looking for - but it was enough for me in my usage.

akus062381 commented 1 year ago

We would love to see this functionality added please!!