I am implementing a custom Cypress in TypeScript:
// support/commands.js
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?
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, becuase 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"],
"types": ["cypress"],
"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')
});
});