Video details

Testing Angular Applications with Cypress | Cecelia Martinez


Cecelia Martinez

In this workshop, learn how to add Cypress to your Angular application and get up to speed with end-to-end testing fast. You will cover installation, writing and debugging failed tests, best practices for test writing, and more intermediate features of Cypress like data management, network stubbing, and leveraging the Cypress Dashboard.


One moment. Sorry about that. There we go. I found it perfect. Yes, there you are. OK, so hopefully everybody can see slides. Yes. Yes. OK, I'm just going to say we're going to say yes. Perfect. OK, excellent. Give me one second just to get. Everything situated on my side here, awesome. Well, thank you so much, everyone, for attending. Joe is going to be the wonderful moderator here today. So if you have any questions or any issues, let me just get all my participant screen pulled up here so I can see if you raise your hand. And then also my chat. All right, zoom all my little windows here. Perfect. OK, so thank you everyone, again for taking the time today to learn about testing angular applications with Cyprus. So here are the repository and link and the slides link. Also, we can post that in the chat as well throughout. You'll be referencing those repeatedly throughout the workshop. So I'd recommend having those open in another tab, the slides as we go along. You can feel free to jump ahead, if you like, during the breaks or anything like that, but I'd recommend not getting too ahead if you can help yourself. So I am Cecilia Martinez, I am a success engineer at Cypress, so I spend the majority of my day talking to Cypress users about their strategy and their test suite, helping them overcome technical issues, helping them decide how and what to test, and also helping them integrate with the Cypress dashboard and with their S.I. I also do a lot of trainings and working on kind of getting people up and running. So that's what I'll be doing today. I'm in Atlanta, Georgia. I also like to do a lot of volunteer work. I'm a woman who code track evangelist for women who code front end. And I'm also on the out in tech leadership team and helped found the Atlanta chapter of Apple Tech. You can find me at Cecillia creates on Twitter and GitHub, also at Cypress, Cecilia for Cypress related. But in most places on the Internet you can find me as Cecilia creates. So I'm going to kind of go over what we're going to be working through today, so like I said, there's going to be kind of break periods every hour. We're going to do a ten minute break and then an optional 10 to 15 minute Q&A. So if you have any specific questions, you can either use the question and answer function naledi here and zoom in, order to submit those questions for that Q&A period. Anything urgent? You can also leverage the chat as well. So the first hour we we're talk about getting started, there's going to be seven different interactive activities like coding activities that we do throughout the workshop, you may have noticed on the repository that there are different branches with solutions for each of those activities. So feel free to leverage those. If you are, encourage you to try and do it yourself first, but feel free to leverage those solution branches if you need help getting started on a certain activity or anything like that, that we'll be working through these periodically throughout the workshop. But so for the first hour, we can talk about getting started. We're going to talk about Cyprus itself, installation folder full of structure and configuration, and we're going to do a couple of easy test activities. And secondly, we talk about testing our application, diving deeper into how you structure tests and all the different types of commands and selectors within Cyprus. And then, like I mentioned earlier, we're going to be doing an assertion, deep dive for the last hour of the workshop, where we talk a lot about different types of assertions that you can make specifically, also about network requests. OK, so as I mentioned before, the workshop set up, I should have done this, been able to get this up and running already. So if everyone could please raise your hand if you have access to the repo and slides. And again, please raise your hand if you have access to the repo and slides. OK, just need a couple more Hendry's so we can make sure that everybody is up and running. So if you could please make sure that you have your hand raised as you have access to the repo and slides and you were able to get them open. And we do have quite a bit of attendees here today, so if you are able to just respond as quickly as you can, whenever we do ask for hand raises, that will allow us to be able to keep moving things forward. OK, so I've got seventy six hands raised. We'd like to see a few more. Let's see if you don't have access to the slides or the repository of Tomas. So now Raj Paria Yuvraaj, you all don't have your hands raised, any issues getting to the slides, the repository. Yeah, OK, so and then also, if you could keep your hand up so worried about, you have access to the repo but not the slides, so are you not able to access the slides if you click on it? Perea. I'm sorry, but see, I guess we can put this like it back in the chat. We see here. Double check, yes. Thank you, Joe. OK, so again, please keep your hand up if you have completed the installation instructions and you can see the Cyprus test Roter. OK, so Aldo Velasco, Amanda Jarrard, Hannu Iris, Jeffrey Manuell, Mark, any if you have any issues, OK. All right. So if you are able to access the slide, it sounds like it may be a issue of having the slides dotcom blocked. So just make sure that you're following along with the with the slides on the screen. We'll be showing them the entire time. OK, thanks, Joe, that's helpful, you may need to use mobile hotspot or Incognito browser, and if anybody has any specific issues with the. With being able to install and then use the Cyprus test, wonder if you can also pop that in the chat. Want to make sure that everybody who is going to be coding today is able to get up and running. Yeah, that's a good idea. Let me see if I can download the slides. Actually, I don't know if we have the email addresses of all the attendees. But I can what I can do as well as after the workshop is make the slides available as a as a PDF file on the repo. In order to get people to be able to access that, let me see if I can do that, actually. Also this site will be posted to YouTube. It's being recorded right now. And when it is posted on YouTube, we can try to get that into the description for the video. Excellent. Thank you very much for that. OK, give me one second. I'm just getting this pulled up here, just waiting for also a few more hands. I do see that not everybody has their hand raised. So if you do have an issue installing or running the Cyprus test runner, please post that in the check as our particular note version we should be using. So on the repository, there's the Cyprus system requirements link. You need to be using node just 10 or 12 and above if you're using NPM to install Cyprus. Yeah, that area is fine. So Anthony posted an error that's that here's a scene in the chat. So that's just because we have not set a basic or written any test yet. So that's that's perfectly normal to have that that output. Anthony. OK, so we have seventy six people with their hand raised. I don't see any other issues in the chat, so I'm going to give it like a last call at this point. So anybody else if you have any installation issues or any issues running in Cyprus, please put that in the chat now. Otherwise, we'll go ahead and move on with the instruction and getting started. OK, so go ahead and everybody can put their hands down. Actually, I think I can maybe do that. OK, quick, thank you very much. OK. All right. So let's go ahead and get started. So we talk about why end to end testing? I don't think I will need to go too much into this with this group. It sounds like we have some pretty avid testers here, but we talk about end to end testing, specifically to increase confidence in your application that's going to function the way that your user expects. The primary reason that I talked to everybody that I talked to that uses Cyprus for and testing it's the primary goal is to reduce the amount of bugs in production specifically. On top of that, you can ensure critical user functionality is maintained. You don't roll out any breaking changes or cause any regression. You can also write tests that mimic your user behavior, not the code based structure. So if unit testing the tests are very tightly coupled to the application structure, however, the application structure doesn't always actually accurately reflect what the user is doing with your application. So there's I wanted to share this blog post. These are three common questions that people who are skeptical, skeptical about Cyprus or end to end testing in general. So I wanted to share this here with Written by Gleib. Just in case you have any questions on any testing or if you're experiencing at your organization kind of any pushback against end to end testing, that may kind of help put you in the right direction. So why Cyprus specifically? So Cyprus has to two products essentially, or two portions of it. There's the free and open source test runner, which is what we're going to be working with today. It runs in a browser alongside your application code. So every time that you're running a test in Cyprus, you're running a test in an actual browser. It has to try and then the query selector library already built in. So if you're familiar with either Moco, which is a test runner or TRI, which is the assertion library, then you already have a head start on using Cyprus. So we try to leverage our existing popular testing library so you can get up and running quickly. So it has built-In weights and retries in the API of Cyprus. So what that means is that it will retry commands up to a certain period of time in order to combat flakiness in your application. So we have that at the command level. And then additionally, with the release of Cyprus 5.0, we have test retries on the test and then the suite level so you can configure it to, say, rerun your test up to three times. And then if it passes one of those, if it passes and it passes and if it fails, it fails, but then it'll flag it as that being something that was tried using the Cyprus dashboard so you can help better identify, identify and then also kind of control the level of tolerance that your organization has for Flake by whether or not you retry tests or how how you implement that workflow. The Cyprus test runner has a lot of features built in for improved debugging. So if you've ever had to debug a failed test and figure out what went wrong, it offers features like time travel, which allows you to step through the dom at each step, each command at each step in the test, and also provides really detailed error. Reporting gives you the stack trace of the error screenshots and videos, and then allows you to open up the test code where the failure occurred. And then we also have because we have great documentation. I learned all about Cyprus from our docs and because we're an open source software project, we have a lot of different community plug ins and a lot of contributions from the community, which I think just makes Cyprus even better. I love the fact that it's open source. OK, so the repository that we're working with today has already has Cyprus installed, so I'm just going to go through really quickly kind of what you would do if you were starting from scratch. But so if you had to install Cyprus from scratch, Cyprus is not a Seelie. It's not something that you install globally. You install it in your project. So in the root of your project directory, you would run NPM, install Cyprus or Jaan as Cyprus in order to add it to your project. Once you've done that, the very first thing that you need to do is open the test runner and when you open the test under, a couple of things will happen. It'll your system will validate or verify that Cyprus could run and then it will open the test runner. And if you it's a brand new project, it's going to put a bunch of example tests in your in your test folder to be able to see what Cyprus can do and get started again. The project that we're working with today has already had Cyprus installed. So you don't need to do these steps and you didn't need to do these steps in order to get started. OK, so taking a look at the folder structure of our project, let's go ahead and actually open up and Vaskov. So this is the Cyprus testing angular project up in Vrsaljko. Hopefully everybody can see. OK, let me know if the font is too small. I can blow it up larger. But as you can see here, we have kind of our Cyprus folder. And we have these are automatically created whenever you open Cyprus for the first time, we integration folder is where our test file is. So we have an empty text file. Additionally, there's a plugins folder in order if you're using any kind of third party plugins fixtures folder, which allows you to save data or files in order to access during your test and then a support folder which essentially allows you to import custom commands. So if you have any, we'll talk about Cypress custom commands a little bit later on today. So that's the folder structure. Again, there's not much to see when we first get started, and that's OK. The Cypress also comes with a configuration folder that is our Cypress Dot JSON. This gets created whenever a project gets created and it has a lot of different types of configurations that are available. All of these links in the slides will click directly to our documentation. So if we take a look at the configuration documentation here, you can see all of the different options that you can pass through here. And so there's quite a few definitely we're only going to worry about a couple today, but the one that we definitely recommend, sorry about that as a best practice in setting is the base Yoro. So the base you out. What that is, is it's the URL for your application. So if you are running locally, it'll be localhost in the port. No, if it's going against a staging environment or a test environment, it'll also that's where it will be. It doesn't necessarily make sense to type out your base. You're you out every single test or every single time you're going to be visiting your application. So we recommend storing it in your configuration in order to just access that at anytime you like. And so with the base, you, Earl, this will actually prefix any time that you use a site visit. So that visit is the command to visit a YORO in this in this case, whenever you have a base, you Yoro it will prefix so you can automatically. So as long as the base Yooralla set, you don't have to type the localhost here, it will just prefix automatically. Additionally, you can set things like viewport within height. This can be really helpful if you're testing in browser and the web for and then also for mobile. And there's a wide variety of different configuration options. But those are the two that I wanted to highlight specifically. OK, that leads us to our first activity, so the first activity is to configure your test suite, so in your Cypress JSON and again, you can kind of use the documentation here to guide you. We're going to go ahead and set a base, YORO, additionally as a recommended best practice. You want to add some scripts to your package. Jason? Whenever you run Cypress locally, as you've noticed before, probably you have to use NPCs, right, or you have to use to download that. So what's more kind of a best practice or what's easier for you is if you add a script that you can just use where you do npm run, scie open and side run and then you have the scripts outlined there instead. So we take about five minutes and set the bases out and your Cyprus thought JSON and you can add sci fi run and sci open scripts to package that JSON. Like I mentioned before, we do have solutions for each of these activities as the, as a branch. So in the repository. They get this pulled up in here. You can see here at the bottom that all the solutions are in. So if you need help getting started, feel free to reference there. Otherwise, just take a few minutes. And as you finish this, go ahead and just raise your hand for me. So, again, the solution here is on the activity one. OK, so the next thing we talk about is test structure, so again, we're using the Moka test a test runner. So this will look familiar to you if you use Moco before you can use either describe or context bloks. I just use describe because that's what I use. The first thing I want to point out, though, is in our test block, this reference type's equals Cyprus. So we're referring here to the Cyprus Intellisense. This allows you to have access to all the documentation and the commands and auto complete when you're typing Cyprus commands. So definitely recommend adding that there's a couple of different ways that you can actually configure it right into your voice code as well. So when we talk about the structure and the syntax of of our test file, we're so within a spec file again, so in our application code, I'm starting our test code. We have our integration folder and we just have a spec JS file and you can write in TypeScript or JavaScript. It's up to you. These tests are all written in JavaScript just to make it easy. So it's more accessible for everybody. But you essentially start with a descried block and you pass through a name for that descried block. The reason that you use to describe block to house everything is that so you can leverage Hooke's. So and you have access here to the before for each the before the after each and the after hook really only recommend using before each typically but essentially but before each will do is any code that is passed through there will run before each block. And again your block refers to your actual individual test. So you may have a described block that has one before each hook that sets up the that logs into your application, for example, in front of every single test. Typically I recommend using the before each hook to manage any kind of common state that, for example, you're visiting like your site visit. You are typically the before h if you're going to be visiting the same page of your application across the entire spec file. That's a great place to put that. If you need to log in your user, if you need to set up your state in any way before each is a great way to do that. Also, if you need to clean up state, do not recommend using after each or an after hook to clean up state. You always want to do it essentially in advance. So this is the syntax and the structure for how you organize the test file itself, where to start simple. And we're going to go ahead and open up the test now and talk about what that looks like and how we can use it while we're writing our tests to help us with that process. So in our voter ID, first thing we want to do is start our application, so let's just vote. You can go into our script so we can see that to start. We can just do npm run, start. And this is going to serve our application. Yes, so one of the things that we don't recommend about using after each is essentially what can happen is if a test not necessarily fails, but if it crashes or something breaks in a test run and you're using and after and after each to clean up any kind of state or to clean up any kind of setting, then that may never run if the test actually fails out. So by using it before each to actually clean up and then set the state, which is what we do in the Cyprus Real World app, you can kind of reduce the variability there in case anything does go wrong during your test run. OK, so now we have our application running, we can go ahead and open up Cyprus, so just do Cyprus open again. I'm working off the starter branch right now, so I don't have all my nifty scripts that you just wrote up. As this is a Cyprus test runner, and if we click on the. Actual tests back, it'll automatically pull these up. This is probably the same thing that happened to you, but it just says no test for fact, we cannot detect any test in the file. Right. Some tests and rerun run. Very helpful message from Cyprus. Thank you. Some things I wanted to point out in the test itself is you can see our runs in the dashboard if you're connected. There's also the settings. So here you can see your configuration and you can also see how it's been overwritten. So on your test run or you'll see that your basic URL will not be. No, it'll be whatever you just set it to and it'll be blue because it's being set in your cypress, that JSON file. So if you ever questioning why something is running a certain way or what's going on, this is how you can see what's been configured and at what level. Additionally, you can also set any proxy configurations, we'll be able to see them here. You actually set them elsewhere. You can choose what file will open code in which we have visual studio code and you can also implement any experiments. So we have component testing, Phil, and then our experimental route to support. You can choose which browser you run in, this will only select whatever browsers are available on your machine. Cyprus does come install with ELECTRON. So I have also have Chrome. If I had Firefox, it would be there as well, or chromium edge. So that's the Cyprus test runner. And again, when you need to run your test, you have to start your application first. And in this case, our application is running at our local host. And that's why we have set our base you out, and that needs to be ready in order for us to run tests against that. So. Let's see, where are we on? Time. OK, pretty good. All right, so our next activity, I'd like you to go ahead and add the Intellisense triple slash directive to your test file and then write to describe Block with a single test that visits the you are out of your application. And remember, we talked about how if you have a base, you are all set, that when you go to visit it'll automatically prefix. So all you have to do is just the slash side visit slash. As long as you have your base, you are all set. And then once you've done that, essentially just write a very simple test that visits you, run the test and see it in action. And remember to start your application server first. So if everyone could put their hands down first before we get started, that would be great. Then we can just now. OK, awesome. And then we'll go ahead and take your pretty quick time, 10 minutes. So we'll see what happens if and if you could raise your hand as you finish. And then if you have any questions, feel free to throw them in the chat room or the Q&A as we work through this. OK, excellent. So we're about 20 minutes above the hour and looks like we have sixty five handrails, so I'm going to go ahead and say, let's go ahead and take a break. Again, there's a solution is for some of the activity to branch. If you have any questions or you don't want to continue working on this, let's go ahead and take a 10 minute break and we're going to follow that up with about some Q&A time so you can either take a break, keep working on the activity if you like, or you can stick around for some Q&A. But we'll go ahead and plan on at the next top of the hour, starting right back up with some more instruction activities. OK, there's a question in the Q and A. That's a really good question, and I kind of want to just Aaron asked about some code here. I'm going to copy and paste this code snippet, actually. Sweet. And. That I wasn't watching the clock when you started the break, are we about oh yeah, about three minutes. I did, yeah. Right, 20 minutes ahead. So this code block, we can kind of see here, this line 12 Hochstetter equals cyborg get. So Cyprus aside, it doesn't actually return anything. It yields an object, but it needs to be changed with Cyprus in order to be able to make assertions off of it. So what you actually would do is just saige get that expect header to equal. So you essentially just do the assertion right off of the offer. That command now in this now on line 12, there's a header variable that doesn't exist. Right. So thank you. So just remove that and just say expects what would you do and what to expect as much to equal and then do it. OK, so it will the experiment will automatically unwrap the H1 into its text content there when you do the two equal. Yeah, exactly. Yeah. So it's like it gets that item of. No, sorry to. Sorry, I'm used to should sometimes. Yes, I have text conduit it, thank you. Oh, OK. That makes a lot more sense. That makes it. Yeah. So. So Cyprus the gets the selectors yield an object, but you have to be it has to be change correctly in order for it to actually run in order. So whatever if you want to assign something to a variable then I will talk a little bit later about how you can assign something to an alias and then you'll you get you get it that way with Cyprus. Cool. Yeah, exactly. So it's got returns, a promise kind of. So that's a good question, Aaron. Yeah, so so here is this operating synchronously or asynchronously? It's operating serially. It's yeah. Olivea, there's a really good section in our documentation about. Oh, gosh, where is it? It's in one of these. Yeah, it's under conditional testing, I think, somewhere in here. Yes, it has to do with element existence and. Seriously? Async. Out to find out, we have a section in our guide that's like all about how Cyprus this is is a thing, but it's also not insurrectionist Cyprus. Here we go. Commands are not asynchronous. OK, so what happens is it's actually like a chain of commands. So you decide, OK, get and then you chain off of those the commands. And so when you make assertions. Commands run seriously, so it actually takes all of the commands and chains them together to run. So if you have any kind of code that's outside of that JavaScript code, then it will run. It has to be wrapped up in Cyprus, order for it to run correctly. Cool. So with with some unit testing asynchronous patterns, sometimes you'll have to either return the promise or like passa done a callback, but it looks like in Cyprus that's not something you have to do. All right. Kind of works as if it were operating synchronously. Yeah. So Cyprus test should really kind of read like English. Right? So it should just it shouldn't it should decide to get that should have text. And that's very that makes a lot of sense when you read it out like that. So the same thing. Reciter visit, we're getting an element and we're clicking on it. And the euro should include that that element that we clicked on again. So you're not you're not returning anything and you're just kind of just clicking through and it's working that way. So this commands run seriously. I'll go ahead and post that in the chat as well. That's a great this this whole guiders is good to read. If you have any questions about the asynchronous synchronous kind of combination of test code and how that works together. All right, awesome. Well, I think we're done with the break, I'm going to go ahead and end the pole here. It seems like space travel one and then there is flying fighter jet and visit Antarctica were the top three. So that some explorers. Yeah, yeah. Like it. All right. Let's go ahead and move over to the Q&A for the benefit of those who are going to be watching this later on YouTube. I think I'll just read the question and then you can answer it. How's that sound? Perfect. OK. Our first question comes from an anonymous attendee. TTD in Cyprus would be awesome to talk about if there's time. Yeah. So PTD with Cyprus, it's a little bit different. So end to end testing, you really do have to have a functional application to be able to test against. Right. So you have to be able to do at least some core functionality when you're getting at the point where you're actually testing from a user perspective. So I would say that it can be helpful to write the user journeys while you're in the process of kind of early prototyping phase, having some user journeys in order to base your application development on and then running those test takes to confirm that the user functionality does work as a core, like a lot of people use Cyprus testing for acceptance testing, for example, and saying, OK, this new feature passes because we can do all of these different functionalities. So that can be helpful in guiding those kind of early prototyping or features. But as far as when you actually go to write the code, it may not be that one to one relationship that you get with unit testing. But great question. OK, our next one comes from another anonymous attendee. Do you have any recommended plug ins for either vote code or so, please, plug ins for Aguer? That's a good question. I don't I don't personally really use any plug ins with voice code. I use like the intel I have that configured from to get the Intellisense code completion. Typically people use cypress plug ins that they're trying to achieve a certain functionality that's not built in. So for example, we have the cucumber preprocessor plug in. If you're using cucumber's syntax to write your test, that will dynamically generate the Cyprus test for you based on the cucumber writing the the actions and then also the feature files, things like that we have in for code coverage, for visual testing, things like that. So if it's if you're trying to do a couple testing, different types of testing that aren't in the box with Cyprus, then that's typically where I see plug ins being used. So but yeah. So otherwise you can get a lot, which is kind of using the Intellisense. So yeah, I notice that voice code is very capable. And so in some ways it eliminates the need for certain plug ins because it does a lot of the stuff for you. It's kind of like with Cyprus, they test retries started as a plug in and once it gets popular enough, if we can just bring it into the application, then we do. So hopefully over time you need less and less plug ins or fewer and fewer. That's cool. All right. Our next one from Kyle says, Can you expand on why Cyprus in comparison to protractor? Yeah. So far, so protractor essentially is just like a wrapper around selenium. So kind of the same issues that you if you one name before or if you're familiar with that, you will similarly have kind of with protractor. Right. So you don't have the kind of built-In you don't have like a GeoEye that you can test with, like you did with the Cyprus test. Right. Or you don't get that like that live feedback during the debugging process. You also running the tests in actual browser. So if that's specific to your user functionality, you don't have those kind of built-In weights and retries that make your test less more reliable unless you also don't get access to like we have the Cyprus dashboard as well. I'm not going too much into that today. That's a kind of like an add on service that you can use, but it gives you additional insight to your test report recordings and things like that. But even if you don't use that, you have the screenshots and the videos. And I know that you do get some kind of assets and things like that that you can leverage with other testing frameworks. But it kind of all just kind of comes packaged together with Cyprus. So I will say that that's a lot of the things that I hear from angular developers. Right? I don't I try not to use. Are they? I just use Cyprus a lot. So I may be a little bit rusty, you know, but that's a lot of things that I hear from people who've migrated to Cyprus. So, yeah, I mean, in your Seelie comes with protractor kind of baked in. So I guess sometimes it might be a question of, well, if this is already here, why do I need to rip that out and use Cyprus? But yes, the nice thing is you don't really have to have anything out. Right. You could just add Cyprus, right? A few tassi if you like it. And then over time, if you find that that's a much better developer experience for you in a test dragon experience, then just start writing the new tests in Cyprus. Right. And it doesn't have to break anything that you already have. Yeah, that's a great point. Simon Narwhal and is awesome for having they have Cyprus built in and it works really well with their dependency graph and everything. So good stuff. So it's awesome. OK, we actually have a few questions that are related to as your dev ops and continuous integration. Do you have any experience with or do you have any example projects or documentation on how you would integrate that into build's? Yeah, totally. So we have an entirely continuous integration guide and that does have a number of different examples depending on the CIA providers. I know specifically as well on the Cypress Realworld app, we have had Circle C configuration, but they're working to also demonstrate that in other systems. But these will have, if you like, the Cyprus example, kitchen sink Grippo. This is where we have sample configuration files in standard. And then also if you want to do it in parallel, I know the question about parallel configuration came up earlier. This is where you can go in and see. So we have as S.I so you can come here and you can see this is a sample config file for running in parallel and you could essentially just copy and paste this, just change whatever is specific to your S.I and run that right there. We also do have docker images that you can leverage that company and solve the Cyprus and also all the dependencies. And then we also have ones that includes specific browsers. So if you wanted to run Chrome Test or specifically in as well, you can use the image that comes included with Chrome. That's really cool. Yeah, definitely recommend checking these out if you have any questions to. We have a number of different webinars as well, like the people who have set it up specifically for their organizations. So in the documentation, again, under the examples, webinars, a lot of these have to do with actually setting up the UI. So I know that. That is a complete code coverage, a lot of these have to do with actually how they set it up in their system specifically. So if you find a certain provider that you want to check out, you can typically find a corresponding webinar config file. Great question, supercool. All right, I think we have time for one more question before we move on and then the rest will cover in our next Q&A break. How would you organize your spec files when you're getting too many? Is there any filename conventions or best practices? Yeah, that's a really good question. So it's isn't it isn't like good. So we had the Cyprus realworld app, which is kind of our like I said before, it's our flagship demonstration app that demonstrates real world best practices with Cyprus. So it's an entire repository that you can just download clone. And then it also has a bunch of Cyprus tests in it. So we have API and UI tests, but you can see that these spec files here, bank accounts, new transactions, notifications, transaction speeds are very closely aligned with the actual application code itself. So if we go into the source file, this is built in react and then the container, you can see that our container names look very similar to our spec files. Now, you don't always want to do that for a lot of modern applications. The views of the application or the containers tend to correspond pretty well to user behavior. So user onboarding, container user settings, container transaction, create a container that that that aligns with user functionality, but a lot sometimes modern application. So if you think about going to like a college website and having to look at all the classes and then sign up for a class, and of course, you may have to visit like three different parts of the application. In that case, you may not have that one to one relationship between a view and between functionality. So in that case, I'd recommend organizing your spec files based on either feature or a part of the application or functionality, or if you have a certain role type like you have an admin user maybe organizing it that way. But I would keep it either either if you can tie it to the application, but only if that actually also corresponds to your user journeys. Yeah. Do it make sense for your project. Yeah, exactly. OK, thank you for your Q and I keep them coming and we'll be monitoring them for the next Q&A break. Back to Celia. Celia, sorry. Oh it's OK. Yeah. You can call me Cecilia. Celia, Cecilia. I've heard all of it's good. See. Excellent. Awesome. OK, so now we're going to dive into our actual application to test and take a look at that and start running some tests for it. So we take a look again back at our repository. This application on your test is one that's just it's a form of angular, real world example application. So essentially really wanted to focus on the test writing. So we have an example application that demonstrates a kind of different crud performance, the CRUD functionalities and things like that. But it's and there is an API that backs up against it. We'll be talking more about the API a little bit later and we dive into network requests. But essentially the functionality of the application is a social blogging site called Conduit. It hits a live API. We can see the live demo here. Looks like a lot of people are making some articles and getting ahead of it, again, ahead of us. That's awesome. But essentially, you're able to post feeds. I'm sorry. Are you able to post articles to a feed? You're able to log in and sign into a feed, and you're also able to kind of leverage some tags and stuff, I guess, is the public API. So we have some goofy tags, but, um. Yeah, so that's that's the application that we're going to be testing against today. Again, pretty straightforward, but it's about getting us to be able to focus on the test. So we talked about the test structure from a syntax perspective. Now I want to talk about what a test structure looks like from kind of like from a behavioral perspective or from a structure perspective. So typical test steps. First things first. You have to visit the page. You have cypresses and actually know to go to your application unless you tell it to. That's where you see a site visit. Then you typically will query for an element, so you get to a page and then you want to do something. Now, the way that Cyprus works is you have to have commands off of an element. So you can't just click you have to click somewhere. Right. And so that's why you say you have to query for an element in order to be able to action on it. Then you typically perform a command and that can be type trigger Double-Click. And then once you perform an action, you will make assertions based on what happens after that action takes place. And last but not least, you will repeat this as needed. So you will run through different steps. Along the way. You'll be making assertions and you can definitely make multiple assertions per command. Definitely recommend doing as many as you need, but not too much. We'll talk a little bit about that as well. And then you'll repeat this process throughout three tests until you get to the point where you've done your entire user story. So we know how to write a test, we kind of need to know the pieces to use to write that test, so we we'll talk about the Cyprus API. So the Cyprus API is the application programming interface. And essentially it's the language that we use to write our Cyprus tests. It breaks down into three major sections, at least in my mind. We have selectors. So we talked about how SEGERT in our example that we just looked at here during the break, Seida will actually you can use that to select an element on the page. We also have and it works just like Clearys Selecter, or if you're familiar with Jay Query, you can also pass through the wild cards and things like that, but you're able to select by either an element type an element. The class ID data attribute any kind of property on the element I mentioned before. You can also do things like wild card patterns that contains we'll just search for the text. So if you say if you were to do it on this page here, if you did not contain Cyprus API basics, the test would pass. And again, that contains is kind of it's like a selector, but it's also. It can also be like a search in itself, because the test will not pass if it cannot find that item. So it's unlike to get where both of the both of these will fail if it can't get the item. But you can use that contains and get on their own if you want to just check for the existence of an element. So they're also self-assertive in their own way. Then we talk about commands. So these have built-In actionability checks, which will dive into a little bit deeper. But essentially it ensures that before it actually clicks that the user could do the same, could perform the same function. So if a user couldn't click on it, Cyprus one click on it. And then finally we have our assertions. So I mentioned earlier that saw that Cyprus has the try assertion library built in. You do get access to all of the types. So you have the bad assertions and the TRD aspersions. I, I you should for everything. That's just what I'm used to. But you can also definitely use expect and then if you really want, so you can also use the TD assertions as well for a cert. So I probably see those these years the least, but you can definitely still use them if you like. No one's stopping you. More power to you. So again, if you have any questions on the assertions, we have them in our documentation as well. But I would recommend checking out the documentation specifically, too, because this is going to give you a lot more robust information about specific use cases for if you have very granular types of assertions that you need to make. And then so we're back into the Cyprus Selecter playground to Cyprus test to demonstrate the Cyprus lecture playground so you can see here is allows you to essentially find out what selectors are if you don't have access to your application code. So let's take a look at that. So we're going to make sure our application is running still is. And go ahead and open up Cyprus. And I'm going to do a quick time check. OK, you're doing good. All right, so we do have a test now, so it should run. All right, so we visited our page, we have a test, so if we want to start writing some some tests here and we want to get some elements to a couple of different ways that you could do this right. You could inspect in the Itzin browser. The nice thing about Cyprus running a browser is you get access to all the dev tools in the browser as well. So whenever you're running in Cyprus and the test run or you can also happen here and see anything that's happening to the console, you can review network requests, which will do a little bit later as well. But, you know, instead of having to kind of dive in here and start taking a look at the geometry, you could just use a selector playground. So Cyprus lecture playground, you can trigger it by clicking and open, select your playground and then you can click on elements or hover over them to see what type of selector Cyprus you recommend. So in this case, you know, if you wanted to get the header, you can click on it. It will prefill here and we can copy it to the clipboard. Go back to our tax code and just paste it there. So now we save our test, Cyprus automatically we'll run it has hot reloading. So whenever you saved your test code or your application code, it will be run the test. And so now we can see that we are able to get the banner and that pass that we don't have any assertion side to it. But it passed. And if it didn't if it wasn't there, then it would have failed. So let's let your playground it will it does have some kind of built-In selectivity. So it will try and select the most specific selector that's available on the element so it can be a good tool to use if you don't necessarily have application to the test code or you're not sure what the best element to select is. And so I would recommend that's a really good tool for it to be able to kind of go in and start writing tests very quickly without having to evaluate the application code too much. All right, so with that, we'll go ahead and close this. Let's go ahead and do our next activity, so it's been about five point, say, five minutes, that should be 10 minutes. They'll spend 10 minutes, well, five to 10 minutes, we'll see how it goes, and we're going to have you go ahead and write a test. It actually is like Saddam element. So if you want a test that visits the application, which you should already have from your last activity, selects the header banner and validates it, contains the text conduit and then select any other element on the page and validates the text or style the element with their assertion. So again, I recommend using the assertions, documentation and then the selector playground, if you like, in order to write a test that just selects and validates the header banner, but then any other type of element in the page. As a bonus, you can also use site that contains to validate subheading or whatever in the text that you'd like on the page. So yeah. So let's go ahead and take a five to 10 minutes in order to to spend some time to write and test. All right, so so about fifty six, OK, so pretty good. Again, if you have any questions on this activity, we are going to do we're going to be doing two more activities in this section. So hopefully you able to to progress. But keep in mind, too, that the solution is on the activity three branch so you can feel free to use that if you have any questions. So Thomas asked this question in the chat. So he gets I don't know, he gets a cookie. So selecter best practices. So we definitely recommend using HTML data attributes or custom data attributes in order to select. This allows you to essentially have the most specific type of selector. And it also makes your test less brittle because if the class changes or somebody changes an ID or if you're using a component library that uses variable class names and you don't know what they're going to be at the time the application renders. Yeah, sorry about that. Let me just go ahead and. So you can use the these are all of the assertions, and then I'm also going to go ahead and share the API here. So these are all of the the commands as well. So this is our API reference that has all of the commands and assertions the only selectors are at InsideOut contains. Sorry about that. Just wanted to make sure that we have the information that we needed there. OK, so like I said, we recommend using a HTML custom data attribute selector. So in this case, you can use data dash site. So we also use data dash test. But essentially what you do is you alter the source code and you say in the file and the source code, you add the attribute data side and that allows you to actually just get that specific element. So you say Ciotat get and you pass through the syntax for a data selector and attribute selector and you say data equals simit, and this allows you to be much more specific with what you're selecting and it reduces some of the variability in your test. So that's a little bit cumbersome to type right with the bracket and the equals. And that does it need quotes or not? I know that I hate typing it out, so I recommend also using a custom command. So we wrote that too much into Cyprus custom commands right now. But I mentioned earlier that in your support file there's a command that starting your support folder, there's a commands that JS file that allows you to write custom commands that you can use in Cyprus. So by adding a custom command that allows you to kind of have that syntax already typed in and you just pass through the selector, it's a lot easier on your typing. It's a lot easier, makes it less repetitive. So we see this in the Cyprus real world map. That's where these commands come from. So in the Cypress Railroad app. And I support Viall, we have this commands and you can see it's just get by selecter or get by selecter, like in this case you're using a wild card so that you can pass through a part of the selector. You don't have to pass through the entire thing. And this case, we wanted to be an exact match and then we can see this in the test files. Let's just go to new transaction so we can see here, get, buy, sell, like new transaction. So all we're doing is passing through a new transaction. And then Cyprus is going to look for any HTML that has an element that has a data attribute that contains that new transaction. And we use that all throughout the test here. So get by. So, like, if I sell, like, get, buy, sell this one, it is going to be exactly Eloqua success. So you don't have to type in that syntax each and every time. All right, so with that in mind, so those are the commands, definitely recommend adding those to your commands that just file and then you can just start using side by side to get by like Urca myself, like, and pass through that selector. So next activity, we're going to take about five minutes here. So update your home, that component that HTML to add a dataset attribute to the header banner and then rewrite your Cyprus test to select using the data attribute instead. So in our test code, we're going to source. We'll go into our app. We're going to go into our home and then home, that component that XHTML and we can see here that we have this one element that has a class of logo. That's how we selected the first time. So you can go ahead and add the data attribute there and then back in your test file, instead of having your side get the kind of the selector from the playground or just the logo font, use the data attribute instead. So I take about five minutes and I'll work through that and I can take some time during that five minutes to answer any questions if anybody has them. And then again, if everyone could lower their hand, sorry, I forget to do this every single time, you can lower your hand and remind me I have a button to push to lower. Oh, OK. Oh, nice. Now, there are a couple of questions around selectors that maybe would be good to address while we're doing this activity. Perfect. Yeah. Great. Let. Find them again. OK, so you mentioned earlier we can use Mocha Chai or jackeroo selectors, or is there anything we should keep in mind when choosing which one to use, or is it just personal preference? Team experience? Gotcha. Yes. So Hypers actually uses all three of those. So my mocha is the test runner. So that's where you see the describe and the blocks that comes from Mocha. The assertions all come from chai. So that's the you should expect. And they assert those all come from from chai now within that which you prefer to use. That depends. So BDO shouldn't expect are what are called the BGT assertions and then assert is the assertion. So it depends on your approach to testing. I primarily see the BD assertions because this is driven by user behavior and user stories, so that typically tends to more align with it than the TD assertions. But again, you can use any of them and then the jury selectors that is built into the side. And so you it essentially just gives you a lot of flexibility because it allows you to pass through like those wild cards and very specific types of selectors if you if you wanted to. But yeah. So the tools are all in there, built in. And then as far as which versions of those that you use, whether it's describer context or whether it's the BTR, TVT, that's going to depend on the strategy approach to your team. Cool, so it's just ultra flexible. Yeah, OK, another one, what are your best practices? We've been using data to see why I think you may have already addressed that. This was posted before that. Yeah, exactly. So data Daschle. I absolutely recommend doing that or take it as. That's just cool. All right. Let's see if there's at least one other one here. Another question I always recommend the use of do it Adarsh Kuai tags. Instead of having our developers select items from the DOM using IEDs or classes, maybe some classes can change over time and be refactored. It is a known practice on my teams that once the data dash Q8 attribute is said, should not be changed without corresponding changes to an automation test. How do I selected Dom Element if I add the following to HTML and he has the H1 class logo dash font and then data dash to a logo conduit. Yeah, that's a great question. So definitely agree with that approach. I think that that's a really good, great best practice. I think that it promotes a good relationship too, between the developer and the test writer, the key in the development team, if they're separate separations of concern there. So the difference is in me, go back to that custom and actually be the best place to explain it. So if you take a look at those custom commands and how we're kind of passing by, the data dash site equals the selector. So you could just do data dash Kuai equals logo at this point. Right? So it would. So the data. So this part here is kind of arbitrary. You can do data, dash whatever you like. It can be data dash side data test data, dash kuai. As long as it matches up with whatever you're passing through to that selector, then that's what needs to be consistent. So yeah. So you would just essentially instead of doing data dash side here or maybe even better actually data, is it a data dash site here. It would just be data Kuai, data Kuai and as long as they match up you'll be good to go. Pretty awesome. Another question does do you still get Intellisense when you use custom commands? Oh, that's a good question. I know that if you are using TypeScript, it will still show you the types and everything for custom commands, which is helpful to know what you need to like, what type of parameters is expecting. But I don't know how robust it would be beyond that. That's a really good question. I'd have to I'd have to find out that one for you and and get back on that. Yeah. It looks like there's some stuff in there. Yeah, OK, yep, so it looks like you can add commands. Yeah. So I know, I know that one typescript like in Real World app, we have all the types written out for the custom commands and they do show like when you hover over them and everything. But I don't know if it if it's going to be as necessarily as robust as what you might get with the Intellisense. So. Right. And my experience with deLites files is you get as much out of it as you put into it. So if you get really awesome, then you'll get a really awesome experience out of it. Yeah. So the type basically. Yeah. I mean it tells you what you what, what you can and can't do. I guess that that's pretty much the point of the typescript. So but yeah. So that that's it does port everything over though. And I do know that so far so good question. OK, so it looks like we have if everybody could just raise their hands as long as they are all set to move forward with this activity. Think. Go back to the activity and again, the solution is on activity for Branch as well. It's going to get a couple more hands before we move forward. All right. Looking good. So the rest of the time that we're going to use we're going to do some activities and structure and kind of instruction around Cyprus commands and how they work. So there's this really great guy, again, in our documentation about interacting with elements. And this is essentially what we're working through in the slides right now. So the common commands that you'll use are click, type, clear, check, select and trigger. There's a few more like double click, right. Click, things like that. But primarily I use these the majority of the time. Something to keep in mind, I did mention this earlier, is that commands must be changed off of a command that yields Assai elements. So you can think of it as it has to be changed off of a selector like site or a site that contains. So we talked earlier a little bit with one of the questions came up about how Cyprus is kind of like a promise. It yields the object that is returned by the selector. And I can I shouldn't say the word returned. It yields the object that the selector finds and then the command must be changed off of that selector and that command will action on the element that was selected. So in a test that was this would look like essentially. We see both sides get the element and then a click on it, right, and that's going to click on the actual button itself. So as a best practice, we. Just sorry, one second. It's making sure something is set up here. So as a best practice, we recommend alternating commands and assertions in order to make commands read triable. So the way that that works is I mentioned earlier that Cyprus has some built-In actionability checks. Just make sure that. OK, so Cyprus has built in actionability checks, and essentially what that means is that, like I said before, it won't do something unless the user can do it, too. So what what that means, what it does is going back here into our actionability checks, Cyprus will check these items. It'll it'll scroll the element into view. It will make sure it's not hidden and make sure it's not disabled, detached, not only animating covered or that it's and it's also at a certain coordinate. So. If you try and click on a button that's behind the sticky header, it's not going to fire. If you try and type in an input that's disabled, it's not going to type. So, again, Cyprus is going to act like your user and it's going to only do things that are actually actionable. So the thing about Cyprus commands is that they're also re triable, so, as I mentioned before, there is a kind of keep going until a certain time out period. So Cyprus has a default timeout period of. Four seconds, I'm pretty sure it's forced it did a three or four seconds and what will happen is and we can see this in the test rudder as it's as the command is running down. So when we run our test here on our site visit. We can see that the command is running down, was running down, and it spins until it resolves, that's because there's a default time out period. So what will happen is Gap will keep trying to get this new to do until it finds it. And if it doesn't, it'll it'll fail, but it'll keep queering over and over and over again during that time period. So what we recommend doing so, as you probably may have seen, is like your application or a test run can be a lot faster than a user. So if you think about what a user would do is a user would get a new to do a stick to do app and they would type it and they would hit enter, they then they would wait until that item appears on the screen before continuing. Right. They're not going to try and delete the item if it doesn't exist yet. So Cyprus also kind of needs to, you know, to do that as well. So in this case, by saying that get should have a length of one by chaining this assertion directly off the site, I get what will happen is if this should fail. So if we say our to do list should have a length of one and it doesn't, it'll go back and get and do the get again. So it'll actually retry the entire chain over again until it passes and each command. So if you didn't have this connected, you just said Ciotat get and you went directly to the should. EDIT and it passes and fails, that's fine or I'm sorry, let's say you had a cigarette and then you want it should have length of one and then you wanted to just delete it, delete the item. If you tried to do that without checking that the item is there first, it's going to fail because it's not able to find that item by saying Cytotec should have length of one before continuing. It's going to make sure that this actually is retried until it passes before continuing. So by stacking these and training these the right way, you make the entire chain retrievable and it reduces the variability in flake in your test. So, again, we have our Sarducci and we're typing, so what you could have would you could you could do to make this even better if, say, Seida get new to do that should not have class disabled or should not be disabled before you type, then it will only type in the in the net element once we know for sure that it's not disabled. So that's a great trick to add for something like a button that only becomes enabled once you've typed in the username and password, for example. That would that could be a flaky test if you said type username type, password type click sign in. But there's validation and if you go to click sign and it's still disabled because our application hasn't updated yet, then that test would fail when really there's not a problem. So you would want to do a site that gets a bit button that should not be disabled, then don't click and will make sure the entire thing passes. So let's practice their four commands in alternating commands and assertions to make them triable and then also make sure that you keep in mind the actionability Cyprus will not action an element unless unless it has to. I'm sorry if it can't now if you have to. You can force things. So, again, we don't recommend this unless there's something in your application that one thing that comes up a lot is a sticky header. So we throw the element into view and then sometimes, like a header will pop over because of the action. Then in that case, sometimes you have to just do a force through which in this case will will bypass the actionable checks and it'll just force it to go ahead and complete. OK, so let's see where we are from time. OK? All right, so activity five, we're going to go ahead and write a test that actually tests them at functionality, so we already are visiting our application. If we look at the application, we're going to go ahead and. Certainly we find it here, the live demo. So we already logging in, we're going to navigate to the site and page so you can see a sign in here, username, password, and then we have a button. And again, this is an example of a button that you can click until one password is filled in. So we're going to have you visit the application, visit the sign in page, use these credentials. They're sensitive. And then once you're logged in. You're going to publish a new article, so once you're signed in, you'll be able to see a page in order to publish a new article, you can use any kind of just title description, content tags you like. Don't worry about assertions. You just kind of use selectors and commands to write the test that goes through that functions and handles this functionality. And so we are coming at towards that for the last 20 minutes or so of the hour. So we're going to be working on this all the way through until the break. Joe, if you could lower the hands for the activity done. Awesome. So and then as you complete the activity, feel free to raise your hand. If you finish early, feel free to go ahead and take your break after this. We're just going to be doing the break and then the Q&A. Do you want to hold off on Q&A for the questions related to this activity, or would you like me to fill out those questions now? Yeah, you can go and throw those at me. We have a quite a bit, so I want to make sure we have time to get through them. Excellent. OK, a couple that I've seen come through that are related to this particular topic. If an alert fails, will it try again until it passes? And is there a limit to the retries? Yeah, so if an assertion fails, it will essentially do the default, the default command, the default time out, so the assertion fails, it'll go back and it'll get the like. It'll kind of redo whatever command it's chained to in order to make that retrievable. And up until that default time out period. So what you can do is if you have concerns about variability in the application or if you have to wait for something to appear, you have a few different options. You can either increase the default time out for that single command or you can also increase the default time out like across your entire test or across different scopes of the application of the test code. However, what I'd recommend doing in that case, if there is you can also leverage, is test retries. So if you have assertions that pass sometimes and fail other times because of what we call flake, talk about Flake a lot. And there's a lot of different types of like at most common that I see is instability related to things not appearing on the DOM the way that we expect them to at that time in the test. The other tends to be either enviromental or API instability. So we're waiting for a resource to load and it never comes back and then everything fails. So in that second case, test retries can be really helpful because it's not that it could be just something specific to the test environment or something like that, or those those failures are going to be very, very intermittent. But then that flake is going to be intermittent. But you don't necessarily want it to to break your build. Right. Or to break your deployment. So test retries can be helpful in that area because it allows you to say, OK, this test was flaky and we had to retry it, but we can quarantine that for next time and find out what's going on. Or we can better decide. Is this worth stopping the deployment for? Is it a real failure or is it like a test failure, test code failure or flight so that when it comes to instability and assertions related to that, you're better off kind of doing like either waiting for something to happen on the back end. So saying wait for this network request to finish first or wait for this element to appear on the page first before proceeding with the test. So those are some depending on the type of flight that you're experiencing, you can you can kind of leverage the time outs or the test retries. But ultimately, those tend to be like eliminating issues with your application. Right. Like if if something is in the job and then it gets detached from the job or it renders 10 times between clicking the button, or if a state is taking too long to update and the button never updates, then that could be something like a performance issue or variability issue or like a hook issue with your application code. So don't always try to engineer around those too much. If if you if you can't if you can help it make sense. One other question. So the command find changed to get does that make that find relative to the element. Yes. So fine get will search within kind of like within that scope. So if you go to find. In our documentation, so it gets the descendant elements of a specific selecter, so it matches exactly how fine works in J query. So in this case, it'll yield footer within the class of Article three question. Another one that's somewhat related, can Cyprus alert a search on accessibility related information, for example, what a visual user would not see, but a screen reader would? Yeah, that's a great question. Let me see. I have a good blog post for that on. One of our Cyprus ambassadors wrote a really great blog post about testing accessibility with Cyprus, Marie Drake, and so I'm just pulling that up. Because that is kind of my source of truth with Cyprus and accessibility, so I can pop this in the chat, too. But she did it 30 days of accessibility testing. And this is a really great break down of all the things that she did on it with it. But a lot of it was using Cyprus as well and talking about how you can really what it has to do with is accessing the state of your application. Right. And accessing some of the elements on those on the HTML so you can have any of the like are your role attributes, for example, and making sure that those are appearing properly. You can also make assertions on any kind of like status variables or state of your application. So if you're able to tap into the redacts view and I guess everyone here, singular and DataStore, then you can make assertions on that data store and make sure that you're setting things up properly there as well. So let me go ahead and pop this in the chat, this blog post. That would be a good resource there and then make sure that we are raising your hand as we complete the activity as well. But yeah, great question. Accessibility testing is something that I think as we get increasingly asked about more and more, so it's definitely becoming more prevalent and more important. Hopefully we didn't have too many that finished, forgot to raise their hand and went on break. Oh yeah. OK, I assume that they just finished early if they went on break already. Cyprus tests how they're written, they should be written pretty English, like a society that should collect all this stuff and you should be able to read it specifically. There is also, like I mentioned, a preprocessor that you can write your future files and you can have your cases and you could have your step actions. And then Cyprus will take that and it'll on its own, essentially take those in defining and and come up with the Cyprus versions of those tests so you can definitely utilize cucumber syntax and feature files if you want to. With Cyprus, you just have to use a third party plug in to make that work. But the readability of Cyprus tests varies a lot from project to project. We have a lot of I would definitely recommend using as many best practices with using custom commands, whatever you can to abstract so that to make it a little bit more readable. So, for example, how we have in the real world that all of these commands here where we say get by, we have a kind of database, but we have a couple of custom commands in here that make it a little bit easier to try to get down to the actual tests here. So we have like a switch user command. Right. And we have a. A couple of different things that we have so many selectors should be visible, so you can kind of use those and leverage those in order to make them more readable. But it's going to depend a lot, basically like what you're used to. Right. So as I process could be readable to somebody who like this, really knows JavaScript a lot and is very comfortable with that. But then if they never touch cucumber, that cucumber test is not going to be as readable to them because they're not familiar with that Gurkin syntax. So I would say it just it depends a lot. There's a lot of variability there. OK, thank you. So we're four o'clock now. We have 23 more open questions. Are you going to have some time at the end to do that? Yeah, exactly. Yeah. And we can kind of a similar thing where when we start off the last activity just kind of start taking questions from there to our own security time. So. OK, so that's everyone. Yeah. Welcome back. Let's go ahead and dive into the last hour of our workshop. So we're going to be talking a lot about assertions during this entire time. This last part of the workshop. So I'm going to talk about types of assertions. And specifically when I talk about types of assertions, I mean the type of things that we assert on so. There's a in my mind, there's three different kinds of categories of things that you make assertions on when you're writing a test. The first is that page elements render as expected. That is a broad category, but it could be things like that content of the application, you know, as the product name showing is the description text appearing, the style. You can make assertions if you don't if you're not using visual testing and you want to make assertions on HTML attributes or classes or know classes in order to make sure things or appear properly or colors, you can also make assertions on visibility or actionability. So we talk about, you know, is an element being covered, like, can I click on it? Does it work? Then the next thing we talk about is the user actions result in expected behavior. So if a user does something on the page, then something the DOM should render a certain way or something else should happen. Right. And so it could be that that links go to correct URLs. That event listeners are firing correctly. If there's a model that should pop up, that model appears. So the functionality of the application or other things that we can kind of make assertions on. And then the last but definitely not least in kind of something that I think people get a lot of value out of, especially with the end to end testing, is that making assertions that expected side effects occur? So these are things like making sure that HTP requests go out with the proper headers of the proper body, depending on what the ID that you're passing through is. For example, making sure that if you are doing a full end to end test and you're actually hitting a database you can use, I don't know the exact I'm sorry I set up task or set up in order to be able to access node or the shell to make up your database. Or you can use hidden an API to make sure that your database actually updated. So this is something that these are the different types of assertions that you can make and that you really should be making along the way as you go through your Cyprus test. So this link here is kind of just goes to our best practice is to add multiple assertions and don't worry about it. So if you're used to writing unit tests, the pattern is kind of get the element making assertion, get the element, make an assertion and really just kind of doing it very granularly. But you can really have these kind of long tests where you say the item, we should type it and then we can say that it has all these different assertions so we can insert on the DOM, we can insert on the HGP request, and we can start on a lot of different things, all within one test and have a lot of assertions in there. So let's go ahead and add some assertions, we're going to go into this a little bit more before we actually start the activity. So the as I mentioned before, that there's two different types of assertions. There's the beauty and there's this. But what I'd like to kind of focus on again is these types of assertions that we're talking about. So when you do this next activity, when you're adding the assertions, you're going to want to do some things to validate the job specifically. So when you look at our application and again, the last time that we did something, when you click on Saidon, that's that's an action, right? You took an application action. You clicked on something and something should have happened. So what are some of the things that we would we would we would assert on this page? So we think of the first category. We have our assertions related to the job. So we may want to say, OK, sign it appears. Right. That would be a big one if we're on the same page. But additionally, you may also want to assert that the URL is log-in, right. That's something else that you want to start on. So this could especially be helpful if you have a spy that has routing handled internally on the front end. Right. And the euro should change, but maybe you're not necessarily actually visiting a new you are out on the site. Right. But you want that to appear correctly in the browser. So that's another type of assertion that you can make. Additionally, you could also make some assertions that if there's anything that was like any HTML request that went out. So, again, when we inspect. Our network requests, we can see we run our application, that we can see that it's. Down, awesome. So, yeah, anyway, we'll take a look at that a little bit later, figure out what's going on with there. So I want you to when you're doing this activity, to think about the different types of assertions. I would say, don't worry about big request that I'm going to figure out what's going on with this API. I wonder if that's related to the issues that we having earlier with the API being down. But I'll go ahead and just add some add some assertions, the application, and then we'll be able to. To go along with that and in reference, and that's winner take about 10 minutes, additionally, I would say it's the bonus. How can you validate the value of the input fields? So, again, if we think about the value and how you can make assertions on property of an element, that you can kind of make an assertion there. So we'll take about 10 minutes to work on this one here. And I will be definitely available for questions as you run through this. But be for the science. Sorry, I just put everyone's hand down, so be sure to raise it when you're done. Good job. Yes. Oh, yes. Perfect. That's a really good question. So the password for the app, lets go ahead and go to the last activity and I'll go ahead and copy and paste these in the chat. Oh thanks Romero. That's awesome. All right. OK, so go ahead and add some assertions, and while everyone's working on this, like I said, you can raise your hand as you complete and then we can go ahead and answer some more questions. Joe, if that's OK. All right, next one in incourt unit testing utilities, there's one stable that allows you to wait for the change detection, to finish running an asynchronous tasks to finish before proceeding with the rest of your test. And protractor also has a similar feature. So this person's wondering, does Cyprus have anything similar that hooks into to endorse change detection cycle, to just wait for everything to resolve? Yeah. So there's not there's no open there's an open issue for that too. So there's not currently a thing to say. Everything has stopped. Right. But what we recommend is kind of making an assertion on whatever the last thing is that you're expecting to happen so that there's an open issue for that. And I can probably have a little more into it, but I'll go ahead for time's sake. I just say not currently. And we do have an open issue. So if you'd like to comment on that, feel free to go. OK, yeah. So I want to go ahead and dive now. Let's see if everyone could just raise their hands. If you finished doing those last hand check, I feel like we're probably have more than if we can get above 50, then I'll feel better. Awesome. Oh, we're just we lost one. All right. So is anybody has any questions? Again, activity six is the branch with the solution on it. Hopefully a potential solution once you can do this a lot of different ways. So. All right, OK, I say we got to fifty. I saw it happen. So we'll go ahead and move on. All right. So let's talk about network reclass. I'm very excited that we were able to stay on on ontime because I wanted to make sure that we got to this. I know we've covered quite a bit, especially for people who are brand new to Cyprus. So I appreciate all the great questions and interaction as we've gone along. So network requests and APIs. So first things first. I need to make sure that this application is still working. It wasn't working a second ago, so let's go ahead and open that up locally. Just to confirm before we get too far with this. Sorry about the confusion. OK, so. Oh, right, so there you go. Our application and then, yeah, so. It looks like we may be OK. Yeah, so it's working in the browser. That's good, so let's go ahead and go from there. All right. So network request. This is one of my favorite things about Cyprus. I like the way that you can. Yeah. It's essentially Cyprus has built in functionality that allows you to tap into the network requests that are happening during your test run. So right now, we have Seida route, which is our default essentially functionality. We do have a route to which is a under experimental support right now. The difference is that route allows you to have access to our object's route to allows you to have access to everything at the network level. And it also gives you a lot more control over how you set the routes and how you step out the responses. That's still an external support, like I said. So I'm going to be working with the regular side at route today. But I wanted to make sure they point that out because in the months to come, you may end up using Route two, which is probably going to get renamed. But so if you have anything here that doesn't fit your use case, for example, like rescuable or WebSocket or waiting for static resources, those are all things that get resolved with Route two. So just let it go for you. Take a look at that if that works better for your specific application. But what the Cyprus what kind of Cyprus route or the Cyprus server functionality does is whatever you run your Cicotte server command, you're saying, hey, Cyprus, like, I want you to keep an eye on the network requests and I'm going to tell you some things that I want you to keep an eye on specifically. So it allows us to spy and Stubbe network requests for a variety of different functions. The complex case that we're going to be looking at today is waiting for network requests. So in this case, we say, hey, Cyprus, there's this there's a network request that's going to go out. I really want you to wait for it. And then once it runs, I'm going to want to validate something about it so you can use this site instead of network requests to make assertions on network requests. That's when you would essentially spy and wait for a network request. But you can also stub Responsys out. So you could do this, for example, if you wanted to set up testate. So if you wanted to return a specific something from a response instead of actually hitting that API, if you wanted to bypass any third party integrations, you would use Stubing in order to essentially mimic that part of the of of the application running and tell tell your test code. Yes, this happened. This is the response you got. It's exactly what you need to keep running your tests. So this allows you to have a lot more control over what's happening in your test and set things up the way that you want to set them up and then also make those assertions that you that you need to do to make sure that and not just the UI that's running properly and happening, but the interaction between your UI and then whatever API that you're hitting against or whatever a network request that your application is making. So this is how we set it up in our test code. We have to essentially start with a side server command. This is just a command that runs by itself and it just enables response. STUBING So this is how you turn on the network request functionality within Cyprus. Typically we see this at the top of a test block, or if you are going to be doing this for every single test, then we'll see it in the before each hook. But you need to essentially do this before you can leverage it in your test code. So site observer enables response Stubing, and then we use side route to define the routes that we want to watch for and then whether or not we're going to step in or not. So we use the same command for spying and for Stubing we pass through. The method is optional. It's get by default. Really, the thing that you need primarily is the URL and this is going to be the the you are the endpoint, the route that you want to watch or you want to stub, and then optionally you can pass through a response parameter that essentially says make the response to this. So if we take a look at our documentation in the network request guide and we take a look at the routing example, this is exactly what we're looking at. So we can see here that we if you take a look at this in our test code, we have aliasing these routes as well. About aliasing earlier. Let's take a look and see what that looks like now. So, again, you would decide that route, method and response are optional. So you're passing through a URL and then you only need to pass a method if it's not get. So if you're watching for a post request or a request and you only need to pass through response if you actually want to stub the response to that request. So in our situation, it's going to look like this, so we have our side up server and then we're saying Ciotat route and we're passing through that just to make it clear. But you don't have to do that necessarily. And we're saying users. And so we're saying Cyprus, Cyprus server, we've set you up set up server. Now, this route, whenever we do a get request to users, we want to save that as a variable called get users. And you can name that whatever you like. But essentially you're using this as that as command to save and name this this request. So we're saving the network request as variable. Then we can access that request once it occurs with sideway so side that weight is a command that you pass through a variable to and you say, Cyprus, I want you to wait until this request completes and then I'm going to do something with it, or then you can progress with the test. So this is something that you can leverage. For example, if you are, you know, one of the requests is going out and it's going and the end is coming back with the assets that you need to load the page. And maybe you have a really big file that you're waiting on and you know that it's going to take a while before anything happens. And the time you may want to wait until that request resolves before you even proceed with the test. Right. So if you if you know that that API call is going to take 10 seconds instead of saying, hey, Cyprus test, wait 10 seconds, say, hey, Cyprus test, wait for this, this network request to resolve. And that's a lot less brittle. It's a lot more stable. It gives you that granular control. So how do we then assert on that request? That's what we want to get to. We want to get to the point where we are able to make assertions on these requests. So what we do is this is the example here. So we set up the server and we say, again, we have our route. Whenever we make a request to our users, they are saying that as get users so we can assert on a couple of different properties on the request, the URL method, status code and then the headers in body for the request and the response. You can use these a couple of different ways. You can say wait and then to the in that case you're waiting for and then you're grabbing that network request and you're saying its method should equal got something like that. Or you can say you can attach the should directly onto it and say like should have property status to everyone. So again, the way that you organize your assertions is very that's up to the testing philosophy at your organization. But you can kind of think of it as you have access to all of these different properties and that request and then you can assert on those however you like. So if you need to know for sure that the ID that you just entered in when you logged in got sent through properly, you can make an assertion on the request body. Right. So this allows us to have a lot more control over essentially just us to tap into all the network activity that's happening when we run our test and then say this one. This one, this one. I want to watch this one. And this one I want to watch and I want to stop. And you can actually just have that outlined at the top of your test and then throughout your test code say, OK, this is the one that I wanted to watch. I need it now. This is the one that I wanted to watch. And Stubbe, I need it now. And then you're able to proceed and either make assertions or use that data to have more control over what commands you run next. So I went through that pretty quickly. We don't have a ton of time, but we are going to do an activity based on this. So we're going to be asserting on network request, so we're going to set up a CIOTAT server and then we're going to do a site at route to watch the post requests for our login and point. So the API for the application does is a live application or is the API so you can actually pass through the entire URL here. When you make your you set up your side of that route so you would decide what route it's going to be a post request, right. And then here, instead of just being users, you're going to do the entire URL. And what that will do is if you do an entire you are out with a GPS that's going to override the basic arrow. So you don't it's so instead of just doing a slash, like if you had your own API that you were running locally because we're hitting an external API, we're going to do it this way. So you'll pass the entire you out and then say you want to aliased the endpoint as login. And again, you aliased using this as command. Sounds like the command and then we're going to have you out of weight in your test for the network request, so again, that's going to look like this, this side Outweight. And then you're going to make an assertion, I have your but that status is two hundred, but feel free to do something else if you like. And again, just say when you're running your tests in Cyprus, you do have access to the network requests. So if you have your test run or open while you're writing the test, which is which is really helpful because you get that instant feedback and they automatically rerun is you save, then you're also able to look at the network requests that are happening. So if we come in here. And the reason that we can kind of know what that's supposed to be right is when we go to Sinon. We can see that those apps are going out. Sorry, always Logan's here. So both of the apps back up. Nice just in time. Excellent. All right. So let's go ahead and take some time and work on through that activity. This is the last activity. So sad time is going by so quickly. So please make sure that if you have any questions. Yes. Thank you. The first. Thank you, Steve. Steven for that in there. I'll go ahead and leave this up on the screen as much as I can, but we'll go ahead and take some questions as well. All right, next question, what are best practices for testing and comparing formatted dates? Oh, wow, that's a good question. Testing and comparing formatted dates. I mean, it's a couple of things that you could do as it just if it's just depending on how it's been formatted. I mean, you could do a couple, you could do a test on that. You could equal certain things. I know that you can also test on like if the date is created, like if it's an object, like a date object, then you may be able to do certain assertions and then object to. For example, I don't have any specific test cases, but there might be something in our examples testing dates in our example repo. All right, this next one is probably the question you came to this workshop for, how can you get more involved in the Cyprus community? What is an ambassador? Oh, yeah, awesome. That's a really, really great question. So a Cyprus ambassador is we pull this up, is that essentially there are community, right? There are people who use Cyprus. They love Cyprus. They advocate for Cyprus. So we have our Cyprus Ambassadors page, which is Cyprus ambassadors. I can go ahead and pop that in the chat as well. Yeah. So if you are interested in becoming an ambassador, so like I mentioned, Marie, she wrote a blog post that says about accessibility. We have information here, the ambassador program overview, and you can also learn more and apply. But you it's pretty cool. You get a free Cyprus dashboard account. You get access to the ambassador back with us here at Cyprus and things like that. So basically, our goal is to provide you kind of information or supplies and resources and support if you're doing meet ups and things like that or talk. So we really just want to kind of support and highlight what people are doing within the Cyprus community. It's it's really great being able to be involved with a project or with a project that is open source and has just a lot of contributions from the community and people are excited about. So absolutely. I mean, you get some swag, too, so, you know, it's always good. All right. Next one. This person is curious when they can step in before versus before each and kind of just Stubing in general. Yeah. So that's really a question. I would say you would step in a hook before or before each, depending on whether you were using it before he each. If you know that you want to run that like every single test. So if you know for every single test that you're going to want to watch a certain end point, then yes. Like define that in the before each hook. And that's the same thing is copy and pasting that at the top of each of your blocks if you are going to do it and a before hook, I, I wouldn't, I wouldn't necessarily recommend doing that unless there's something that you need to do. For example, if you want to just like validate the API before you start your test and say hey like make a request, this API and its response should be two hundred. That's something that and if not then then fail and don't proceed. Right. That's something that you could do in a before hook for example. So yeah. Good question there. OK, next, how can I go to page. How come I can go to a page using site visit slash login but not site visit editor. It just depends on if that, if that page exists. So I'm not sure if there is like a slash editor or if that's something that you need to be logged into. So that might be what it is if you go to the editor and it may just be redirect, redirected you to the login, but you should be able to visit any page that exists on that base. Yoro. OK, suppose we have to write lots of tests of our home page. How do you suggest that we divide them? What about putting side up visits and a B for each without repeating it? Yeah, exactly, so Silat visited the before each excellent best practice, how they recommend doing that, there's anything that you can abstract out that way, especially if maybe you can make it a custom command right where you log in and and you go to the home page and that's in your before each hook. So you us a best practice. OK, I'm sorry, there's a couple of questions we already answered, so I'm just clearing them out. Thank you. There's a lot of questions. Yes, this is this has been a really great group here. OK, next one. How do we use Cyprus to test HTML with canvas, typically a third party component, which is the best practice to do that? Yeah. So there is a blog post on TESTIN HTML Canvas Cyprus. I just just came up the other day, so there it depends. There's a couple of different things that you can do. Right. It's its own kind of element. So there is a blog post here that I have had people refer to and say that they've had success with it, so. Going to go ahead and pop that in the chat as well. Oh, sorry, twice blog, so nice that named it twice. Yes, I want to make sure everybody got it. All right, awesome. The next one posted some code. So if you want to take a look at the question there, this doesn't work for me. So I don't get and then it looks like it's kind of a CSI selecter, maybe generated from the tools or something like that that has a whole bunch of direct child. I see. I feel like a but if you do the site that contains new article Dot Click, it works. And so this could be an actionability issue. So sometimes we see sometimes where when you go to click on something and select your playground, you may have experiences before. A lot of times with modern UI libraries, they'll have multiple elements kind of stacked on each other and only one of them actually fires that click. Right. So maybe it may have like a div and then a span and then the actual button and then like the text on top of the button. And it's so it may be that when you're using the selector playground or when you're going to select the element, you're selecting part of the element that isn't actually where that click is fired off of. So we've seen this a lot of times, the component libraries. So what you kind of need to do is figure out which element is the one that actually will generate that click. And so, yeah, and Simon says here it doesn't play too well with the angular CSS encapsulation. So whenever you have things that are kind of. Yeah. That extra level of variability, that's why again, we recommend using data attributes because that bypasses all of that. It doesn't matter what the content library is doing, all that, things like that. Right. So you're able to add that element, the data side attribute. Right. On the element that, you know, is tied to that click event and you know, it's going to fire no matter what. So, yeah, you know, when you're doing user and testing, basically, I mean, the user's not going to be like, oh, OK, I'm going to look in the container for the second child, like your test. I think you can correct me if I'm wrong. They should read more like what the user would be experiencing as they go through your application. Yeah, exactly. So this electric playground is nice and it's definitely a good way to kind of get used to understanding how that process works and kind of finding things if you don't have access to the code base. But as a best practice, absolutely. Go with that data. Actually, you get exactly the element that you need. Yeah, OK, great question. Next question. What's the way of handling multiple browser tabs in Cyprus? Most of the time this use case is needed when the user clicks an anchor that opens in a new tab than the users want to switch to that tab to verify that that content loaded. Yeah, exactly. Yeah. So as I mentioned earlier, multiple browsers are browser tabs is one of the kind of limitations that we do have recipes. Here you go. Tab handling and links. So this is how you can kind of handle tabs that open in a new window and bypass that kind of work around that. So that's leered. Sorry about that. There we go. So there's an example of some kind of best practices around that. All right, cool. Next one, is there a way to test the look of the apple testing Cyprus like the button is in the right place? Yeah, so the look at the app again, I recommend using a visual testing, some kind of plug in our capital is our pursey or one of the snapshot design for for that level of granularity, like if the exact location otherwise you're going to you can you can assert on its coordinates if you want to. But I don't know if I would recommend anybody put themselves through that in a certain on the coordinates of each and every element of the page. So. Right. And I mean, that meets your tests and kind of going back to why some people absolutely hate N10 testing to begin with is maybe because you've made your test too brittle, that they're not going to survive any code changes. Absolutely. Absolutely. Yeah. Great. Great point there. OK, the next one, I think this one was already answered, but it says to Cyprus, have the ability to mock up requests. Yeah, absolutely. So you would just pass in that response parameter on the side at route and then you'll be able to kind of mock step whatever the response would be for that request. OK? And then also there's another one that says, what about using a mock server instead of fixed your data? Yep. So same thing. Essentially, that's what the route does. You don't have to, like, access a fixture. You can just mock that server out with the response so it is fixed. Your data can be can be easier. So, OK, next one, is it possible to query some endpoint for data and before all and reuse that data in multiple blocks, maybe using aliases. Yeah. So we do this in the. Yeah, absolutely. So exactly. So you would essentially say you can make them do the weight and then you would alias it and then you can access those. So you would want to do it before each hook and then you can access those aliases throughout the test in order to do whatever you want with it. Right. Make assertions, things like that. OK, this person I think my question is this person must have made this question right after you said that there was lots of great questions, they asked, is this question a really great question? Yeah, it's OK. It's OK. All right. What about network requests with specific parameters, body query, string path? Can we provide a function to match the request instead of a string? Yes, so that's where Route two is going to come in handy for you. So, again, this is experimental support currently, but it allows you to have a lot more granularity because you can pass through like a root handler and a root matcher argument. So the root matter is you can essentially what this kind of came a lot of use cases historiographical to be able to say this is what the actual request is and then have more granularity over it to be able to match those specifically as opposed to just a single endpoint. Right. For you. Wow, that's not very helpful with regular route. So that's what route to bring that functionality to the table. That's pretty cool. And just as a reminder, if you're going to go ahead and raise your hand if you're done with the activity. Yes. Thank you. Get a. A few more that are done. OK. All right, next one, can you use it as four elements returned from selectors? Yes, that is the other use case. So one of these Hiriko variables and aliases. So this is one of the other use cases rate is for the return values. So the talks about how you can't really get the return value by assigning it to a variable. So this won't work. Great button that click. So instead what you can use is aliases. Right. So you can excuse me, you can either do that as a returning the element and then saving it as a variable to be able to share context. So you can say get the button, invoke the text as text and then you can say it like this text is now available so you can take whatever the value you want from that. You can also do it for the entire thing if you wanted to get the entire button and then you would say, you know, and maybe you would aliased as a button and then you would say button dot text as opposed to this. In this case, we're saving just the text. But you could also do the button and then save the button as a button and then do button. That text equals right that way. So we'll. All right, can Cyprus be used to add a delay to request responses and validate the behavior of the AFP while waiting for the response? Yes, it can. Yes, it can. So let me see if I can. I know we have an example for this. Oh, my gosh. There's somebody showing up with that screen. Yes. So there's ways to. Definitely like basically resource loading. Yeah, yeah, let me find it, though, I'm going to find it in a different window because I'm going to do some Googling here. Well, I think it's in our box, but, yes, there absolutely is a way to do that. I just have to figure I just have to find the example for it. But essentially, let's see, delay. Slow request is just. Yeah, how to see. Download a PDF file. Debugging time outs. All right, let's move on to the next question, I'll look for it and then I'll see if I can find it and put that out, simulating network delays, OK? All right. Don't ask five questions. Maybe some more will keep on rolling in. But we've gotten through a lot here. Is there a recommended folder structure for everything inside the Cyprus directory, including within the integration directory? Yes, so. Folder structure, so I will say that you can also override the folder names with the Cyprus configuration. So in the Cyprus realworld app, I keep coming back to this because it's the best. But you can see this in our Cyprus, that JSON. Because we have API and UI tests, we didn't think that the integration was the best folder name, right. So we've set the integration folder here to be Cyprus tests instead. So you can override all these values if you do want to change any of your folder names. So in this case, we have our tests. The rest of the folder structure here is going to be pretty consistent. You always have your fixtures, your plug ins, your support and your tests. You can, however, and here command stats, for example, you can have multiple command files if you wanted. So if you wanted to split out your commands based on the different areas of the text of there are different areas, the tests that are being used and say these are the commands related to our user page, this is manually just adding to the commands related to admin. You could break those out in order to have more control and granularity when updates happen. But typically what I tend to see a lot is you have like a main test folder and then you may have the different types of tests, but then your spec files will be there will be broken out. In this case, we don't have a lot of different. They're pretty long spec files. But I've also seen people have folders where they group up, they group the folders because that allows them to pass through globs to run only certain parts of the test at a time. So in this case, we can do this here with passing a spec that you can give dash dash spec and then just pass the spec file. If you only wanted to run the transaction feeds test, you can also do this in the Cyprus test run or UI by selecting a specific spec file. But I've also seen people where they say, well, I want to group all of my transactions. Let's say we had transaction feeds view and new transaction and we say I want my transaction test to be together. So they may have a folder that says transactions and then they have the spec files in there and then they could pass the Glaube that just says transactions and then the asterisks and then run all of their transactions backfills. So I definitely recommend that if you are going to do like grouping to have it either be tied to the functionality of your application or to the different areas of your application. All right. Thank you. Next one is I'm just going to paraphrase this one, so. It's kind of about the balance between doing replacing all your manual tests with Cyprus versus doing some integration tests that may run faster, any guidance on where you would strike that balance? Yeah, it's I gosh, it just depends so much on the strategy, right, it's just. So when I see a lot of is. If there is a core and and functionality that you just know has to work all the way across. So if it's if that's if it's like going to your website adding something, you're making a payment and making sure that and doing that right. And for you, it's very, very worthwhile to have a full and an artist that hits all the integration to make sure that that works. I've seen people say it is worth the resources and effort to do all of that together. But a lot of people are able to do a combination of UI integration, API and unit tests. Right. And then get the same, if not exactly the same, then close enough that level of coverage and confidence, because really it's about it's about confidence that what you're deploying is going to work and that you're not going to have regressions. Right. So it's it just really depends on, like, the risk tolerance and how much control you really need to have over those certain core core functionalities. So I see a lot of really I typically recommend you do something like contact testing for your integrations and then you have your UI tests. And that may be NetNet may also hit your API, but that's going to be your entire like the kind of flow of your application. And then you may have separate like API tests as well. But this is real world that we were able to get one hundred percent API coverage using are like UI tests. So it just really depends on the application, what your priorities are as an organization for testing and then letting that kind of dictate where you go from there. Well, it depends. So long story short is saying it depends. All right, this is a follow up question about the ambassadors. Is there any mentorship via the ambassadors? I would love Cyprus and would love to grow into something like an ambassador. That's a good question. I do know that we have a Cyprus lecture for the ambassadors and everything that we interact with a lot. I don't necessarily know if that's like a functional part of the program itself, like if it's if that's rolled in. But I do know the people who run it are super, super nice. So if you want to email them questions or reach out to that team, you're more than welcome to. I just I think that they'll be open to just confirming anything or putting you in the right direction. Yeah. All right, next one is a code question about why one thing works and the other doesn't. So the one that works is Sadoway. At Log-in, its status should equal two hundred and this one error site, Ottway at login should have property status. Two hundred. OK, I'm looking at that now. Its status should equal should have property. OK, so. It looks like it's because the response type doesn't have that property on it for some reason. Well, I don't know. Yeah, I'm not sure why that's happening. Sorry, I could definitely take a look at it and more specifics that we have about five minutes left. So sorry. OK, two more questions. I think we can do this. You mentioned earlier testing an application that uses indirects with Cyperus. As we have seen, there are lots of examples. Is there an example you could quickly point out feel free to call me out as lazy? No, actually, so I would say I'm doing a talk later on this week and then about testing specifically. So there is a I can actually share the repo for that probably while you answer the next question. Well, and the next question is actually almost the same. I don't know if anyone has already asked. I'm interested if our cars and can be tested. If so, please send me an example. Yeah, absolutely. So let me go ahead and share. This is a sneak peek. Those are my slides for Thursday and GISTER. So there's a repo there, too, so a sneak peek and then keep an eye on Thursday for my actual talk on it. So. So I just I'm sharing my story with some resources here, too. They're also on the slides, but we have a lot of documentation. We have our Twitter community chat. We have the real world application. Definitely recommend that. And then Cyprus is on GitHub or open source. You can post issues if you have any feature requests or if you have any bugs. Otherwise, there is the best place to get interactive kind of feedback from the community. So awesome. We did go through all sixty nine questions. Good job. All right. Great questions, everyone. I know I said that all the time. It's like my. But they really were great. They really were great questions. So also. Yeah. So I will say that again, all the solutions for the activities that we covered are in the in the branches for the repository. And yeah, the kind of the next steps is just using the documentation. Start using Cyprus. Like I said, you don't really have to delete anything else. You can just start building on top of what you already have. And yeah. Thanks so much for all the awesome awesome questions and interaction makes makes makes my job a lot easier. So. All right. And we have one final poll question for anyone who'd like to participate. What do you think Cecilia does when she's not coding? Oh, wow. That's a good one. I'm not going to answer it. So I was and I wanted to also give a shout out to to Joe, who has been amazing as a moderator. Thank you so much. Thank you for that, because I don't think that you got any breaks either. So. But that's OK. I'm not used to having breaks. I'm a manager. I have meetings all day. Yeah. Gotcha. That. Yeah, I'm just like the somebody like I'm running a few minutes late for that. First I'm like I said, I'm gonna get a coffee shop. Yeah. So just a quick question. The chat there any webinars for advanced topics. Yeah. So I put in the chat earlier the Cypress Patterns and Practices webinar link. That is a really, really good one for more advanced topics that goes over programatic. It goes over customizing the command line. And I'm describing it again here and it also goes over S.I. So like integrating with S.I. So those that in that's done by Amir and Kevin from our DCS team highly, highly recommend that word. That as well, so I'm putting the YouTube link and the slides and the chat there, so that's yeah. So if you're already up and running with Cypress and this was like kind of like refresher for you, patterns and practices is a great next step. Awesome. All right, I'm going to end the pole in five seconds, so finish up your vote if you haven't already. And then I also wanted to say, if anybody has any questions for Cyprus success at Cyprus Daddio is our kind of default email address that you can reach out to. And chances are it'll be me that gets it. All right, Cecilia, this is what you've got to do as soon as we're done and you've got to do some cooking, baking and playing border video games, OK? The video games and board games is absolutely correct. I have to give a shout out to functions and dragons. It's like a Tuesday night DMD group highly. They recommend checking that out on Twitch. But yeah, cooking. We'll see. We'll see. And actually, I guess this is a good chance to plug. We're going to on Friday do a virtual board game for this conference. You can't see it because of Zoom had the screen. But this is a rolling right game that can basically support unlimited characters. And I'm going to be running that. So be sure to go to that. It's going to be a lot of fun. Excellent, excellent. Thank you so much, everyone. Thank you, Joe. This was very excellent workshop experience. Appreciate it.