Production-Grade Angular Cypress Overview
Transcript from the "Cypress Overview" Lesson
>> And so just before I get into walking through what this looks like and how it exists within the project, I want to just take a real quick moment and just talk about how the tests are structured in kind of those components before we see it in code.
[00:00:15] So in terms of structuring our tests, there are kind of three main components, you have your specs, your page objects, and your HTML templates. And there's a few other components here, but these are the main pieces. So specs, what we expect to happen, broke down in individual tests.
[00:00:35] So this is very much like an end-to-end test. Now page objects, this is responsible for managing the sequencing and the interaction with the elements on the page. And now we have our variation of this, which so I consider we have smart page objects which are actually kind of, you can think of those as kind of like macros, where you're managing the sequencing.
[00:01:04] But also within a page object, which I would referred to as maybe like a static page object is that, I keep a key value object that helps locating elements on the page. And then from here, we have our HTML templates, which this exists within our main application, and this is what we use to allow Cypress to then query our application and get access to it.
[00:01:35] So with that said, let's hop into the code, let's walk through this, and let's see what this looks like. So normally like connects it together because of the dependencies, but, All right, from the command line, we'll go, nx run. And thanks for the great input there, we'll go end-to-end.
[00:01:58] And then we're running the end-to-end test on dashboard. So this is dash dash watch. And what this is going to do is, it's going to compile the application and it's going to pull up the console. And once it does this, then we'll be able to see the specs that we have in our project, and then we can run them individually or all at once.
[00:02:24] And so in this case, we just have a single spec. And this is gonna run over here in the test runner, and that was kinda fast. So let me do this again. And so if you wanna see it again, and you can just refresh. And from here, you can do some really interesting things.
[00:02:48] So, we could time travel, as I mentioned. And so, we have the test body here and you can actually start to walk through the test that you're going. So let's go to something a little more interesting. Let's go with, we want to update a widget. So you can see here that, let me just unpinned this real quick, that here, if I go to, and you can actually just mouse over it and you can see that I'm typing so as you see as I mouse over this, I'm adding in these exclamation points.
[00:03:31] And then at the bottom, then they go into here. So now we can start to time travel through our test. So we have three widgets, and we're able to time travel through this, and see the test running. Now another thing that we can do besides time travel, which I think is pretty awesome, is that if you want to get access to a particular element in your end-to-end test, what you can do is you can select this little kinda target here, and go through, and click on your elements.
[00:04:12] So this is really, really helpful to click this, and it'll give you a selector that you can then copy and pull into your test. And so a lot of times what I do, is that I'll instrument my templates with very specific IDs like test ID. So it's easy for me to just go, and look that up, and pull it out.
[00:04:37] But there are times where I need to pull maybe a sub element out. And from here, I can just basically select this item, or I can use this target here and I could say, like I take this and it gives me the selector to do that. And so this is also really, really helpful because one of the ways for your end-to-end test to become very, very brittle is when you are using like the CSS, like I would say CSS selectors, specifically, that you're trying to find this element on the page that may or may not exist and you're having to do these complex queries in to your templates.
[00:05:19] And so by using, you'll see here I have this data site, and we'll talk about this in a moment. But by using very specific test IDs in your template, it makes it very easy to locate. But occasionally, you may want to look something up or like a subset of that, and you can use this tool here to just go and click on it.
[00:05:40] So in this case, I only have one image on the page. And if I didn't want to add an ID, then I could just say, cy.get.image. So not only is it giving you the selector, but it's giving you the command to get that element off the page. So I wanna let that sink in for a second, the test runner is helping you write your test in the fact that it's servicing all the stuff that you could and would want to see.
[00:06:14] And so I need to get access to, for instance, let's go with, I'll close this back down, this particular button here. So I can click on here, and if I needed to do some down and dirty, I could just grab this particular selector. And so I think that's really, really important is that, not only can you see your test being run in real time, that you can also set it up that if a test fails, you can capture that video or you can capture that image.
[00:06:51] So now you're running a test, it fails. And now you can capture that output and store it, and then service this back to someone on your team to say like, what happened? Well, we have an image for it like it failed and you can check it out. And so that's another really, really, really cool thing is, where did it go wrong?
[00:07:11] Well, you can very easily set it to capture an image or a video of that particular test. And the fact that you can just basically walk through this, it's very easy to replicate that. And so these are just a couple of things that I really, really, really like about Cypress in the test runner.
[00:07:34] Now, let me hop into the project itself, and I want to just point out a couple elements. Well, let me actually show you one more thing real quick. And I'm going to stop this, and we're just going to do this one more time. And you're going to see something in this code that is really worth pointing out when you are building automated end-to-end test.
[00:08:02] You'll notice here that there is this route segments in the test. So I'm saying route, get widgets, and this is stubbed. You'll notice here that in my widgets, it's Cypress widget 00, 01, etc. So that's the other thing I want to point out is that, we're loading the application but I'm actually pulling in stubbed data.
[00:08:33] So this is another super amazing thing is that, we're setting up these routes, the stubbed routes, and then before the test runs, we're able to essentially get and hit those routes and do stuff. So this is why you're seeing Cypress data in the application. And so I'll show you where that's coming from as well.
[00:08:58] And also notice this is running the application, like I can actually click on here and interact with this. So it's pulling the application up, running it. We can select it, we can drill into it, we can time travel, and then we can also mock out the request for that data.
[00:09:16] So you wanna be really, I would say that when you're running end-to-end test, there is a time and a place for using real APIs, especially like in a large scale integration test. There are times to use a real API to make sure that everything works. In most cases, a major barrier to entry to running end-to-end test is that you're using real APIs and all sudden now, you've got all this test data in your database or you're manipulating sensitive data.
[00:09:49] Well, the way around that is to mock out your APIs, so that I can run this a 1000 times a day and not affect any data inside of a database. And then at some point I would say, like run this every time you check your code in or anytime you're about to release, but then at some point that you do flip to a real API and you let it run against the real API.
[00:10:11] But, more often than not, I would say probably, if you do this a 100 times, I would say maybe just a handful of times, would you actually run this against a real API? Because if you're just doing this locally, like you don't want to have to worry about, I'm running this locally, and I have to worry about the data, and the time that it takes to make these real API request.
[00:10:33] So, with that said, I'm going to close this down. Now, real quick, you will notice as well, I'm running Chrome, but you can add in additional browsers into your console, and you can run it against that as well. So I'm gonna just close this down, and I wanna hop in the code, and I wanna just walk through the pieces that are in this branch that make this possible.