'Cypress custom command is not recognized when invoked

I've created the following custom command in my cypress/support/commands.js file.

Cypress.Commands.add("login", (username, password) => {
    cy.request({
        method: 'POST',
        form: true,
        url: '/test/login/',
        body: {'username': username, 'password': password}
    })
})

I had tests passing and login working before moving the login functionality to this custom command. I'm invoking it in my spec with cy.login(testuser, testpwd), but I'm getting the following error message: TypeError: cy.login is not a function. The docs say that /cypress/support/commands.js is loaded before any test files are evaluated, so I assumed that simply placing a custom command in there would make the command available. I'm running the tests through the local (GUI) test runner.



Solution 1:[1]

All the code and referenced modules in index.js are loaded before your test file. So you need to refer(require) commands.js in your index.js file. You can however import commands.js module directly in your test file but then you need to include it every test file. Recommended approach is to include it in index.js file and you are not worried about explicitly refer in your test files.

Solution 2:[2]

To expand on @Dinesh Kumar's excellent answer, it's also important you haven't disabled support for the default support file (I know, unfortunate naming scheme in this case) inside your cypress.json by adding the line: supportFile: false.

Delete that line from your cypress.json if it's there. You can also specify a different path if you're not happy using the default path of cypress/support/index.js.

Working index.js with commands.js file - both in the support folder:

// index.js
const customCommands = require('./commands.js')

module.exports = {
  commands: customCommands
}

And double check your settings:

// cypress.json
{
  "baseUrl": "http://demo.your-domain.test",
  "supportFile": false,  // <-- delete this line present
  ...
}

Solution 3:[3]

It may help to put a line import './commands.js' into index.js.

Solution 4:[4]

For me it worked when I added the type signature of the custom command in the file cypress/support/index.d.ts. For more information visit: Cypress example - Custom Commands

declare namespace Cypress {
  interface Chainable {
    clearLocalStorageIframe(): void
  }
}

I am using 7.2.0 Cypress and command.ts and index.ts file extension I have changed it to .ts

Solution 5:[5]

TL;DR: Check if your IDE tried to resolve cy

I slipped into this problem, because my IDE's autocomplete feature added a dependency to resolve the undeclared cy object – that gets injected by cypress.

const { default: cy } = require('date-fns/esm/locale/cy/index.js');

This was very unfortunate, as there is an ongoing (in 2022) issue with the custom commands and you can find a tons of hints..

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dinesh Kumar
Solution 2
Solution 3 Teresa
Solution 4 dgraf
Solution 5 pico_prob