I am implementing a custom Cypress command in TypeScript:
// support/commands.ts
const login = () => {
console.log('Logging in...');
};
Cypress.Commands.add('login', login);
declare namespace Cypress {
interface Chainable {
login: typeof login;
}
}
I try to call it using:
describe('Login Scenario', () => {
it('should allow a user to login', () => {
cy.visit('/');
cy.login();
});
});
Yet, it seems the command is not set up:
TypeError: cy.login is not a function
If I write the command in pure JavaScript (removing the namespace declaration and updating the call to (cy as any).login();
, it works.
What am I missing?
Cypress ships with official type declarations for TypeScript. This allows you to write your tests in TypeScript.
Cypress custom commands are described by users and not the default commands from Cypress. These customized commands are used to create the test steps that are repeated in an automation flow. We can add and overwrite an already pre-existing command. They should be placed in the commands.
The best place to define the custom commands is in the cypress/support/commands. js file, as it loads before any of the test-script files.
I fixed it by adding index.d.ts
file in my commands folder. In this file I added something like this:
import { MyCustomType } from '../Types';
declare global {
namespace Cypress {
interface Chainable<Subject = any> {
login(): Chainable<MyCustomType>;
}
}
}
If you don't import or export anything, just omit global namespace declaration:
declare namespace Cypress {
interface Chainable<Subject = any> {
login(): Chainable<MyCustomType>;
}
}
Keep in mind that it won't work with Typesciprt < 2.3, because default generics type has to be supported.
Here is what I use and I do not have to add
/// <reference types="cypress" />
at the top of every file.
I have my custom typings under <projectroot>/cypress/support/index.d.ts
/// <reference types="cypress" />
declare namespace Cypress {
interface Chainable<Subject> {
getByDataTest(tag: string): Chainable<any>
}
}
And my <projectroot>/cypress/tsconfig.json
looks like
{
"compilerOptions": {
"strict": true,
"baseUrl": "../node_modules",
"target": "es5",
"lib": ["es5", "dom"],
"typeRoots": ["./support"]
},
"include": ["**/*.ts"]
}
And TypeScript is finally happy
describe('when I want to select by data test tag', () => {
it('should select by data test tag', () => {
cy.getByDataTest('yolo').should('exist')
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With