Custom Commands | Bondar Academy
Course: Cypress UI Testing with JavaScript
Module: Page Object Design Pattern
Instructor: Artem Bondar
Lesson Summary
In this lesson, we explore Cypress custom commands , which allow you to create reusable commands that can be called globally in any test or spec file. Creating Custom Commands Custom commands are defined in the commands.js file located in the support folder. The syntax for creating a custom command is as follows: Cypress.Commands.add('commandName', (args) => { // command body }); For example, to create a command for opening the home page: Cypress.Commands.add('openHomePage', () => { cy.visit('/'); }); Using Custom Commands Once defined, you can call the custom command in your tests simply by using: cy.openHomePage(); Limitations of Custom Commands IntelliSense Limitations: Custom commands do not appear in IntelliSense suggestions, making it harder to discover them. No Navigation: You cannot navigate directly to the implementation of a custom command from your test files. Improving IntelliSense To enhance IntelliSense for custom commands, create a new namespace and interface in a separate file: declare namespace Cypress { interface Chainable { openHomePage(): Chainable ; } } This allows for better recognition of custom commands in your IDE. Best Practices Use custom commands for global operations that are frequently needed across tests. Avoid creating too many custom commands to maintain clarity and ease of navigation. For specific functionality, prefer using JavaScript functions or methods instead. In summary, custom commands are powerful tools in Cypress, but should be used judiciously to maintain an organized and efficient testing framework.
Video Transcript
Hey guys, in this lesson, we will talk about Cypress custom commands. So what is that first of all? Custom command in Cypress is the command that can be called globally anywhere in any test, in any spec file. In this lesson, I will show you how to create those. So going back to our project, and custom commands are declared under support folder in the commands.js right here. So here Cypress already offering us like a layout, how to create the custom command. So Cypress commands add, then you add the name of the command, and then the body of the command. So let me copy this thing and paste it over here. So login is the name of the command, email and password are arguments that you can pass, and these three dots is the body of the custom command that you can put any code inside of it. So for example, let's create, as an example, a very simple custom command that will be responsible for opening our application. Currently, we are using this CyVisit with a forward slash to open the app, but let's say we create a command that will be responsible for it. So I'll take this CyVisit forward slash and paste it over here. And then let's say I will change it instead of login, I will change the name to open home page, something like this. And our custom command will not have any arguments, so it will be just empty function, and that's it. So now we can go to the test, for example, to the page object. Instead of calling CyVisit, I can type cy and then call the custom command, open home page, like this. And that's it, and now I will comment this thing out. And the line that is responsible for opening the home page is now moved to the custom command that we can call anywhere inside of the code, in any spec file, in any test, and so on. It becomes kind of a global command, so let's try to run this command. So running page objects, and here we go. You can see our test working as before. Navigating to the application and executing the test scenario. So now let's talk about some of the limitations for the custom commands. So limitation number one is that this custom command become kind of invisible for IntelliSense. So for example, if I type cy and click dot, and then open, and this open home page is just the suggestion of the VS code. But it does not tell us, okay, what are custom commands available? For example, like get command, get all cookies, you see a little rectangle over here. It is a method related to Cypress with IntelliSense telling what this method is doing. For us, no, it doesn't work. Also, we cannot navigate directly to this custom command from the test file to find the implementation of the custom command. For example, if you are using page objects, you can open any custom command, any method, for example, form layout page. On the keyboard, you just press Command key if you are on Mac. Or if you're on Windows, hold the Alt key and hold Alt and click. And then the file where this method is located automatically opened for you. Or any other method, for example, submit using the grid. I hold the Command key on the Mac and click, and here we go. The method is open, right? But you cannot do the same thing with a custom command. So look, I hit the Command key and nothing happens. I cannot open it and click. There is a kind of a workaround how you can make the IntelliSense working with a custom command. So for that, you can create a new file and I need to declare a new namespace. Namespace, cypress, like this. And within this namespace, I need to create interface. Interface chainable, like this. And then within this interface chainable, I can create my custom command, like this, declare it. And then provide the type for this command as chainable and void. Void, like this, because this command does not return anything. And then if I go back to the file, and now look, when I'm hovering over, we kind of having some sort of IntelliSense that is telling us, yeah, this custom command exists. And then I can add some description to this. So I type forward slash and then star, star, creating the block. I showed this annotation in the previous lesson. And then you can add some description to this command. For example, command to open home page of application, something like this. When you go back over here, hovering over, and look, now you have at least some sort of IntelliSense that is telling what this command is doing. And also, CY, if I type CY and type open home page, look, right now it is recognized as the method that is available and you can use. So kind of a workaround. But still, you are not able to navigate directly to the method implementation. If I click command click, it navigates me just to this namespace file. It's not navigating me to commands.js where the actual file is located. And what all that means. So don't abuse using custom commands, first of all, in your framework. Create custom commands only for something that is kind of global for your framework. That can be used in most of your tests, in all of your tests here and there. For example, open application. For example, make some setup or seed some test data or something like this. Some global operations. Don't create a lot of custom commands because if you create a lot of them, it will be hard to navigate what commands do you have, what you don't. You will forget what commands are available. And if you want to go to implementation, you cannot make just command click. You will need manually open commands.js file, find your custom commands and then figure out, okay, this is what my command is doing and where's the source code. So use the custom commands only for type of global operations. That's it. For the rest of the stuff that you need in the framework, use JavaScript functions, use JavaScript methods, page objects, and all that stuff. The convenience of the custom command that is available through cy.notation. And since it is available through cy.notations, use it, as I said already, only for some basic global operations inside of the framework. So that's it. That's all about custom commands. You can also override custom commands, override existing commands in the Cypress. But I think you will not really need this functionality that often. If you will need it, you can check in Cypress documentation how to do it. All right, guys, that's all I wanted to share with you. So one more time, custom commands are defined in the commands.js on the support folder. You create cypresscommands.add, provide the method name, and then inside of the custom command, put whatever code you need for your custom command. Index.d.ts will enable the IntelliSense for your custom commands. And don't abuse custom commands. As a best practice, keep as complex as possible and keep them only for the global operations for your entire framework. All right, that's it, guys, and I'll see you in the next lesson.