Learn how to perform amazing end-to-end testing for Angular Firebase apps using Cypress.io. You'll never write e2e tests in Angular 6 the same again https://angularfirebase.com/lessons/cypress-angular-testing-end-to-end/

- Why Cypress https://docs.cypress.io/api/introduction/api.html
2024-02-04T07:29:29.417Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
1ab017fe-c1e0-43f4-9b32-93b2329feaa2
5d53368cff658734f028d1477d10ce4004bc62bcc21e59126916ec7c522acb06
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
Cypress is an end to end testing library that will change your life as a developer.
I say that because it allows you to speed up the testing process of the user experience and it will help you catch bugs that you didn't even know existed.
It's super easy to set up and the learning curve is very minimal.
So if you have an existing app, I recommend that you follow along with this episode in your own project to See what I mean firsthand.
If you're new to the channel, make sure to like and subscribe and you can find the source code at angularfirebase.com.
In case you're not familiar, end to end testing is the process of loading up your web application in the browser and testing things as if it was a real user performing these actions such as clicking buttons, filling out forms, and things like that.
So if you're an Angular developer, you might already know that Angular ships with its own end to end testing library called Protractor.
So why do we need Cypress?
The short answer is that Cypress just provides a better developer experience, but the longer answer is that Protractor was originally developed for AngularJS, And it just hasn't evolved the way Cypress has.
First of all, Cypress provides a really nice DSL for writing expressive end to end tests, which we'll see in the code here Coming up.
Then it provides this really nice test runner which is an Electron app that will run your app in the browser and then give you time travel debugging capabilities for each spec.
So for every action that takes place in the app, it will save a snapshot of the state as well as an image of the UI.
So you know how things change before and after some Action took place.
And in my experience, writing a really good test suite is much more effective at preventing bugs than using a state management library like Redux or something along those lines.
For this project, I'm going to be starting from the Firestarter demo app, which already has user authentication and a Firestore database feature implemented in it.
Over the next few minutes, we'll test that the user can sign up, log out, log back in, create some items in the database, and do a few other things in between.
The first thing we need to do is install it with npm install Cypress save dev.
Then I'm also installing a library called Chance, which we'll use to generate random fixtures for our specs.
I I've completely removed protractor from this project, and I'm going into the package JSON and changing the end to end script to say Cypress open.
Now Now you can run the script from the command line and it will take you through a series of steps to set up Cypress in your project.
I also highly recommend that you link your GitHub project to it because you can actually record your test and then save them in the cloud.
Recordings are great for your own reference, but they're even better if you have clients that wanna see the user experience happen step by step.
When you finish the setup, you'll see a few new things in your project.
Cypress JSON holds your global configuration options.
Then all of your testing code is in the Cypress directory.
You can set up your specs to run on TypeScript, but I don't see much benefit in doing that because you can pull in the types in just a plain JavaScript file as well.
You'll notice 4 different files here.
Fixers hold default data that you want to reuse throughout your tests, then integration is where you write your main specs.
That's where we'll spend most of the time here.
You can also write plugins that hook into different life cycle events in the testing process.
One example would be transpiling your code to TypeScript if you decide to t s.
And then you have a support directory where you can write your own custom commands for Cypress or overwrite existing commands.
We'll do this later in the video.
At this point, I just want to jump into writing our first test because it's really easy to do.
I've created a file called sample spec dotjs in the integration folder.
Then I'll reference the types so we can get really good tooling and autocomplete in our plain JavaScript file.
And I'll also bring in Chant so we can automatically generate Email addresses and text and things like that.
At this point, it's important to point out that Cypress uses Mocha and Chai as its underlying test libraries.
So you can't really use Jest or Jasmine as far as I know, but this doesn't really matter because you'll mostly be using the Cypress API to write your specs.
The first step is to describe the test suite which we'll call Firestarter.
And then I'll set a couple of global variables here.
1 is for an email address that will be randomly generated for each time this test runs and then another one for the password.
The state does not get reset between each test.
So if you want to go back to the home page, for example, you can set up a before each callback to redirect the user back to the home page, which we can do with sai.visitandtheurl.
Before we get started testing anything complex, let's just make sure we can find some text within the rendered page.
Calling cy contains will look for that text in the page, And that's all you need to write to test that content is in the page.
But you can also write more traditional test code where you explicitly declare your subject.
For example, if we expect 2 to equal 2.
I very rarely write tests like this in Cypress, but I just want you to know that it's possible.
So if we look at the spec, you can see it first ran our before each callback, then it lets us know whether our test passed or failed.
And if we hover over the contains, it will Highlight where it found that text in the page.
In this particular app, I have router guard set up to block certain routes if an unauthenticated user tries to access them.
In In this next spec, I'll show you how to navigate around the app and then verify that that particular route gets blocked.
This app has a drop down on mobile layouts, So we need to make sure that the actual link that we wanna click is visible on the page before we try to click it with Cypress, which in this case means clicking the element that has an ID of Nav toggle.
To do that, we can call Cypress get along with a selector, which works very similar to jQuery.
The get method is very powerful, and you'll be using it frequently in Cypress.
So once we click that button, the page then should contain the words Firestore.
And then we'll go ahead and click on that link which should normally bring us to the Firestore page.
However, it's currently blocked by a router guard, so it should show a notification message that that user is not authorized to visit that page.
In this app, I have a notification message component which I can grab and then I'll get the children elements from that component.
And somewhere inside those DOM elements, we should have the text You must be logged in.
This should method is super powerful in Cypress.
You can chain it onto any element that you've grabbed to make assertions about For the first argument, you can chain assertions together.
Then the second argument is optional and is the value that you want to compare.
What's really nice is We can chain multiple assertions together by using and.
For example, this text might be contained in the DOM, but we also wanna make sure that visible to the user, which we can do by asserting that the notification message should be visible.
If you uncomment the cy.pause line of code that I have at the top of the spec, It'll allow us to go through each item step by step.
So with that one line of code, we can just click the next button up here at the top and it will take us through each step and show us where the UI is being clicked and what is happening in response.
When it clicks the button, it will navigate to a new URL and then you'll see it asserts that that notification message has the corresponding Next.
So now let's go ahead and sign up a new user.
And we'll do this with email password, so we actually have to type into a form.
The first thing we'll do is click the toggle button and then click the login link.
Then we'll make sure that that takes the user back to the URL page, which we can do with Cypress URL and then a should assertion.
Now a best practice I'd like to point out is that you should generally avoid using IDs or CSS classes to select elements from the DOM.
That'll make your test brittle because those things are likely to change.
A better approach is to use a data attribute or the actual component name itself.
In this case, I'm using the name attribute on an input element which is very unlikely to change in most cases.
Then if you remember earlier, we set up a global email address, So I can simply type that email address into the form with the type operator.
I'll do the same thing for the password then find the submit button and click it.
Then we can verify that we have this new user and we could even verify things in local storage.
But for now, we'll just make sure that it has the right message in the page.
And then from there, we'll go ahead and log the user out, so we can log them back in in the next step.
When we time travel through the spec, you can see that it's actually typing in the randomly generated Email address into the form input.
And then it highlights the submit button with a red dot, shows you that it gets clicked, and then it navigates back to the new page with the proper message displayed.
Then you'll also see all of the asynchronous XHR requests that Firebase is making with the identity toolkit to log in the user.
The The next thing I wanna do is show you how to extend Cypress with your own custom method.
So let's imagine we often need to log in the user to do something in our app.
Instead of repeating our test code over and over again, I'm going to create a login method that we can reuse throughout our test suites.
We will go into the support folder and then in the commands and then call Cypress commands add.
The second argument is just a function that We'll run the steps needed to execute this command.
In most cases, you'd probably want to log the user in programmatically, but in this case, we'll just go ahead and have the user click different UI elements until they're logged into their account.
So what we've really done is just created a helper method that we can use in our specs to keep them concise Unreadable.
So getting back to our main spec now, we can log the user in that we just logged out in the previous spec and then do whatever else we need to do the logged in user.
The bottom line is it's just a really convenient way to share code throughout your tests.
There's so much more you can do with Cypress that I'll have to make a whole another video about more advanced concepts.
Again, the API is really well documented and intuitive, so I recommend that you give it a try.
I've been using it for the last few weeks and it's completely change the way that I do end to end testing in Angular.
I'm gonna go ahead and wrap things up there.
If this video helped you, please like and subscribe.
And if you're ready to start building a serious app, Consider becoming a pro member at angularfirebase.com.
You'll get access to all kinds of exclusive content designed to get your app into production faster.
Thanks for watching And I'll talk to you soon.

Speaker 0: Cypress is an end to end testing library that will change your life as a developer. I say that because it allows you to speed up the testing process of the user experience and it will help you catch bugs that you didn't even know existed. It's super easy to set up and the learning curve is very minimal. So if you have an existing app, I recommend that you follow along with this episode in your own project to See what I mean firsthand. If you're new to the channel, make sure to like and subscribe and you can find the source code at angularfirebase.com.

In case you're not familiar, end to end testing is the process of loading up your web application in the browser and testing things as if it was a real user performing these actions such as clicking buttons, filling out forms, and things like that. So if you're an Angular developer, you might already know that Angular ships with its own end to end testing library called Protractor. So why do we need Cypress? The short answer is that Cypress just provides a better developer experience, but the longer answer is that Protractor was originally developed for AngularJS, And it just hasn't evolved the way Cypress has. First of all, Cypress provides a really nice DSL for writing expressive end to end tests, which we'll see in the code here Coming up.

Then it provides this really nice test runner which is an Electron app that will run your app in the browser and then give you time travel debugging capabilities for each spec. So for every action that takes place in the app, it will save a snapshot of the state as well as an image of the UI. So you know how things change before and after some Action took place. And in my experience, writing a really good test suite is much more effective at preventing bugs than using a state management library like Redux or something along those lines. For this project, I'm going to be starting from the Firestarter demo app, which already has user authentication and a Firestore database feature implemented in it.

Over the next few minutes, we'll test that the user can sign up, log out, log back in, create some items in the database, and do a few other things in between. The first thing we need to do is install it with npm install Cypress save dev. Then I'm also installing a library called Chance, which we'll use to generate random fixtures for our specs. I I've completely removed protractor from this project, and I'm going into the package JSON and changing the end to end script to say Cypress open. Now Now you can run the script from the command line and it will take you through a series of steps to set up Cypress in your project.

I also highly recommend that you link your GitHub project to it because you can actually record your test and then save them in the cloud. Recordings are great for your own reference, but they're even better if you have clients that wanna see the user experience happen step by step. When you finish the setup, you'll see a few new things in your project. Cypress JSON holds your global configuration options. Then all of your testing code is in the Cypress directory.

You can set up your specs to run on TypeScript, but I don't see much benefit in doing that because you can pull in the types in just a plain JavaScript file as well. You'll notice 4 different files here. Fixers hold default data that you want to reuse throughout your tests, then integration is where you write your main specs. That's where we'll spend most of the time here. You can also write plugins that hook into different life cycle events in the testing process.

One example would be transpiling your code to TypeScript if you decide to t s. And then you have a support directory where you can write your own custom commands for Cypress or overwrite existing commands. We'll do this later in the video. At this point, I just want to jump into writing our first test because it's really easy to do. I've created a file called sample spec dotjs in the integration folder.

Then I'll reference the types so we can get really good tooling and autocomplete in our plain JavaScript file. And I'll also bring in Chant so we can automatically generate Email addresses and text and things like that. At this point, it's important to point out that Cypress uses Mocha and Chai as its underlying test libraries. So you can't really use Jest or Jasmine as far as I know, but this doesn't really matter because you'll mostly be using the Cypress API to write your specs. The first step is to describe the test suite which we'll call Firestarter.

And then I'll set a couple of global variables here. 1 is for an email address that will be randomly generated for each time this test runs and then another one for the password. The state does not get reset between each test. So if you want to go back to the home page, for example, you can set up a before each callback to redirect the user back to the home page, which we can do with sai.visitandtheurl. Before we get started testing anything complex, let's just make sure we can find some text within the rendered page.

Calling cy contains will look for that text in the page, And that's all you need to write to test that content is in the page. But you can also write more traditional test code where you explicitly declare your subject. For example, if we expect 2 to equal 2. I very rarely write tests like this in Cypress, but I just want you to know that it's possible. So if we look at the spec, you can see it first ran our before each callback, then it lets us know whether our test passed or failed.

And if we hover over the contains, it will Highlight where it found that text in the page. In this particular app, I have router guard set up to block certain routes if an unauthenticated user tries to access them. In In this next spec, I'll show you how to navigate around the app and then verify that that particular route gets blocked. This app has a drop down on mobile layouts, So we need to make sure that the actual link that we wanna click is visible on the page before we try to click it with Cypress, which in this case means clicking the element that has an ID of Nav toggle. To do that, we can call Cypress get along with a selector, which works very similar to jQuery.

The get method is very powerful, and you'll be using it frequently in Cypress. So once we click that button, the page then should contain the words Firestore. And then we'll go ahead and click on that link which should normally bring us to the Firestore page. However, it's currently blocked by a router guard, so it should show a notification message that that user is not authorized to visit that page. In this app, I have a notification message component which I can grab and then I'll get the children elements from that component.

And somewhere inside those DOM elements, we should have the text You must be logged in. This should method is super powerful in Cypress. You can chain it onto any element that you've grabbed to make assertions about For the first argument, you can chain assertions together. Then the second argument is optional and is the value that you want to compare. What's really nice is We can chain multiple assertions together by using and.

For example, this text might be contained in the DOM, but we also wanna make sure that visible to the user, which we can do by asserting that the notification message should be visible. If you uncomment the cy.pause line of code that I have at the top of the spec, It'll allow us to go through each item step by step. So with that one line of code, we can just click the next button up here at the top and it will take us through each step and show us where the UI is being clicked and what is happening in response. When it clicks the button, it will navigate to a new URL and then you'll see it asserts that that notification message has the corresponding Next. So now let's go ahead and sign up a new user.

And we'll do this with email password, so we actually have to type into a form. The first thing we'll do is click the toggle button and then click the login link. Then we'll make sure that that takes the user back to the URL page, which we can do with Cypress URL and then a should assertion. Now a best practice I'd like to point out is that you should generally avoid using IDs or CSS classes to select elements from the DOM. That'll make your test brittle because those things are likely to change.

A better approach is to use a data attribute or the actual component name itself. In this case, I'm using the name attribute on an input element which is very unlikely to change in most cases. Then if you remember earlier, we set up a global email address, So I can simply type that email address into the form with the type operator. I'll do the same thing for the password then find the submit button and click it. Then we can verify that we have this new user and we could even verify things in local storage.

But for now, we'll just make sure that it has the right message in the page. And then from there, we'll go ahead and log the user out, so we can log them back in in the next step. When we time travel through the spec, you can see that it's actually typing in the randomly generated Email address into the form input. And then it highlights the submit button with a red dot, shows you that it gets clicked, and then it navigates back to the new page with the proper message displayed. Then you'll also see all of the asynchronous XHR requests that Firebase is making with the identity toolkit to log in the user.

The The next thing I wanna do is show you how to extend Cypress with your own custom method. So let's imagine we often need to log in the user to do something in our app. Instead of repeating our test code over and over again, I'm going to create a login method that we can reuse throughout our test suites. We will go into the support folder and then in the commands and then call Cypress commands add. The second argument is just a function that We'll run the steps needed to execute this command.

In most cases, you'd probably want to log the user in programmatically, but in this case, we'll just go ahead and have the user click different UI elements until they're logged into their account. So what we've really done is just created a helper method that we can use in our specs to keep them concise Unreadable. So getting back to our main spec now, we can log the user in that we just logged out in the previous spec and then do whatever else we need to do the logged in user. The bottom line is it's just a really convenient way to share code throughout your tests. There's so much more you can do with Cypress that I'll have to make a whole another video about more advanced concepts.

Again, the API is really well documented and intuitive, so I recommend that you give it a try. I've been using it for the last few weeks and it's completely change the way that I do end to end testing in Angular. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe. And if you're ready to start building a serious app, Consider becoming a pro member at angularfirebase.com.

You'll get access to all kinds of exclusive content designed to get your app into production faster. Thanks for watching And I'll talk to you soon.
Cypress is an end to end testing library that will change your life as a developer. I say that because it allows you to speed up the testing process of the user experience and it will help you catch bugs that you didn't even know existed.
It's super easy to set up and the learning curve is very minimal. So if you have an existing app, I recommend that you follow along with this episode in your own project to See what I mean firsthand. If you're new to the channel, make sure to like and subscribe and you can find the source code at angularfirebase.com.
deep learning
In case you're not familiar, end to end testing is the process of loading up your web application in the browser and testing things as if it was a real user performing these actions such as clicking buttons, filling out forms, and things like that. So if you're an Angular developer, you might already know that Angular ships with its own end to end testing library called Protractor. So why do we need Cypress? The short answer is that Cypress just provides a better developer experience, but the longer answer is that Protractor was originally developed for AngularJS, And it just hasn't evolved the way Cypress has. First of all, Cypress provides a really nice DSL for writing expressive end to end tests, which we'll see in the code here Coming up. Then it provides this really nice test runner which is an Electron app that will run your app in the browser and then give you time travel debugging capabilities for each spec.
So for every action that takes place in the app, it will save a snapshot of the state as well as an image of the UI. So you know how things change before and after some Action took place. And in my experience, writing a really good test suite is much more effective at preventing bugs than using a state management library like Redux or something along those lines.
software
For this project, I'm going to be starting from the Firestarter demo app, which already has user authentication and a Firestore database feature implemented in it. Over the next few minutes, we'll test that the user can sign up, log out, log back in, create some items in the database, and do a few other things in between. The first thing we need to do is install it with npm install Cypress save dev. Then I'm also installing a library called Chance, which we'll use to generate random fixtures for our specs. I I've completely removed protractor from this project, and I'm going into the package JSON and changing the end to end script to say Cypress open. Now Now you can run the script from the command line and it will take you through a series of steps to set up Cypress in your project.
I also highly recommend that you link your GitHub project to it because you can actually record your test and then save them in the cloud. Recordings are great for your own reference, but they're even better if you have clients that wanna see the user experience happen step by step.
software
When you finish the setup, you'll see a few new things in your project. Cypress JSON holds your global configuration options. Then all of your testing code is in the Cypress directory. You can set up your specs to run on TypeScript, but I don't see much benefit in doing that because you can pull in the types in just a plain JavaScript file as well. You'll notice 4 different files here. Fixers hold default data that you want to reuse throughout your tests, then integration is where you write your main specs. That's where we'll spend most of the time here. You can also write plugins that hook into different life cycle events in the testing process.
One example would be transpiling your code to TypeScript if you decide to t s. And then you have a support directory where you can write your own custom commands for Cypress or overwrite existing commands. We'll do this later in the video. At this point, I just want to jump into writing our first test because it's really easy to do.
programming
I've created a file called sample spec dotjs in the integration folder. Then I'll reference the types so we can get really good tooling and autocomplete in our plain JavaScript file. And I'll also bring in Chant so we can automatically generate Email addresses and text and things like that. At this point, it's important to point out that Cypress uses Mocha and Chai as its underlying test libraries. So you can't really use Jest or Jasmine as far as I know, but this doesn't really matter because you'll mostly be using the Cypress API to write your specs. The first step is to describe the test suite which we'll call Firestarter. And then I'll set a couple of global variables here. 1 is for an email address that will be randomly generated for each time this test runs and then another one for the password. The state does not get reset between each test. So if you want to go back to the home page, for example, you can set up a before each callback to redirect the user back to the home page, which we can do with sai.visitandtheurl. Before we get started testing anything complex, let's just make sure we can find some text within the rendered page. Calling cy contains will look for that text in the page, And that's all you need to write to test that content is in the page. But you can also write more traditional test code where you explicitly declare your subject. For example, if we expect 2 to equal 2. I very rarely write tests like this in Cypress, but I just want you to know that it's possible. So if we look at the spec, you can see it first ran our before each callback, then it lets us know whether our test passed or failed. And if we hover over the contains, it will Highlight where it found that text in the page. In this particular app, I have router guard set up to block certain routes if an unauthenticated user tries to access them. In In this next spec, I'll show you how to navigate around the app and then verify that that particular route gets blocked. This app has a drop down on mobile layouts, So we need to make sure that the actual link that we wanna click is visible on the page before we try to click it with Cypress, which in this case means clicking the element that has an ID of Nav toggle. To do that, we can call Cypress get along with a selector, which works very similar to jQuery. The get method is very powerful, and you'll be using it frequently in Cypress. So once we click that button, the page then should contain the words Firestore. And then we'll go ahead and click on that link which should normally bring us to the Firestore page. However, it's currently blocked by a router guard, so it should show a notification message that that user is not authorized to visit that page. In this app, I have a notification message component which I can grab and then I'll get the children elements from that component. And somewhere inside those DOM elements, we should have the text You must be logged in. This should method is super powerful in Cypress. You can chain it onto any element that you've grabbed to make assertions about For the first argument, you can chain assertions together. Then the second argument is optional and is the value that you want to compare. What's really nice is We can chain multiple assertions together by using and. For example, this text might be contained in the DOM, but we also wanna make sure that visible to the user, which we can do by asserting that the notification message should be visible. If you uncomment the cy.pause line of code that I have at the top of the spec, It'll allow us to go through each item step by step. So with that one line of code, we can just click the next button up here at the top and it will take us through each step and show us where the UI is being clicked and what is happening in response.
When it clicks the button, it will navigate to a new URL and then you'll see it asserts that that notification message has the corresponding Next. So now let's go ahead and sign up a new user. And we'll do this with email password, so we actually have to type into a form.
email
The first thing we'll do is click the toggle button and then click the login link. Then we'll make sure that that takes the user back to the URL page, which we can do with Cypress URL and then a should assertion. Now a best practice I'd like to point out is that you should generally avoid using IDs or CSS classes to select elements from the DOM. That'll make your test brittle because those things are likely to change. A better approach is to use a data attribute or the actual component name itself.
In this case, I'm using the name attribute on an input element which is very unlikely to change in most cases. Then if you remember earlier, we set up a global email address, So I can simply type that email address into the form with the type operator. I'll do the same thing for the password then find the submit button and click it.
email
Then we can verify that we have this new user and we could even verify things in local storage. But for now, we'll just make sure that it has the right message in the page. And then from there, we'll go ahead and log the user out, so we can log them back in in the next step. When we time travel through the spec, you can see that it's actually typing in the randomly generated Email address into the form input. And then it highlights the submit button with a red dot, shows you that it gets clicked, and then it navigates back to the new page with the proper message displayed. Then you'll also see all of the asynchronous XHR requests that Firebase is making with the identity toolkit to log in the user. The The next thing I wanna do is show you how to extend Cypress with your own custom method. So let's imagine we often need to log in the user to do something in our app. Instead of repeating our test code over and over again, I'm going to create a login method that we can reuse throughout our test suites. We will go into the support folder and then in the commands and then call Cypress commands add. The second argument is just a function that We'll run the steps needed to execute this command. In most cases, you'd probably want to log the user in programmatically, but in this case, we'll just go ahead and have the user click different UI elements until they're logged into their account. So what we've really done is just created a helper method that we can use in our specs to keep them concise Unreadable. So getting back to our main spec now, we can log the user in that we just logged out in the previous spec and then do whatever else we need to do the logged in user. The bottom line is it's just a really convenient way to share code throughout your tests. There's so much more you can do with Cypress that I'll have to make a whole another video about more advanced concepts. Again, the API is really well documented and intuitive, so I recommend that you give it a try. I've been using it for the last few weeks and it's completely change the way that I do end to end testing in Angular.
I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe. And if you're ready to start building a serious app, Consider becoming a pro member at angularfirebase.com. You'll get access to all kinds of exclusive content designed to get your app into production faster. Thanks for watching And I'll talk to you soon.
youtube
software development
multimedia
software
streaming
microsoft
video gaming
Cypress is an end to end testing library that will change your life as a developer. I say that because it allows you to speed up the testing process of the user experience and it will help you catch bugs that you didn't even know existed. It's super easy to set up and the learning curve is very minimal. So if you have an existing app, I recommend that you follow along with this episode in your own project to See what I mean firsthand. If you're new to the channel, make sure to like and subscribe and you can find the source code at angularfirebase.com. In case you're not familiar, end to end testing is the process of loading up your web application in the browser and testing things as if it was a real user performing these actions such as clicking buttons, filling out forms, and things like that. So if you're an Angular developer, you might already know that Angular ships with its own end to end testing library called Protractor. So why do we need Cypress? The short answer is that Cypress just provides a better developer experience, but the longer answer is that Protractor was originally developed for AngularJS, And it just hasn't evolved the way Cypress has. First of all, Cypress provides a really nice DSL for writing expressive end to end tests, which we'll see in the code here Coming up. Then it provides this really nice test runner which is an Electron app that will run your app in the browser and then give you time travel debugging capabilities for each spec. So for every action that takes place in the app, it will save a snapshot of the state as well as an image of the UI. So you know how things change before and after some Action took place. And in my experience, writing a really good test suite is much more effective at preventing bugs than using a state management library like Redux or something along those lines. For this project, I'm going to be starting from the Firestarter demo app, which already has user authentication and a Firestore database feature implemented in it. Over the next few minutes, we'll test that the user can sign up, log out, log back in, create some items in the database, and do a few other things in between. The first thing we need to do is install it with npm install Cypress save dev. Then I'm also installing a library called Chance, which we'll use to generate random fixtures for our specs. I I've completely removed protractor from this project, and I'm going into the package JSON and changing the end to end script to say Cypress open. Now Now you can run the script from the command line and it will take you through a series of steps to set up Cypress in your project. I also highly recommend that you link your GitHub project to it because you can actually record your test and then save them in the cloud. Recordings are great for your own reference, but they're even better if you have clients that wanna see the user experience happen step by step. When you finish the setup, you'll see a few new things in your project. Cypress JSON holds your global configuration options. Then all of your testing code is in the Cypress directory. You can set up your specs to run on TypeScript, but I don't see much benefit in doing that because you can pull in the types in just a plain JavaScript file as well. You'll notice 4 different files here. Fixers hold default data that you want to reuse throughout your tests, then integration is where you write your main specs. That's where we'll spend most of the time here. You can also write plugins that hook into different life cycle events in the testing process. One example would be transpiling your code to TypeScript if you decide to t s. And then you have a support directory where you can write your own custom commands for Cypress or overwrite existing commands. We'll do this later in the video. At this point, I just want to jump into writing our first test because it's really easy to do. I've created a file called sample spec dotjs in the integration folder. Then I'll reference the types so we can get really good tooling and autocomplete in our plain JavaScript file. And I'll also bring in Chant so we can automatically generate Email addresses and text and things like that. At this point, it's important to point out that Cypress uses Mocha and Chai as its underlying test libraries. So you can't really use Jest or Jasmine as far as I know, but this doesn't really matter because you'll mostly be using the Cypress API to write your specs. The first step is to describe the test suite which we'll call Firestarter. And then I'll set a couple of global variables here. 1 is for an email address that will be randomly generated for each time this test runs and then another one for the password. The state does not get reset between each test. So if you want to go back to the home page, for example, you can set up a before each callback to redirect the user back to the home page, which we can do with sai.visitandtheurl. Before we get started testing anything complex, let's just make sure we can find some text within the rendered page. Calling cy contains will look for that text in the page, And that's all you need to write to test that content is in the page. But you can also write more traditional test code where you explicitly declare your subject. For example, if we expect 2 to equal 2. I very rarely write tests like this in Cypress, but I just want you to know that it's possible. So if we look at the spec, you can see it first ran our before each callback, then it lets us know whether our test passed or failed. And if we hover over the contains, it will Highlight where it found that text in the page. In this particular app, I have router guard set up to block certain routes if an unauthenticated user tries to access them. In In this next spec, I'll show you how to navigate around the app and then verify that that particular route gets blocked. This app has a drop down on mobile layouts, So we need to make sure that the actual link that we wanna click is visible on the page before we try to click it with Cypress, which in this case means clicking the element that has an ID of Nav toggle. To do that, we can call Cypress get along with a selector, which works very similar to jQuery. The get method is very powerful, and you'll be using it frequently in Cypress. So once we click that button, the page then should contain the words Firestore. And then we'll go ahead and click on that link which should normally bring us to the Firestore page. However, it's currently blocked by a router guard, so it should show a notification message that that user is not authorized to visit that page. In this app, I have a notification message component which I can grab and then I'll get the children elements from that component. And somewhere inside those DOM elements, we should have the text You must be logged in. This should method is super powerful in Cypress. You can chain it onto any element that you've grabbed to make assertions about For the first argument, you can chain assertions together. Then the second argument is optional and is the value that you want to compare. What's really nice is We can chain multiple assertions together by using and. For example, this text might be contained in the DOM, but we also wanna make sure that visible to the user, which we can do by asserting that the notification message should be visible. If you uncomment the cy.pause line of code that I have at the top of the spec, It'll allow us to go through each item step by step. So with that one line of code, we can just click the next button up here at the top and it will take us through each step and show us where the UI is being clicked and what is happening in response. When it clicks the button, it will navigate to a new URL and then you'll see it asserts that that notification message has the corresponding Next. So now let's go ahead and sign up a new user. And we'll do this with email password, so we actually have to type into a form. The first thing we'll do is click the toggle button and then click the login link. Then we'll make sure that that takes the user back to the URL page, which we can do with Cypress URL and then a should assertion. Now a best practice I'd like to point out is that you should generally avoid using IDs or CSS classes to select elements from the DOM. That'll make your test brittle because those things are likely to change. A better approach is to use a data attribute or the actual component name itself. In this case, I'm using the name attribute on an input element which is very unlikely to change in most cases. Then if you remember earlier, we set up a global email address, So I can simply type that email address into the form with the type operator. I'll do the same thing for the password then find the submit button and click it. Then we can verify that we have this new user and we could even verify things in local storage. But for now, we'll just make sure that it has the right message in the page. And then from there, we'll go ahead and log the user out, so we can log them back in in the next step. When we time travel through the spec, you can see that it's actually typing in the randomly generated Email address into the form input. And then it highlights the submit button with a red dot, shows you that it gets clicked, and then it navigates back to the new page with the proper message displayed. Then you'll also see all of the asynchronous XHR requests that Firebase is making with the identity toolkit to log in the user. The The next thing I wanna do is show you how to extend Cypress with your own custom method. So let's imagine we often need to log in the user to do something in our app. Instead of repeating our test code over and over again, I'm going to create a login method that we can reuse throughout our test suites. We will go into the support folder and then in the commands and then call Cypress commands add. The second argument is just a function that We'll run the steps needed to execute this command. In most cases, you'd probably want to log the user in programmatically, but in this case, we'll just go ahead and have the user click different UI elements until they're logged into their account. So what we've really done is just created a helper method that we can use in our specs to keep them concise Unreadable. So getting back to our main spec now, we can log the user in that we just logged out in the previous spec and then do whatever else we need to do the logged in user. The bottom line is it's just a really convenient way to share code throughout your tests. There's so much more you can do with Cypress that I'll have to make a whole another video about more advanced concepts. Again, the API is really well documented and intuitive, so I recommend that you give it a try. I've been using it for the last few weeks and it's completely change the way that I do end to end testing in Angular. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe. And if you're ready to start building a serious app, Consider becoming a pro member at angularfirebase.com. You'll get access to all kinds of exclusive content designed to get your app into production faster. Thanks for watching And I'll talk to you soon.
Cypress
cypress
is
is
an
an
end
end
to
to
end
end
testing
testing
library
library
that
that
will
will
change
change
your
your
life
life
as
as
a
a
developer.
developer
I
i
say
say
that
that
because
because
it
it
allows
allows
you
you
to
to
speed
speed
up
up
the
the
testing
testing
process
process
of
of
the
the
user
user
experience
experience
and
and
it
it
will
will
help
help
you
you
catch
catch
bugs
bugs
that
that
you
you
didn't
didn't
even
even
know
know
existed.
existed
It's
it's
super
super
easy
easy
to
to
set
set
up
up
and
and
the
the
learning
learning
curve
curve
is
is
very
very
minimal.
minimal
So
so
if
if
you
you
have
have
an
an
existing
existing
app,
app
I
i
recommend
recommend
that
that
you
you
follow
follow
along
along
with
with
this
this
episode
episode
in
in
your
your
own
own
project
project
to
to
See
see
what
what
I
i
mean
mean
firsthand.
firsthand
If
if
you're
you're
new
new
to
to
the
the
channel,
channel
make
make
sure
sure
to
to
like
like
and
and
subscribe
subscribe
and
and
you
you
can
can
find
find
the
the
source
source
code
code
at
at
angularfirebase.com.
angularfirebase.com
In
in
case
case
you're
you're
not
not
familiar,
familiar
end
end
to
to
end
end
testing
testing
is
is
the
the
process
process
of
of
loading
loading
up
up
your
your
web
web
application
application
in
in
the
the
browser
browser
and
and
testing
testing
things
things
as
as
if
if
it
it
was
was
a
a
real
real
user
user
performing
performing
these
these
actions
actions
such
such
as
as
clicking
clicking
buttons,
buttons
filling
filling
out
out
forms,
forms
and
and
things
things
like
like
that.
that
So
so
if
if
you're
you're
an
an
Angular
angular
developer,
developer
you
you
might
might
already
already
know
know
that
that
Angular
angular
ships
ships
with
with
its
its
own
own
end
end
to
to
end
end
testing
testing
library
library
called
called
Protractor.
protractor
So
so
why
why
do
do
we
we
need
need
Cypress?
cypress
The
the
short
short
answer
answer
is
is
that
that
Cypress
cypress
just
just
provides
provides
a
a
better
better
developer
developer
experience,
experience
but
but
the
the
longer
longer
answer
answer
is
is
that
that
Protractor
protractor
was
was
originally
originally
developed
developed
for
for
AngularJS,
angularjs
And
and
it
it
just
just
hasn't
hasn't
evolved
evolved
the
the
way
way
Cypress
cypress
has.
has
First
first
of
of
all,
all
Cypress
cypress
provides
provides
a
a
really
really
nice
nice
DSL
dsl
for
for
writing
writing
expressive
expressive
end
end
to
to
end
end
tests,
tests
which
which
we'll
we'll
see
see
in
in
the
the
code
code
here
here
Coming
coming
up.
up
Then
then
it
it
provides
provides
this
this
really
really
nice
nice
test
test
runner
runner
which
which
is
is
an
an
Electron
electron
app
app
that
that
will
will
run
run
your
your
app
app
in
in
the
the
browser
browser
and
and
then
then
give
give
you
you
time
time
travel
travel
debugging
debugging
capabilities
capabilities
for
for
each
each
spec.
spec
So
so
for
for
every
every
action
action
that
that
takes
takes
place
place
in
in
the
the
app,
app
it
it
will
will
save
save
a
a
snapshot
snapshot
of
of
the
the
state
state
as
as
well
well
as
as
an
an
image
image
of
of
the
the
UI.
ui
So
so
you
you
know
know
how
how
things
things
change
change
before
before
and
and
after
after
some
some
Action
action
took
took
place.
place
And
and
in
in
my
my
experience,
experience
writing
writing
a
a
really
really
good
good
test
test
suite
suite
is
is
much
much
more
more
effective
effective
at
at
preventing
preventing
bugs
bugs
than
than
using
using
a
a
state
state
management
management
library
library
like
like
Redux
redux
or
or
something
something
along
along
those
those
lines.
lines
For
for
this
this
project,
project
I'm
i'm
going
going
to
to
be
be
starting
starting
from
from
the
the
Firestarter
firestarter
demo
demo
app,
app
which
which
already
already
has
has
user
user
authentication
authentication
and
and
a
a
Firestore
firestore
database
database
feature
feature
implemented
implemented
in
in
it.
it
Over
over
the
the
next
next
few
few
minutes,
minutes
we'll
we'll
test
test
that
that
the
the
user
user
can
can
sign
sign
up,
up
log
log
out,
out
log
log
back
back
in,
in
create
create
some
some
items
items
in
in
the
the
database,
database
and
and
do
do
a
a
few
few
other
other
things
things
in
in
between.
between
The
the
first
first
thing
thing
we
we
need
need
to
to
do
do
is
is
install
install
it
it
with
with
npm
npm
install
install
Cypress
cypress
save
save
dev.
dev
Then
then
I'm
i'm
also
also
installing
installing
a
a
library
library
called
called
Chance,
chance
which
which
we'll
we'll
use
use
to
to
generate
generate
random
random
fixtures
fixtures
for
for
our
our
specs.
specs
I
i
I've
i've
completely
completely
removed
removed
protractor
protractor
from
from
this
this
project,
project
and
and
I'm
i'm
going
going
into
into
the
the
package
package
JSON
json
and
and
changing
changing
the
the
end
end
to
to
end
end
script
script
to
to
say
say
Cypress
cypress
open.
open
Now
now
Now
now
you
you
can
can
run
run
the
the
script
script
from
from
the
the
command
command
line
line
and
and
it
it
will
will
take
take
you
you
through
through
a
a
series
series
of
of
steps
steps
to
to
set
set
up
up
Cypress
cypress
in
in
your
your
project.
project
I
i
also
also
highly
highly
recommend
recommend
that
that
you
you
link
link
your
your
GitHub
github
project
project
to
to
it
it
because
because
you
you
can
can
actually
actually
record
record
your
your
test
test
and
and
then
then
save
save
them
them
in
in
the
the
cloud.
cloud
Recordings
recordings
are
are
great
great
for
for
your
your
own
own
reference,
reference
but
but
they're
they're
even
even
better
better
if
if
you
you
have
have
clients
clients
that
that
wanna
wanna
see
see
the
the
user
user
experience
experience
happen
happen
step
step
by
by
step.
step
When
when
you
you
finish
finish
the
the
setup,
setup
you'll
you'll
see
see
a
a
few
few
new
new
things
things
in
in
your
your
project.
project
Cypress
cypress
JSON
json
holds
holds
your
your
global
global
configuration
configuration
options.
options
Then
then
all
all
of
of
your
your
testing
testing
code
code
is
is
in
in
the
the
Cypress
cypress
directory.
directory
You
you
can
can
set
set
up
up
your
your
specs
specs
to
to
run
run
on
on
TypeScript,
typescript
but
but
I
i
don't
don't
see
see
much
much
benefit
benefit
in
in
doing
doing
that
that
because
because
you
you
can
can
pull
pull
in
in
the
the
types
types
in
in
just
just
a
a
plain
plain
JavaScript
javascript
file
file
as
as
well.
well
You'll
you'll
notice
notice
4
4
different
different
files
files
here.
here
Fixers
fixers
hold
hold
default
default
data
data
that
that
you
you
want
want
to
to
reuse
reuse
throughout
throughout
your
your
tests,
tests
then
then
integration
integration
is
is
where
where
you
you
write
write
your
your
main
main
specs.
specs
That's
that's
where
where
we'll
we'll
spend
spend
most
most
of
of
the
the
time
time
here.
here
You
you
can
can
also
also
write
write
plugins
plugins
that
that
hook
hook
into
into
different
different
life
life
cycle
cycle
events
events
in
in
the
the
testing
testing
process.
process
One
one
example
example
would
would
be
be
transpiling
transpiling
your
your
code
code
to
to
TypeScript
typescript
if
if
you
you
decide
decide
to
to
t
t
s.
s
And
and
then
then
you
you
have
have
a
a
support
support
directory
directory
where
where
you
you
can
can
write
write
your
your
own
own
custom
custom
commands
commands
for
for
Cypress
cypress
or
or
overwrite
overwrite
existing
existing
commands.
commands
We'll
we'll
do
do
this
this
later
later
in
in
the
the
video.
video
At
at
this
this
point,
point
I
i
just
just
want
want
to
to
jump
jump
into
into
writing
writing
our
our
first
first
test
test
because
because
it's
it's
really
really
easy
easy
to
to
do.
do
I've
i've
created
created
a
a
file
file
called
called
sample
sample
spec
spec
dotjs
dotjs
in
in
the
the
integration
integration
folder.
folder
Then
then
I'll
i'll
reference
reference
the
the
types
types
so
so
we
we
can
can
get
get
really
really
good
good
tooling
tooling
and
and
autocomplete
autocomplete
in
in
our
our
plain
plain
JavaScript
javascript
file.
file
And
and
I'll
i'll
also
also
bring
bring
in
in
Chant
chant
so
so
we
we
can
can
automatically
automatically
generate
generate
Email
email
addresses
addresses
and
and
text
text
and
and
things
things
like
like
that.
that
At
at
this
this
point,
point
it's
it's
important
important
to
to
point
point
out
out
that
that
Cypress
cypress
uses
uses
Mocha
mocha
and
and
Chai
chai
as
as
its
its
underlying
underlying
test
test
libraries.
libraries
So
so
you
you
can't
can't
really
really
use
use
Jest
jest
or
or
Jasmine
jasmine
as
as
far
far
as
as
I
i
know,
know
but
but
this
this
doesn't
doesn't
really
really
matter
matter
because
because
you'll
you'll
mostly
mostly
be
be
using
using
the
the
Cypress
cypress
API
api
to
to
write
write
your
your
specs.
specs
The
the
first
first
step
step
is
is
to
to
describe
describe
the
the
test
test
suite
suite
which
which
we'll
we'll
call
call
Firestarter.
firestarter
And
and
then
then
I'll
i'll
set
set
a
a
couple
couple
of
of
global
global
variables
variables
here.
here
1
1
is
is
for
for
an
an
email
email
address
address
that
that
will
will
be
be
randomly
randomly
generated
generated
for
for
each
each
time
time
this
this
test
test
runs
runs
and
and
then
then
another
another
one
one
for
for
the
the
password.
password
The
the
state
state
does
does
not
not
get
get
reset
reset
between
between
each
each
test.
test
So
so
if
if
you
you
want
want
to
to
go
go
back
back
to
to
the
the
home
home
page,
page
for
for
example,
example
you
you
can
can
set
set
up
up
a
a
before
before
each
each
callback
callback
to
to
redirect
redirect
the
the
user
user
back
back
to
to
the
the
home
home
page,
page
which
which
we
we
can
can
do
do
with
with
sai.visitandtheurl.
sai.visitandtheurl
Before
before
we
we
get
get
started
started
testing
testing
anything
anything
complex,
complex
let's
let's
just
just
make
make
sure
sure
we
we
can
can
find
find
some
some
text
text
within
within
the
the
rendered
rendered
page.
page
Calling
calling
cy
cy
contains
contains
will
will
look
look
for
for
that
that
text
text
in
in
the
the
page,
page
And
and
that's
that's
all
all
you
you
need
need
to
to
write
write
to
to
test
test
that
that
content
content
is
is
in
in
the
the
page.
page
But
but
you
you
can
can
also
also
write
write
more
more
traditional
traditional
test
test
code
code
where
where
you
you
explicitly
explicitly
declare
declare
your
your
subject.
subject
For
for
example,
example
if
if
we
we
expect
expect
2
2
to
to
equal
equal
2.
2
I
i
very
very
rarely
rarely
write
write
tests
tests
like
like
this
this
in
in
Cypress,
cypress
but
but
I
i
just
just
want
want
you
you
to
to
know
know
that
that
it's
it's
possible.
possible
So
so
if
if
we
we
look
look
at
at
the
the
spec,
spec
you
you
can
can
see
see
it
it
first
first
ran
ran
our
our
before
before
each
each
callback,
callback
then
then
it
it
lets
lets
us
us
know
know
whether
whether
our
our
test
test
passed
passed
or
or
failed.
failed
And
and
if
if
we
we
hover
hover
over
over
the
the
contains,
contains
it
it
will
will
Highlight
highlight
where
where
it
it
found
found
that
that
text
text
in
in
the
the
page.
page
In
in
this
this
particular
particular
app,
app
I
i
have
have
router
router
guard
guard
set
set
up
up
to
to
block
block
certain
certain
routes
routes
if
if
an
an
unauthenticated
unauthenticated
user
user
tries
tries
to
to
access
access
them.
them
In
in
In
in
this
this
next
next
spec,
spec
I'll
i'll
show
show
you
you
how
how
to
to
navigate
navigate
around
around
the
the
app
app
and
and
then
then
verify
verify
that
that
that
that
particular
particular
route
route
gets
gets
blocked.
blocked
This
this
app
app
has
has
a
a
drop
drop
down
down
on
on
mobile
mobile
layouts,
layouts
So
so
we
we
need
need
to
to
make
make
sure
sure
that
that
the
the
actual
actual
link
link
that
that
we
we
wanna
wanna
click
click
is
is
visible
visible
on
on
the
the
page
page
before
before
we
we
try
try
to
to
click
click
it
it
with
with
Cypress,
cypress
which
which
in
in
this
this
case
case
means
means
clicking
clicking
the
the
element
element
that
that
has
has
an
an
ID
id
of
of
Nav
nav
toggle.
toggle
To
to
do
do
that,
that
we
we
can
can
call
call
Cypress
cypress
get
get
along
along
with
with
a
a
selector,
selector
which
which
works
works
very
very
similar
similar
to
to
jQuery.
jquery
The
the
get
get
method
method
is
is
very
very
powerful,
powerful
and
and
you'll
you'll
be
be
using
using
it
it
frequently
frequently
in
in
Cypress.
cypress
So
so
once
once
we
we
click
click
that
that
button,
button
the
the
page
page
then
then
should
should
contain
contain
the
the
words
words
Firestore.
firestore
And
and
then
then
we'll
we'll
go
go
ahead
ahead
and
and
click
click
on
on
that
that
link
link
which
which
should
should
normally
normally
bring
bring
us
us
to
to
the
the
Firestore
firestore
page.
page
However,
however
it's
it's
currently
currently
blocked
blocked
by
by
a
a
router
router
guard,
guard
so
so
it
it
should
should
show
show
a
a
notification
notification
message
message
that
that
that
that
user
user
is
is
not
not
authorized
authorized
to
to
visit
visit
that
that
page.
page
In
in
this
this
app,
app
I
i
have
have
a
a
notification
notification
message
message
component
component
which
which
I
i
can
can
grab
grab
and
and
then
then
I'll
i'll
get
get
the
the
children
children
elements
elements
from
from
that
that
component.
component
And
and
somewhere
somewhere
inside
inside
those
those
DOM
dom
elements,
elements
we
we
should
should
have
have
the
the
text
text
You
you
must
must
be
be
logged
logged
in.
in
This
this
should
should
method
method
is
is
super
super
powerful
powerful
in
in
Cypress.
cypress
You
you
can
can
chain
chain
it
it
onto
onto
any
any
element
element
that
that
you've
you've
grabbed
grabbed
to
to
make
make
assertions
assertions
about
about
For
for
the
the
first
first
argument,
argument
you
you
can
can
chain
chain
assertions
assertions
together.
together
Then
then
the
the
second
second
argument
argument
is
is
optional
optional
and
and
is
is
the
the
value
value
that
that
you
you
want
want
to
to
compare.
compare
What's
what's
really
really
nice
nice
is
is
We
we
can
can
chain
chain
multiple
multiple
assertions
assertions
together
together
by
by
using
using
and.
and
For
for
example,
example
this
this
text
text
might
might
be
be
contained
contained
in
in
the
the
DOM,
dom
but
but
we
we
also
also
wanna
wanna
make
make
sure
sure
that
that
visible
visible
to
to
the
the
user,
user
which
which
we
we
can
can
do
do
by
by
asserting
asserting
that
that
the
the
notification
notification
message
message
should
should
be
be
visible.
visible
If
if
you
you
uncomment
uncomment
the
the
cy.pause
cy.pause
line
line
of
of
code
code
that
that
I
i
have
have
at
at
the
the
top
top
of
of
the
the
spec,
spec
It'll
it'll
allow
allow
us
us
to
to
go
go
through
through
each
each
item
item
step
step
by
by
step.
step
So
so
with
with
that
that
one
one
line
line
of
of
code,
code
we
we
can
can
just
just
click
click
the
the
next
next
button
button
up
up
here
here
at
at
the
the
top
top
and
and
it
it
will
will
take
take
us
us
through
through
each
each
step
step
and
and
show
show
us
us
where
where
the
the
UI
ui
is
is
being
being
clicked
clicked
and
and
what
what
is
is
happening
happening
in
in
response.
response
When
when
it
it
clicks
clicks
the
the
button,
button
it
it
will
will
navigate
navigate
to
to
a
a
new
new
URL
url
and
and
then
then
you'll
you'll
see
see
it
it
asserts
asserts
that
that
that
that
notification
notification
message
message
has
has
the
the
corresponding
corresponding
Next.
next
So
so
now
now
let's
let's
go
go
ahead
ahead
and
and
sign
sign
up
up
a
a
new
new
user.
user
And
and
we'll
we'll
do
do
this
this
with
with
email
email
password,
password
so
so
we
we
actually
actually
have
have
to
to
type
type
into
into
a
a
form.
form
The
the
first
first
thing
thing
we'll
we'll
do
do
is
is
click
click
the
the
toggle
toggle
button
button
and
and
then
then
click
click
the
the
login
login
link.
link
Then
then
we'll
we'll
make
make
sure
sure
that
that
that
that
takes
takes
the
the
user
user
back
back
to
to
the
the
URL
url
page,
page
which
which
we
we
can
can
do
do
with
with
Cypress
cypress
URL
url
and
and
then
then
a
a
should
should
assertion.
assertion
Now
now
a
a
best
best
practice
practice
I'd
i'd
like
like
to
to
point
point
out
out
is
is
that
that
you
you
should
should
generally
generally
avoid
avoid
using
using
IDs
ids
or
or
CSS
css
classes
classes
to
to
select
select
elements
elements
from
from
the
the
DOM.
dom
That'll
that'll
make
make
your
your
test
test
brittle
brittle
because
because
those
those
things
things
are
are
likely
likely
to
to
change.
change
A
a
better
better
approach
approach
is
is
to
to
use
use
a
a
data
data
attribute
attribute
or
or
the
the
actual
actual
component
component
name
name
itself.
itself
In
in
this
this
case,
case
I'm
i'm
using
using
the
the
name
name
attribute
attribute
on
on
an
an
input
input
element
element
which
which
is
is
very
very
unlikely
unlikely
to
to
change
change
in
in
most
most
cases.
cases
Then
then
if
if
you
you
remember
remember
earlier,
earlier
we
we
set
set
up
up
a
a
global
global
email
email
address,
address
So
so
I
i
can
can
simply
simply
type
type
that
that
email
email
address
address
into
into
the
the
form
form
with
with
the
the
type
type
operator.
operator
I'll
i'll
do
do
the
the
same
same
thing
thing
for
for
the
the
password
password
then
then
find
find
the
the
submit
submit
button
button
and
and
click
click
it.
it
Then
then
we
we
can
can
verify
verify
that
that
we
we
have
have
this
this
new
new
user
user
and
and
we
we
could
could
even
even
verify
verify
things
things
in
in
local
local
storage.
storage
But
but
for
for
now,
now
we'll
we'll
just
just
make
make
sure
sure
that
that
it
it
has
has
the
the
right
right
message
message
in
in
the
the
page.
page
And
and
then
then
from
from
there,
there
we'll
we'll
go
go
ahead
ahead
and
and
log
log
the
the
user
user
out,
out
so
so
we
we
can
can
log
log
them
them
back
back
in
in
in
in
the
the
next
next
step.
step
When
when
we
we
time
time
travel
travel
through
through
the
the
spec,
spec
you
you
can
can
see
see
that
that
it's
it's
actually
actually
typing
typing
in
in
the
the
randomly
randomly
generated
generated
Email
email
address
address
into
into
the
the
form
form
input.
input
And
and
then
then
it
it
highlights
highlights
the
the
submit
submit
button
button
with
with
a
a
red
red
dot,
dot
shows
shows
you
you
that
that
it
it
gets
gets
clicked,
clicked
and
and
then
then
it
it
navigates
navigates
back
back
to
to
the
the
new
new
page
page
with
with
the
the
proper
proper
message
message
displayed.
displayed
Then
then
you'll
you'll
also
also
see
see
all
all
of
of
the
the
asynchronous
asynchronous
XHR
xhr
requests
requests
that
that
Firebase
firebase
is
is
making
making
with
with
the
the
identity
identity
toolkit
toolkit
to
to
log
log
in
in
the
the
user.
user
The
the
The
the
next
next
thing
thing
I
i
wanna
wanna
do
do
is
is
show
show
you
you
how
how
to
to
extend
extend
Cypress
cypress
with
with
your
your
own
own
custom
custom
method.
method
So
so
let's
let's
imagine
imagine
we
we
often
often
need
need
to
to
log
log
in
in
the
the
user
user
to
to
do
do
something
something
in
in
our
our
app.
app
Instead
instead
of
of
repeating
repeating
our
our
test
test
code
code
over
over
and
and
over
over
again,
again
I'm
i'm
going
going
to
to
create
create
a
a
login
login
method
method
that
that
we
we
can
can
reuse
reuse
throughout
throughout
our
our
test
test
suites.
suites
We
we
will
will
go
go
into
into
the
the
support
support
folder
folder
and
and
then
then
in
in
the
the
commands
commands
and
and
then
then
call
call
Cypress
cypress
commands
commands
add.
add
The
the
second
second
argument
argument
is
is
just
just
a
a
function
function
that
that
We'll
we'll
run
run
the
the
steps
steps
needed
needed
to
to
execute
execute
this
this
command.
command
In
in
most
most
cases,
cases
you'd
you'd
probably
probably
want
want
to
to
log
log
the
the
user
user
in
in
programmatically,
programmatically
but
but
in
in
this
this
case,
case
we'll
we'll
just
just
go
go
ahead
ahead
and
and
have
have
the
the
user
user
click
click
different
different
UI
ui
elements
elements
until
until
they're
they're
logged
logged
into
into
their
their
account.
account
So
so
what
what
we've
we've
really
really
done
done
is
is
just
just
created
created
a
a
helper
helper
method
method
that
that
we
we
can
can
use
use
in
in
our
our
specs
specs
to
to
keep
keep
them
them
concise
concise
Unreadable.
unreadable
So
so
getting
getting
back
back
to
to
our
our
main
main
spec
spec
now,
now
we
we
can
can
log
log
the
the
user
user
in
in
that
that
we
we
just
just
logged
logged
out
out
in
in
the
the
previous
previous
spec
spec
and
and
then
then
do
do
whatever
whatever
else
else
we
we
need
need
to
to
do
do
the
the
logged
logged
in
in
user.
user
The
the
bottom
bottom
line
line
is
is
it's
it's
just
just
a
a
really
really
convenient
convenient
way
way
to
to
share
share
code
code
throughout
throughout
your
your
tests.
tests
There's
there's
so
so
much
much
more
more
you
you
can
can
do
do
with
with
Cypress
cypress
that
that
I'll
i'll
have
have
to
to
make
make
a
a
whole
whole
another
another
video
video
about
about
more
more
advanced
advanced
concepts.
concepts
Again,
again
the
the
API
api
is
is
really
really
well
well
documented
documented
and
and
intuitive,
intuitive
so
so
I
i
recommend
recommend
that
that
you
you
give
give
it
it
a
a
try.
try
I've
i've
been
been
using
using
it
it
for
for
the
the
last
last
few
few
weeks
weeks
and
and
it's
it's
completely
completely
change
change
the
the
way
way
that
that
I
i
do
do
end
end
to
to
end
end
testing
testing
in
in
Angular.
angular
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
wrap
wrap
things
things
up
up
there.
there
If
if
this
this
video
video
helped
helped
you,
you
please
please
like
like
and
and
subscribe.
subscribe
And
and
if
if
you're
you're
ready
ready
to
to
start
start
building
building
a
a
serious
serious
app,
app
Consider
consider
becoming
becoming
a
a
pro
pro
member
member
at
at
angularfirebase.com.
angularfirebase.com
You'll
you'll
get
get
access
access
to
to
all
all
kinds
kinds
of
of
exclusive
exclusive
content
content
designed
designed
to
to
get
get
your
your
app
app
into
into
production
production
faster.
faster
Thanks
thanks
for
for
watching
watching
And
and
I'll
i'll
talk
talk
to
to
you
you
soon.
soon
success
The Cypress end-to-end testing library provides a better developer experience but is more effective at preventing bugs. Developmenters can run tests and generate random fixtures after installing Pro stores and building a package JSON. They can also use the Cypress API to write test code and navigate through mobile layouts, chaining multiple assertions, and avoiding using IDs or CSS classes. Pro member access is recommended for more exclusive content access. The recommended helper method for rebuilding the app is well documented, and signing up as a pro member is recommended for more access to exclusive content.
Cypress End-to-End Testing
Cypress is an end to end testing library that will change your life as a developer. I say that because it allows you to speed up the testing process of the user experience and it will help you catch bugs that you didn't even know existed. It's super easy to set up and the learning curve is very minimal. So if you have an existing app, I recommend that you follow along with this episode in your own project to See what I mean firsthand. If you're new to the channel, make sure to like and subscribe and you can find the source code at angularfirebase.com. In case you're not familiar, end to end testing is the process of loading up your web application in the browser and testing things as if it was a real user performing these actions such as clicking buttons, filling out forms, and things like that. So if you're an Angular developer, you might already know that Angular ships with its own end to end testing library called Protractor. So why do we need Cypress? The short answer is that Cypress just provides a better developer experience, but the longer answer is that Protractor was originally developed for AngularJS, And it just hasn't evolved the way Cypress has. First of all, Cypress provides a really nice DSL for writing expressive end to end tests, which we'll see in the code here Coming up. Then it provides this really nice test runner which is an Electron app that will run your app in the browser and then give you time travel debugging capabilities for each spec. So for every action that takes place in the app, it will save a snapshot of the state as well as an image of the UI. So you know how things change before and after some Action took place. And in my experience, writing a really good test suite is much more effective at preventing bugs than using a state management library like Redux or something along those lines. For this project, I'm going to be starting from the Firestarter demo app, which already has user authentication and a Firestore database feature implemented in it. Over the next few minutes, we'll test that the user can sign up, log out, log back in, create some items in the database, and do a few other things in between. The first thing we need to do is install it with npm install Cypress save dev. Then I'm also installing a library called Chance, which we'll use to generate random fixtures for our specs. I I've completely removed protractor from this project, and I'm going into the package JSON and changing the end to end script to say Cypress open. Now Now you can run the script from the command line and it will take you through a series of steps to set up Cypress in your project. I also highly recommend that you link your GitHub project to it because you can actually record your test and then save them in the cloud. Recordings are great for your own reference, but they're even better if you have clients that wanna see the user experience happen step by step. When you finish the setup, you'll see a few new things in your project. Cypress JSON holds your global configuration options. Then all of your testing code is in the Cypress directory. You can set up your specs to run on TypeScript, but I don't see much benefit in doing that because you can pull in the types in just a plain JavaScript file as well. You'll notice 4 different files here. Fixers hold default data that you want to reuse throughout your tests, then integration is where you write your main specs. That's where we'll spend most of the time here. You can also write plugins that hook into different life cycle events in the testing process. One example would be transpiling your code to TypeScript if you decide to t s. And then you have a support directory where you can write your own custom commands for Cypress or overwrite existing commands. We'll do this later in the video. At this point, I just want to jump into writing our first test because it's really easy to do. I've created a file called sample spec dotjs in the integration folder. Then I'll reference the types so we can get really good tooling and autocomplete in our plain JavaScript file. And I'll also bring in Chant so we can automatically generate Email addresses and text and things like that. At this point, it's important to point out that Cypress uses Mocha and Chai as its underlying test libraries. So you can't really use Jest or Jasmine as far as I know, but this doesn't really matter because you'll mostly be using the Cypress API to write your specs. The first step is to describe the test suite which we'll call Firestarter. And then I'll set a couple of global variables here. 1 is for an email address that will be randomly generated for each time this test runs and then another one for the password. The state does not get reset between each test. So if you want to go back to the home page, for example, you can set up a before each callback to redirect the user back to the home page, which we can do with sai.visitandtheurl. Before we get started testing anything complex, let's just make sure we can find some text within the rendered page. Calling cy contains will look for that text in the page, And that's all you need to write to test that content is in the page. But you can also write more traditional test code where you explicitly declare your subject. For example, if we expect 2 to equal 2. I very rarely write tests like this in Cypress, but I just want you to know that it's possible. So if we look at the spec, you can see it first ran our before each callback, then it lets us know whether our test passed or failed. And if we hover over the contains, it will Highlight where it found that text in the page. In this particular app, I have router guard set up to block certain routes if an unauthenticated user tries to access them. In In this next spec, I'll show you how to navigate around the app and then verify that that particular route gets blocked. This app has a drop down on mobile layouts, So we need to make sure that the actual link that we wanna click is visible on the page before we try to click it with Cypress, which in this case means clicking the element that has an ID of Nav toggle. To do that, we can call Cypress get along with a selector, which works very similar to jQuery. The get method is very powerful, and you'll be using it frequently in Cypress. So once we click that button, the page then should contain the words Firestore. And then we'll go ahead and click on that link which should normally bring us to the Firestore page. However, it's currently blocked by a router guard, so it should show a notification message that that user is not authorized to visit that page. In this app, I have a notification message component which I can grab and then I'll get the children elements from that component. And somewhere inside those DOM elements, we should have the text You must be logged in. This should method is super powerful in Cypress. You can chain it onto any element that you've grabbed to make assertions about For the first argument, you can chain assertions together. Then the second argument is optional and is the value that you want to compare. What's really nice is We can chain multiple assertions together by using and. For example, this text might be contained in the DOM, but we also wanna make sure that visible to the user, which we can do by asserting that the notification message should be visible. If you uncomment the cy.pause line of code that I have at the top of the spec, It'll allow us to go through each item step by step. So with that one line of code, we can just click the next button up here at the top and it will take us through each step and show us where the UI is being clicked and what is happening in response. When it clicks the button, it will navigate to a new URL and then you'll see it asserts that that notification message has the corresponding Next. So now let's go ahead and sign up a new user. And we'll do this with email password, so we actually have to type into a form. The first thing we'll do is click the toggle button and then click the login link. Then we'll make sure that that takes the user back to the URL page, which we can do with Cypress URL and then a should assertion. Now a best practice I'd like to point out is that you should generally avoid using IDs or CSS classes to select elements from the DOM. That'll make your test brittle because those things are likely to change. A better approach is to use a data attribute or the actual component name itself. In this case, I'm using the name attribute on an input element which is very unlikely to change in most cases. Then if you remember earlier, we set up a global email address, So I can simply type that email address into the form with the type operator. I'll do the same thing for the password then find the submit button and click it. Then we can verify that we have this new user and we could even verify things in local storage. But for now, we'll just make sure that it has the right message in the page. And then from there, we'll go ahead and log the user out, so we can log them back in in the next step. When we time travel through the spec, you can see that it's actually typing in the randomly generated Email address into the form input. And then it highlights the submit button with a red dot, shows you that it gets clicked, and then it navigates back to the new page with the proper message displayed. Then you'll also see all of the asynchronous XHR requests that Firebase is making with the identity toolkit to log in the user. The The next thing I wanna do is show you how to extend Cypress with your own custom method. So let's imagine we often need to log in the user to do something in our app. Instead of repeating our test code over and over again, I'm going to create a login method that we can reuse throughout our test suites. We will go into the support folder and then in the commands and then call Cypress commands add. The second argument is just a function that We'll run the steps needed to execute this command. In most cases, you'd probably want to log the user in programmatically, but in this case, we'll just go ahead and have the user click different UI elements until they're logged into their account. So what we've really done is just created a helper method that we can use in our specs to keep them concise Unreadable. So getting back to our main spec now, we can log the user in that we just logged out in the previous spec and then do whatever else we need to do the logged in user. The bottom line is it's just a really convenient way to share code throughout your tests. There's so much more you can do with Cypress that I'll have to make a whole another video about more advanced concepts. Again, the API is really well documented and intuitive, so I recommend that you give it a try. I've been using it for the last few weeks and it's completely change the way that I do end to end testing in Angular. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe. And if you're ready to start building a serious app, Consider becoming a pro member at angularfirebase.com. You'll get access to all kinds of exclusive content designed to get your app into production faster. Thanks for watching And I'll talk to you soon.
The Cypress end-to-end testing library provides a better developer experience but is more effective at preventing bugs. Developmenters can run tests and generate random fixtures after installing Pro stores and building a package JSON. They can also use the Cypress API to write test code and navigate through mobile layouts, chaining multiple assertions, and avoiding using IDs or CSS classes. Pro member access is recommended for more exclusive content access. The recommended helper method for rebuilding the app is well documented, and signing up as a pro member is recommended for more access to exclusive content.