Testing Web Applications Using Cypress

Rate this content
Bookmark

This workshop will teach you the basics of writing useful end-to-end tests using Cypress Test Runner.


We will cover writing tests, covering every application feature, structuring tests, intercepting network requests, and setting up the backend data.


Anyone who knows JavaScript programming language and has NPM installed would be able to follow along.

173 min
05 Jul, 2021

Comments

Sign in or register to post your comment.

Video Summary and Transcription

The Workshop covers various topics related to Cypress, including app control, network calls, continuous integration, and debugging. Cypress provides intelligent features such as command logging, test reruns, and powerful assertions. The documentation for Cypress is comprehensive and includes syntax, examples, and historical changes. Tests in Cypress should focus on expected behavior and utilize assertions for accurate results. Cypress offers features like time-travel debugging, conditional testing, and intercepting network requests for effective testing.

Available in Español

1. Introduction to the Workshop

Short description:

Thank you for attending this workshop. This workshop will cover a lot of topics related to Cypress. We'll cover the app, basic deaths, selecting elements, controlling the application, and network calls. We might also touch on continuous integration, retryability, and debugging. The workshop will be hands-on, so make sure to clone the repository and perform npm install. We have a Discord and Zoom chat for questions and assistance. Let's get started!

That's it. Have a good day. Thank you for attending this workshop. I love Cypress and I love giving this workshop. And if you are a really advanced user of Cypress, I think you'll find something to benefit from this workshop as well.

A little bit of housekeeping and rules. So this workshop will be for 3 hours, right? We'll take a short, five minute break at the start of each hour. Because it's hard to sit in one place for 3 hours. And so, because obviously you are in your office or at home or wherever you are, you can take a break whenever you want. I can't control you. So make sure to be comfortable. If for some reason we disconnect, right, I will try to reconnect to this session right away so that we can continue. So unless there are some really bad problems, I expect the session to continue and finish.

I will keep an eye on the Zoom chat and on the Discord chat. So one of the benefits of a workshop is that feel free to ask questions, right? I will try to answer as many questions as possible. This workshop will be recorded, so you will get a recording and you will receive this video later. So if you have any questions, post them in the Zoom chat or on Discord, and I will answer them either live or as soon as a moment is right.

Okay, so I expect everyone to have this repository cloned and ready to go. So if you haven't, please clone this repository so you have it locally. You will need the node, so I assume that you have it installed. And the first thing you want to do is make sure that you perform npm install. It might take maybe 5 minutes if you are starting from scratch, because it will install dependencies and cypress and everything. So this repository has everything, right? It has the application. We'll be testing. It has the spec files already. And it has the slides.

So I'm going to start sharing with slides. All the slides are just markdown files. And I'm using this get-page link to actually show the markdown. It's a good thing that it still is January, because I'll have to move the slides somewhere else next month.

I am Gleb Bakhmutov. I used to be VP of Engineering. Now I'm just an engineer, because I don't want to do all the meetings and like roadmaps, and so on. So right now I'm so lucky, I can just code and do workshops and write blog posts and do things that I find interesting. You can always write me an email after the workshop or during. I'm Gleb at Cyprus. You can also always contact me on Twitter. I try to be, you know, reactive and always reply to whoever's writing to me. I have a lot of blog posts on Cyprus blog and on my personal blog. You'll find a lot of in-depth kind of explanations. And I also do little Cyprus videos on YouTube. I've been using Cyprus for close to five years because I worked on Cyprus for four years and I used it for a year before so I'm really happy about Cyprus.

We'll cover a lot of stuff. I mean, as time allows. I will post the link to the repo in all channels. We'll cover a lot of stuff. We'll cover the app. It's a simple to do and VC app so we don't have to spend much time on it. We'll cover basic deaths, that kind of interactive page. We'll see how we can select elements using selector playground and the new studio and how I would control the application before the test so that we all start application in a known state. And then we'll look at network calls and how we can spy stop them, stop them with data over picture data. I probably will not get to this section. Maybe I'll cover continuous integration. Maybe I'll mention something about retryability and debugging while we cover previous section, but this workshop, this repository has all this content. So if you wanna kind of look at what the features do, right, or how to do plugins, so how to set up code coverage, the material is there, but we'll just won't have time to get for it because this workshop can be long. We're not gonna take lunch, but we'll take short breaks. Usually this workshop we do physically, right? And people talk and can help because it's a virtual workshop. It's harder, right? But just use chats with your opinions and questions.

I found that a best workshop and getting the most out of it depends on three steps. So first I will go through the slides, I'll explain the topic, and then I'll show how to do a specific test, right? So I'll type it and I'll show like what happens inside Cypress and so on. And then inside each integration spec file, there'll be exercises, right? Like writing more tests one by one. And both things I encourage you to do by yourself and I'll do them later, right? And I'll kind of show the solution, but the best thing for the workshop is to be hands on. So I really encourage you to work on your machine, during this workshop, okay? And if you get stuck, again, pause the question in the discord or on zoom, right? And I'll try to help. But the best thing is kind of listen to what I explain and then code together as I code and then try to go for the next exercises. Okay, I already said that you will need to clone the repository and do NPM install. Larick can you help people because some people do not see the discourse channel. Okay. I guess we will duplicate. Excellent. So here's what we have in our repository. So if you look at all files, all right, we have a lot of stuff. The application is inside to do MVC, okay? So it's in the sub folder and this has its own packages. So if you don't PM install, it actually installs with dependencies there as well. It's the details are not that important about the application. Then we have Cypress integration folder. That's what all the test files will be, okay. And so for each section, right they're all on like named, zero, one, zero, two, they're all numeric one after another, whereas sub folders. So if I go and I look at, let's say Cypress integration you will see that the first kind of spec file will open is here. And then for next section is your two and so on. So every section we'll just work in a different folder and everything is independent. So you don't have to kind of finish what previous chapter to go to the next one. They're all independent. And while we are testing replication, replication would be just running. So we'll start it and it will just stay. Okay, so is everyone ready? Okay, I assume everyone's ready. So from the terminal, write one inside the repository. You can execute NPM start. And you should see this, right? If you install everything, if you have no, that's what you will see, right? It literally just started application and it should be running at localhost 3000. Okay, so we're gonna just run that application in the background at all times.

2. Starting with Cypress

Short description:

When working with the application, we observe network calls, such as GET and POST to the todos endpoint. The app sends the todo with its title and ID. Reloading the page fetches the items again. The data is stored in a data.json file. Cypress is used to test rest API calls. We start with Cypress by creating a new project, installing Cypress as a dev-dependency, and opening Cypress with NPX Cypress open.

Okay, so we're gonna just run that application in the background at all times. Okay, so it's a TodoMVC because that's the hardest application, almost difficult application I know how to code. If you have view, you can see the view interaction. It doesn't really matter how the application is implemented. We can run the CSS pretty much against any implementation because Cypress doesn't care about the permutation details, right? It does the browser, it does the UI, right? But user doesn't care how it's implemented. So why should Cypress?

Okay, let's open DevTools. So the one thing we wanna know right away is what happens when we'll work with the implementation, like this application, right? So the thing that I usually try to observe are like what are the network calls that happen when the application loads, right? So I can reload and I can see what we get in document, we get in a bunch of you know, scripts, right? And at the end, our application is making AJAX call, so we can inspect it. So our application is doing a GET to todos, right? And gets an empty list, cuz there are no todos. So inside of a page, we kinda have like standard mark markup, right? We have classes for the main section. We have a header, that's where we probably will have input box, and when we just play all to those in unordered list. And so for every todos, we'll just show it on the screen. So that's our markup. You can take a look at todo.mvc.app.js, it has a view store, but it's a implementation details. I don't really care. But I have a question for you, right? My audience. So what happens when you add a new todo item? So you can do it yourself. Let's type, you know, first to do. Okay, so when we press Enter, you can see that there is another call that application is making, and it's a POST, right? So it sends something to the todos endpoint, right? The server responds with 201, which means a new item was created. And what does the app send? Well, it sends the todo. And notice that the app sends the title, right? Which is first to do completed false. So by default, every item is incomplete and the frontend also sends the ID. So the app is creating the ID for the app, for to-do item, and sends it, right? So it's not even server-side, it's just client-side. And if we send second todo, right, I can see another call, okay, another ID, another item. And what happens when we reload? Okay, we can see that the items came back. We can see that this original call to get todos, right, fetches the items. So application, when it starts, fetches the items. Okay, so this is how it works. So it gets to the server by using Ajax calls. Now here's another question but you should look locally. You wanna figure out where the items were stored. So for this, I will switch to my code editor. Okay, so you can use any code editor, right? But I love VS Code nowadays. So it's so simple. Kareem, no, the presentation is not private. So if you go to the code, all right, you can follow along if you get lost or if you wanna spend more time, you can take this link and just click on any of the links. So right now I'm at the intro. Okay, so let's find where the application saves the data. All right, so it sends it, stores it, and then when we reload, we can see the data again. So it has to store somewhere. Okay, if you have troubles running application, make sure you have the right version of Node, at least 12, all right, and that you can execute npm start. One thing, it might be because this is using, where's our start, if you haven't troubles, maybe go directly into todo.nvc subfolder and do npm start there. Make sure you do npm install first. So if in my text editor, if I look around, right, and I go to todo.nvc, I can see this data JSON file. Okay, and yes, Martin, you're right. I'm not ignoring it because usually it's started with a simple, empty file. Okay, so this is where my server is storing the data. Let's verify it. Let's see, is it data JSON? Okay, so yeah, that's where it's at. Yeah, yeah, Lindsey, try installing dependencies again and trying to start on the one. All right, Nikolai, if you have a Grafana app, that's not me, that probably is some other app that you're running locally. Okay, so at startup, right, when application is starting, it's getting those items again, right, so we always return, okay? Okay, this is kind of a structure application and I'm only using it, you know, to kind of explain, but this is a modern application, right? It has a UI layer, this is all the markup, the input, the list of items, they're all there. Under the hood, the app is using Datastore and the Datastore is making rest API calls, so in this presentation, I will only talk about, kind of testing rest calls. They're a little bit simpler to test than GraphQL, you know, GraphQL is more advanced and just look at our documentation if you need to intercept and spy on GraphQL calls or other types of calls. Okay, I have a more kind of detail explanation of app and how you can test it, but for now, let's start with Cypress. So I finished the introduction and let me start with the next one.

Okay, so the first thing I wanna show is, you know, what happens when you just start with Cypress, right? I had the question actually, but it's kinda, you know, in the Zoom chat or in Discord, you know, how long have you used Cypress? How long have you used Cypress for, right? So, I use Cypress for longer than four years. I'm wondering if majority of people six months, three years, not yet one day. Excellent, so we have a range from just starting to veterans. Perfect, perfect, so everyone is welcome.

Okay, so this section is for people who just started Cypress, right, or wanna try. So, we'll write first test, we'll set up, and I'll explain documentation. So, for this test, we'll create a new folder, all right? So, you did install in, you know, to MVC in testing workshop, right? But here's what happens when you start from scratch. So, let me just show how it's happened. So, I'll do, I'll go to my temp folder, and I'll make a directory like first. And I'll make a directory like first-use-site. All right, and I'll switch. So, here's what happens if you just create a new project. Right, so I'm using NPM in here to quickly create package JSON. When I install Cypress and I save it as dev-dependency, it's not production-dependency, right? It's not something necessary for your app to run, right? No, but it's something that you want to install if you're developing, so that's why it's a dev-dependency. So, I'm installing Cypress, right? Using NPM install Cypress. Come on. Okay. So, because I already installed that version of Cypress, right, it found it, so I never have to re-download that big file. Okay, so what do we have here? Right now, just pack a JSON, right, and node modules. Now we wanna open Cypress and there are different ways. The best way, I would say, the most modern and portable way after doing PM install Cypress is to do this, NPX Cypress open, I suggest you do that with me. All right, NPX Cypress open. So, this is a folder where we just installed Cypress, we run it for the very first time. Okay. Notice that it shows that to help get you started, it created a bunch of files. Okay. So, here's what we see. Oh, by the way, sometimes I don't do NPX Cypress open. So, instead I just create scripts in my package file and then I can open with a command. And then I can just create a command. But first time you start a Cypress in a folder, right? It creates a bunch of files. So, the most kind of useful is cypress.json. Okay. Then you can follow the contents by looking at, for example, a markdown, and then you'll have all the files. Look all the commands and you can go back and forth.

3. Cypress Configuration and Test Files

Short description:

The cypress.json file contains settings such as the base URL and viewport. The integration folder contains test files, and the fixtures folder is for test data. The support folder is for common utilities and custom commands. The plugin allows control over Cypress. When running Cypress for the first time, check the scaffolded examples. To code together, create a new project with a spec.js test file. The simplest test is to visit the TodoMVC page. Cypress watches the integration folder and supports TypeScript. Cypress comes with a bundled electron browser, but other installed browsers can be used. Install TypeScript if needed.

Okay, so the file cypress.json, let me switch to this. Let me open my code editor so we can see everything. So this is the folder. Cypress.json is a file where I'll have all the settings. So for example, if I want to set the base URL, right, like which URL my tests or like my app is running, I can do it. I can use Viewport, right, and so on. So these are all the settings.

But integration is the second most important thing. That's where your test files will be. So when Cypress started for the first time, we scaffolded those folders, integration. And you can have subfolders there and so on. These are all the tests that we create kind of as an example. So we can open any one of those files that it created and see kind of what Cypress tests look like. We'll get to this in a second.

The fixtures folder, this is where you can put files that you want to use as data during your test. So you don't have to recode them. Then there's a command Cypher fixture that can load those files. Support is a place for common utilities, right? If you want to run, for example, something before every spec file or before every test, you want to put it here. It's kind of common things that you want your test to have. You can also create custom commands, for example, for logging in so you can reuse them and put them in support. And finally, plugin is something that allows you to control how Cypress runs, but it runs in Node before the browser starts. For example, you'll be able to query a database, all right? Or change the configuration before Cypress runs using plugins file. Okay.

The one thing that I suggest when you run Cypress for the first time, look at those examples we just scaffolded. All right, so inside integration, we create a whole folder that has a bunch of examples, how to type into element, how to do assertions. When Cypress starts, it shows those files right here, right? Let me just switch here. So for example, if I wanna see how does Cypress type and click, you can click on the example spec, right? My machine is slower than usual, I think because of Zoom. Okay, so now it shows how it types, for example. I set the viewport to 200 pixels in Cypress JSON. That's why it kind of looks weird, let me change it. Every time you change something in Cypress JSON, it closes the browser because the changes might be pretty big, right? So this is more typical. What you see on the right is the website. So we'll load our example website so we can actually show how the test can type, focus, click, right? Do all the commands and actions like a real user can. Perfect, so by using both examples, right? That we scaffold. You can kinda get the sense of what Cypress is and what it can do, okay? This is like examples of different assertions that it can do. The cool thing is that you can open each test and you can see what it does, right? Like all the commands with RAM. For example, in my assertions, right? The name of a test is right here. The same thing. And then what you see right here corresponds to what happens, what's written here. So you can see before each we visit the page and then we get something with class assertion table and you can see both commands like one by one. So you can see how what you write, how it runs here. Okay. If you do a lot of industrializations, like you probably don't want to scaffold that folder again and again so I have a little package that allows you to bypass it and just create Cypress JSON and empty integration folder and so on. So what we scaffold right here, all those examples, notice they run against example Cypress.AR. So we call this project Kitchen Sync. It has its own repository and you can just go to that example link yourself whenever you want. So if you kind of scaffold it and you saw something and then you want to show it to someone else, for example, the same assertions, the page is right here. So you can look at both steps and like loop them up and see, how did I get the table with class? Oh, okay. So I got the table and then I found something and I made an assertion but like it has a class success. Okay, this is what we publish and maintain at all times. Okay.

So why don't we code together? Okay, so we have this new project, right, where there is nothing else. Okay, so I will even close the browser. Okay, so in my text editor, I will just delete this folder, examples, so I only have Cypress integration and I can create new file, spec.js, so it's JavaScript file. That will be our test. Okay. And this is the simplest test that we can do. We can, let me paste it here, okay. So what does it do? Well, the name of the test is called loads and Cypress uses mocha syntax. So each test is a call to function it. We're describing the page, so we're saying app, it loads. And then the callback function has all our commands. So our test will be very simple. Remember we have a TodoMVC running on localhost 3000. So all we wanna do is just visit the page. If you wanna write this in TypeScript, yes, you can use TypeScript. Okay, so let me switch. Notice Cypress is watching the integration folder. So it actually notices different extension. Okay, notice that since this is, let me zoom it a little bit. Notice the little squeaky lines. So because Cypress, these are global objects. So our text editor doesn't know about them, like where are they coming from. So if you really wanna fix them, you can say Cypress reference types Cypress. So this thing, the special line that I'll post here, right? Is something that tells my code editor where to load was global type definitions for it function and site. And it will go inside node modules, find module Cypress, which we installed with npm install and will load them and now it will understand. Now, look, if I hover over Cypress, it shows our documentation. Okay. And it shows documentation for every command, for example. So site visit, right? I can see how to use it and so on. Okay, so let's run it. But one thing that you will notice, Cypress comes in with bundled electron browser. Okay, this is a browser that's very similar to Chrome. It's really, it's Chrome, but like one or two versions behind the latest release Chrome browser. I can switch this browser, and it finds automatically the browsers that are installed on my machine. So I have a bunch of versions of Chrome, bunch of versions of Firefox, Edge, right? All the browsers that Cypress can control and use. So let me like try running the test in Chrome Canary. And then I click on the spec file. Ah, but I didn't install TypeScript. So to answer your question, I have to also do npm install TypeScript if I wanna run TypeScript, which I forgot to do.

4. Understanding Cypress and its Features

Short description:

The speaker explains how Cypress understands JavaScript code and provides IntelliSense support. They demonstrate how Cypress logs commands and allows for easy test reruns. The speaker also addresses common questions about documentation, browser configuration, misspelled commands, and file watching issues. They highlight the power of the visit command, which can detect server errors and slow page loads. Additionally, the speaker showcases Cypress's intelligence for assertions and provides information on finding documentation.

So the simplest thing is to rename this back to JavaScript. Now, Eric, don't be disappointed because when you use this reference types, this works just as well. So notice that it still understands everything. All right, so I can use my IntelliSense by just having this. Okay, let me run it. All right. Okay, so this is our test. All right, again, what you see on the right is the website running in Iframe. On the left, you see what we call command log. It shows all the commands, right? You see a number of successful and failing tests, how long it took. You know, I can re-run the test, okay? I can also run the test by focusing on the command log and just pressing R on my keyboard, right? Then it just re-runs. Okay, a couple of questions. Documentation for our customer methods that we created and support files, look up our documentation. I will kind of describe documentation in a second, but the other thing is that, how do I describe, for example, different browsers? What if my browsing is non-standard location? You can control the path to a browser from plugins file. Can I tell VS Code that I'm using Cypress about this line? If you use TypeScript, yes, if not, I find that this is the simplest way to do it. But one thing that I want to point out, one more secret, so we are in JavaScript project. We didn't install anything. Okay. And it still understands the command. But if we, for example, let's say misspell a command, right? So if we run this, this obviously fails. But we really want to know about this. Oops. Okay, so notice this is not function. So we're writing our spec files inside Cypress integration folder. Okay. If you have a Webpack compilation error, look at the Webpack compilation error and see what it says. But here's a trick. So because of reference types, it understands the global, but this is not there. Add another comment, TS Chuck. So now we still using JavaScript, right? But our code editor will highlight everything that doesn't make sense. See how it says property business doesn't exist on type Cy. Did you mean visit? Because it knows where the very close method called visit. So now I'm gonna fix it, and now everything is fine. Another thing you notice is that every time I edit and save a file, Cypress reruns it, okay? So which is very convenient. I usually keep my editor on one side of a screen, and then, you know, I code, say, on another, and I keep rerunning the test, right? As I update it, okay? If your file watching is not working, look at our issues, maybe there is something about your operating system, or maybe about your editor, or maybe your antivirus software prevents file watching. So I talked about this. So this test, right? Like, it looks very simple. We're just visiting a URL, okay? Now, here's where it's powerful. Imagine that I, for example, tried to access a wrong URL. Maybe my server is closed, maybe it's not running, right? If your test is running headlessly, make sure you're using a cypress open command and not cypress run. I'll talk about cypress run in a second. So my website is not responding. My server is down. Everything is broken, right? Notice cypress gives you a meaningful error. It says, fail, try to load and then this. It tells me the network error, connection refuse. It tells me what are possible explanations for why this is wrong. It even tells me like which command fail. So if I click on open an ID, it goes immediately to that place in my file. So even side visit can be considered a good end-to-end test because if the server is not responding, if it's responding with non like 200 code, if it's like 500 or 404, this command will fail. If your page doesn't load and doesn't fire, page load event, this command will fail. If your website is slow, right, and by default, visit waits for I forgot, I think, 60 seconds for the page to successfully load, you can control it. You can change it in your Cypress JSON or even in your visit parameters. I think timeout. Oh, yeah. I think timeout is the one you can change inline. Or there is a dedicated option in Cypress JSON that you can set. Okay? But even a simple visit is already telling us something. The server respond doesn't crash, right? So this is what's happening. Here's something else that I wanna show. Like I mentioned, switching the browser, I explain this, how to set up IntelliSense. The cool thing about this is that once you start writing more assertions, right? Let's say I want to confirm that there are three assertions. I can use Sy Get and say, to do. Get me all elements with class to do. Okay? So right now it found three elements. It shows three matched elements. And notice that the Get will run only after Physit successfully completes. Okay? So Cypress chains commands and runs them one by one and the previous command had to successfully finish. So let's say you want to confirm that there are three to dos. You say, let me maybe make a little bit smaller voice. It's hard to see what's going on. So you found the elements. And when you say, Should have length three. So whatever you find should have length three. Okay? So this is called a command and Should is an assertion. And as I said, we have intelligence for every command but also we have intelligence for assertions. And Cypress comes in with chai assertions, chai.jQuery assertions and chai.xenon assertions like all bundled in. Like you don't have to install anything. Like I didn't install anything. And notice like here we use length assertion, should have length three and notice when you use intellisense it actually shows you the right assertion. I mean, the right documentation for that assertion. Right? And the right examples, right. Should have length three and so on. If, for example, you say should have class and you say to do, each element found has that class. If you hover, it shows you again, documentation for that particular assertion. TS check, I explain, it actually will use types to highlight. And now where to find documentation. If you never use Cypress, or if you just started, or if you've been using it for years, your best bet is always, when you have questions, is to go to docs.cypress.io. This is where all our documentation is located, or majority. So the one thing that you might find interesting is how does Cypress work? Like, what are the main features and the core concept? Like, what is special about Cypress? It's all described here.

5. Documentation and Test Setup

Short description:

As engineers, we spend a significant amount of time updating the documentation for Cypress. The documentation provides detailed information on commands, including syntax, parameters, examples, and related commands. The documentation also covers common use cases and provides historical changes for each command. Additionally, there are longer recipes, tutorial videos, and external courses available for learning Cypress. The documentation is searchable, making it easy to find information on assertions and other topics. Cypress does not control multiple browsers simultaneously, but you can find answers to common questions in the FAQ section. Cypress is an open-source test runner, and the company makes money through the Cypress dashboard for organizations.

So as engineers, we're not working on Cypress and then telling someone else to write documentation. Every pull request to Cypress has corresponding pull requests to documentation. We literally spend like 25% of our time updating the docs. Majority of my things lately has been documentation pull request, documentation pull request, documentation. We do spend a lot of time on documenting things.

Core concept, Command API. So where do you find documentation for commands? Go under API, right? And you will see every command that I've been using is right here. So we use, let's say, visit, okay? Here is how every command is documented. We show how to use it, like its syntax, explanation of every parameter, okay? Otherwise, so the time out for logging site. We show examples, examples with options, right? Like all common use cases. We discuss how it, like what every command does in particular case. For example, if your server redirects, we follow the redirects when we do visit. What about the protocols, right? Even if you don't have a server, you can use a page. Thank you for kind words, right? We tell you the rules, right? So I said that your server has to respond with something with content HTML, but it has to be 200 and eventually. And the page has to send a lot, right? Then we have examples. At the very bottom, we usually have a history, right? How did this command change if you change in different versions? Okay. And one more thing that's important, at the bottom of every command are related commands. So for example, if you just wrote, started using visit, and then you kind of have a question, well, what about visiting another page, but going back in history, right? Like going to the main page, going to about page, and then clicking the back button. How does that work? How do I? We usually put links like that in see also. So if you learn visit, go and read see also. Look at our examples. Okay? So there are a lot of commands. Nice trick. A nice trick that you can remember is that everything that we do has a little short link. So for example, if you want to know how visit works, you can do not docs.cypress.io, but on cypress.io and then visit. And this will automatically redirect you at all times. Right? So if you want to know how get command works, you got to get. So this on command, that's what we use to make sure that the links we give in our docs and our types and everything, are not... Don't become broken if we move documentation around. As a clip, all go immediately directly to this documentation. Okay? And when we edit something, if we hover, it actually tells you, you want to go to on cypress.io.visit. So that's how we make sure the links are not broken. If you have different settings for environment, look at the section about environments in this repository. So one other thing, if you just want to know and learn, we have under examples, we have longer recipes with show like advanced things, right? We have tutorial videos and playlist and example of building the thing. I also suggest like this workshop is there, but I also suggest you check out this page, the courses, right. So these are external courses where people have developed. Most of them are video courses that show how to use Cypress, right. And a lot of them are, well, not a lot, maybe one quarter. It's free. So you don't have to pay money to learn this, right? You can find and start by watching free courses and then see what else in it. Okay, a couple of questions. Where to find the list of every assertion, right? So one thing that you always want to do when finding something is to use the search, right? Notice I typed assertion and immediately went to assertions page where we document things. This is not exhaustive because the way Chai works, you can combine those things, right? And have like assertions, like that, for example, combine several modifier keywords, right? Most of the times I kinda think in my head, what am I trying to say? Should have length, should have class, and that would be the assertion. And as you type, if you have intellisense, it will tell you what's happening. Can Cypress control multiple browsers at the same time? No. So can Cypress control multiple browsers? Maybe, is that right? So you can find questions or answers to question like that usually by typing them in our search. So I talked about this. Important thing, FAQ, and we keep this updated, questions that are too small for a recipe, but larger than, or not related to documentation, right? So for example, how do you verify the text of an element? Usually you say something like this. But what if it has non-breaking space, like all those little extra details, right, are here. But assertions, I try assertions. I personally don't care for just assertions, right? Like, I think ChaijQuery is already working, so we're not gonna switch. Some people try to, for example, add to our assertions, just assertions, I find those like duplicates and not as powerful, especially if you look at Synon, right, versus just mux. Synon is a lot more powerful, so we're not gonna add things. One other thing. If you wanna know what has changed, we have a change log, right. So every version of Cypress is documented and you can find like what changed with links to every PR and so on. If you wanna know what we work on, it's under road map. Okay, so kinda big ticket items have their own roadmap. Question, how does Cypress make money, do we have like, no. Is Cypress free? Yeah, so everything I'm showing today is absolutely our open-source MIT license test runner. We make money out of Cypress dashboard where organizations when they have a lot of tests, they want to record video with test results, run them in parallel, have test analytics and things like that. One GitHub, Bitbucket, Jira integration, Slack integration, that's how we make money, not from the test writing. So my advice at the end of this section is make sure you set up IntelliSense. Like I've done here with this line. If you use TypeScript, if you set up TypeScript, then you don't even have to do that. But if you're just starting with JavaScript, you don't wanna mess with anything, make sure you add this line and it's beautiful, it works, it will help you use the right command, see examples for that command. It's hard to kind of scroll here, you know? But once you set it up, it's all good. Okay, so this was the introduction to the new project. Let's go to the next one. Let's write test for our app. Okay, so I'm gonna switch here. Okay, so let's look at first kind of command contains and test retrieve, okay? So I'm asking everyone. So to do MVC is running, right? It's all good, it's still there. And we wanna now close Cypress like we were running it, right, we don't need that. So that first project, we can forget about it. So instead, I'm gonna go back to my testing workshop Cypress, okay, so my app is running. Gamels here. And here I can start Cypress using this command NPM run site open or I can do NPX Cypress open. Okay, so now we're back in our testing workshop Cypress depository. Okay, switch back so I don't have multiple browsers. So, I wanna open this zero one basic. So I'm gonna basically by the way, so this little thing is a filter. So you can quickly kind of limit yourself to a sub folder or part of the file. Okay, and in my text editor, I wanna open the same file. So I'm gonna open, so I don't need this, right here, Cypress. Where is it? Cypress integration spec. Okay, so I have this test and I hope you can open in your text editor and in Cypress as well, okay? So let's see. Does this test work? If I click on it, here's what happens. Okay, the test fails. Okay, so this is very common.

6. Writing Tests in Cypress

Short description:

When writing tests in Cypress, it's important to understand why they fail and ensure they pass for the right reasons. The contains command is used to find a selector with specific text. It's crucial to inspect the elements found by the command to ensure they are correct. Additional syntax like cucumber is not necessary and can make writing JavaScript more difficult. Cypress provides assertions that automatically retry commands, allowing for dynamic elements. When working with Cypress, it's recommended to use Cypress Open for browser interaction and Cypress Run for headless testing.

It's fine. We're writing tests. We wanna see them fail for the right reason, right? And we wanna fix them or fix the application and we want to see them pass. So you will see a lot of failing tests, like I guarantee it.

Okay, so the one thing that you might notice is that we're using contains command. Okay, so we can open our text editor. So cite contains. So where are the documentation for this command? Well, it's on on cypressio contains. Okay, contains. Okay, so you can kind of guess by reading out documentation what site contains does. So in this case, let me open documentation. This is what it does. You're trying to find a selector with particular text, right? So our selector is H1 element, right? The header element with text to do this app. Okay, okay. Why is it failing though? Well, let's look at this, right? So it tries to find to do this app. Hmm, but our H1, right? Like this big thing, it doesn't say to do this. It just says to do this, right? So if you want to see this succeed, we probably want to fix the test and use not to do this app, but just to do this. Ah, close, right? Maybe it's to do this. Okay, it's to do this. Here's important thing, right? So contains passed. Go and hover over the command, right? Notice when you hover the command, it highlights the element that is found, right? So the get found the input box. It found the footer. Okay. And then the contains found this thing, all right? So it did find the expected element. It's very easy to find a wrong element, right? For example, if you don't use h1, site-contain still works, then just look for all elements, right? You can find wherever, just by text. So if we look at to dos, it found it. But what if we use to do, all right? Still the right one. What if we use to do MVC? Actually, no, it's to-do MVC, right? We might assume that it found something on the top. But notice it found this element. So when you write a test and it passes for the first time, make sure you inspect what it does, right? Does it find the right element? Could it be confused by something else? And if it finds something wrong, then update the thing, right? Maybe add the selector or a better selector, right? To make sure that the test is passing for the right reason.

So there was a question about how do we make this more readable? Maybe we want to use some kind of special syntax like cucumber and I think most things are overkill as you will see in down the line in this workshop, but tests are pretty readable already. I personally find extra cucumber syntax. Don't add much, but they actually make writing JavaScript a lot harder. So, and they add overhead in your setup. So like I don't think adding specifically something makes sense. I will talk about selectors just in a second using page objects. We'll get to those.

Okay. So we wrote the thing, right. By the way, if we change it, right, we'll say like if it's if something like this, right. Or if, for example, we use the right tags but like wrong selector. Okay. So when we debug in something like this, we can open DevTools, this is a real browser, right. So, you know, feel free to open DevTools and keep them open. I think it's fine. Let's go to elements tab. And let's see this thing. We found the element. Okay. So it's H1, right? Because we see it should be. We can also say, just find me element with an attribute data site equals app title. Okay. So we can always use the DevTools, right, to find things. Okay. Something else.

Okay. Before I get to a selectors, I want to show something else. So let's say, I'm using a wrong selector. Notice this blue spinner. Right? And notice that the test doesn't fail immediately. It's very important in Cypress, right? Cypress doesn't know anything about your application and how you implement, it doesn't know how fast that element should appear. Maybe it's created dynamically after one second. Who knows, right? Maybe the application first fetches the title from the server and then puts it there and updates it. So Cypress has these assertions that are kind of like almost like user directions. Hey, when app loads, then there should be this text in that selector. If you're raising your hand, can you ask questions in a chat, right? So here's the thing. Cypress assumes that every command will pass after some timeout, by default four seconds, right? So as you can see, this takes four seconds before it fails. So Cypress retries that command, it literally goes and searches again for this select or this test. If not, tries again, if not tries again. So all the commands that can safely retry, retry automatically. And with blue spinner, it's what you see the command, retrying, retrying. Maybe your app will update. By default, it's four seconds, you can change it globally or per command. So let me look, set very long, and now it will retry, retry, retry, because we never know when your app actually will finish updating UI, all right? And like this can happen for multiple reasons. So if I can go here in this application, right? And right now it's app title. But if I change it, and I add to, yeah, did you see the test just passed? because all of a sudden it found the element, all right? So commands with the querying commands like find-me-element, there should be five, right? The command plus assertion, they keep retrying and that blue spinner and progress bar shows you how long does it take for it to work? The other thing that's important here is that we're using Cypress Open, right? Here's the difference. So I'm going to make this test fail Right? This fails after four seconds. Great. I'm going to close Cypress just for now. Okay. And now it's running this test. So when you work with Cypress and you work on the app, you use Cypress Open. That's what brings the browser, that's where you can watch the files, everything. There is also Cypress run command. And so right now I have my app running. I will do instead of Cypress Open, Cypress Run. Now, because we have a lot of different spec files, I want to run just the one we were editing. So I'll say spec cypress-integrations 01 basic spec. So this test fails, right? This is what happens when you run Cypress headlessly.

7. Running Cypress Headlessly and Selecting Elements

Short description:

When running Cypress headlessly on a continuous integration service, the test fails and provides an error message. Screenshots and videos are automatically captured during the test run. It's important to have a powerful machine to avoid stuttering in the video. Cypress offers best practices for selecting elements, including using IDs, roles, text, and specific data attributes. XPath is not recommended. Page objects can be used to create reusable code. The section also highlights the retry functionality of Cypress commands.

So this test fails, right? This is what happens when you run Cypress headlessly. And this is what you would do on continuous integration service. Right? You would say Cypress Run. And so it says, okay, this is my version. This is the files that I will run. And so it goes through this file, right? And it just has, you know, non-graphical terminal UI. All right? But this fails, just like we know it's supposed to, right? And it gives us the error message. Could not find the text content within that selector. Okay? And then it shows screenshots. So you can open those screenshots. They're under Cypress screenshots and named after name of the spec file and the failing test. So this is how my app looked when it failed. Right? So this is the headless mode, right? We never saw Cypress come up or not. You can also run the same thing in headed mode. So, and you can run right now trends of electron but you can say browser Firefox or browser, right? And by using headless or headed, you can change how it runs. So right now we're running in noninteractive mode but in headed. It doesn't make a difference. It's all the same. Okay. It will just fail and finish. Right and the screenshot is saved. My machine is slower, right? Because of Zoom. Here's another thing. So take screenshots. So you can disable screenshots. You can disable the video but it takes automatically. Let me show a video really quick. Again named after the spec file. Okay. So on your CI, on every operating system, you don't have to install anything, right? It works out of a box. It takes a video of the test run. Now notice how video is a little bit jerky. It's not as smooth as it could be because my machine is now busy with Zoom and recording, right? So when you see kind of like this little gaps in video or dropped frames or like pauses and stuttering, that means your CI doesn't have enough CPU, all right? To actually run Cypress because your application might be large, right? You might be doing a lot. Cypress adds its own overhead, right? Like all this command logs and right? And we're also capturing with video. So you need a more powerful machine if you see stuttering inside the video. The speed doesn't really matter, both headless will I think run approximately the same. Cypress is not good for scraping but it's good for running tests. Okay. So this was the Cypress run, right? Recording. So how do you select an element? So we have our opinion. We have best practices, right? And so we'll take a break after I finish this little section. Okay, before we go. So here's our opinion, right? And you might agree or might not. So let's say we have a button and it has ID, right? Some classes and so on, right? We have role and we can also add custom attributes and we also have the label on the button, right? Submit. Okay. So, you know, if we just say, get me a button, well, that's kinda weird, right? Cause there might be a bunch of buttons. So it's, we definitely don't recommend it. We also don't recommend using classes that are used for styling, right? Like, you know, bootstrap button and button large, or tailwind. This can all change. So probably shouldn't. You might want to use IDs. I mean, IDs are pretty stable, but they can still change, right? And they can clash or whatever. Using roles, right? Or using something that you use for, for the form. I mean, you, you can use it, but now it becomes like a judgment call, and like, it depends, right? Maybe you will move away from a form and then you have to write with that. Things like text, right? Something that's visible to the user. I think much better, because they're like the obvious, if a site contain submit is not there, like fails to find element, you just look at screen shots. It's like, oh, wait, we renamed it to like order. And so it's easy to fix. And also we really prefer using specific data attributes. All right, like by adding data, like test ID or data side. All right, okay. So let's say, why is it better? Well, because the text could be translated, right? Your application might show different text. So for just now, you know, contains, but by using ideas, right? You can do this easily, okay. And anyone who looks at this markup and says, okay, how do I find the button? Timur, can you ask a question in the chat or, yes, on Zoom or on discord, please? Anyone looking at this markup will say, okay, data side is for my testing needs. Perfect, there is no doubt. XPath, I don't recommend. We have XPath plugin, XPath are so hard to understand and see. So I wouldn't recommend it. Okay, what else? So testing library likes roles. Fine, get by label. Feel free to use it. You can just import and it adds custom commands. So I, it adds just a little bit, but it's your call. What if you wanna use page objects? So let's say here. Okay. Let's say here, instead of like accessing this directly, you create an object, right. Page object, right. And you say title selector. And you just move it here. And instead of accessing, you say page object, title selector. It works exactly the same. It's up to you. If you feel like you have many tasks that need to access title selector, move it somewhere, right. And like reuse the code. It's just normal JavaScript. You can create your own abstraction so that you don't hard code the selector, okay. What selected do you choose for label element with item into the list, right? So we'll get to that in a second once we start writing those tests. So in this section, right before we take a short five minute break, I showed how commands retry, right. So it doesn't happen instantly. You just say, find something and assertion and it keeps retrying, retrying if it's safe to retry and you can control the assertion.

8. Running Cypress and Organizing Tests

Short description:

In this section, we learned about running Cypress in non-interactive or headless mode on CI using Cypress Run. We also discussed the importance of adding items in the TodoMVC app and how to organize tests using Mocha Hooks. We wrote our first test, which involved opening the app, finding the input field, typing and confirming the presence of two items. We also explored Cypress's time-traveling debugging feature and learned about making tests independent using beforeEach hooks.

And then I showed what you can run Cypress in non-interactive or headless mode on CI using Cypress Run and it takes videos and capture screenshots. Okay, I'm gonna take a five minute break. So now my time is 1110. So let's continue at 1115, okay? In five minutes, stretch your legs and we're gonna start writing test and best we will like use selectors and see how we can select the element to confirm. Yes, various Cucumber plug in for Cypress so you'll be able to run, write tests using Cucumber.

Okay, one quick question. If you use Datasite, right? Do you want to strip it in production? No, not worth it. Both attributes they add very little, your page is gif zipped and compressed. So both things add minimal overhead. You probably have like a single image what is larger by 10 times and all those things. And if you strip Datasite attributes from your production code, well you won't be able to test the application code, right? In production. So I say, keep them in. By the way, yes, Cynthia, we recently published a blog post how to run Cypress on M1, now a Cypress blog if anyone is struggling. I personally don't have M1, my laptop is probed from back in the days. But it seems to work pretty well. And I have all the ports, so I'm not switching any time soon. Okay, so let's continue. We kind of wrote the first test, right? But now, let's exercise our app and how we can organize our test using Mocha Hooks.

Okay, so we have TodoMVC. What's the most important thing that TodoMVC has as an app, right? And this is what you discuss with your team or decide yourself. Is the most important thing to be able to check or complete an item? Is the most important one to delete or is the most important one to add? I mean, if you cannot add an item, well, none of our features would work. I say, add an item. So let's start adding items. We will work in Cypress integration 02. That's our current section. So I will open that file right here in my text editor. So Cypress integration 02 adding items, SPAC. Okay, we already have a couple of placeholder that's there. We don't do anything. And we can start Cypress and BX Cypress. Open, in interactive mode. 02 SPAC. Right now, I believe most of us does nothing. So we will either fail or do nothing. Okay, or we adjust placeholder tests. So no commands for issue. Okay, the one thing that I note here is that those tests will probably fail because we are not deleting any items. So before running the test, you probably want to make sure you delete everything. And that there are no items. Okay? We'll learn how to reset it a little bit later. So let's write our first test. It's end to end, but means we want to open the app. We want to find the input field. We want to type something, click enter. Type something else, click enter. And we want to confirm that there are two items. So I will do it to show how it works. And I encourage you to follow along. Let me just close this thing so it's. So this is the test. In order for us to concentrate on just this particular test, I will say it dot only. So this is a modifier for mocha, that says I just want to run this test. So if I save it, notice how Cypress only now has that particular test. Okay? So what do I do? Well, first things first. I don't even have my site. So I have to visit HTTP localhost 3000. Okay, great. Well, then I have to find this input field. So what I can do right now, I can open my dev tools and under elements, hover over that element, right? Maybe inspect it, see what kind of classes that has data attributes. Notice when we hover, the dev tools itself tells me it's an input with class new to do, right? Like right right there. So I can say, so I get, it doesn't sometimes gets in a way when it's that large. Input, new to do. Okay, does it find the right thing? It does find the right thing, great. So now that I found that input, I encourage you to type along, right? So you kind of get sense. I will type just like a user, right? So let's say first to do. And when we want to type enter with special key enter, we'll just say enter but in curly braces, okay? So think about this. So we found input, we typed and notice the command log, right, shows something interesting. So I'm going to click on a command to pause it. And now it shows first of all, the input element by this thing into. So this red dot is the central element we're typing in. And also because Cypress looks at your app and it notices changes before and after the command, it actually has two snapshots, right? So notice like right here when we hover over visit, it shows an application not like it is right now, but how it was during the visit command. So Cypress takes automatically dump snapshots. And when you hover, it actually restores those, right? So you can kind of see how the app looked at each particular step. So we call it time traveling debugging. And so when it typed, Cypress noticed before and after, it looked differently, right? So before we typed, there was nothing after a new item was added, okay? If I want to continue typing, it's kind of like chaining. If you still have an element, you can type more. So second to do, enter. So it typed first one, then the second one. And now we have three total elements. Okay, question was, well, I have this test and then I have this test, right? Do I have to use visit? Okay, so let's run two tests together, all right? So I'll say only and only. So now we have two tests. You want to make your test as independent from each other as possible. So if you assume that the previous test has to run before this test can start, that brings dependencies, right? So it becomes hard to just concentrate on a single test because you have to run the previous test once, right? What happens if you wanna continue working just on a second? Well, you have to still run both. So the way we advise is to make every test independent. If you want to have something done before the test, move it into beforeEach hook. So beforeEach is a Mocha syntax that says before each test run this callback. So in our case, we want to visit the page before each test, so I'll move it here and I'll remove it here, okay? So now, every test will run in this. So this is how you refactor a common code into beforeEach. But it's also before, which runs just once. I'm not great fan of single before, right? To me, it's always easier to understand a test if it does exactly the same thing, before each.

9. Marking Items as Completed

Short description:

In this section, we add a couple of items and confirm the expected number of items. We then mark the first item as completed and confirm that it is displayed as completed. We also check that the second item does not have the completed class. We use the first command to select the first element and find the toggle element inside it. After clicking, we assert that the element has the completed class. If it doesn't, we start again from the top and confirm the first item's class. We then use the first command to select the second item and assert that it does not have the completed class.

Another thing, oh, let's finish this test, right? So before I continue. So this test added a couple items. But we never confirmed that the app actually works, right? We never confirmed that there are a couple of items. So let's say you have item. You wanna confirm that there are expected number of items. So again, let me just pop in the DevTools. Inspect the item. Right. And then I have a choice. Well, I have list item class todo. Okay, so nothing special, but why not? So I'll say, sci get, so get me all items, list items with class todo. Should have length. And I already kind of showed this. There should be two items. And I'm going to delete this. Great. And I know I did recommend not using classes, right? But it's my advice, so I can break it whenever I want. No, it's up to you to pick a good select, right? In demo apps, usually it's not that important. Another thing is that because this application is part of TodoMVC kind of standard thing, we kind of work with what they give us, right? Like we didn't re-implement this application. The good thing is that these tests work against if you go to TodoMVC, right? The actual thing, pretty much all of those implementations, you can run our tests against those TodoMVCs and then the tests work. So in a situation where you don't control the selectors, you have to work with what's given, okay? Okay, so now our test fails because we never reset the data, which we'll do later, okay? But the most important thing here that it works now. So now let's continue.

So now that we have a couple of to-dos, we want to mark an item completed. So what, how can we do it? Well, let's start with this test. Let me just make it a little bit smaller so it would make a lot of sense. So I can do the following. I can take this code, all right, add it here. All right. Add it here. And again, why do I, you know, enter a couple to this? If the previous test already created, because I don't want one test depend on the state on the data left from another test. I want every test create everything it needs in order for it to go for the whole thing. Okay. We're going to refactor it in a second. So like the repetition is very small. Okay. So we have two items, right? Now we wanna make sure, and I encourage you to type along, right? So now we wanna find and mark an item as completed. So what do we do here? Well, we found the do-to items. We confirm that there are two of them. Then we'll take the first one. So first is a command that says, if you have previous list of DOM elements, just take the first one, and we have to somehow toggle it, right? Or mark it completed. So let's see how it works. So we have an item. If we open the DevTools, but wait, if the DevTools don't open for some reason, we have a problem with the bio-protocol or something, close it and run it again. So what am I gonna do? So let's say let's say, I will go to the class and I will specify the COM team component. Let's use group for this so that I can go to the div and now I can run it. Let's keep this, it should open all my lists. Let me remove it. Okay, so it found two elements, took the first element, list item, and then found the element. So the difference between find and get. Get starts from the top, from the whole document and then finds all elements that match the selector. Find starts with a previous element. So you cannot just say a sided find cause there is no parent element. But if you have a previous element, in this case, you have it. When it returns you just one found element with selector. Right, so in our case, we've took this whole big list item and inside, we found an element with class toggle. Okay. And I'll say click. Okay, so found first one, found the toggle and then clicked. Now one little thing is that the element is no longer visible. Right, sometimes especially checkboxes and UI libraries, they have to hide elements under another one or becomes visible only on hover, right? So you might see these things or if there was element and then it was removed, it will become no longer visible, okay? So we added a couple items, we confirmed a number, we complete the first item, it was a command. So now we have to confirm that it actually is displayed as completed. Again, how does our app do it? If we look at this element, we can see that the app adds this class, completed. So after clicking, we wanna confirm this element now has class complete. So I'm gonna just copy paste this, so we're gonna find our elements again, we're gonna take first and we'll write an assertion. So should have class completed. And I'm gonna copy, so again, this is our check at the end, we found the two items, we found the first one, and then. So could you change the should after the click while, so think about this, when we found the toggle button, right, and if we click on it and then should have class completed, but it's not the toggle button. Right, so let's see what happens. You know, I oftentimes I just code, like I want just to see what happens. Okay. So it failed, right. And it shows you where element, right. And it shows you to have class completed and then it shows that it was toggle, right. So it wasn't, it's added on a parent element. So we could potentially do click and then say parent, right, kind of go back. I don't know if it's gonna work or not, but it's debut. So we wanna say parent to the, okay, so it's still not. So we can inspect and see which particular element it found when it says parent. It says it could not find the parent with class, right? So at this point, the test is already kind of weird. Let me close this. So I would say, no. Start again, like we did it here. Where we went again to the top. Okay, so we confirmed that our first item gets the class. We have to confirm that the second item doesn't get the class. Imagine our application makes a logical mistake, right? Maybe some user says, okay. I marked the first one complete, but it actually marked all of them completed. We forgot like the filter thing. So we want to add a second thing. We want to say the second item should not have class completed, okay? And the question is, how do we select the second one, right? Well, we have a special command first, just for clarity.

10. Using Equals Command and Refactoring Code

Short description:

The equals command allows for selecting elements by index. Refactoring the code involves avoiding hard-coding the URL and using utilities for common interactions. Page objects are not recommended for every element. Instead, refactor code as necessary and remember to use JavaScript. Deleting an item involves finding the item, clicking the delete button, and adding assertions to confirm the deletion. The contains command is used to verify the remaining items.

There is another command equals, all right? Where you can select, you know, first element or second, or you can select from the back with negative things. So if we want to select the second item, we use equals index equals one, so I'll move this. Okay, so we found the first item, right? And it has class completed, and we found the second element and it doesn't have it, all right? And you can, you know, chain. So this, like any selector works, right? Right? This, you know, CSS, jQuery, selector. So you can create pretty complex things, but make sure you're not over-complicating this.

Okay, so I answered this thing. Now, what else do we do? So this is how we did this. So let's refactor the code. We already visiting the thing before each test, right? So all the common things that we do before the test are factored out. Another thing, we are hard-coding the URL, which is definitely something I would not recommend. So what we can do instead, and by the way, by hard-coding the URL, notice what happens here. Not in this file. If it were... if it were like a HTTPS page, you would see the page reload completely because Cypress doesn't know which domain you want to visit. So if it's HTTPS, right? You want to put that URL into Cypress URL, Cypress JSON file, okay? So this is where URL, but all our tests kind of work with, all right? So now in my spec file, I can just say, visit like the root of base URL. Okay, so this is better for multiple reasons. One, you will avoid like with reload on site visit that happens with HTTPS sites. Second, you'll be able to override this URL, the base URL on the flight. So the easiest thing, if you, for example, running on CIS, right? And you want to like test your staging site, you will say, NPX Cypress run, and then you'll say config base URL and you say HTTPS, you know, QA company. So this is how you change your base URL. Another thing you can do is use environment variables in this case. So you can say, Cypress base URL, you know, HTTPS, QA, Cypress, or like whatever company you're. So this again, changes the base URL so that you don't hardcode it, okay?

Again, did you recommend not to use classes for selectors question? Absolutely, right? But to do is more semantic. But again, it's useful styling as well but this is not the application that I can control. Another thing is to, instead of creating complex page objects for everything. Look at this file, right? So I need to create to do items in every test. So, okay, I'll say add item and text and I'll say size, what is it? So pretty much copy what I had in this test. And I will just have to change it to say text, right? So whatever I pass here, I'll type into the input box. And now I can say first to do, second to do, and I can remove this things. Alright, it works exactly the same way. Right. And these things are very lightweight. But individual functions right now, notice that it says text any, I can just describe them using just doc, add new to-do item. And I can say param string text, okay? So now IntelliSense is working. It knows that it expects text. Okay. And because typePress already comes with everything, right, necessary, you can just take that function. And we are right here in the spec file, and then we can create, you know, utils. You can copy that, export. And then inside your spec, you can say, import add item from utils. Perfect. Works exactly the same way. Right? But I don't need complex abstractions for everything. Just as soon as I see, like, oh I'm using the same interaction with my page, I can create little utilities. And notice even inside this task, right, that marks completed. I only really abstract what is necessary. Like, I don't want to abstract this thing. I don't want to create complex things on top of my page UI, but say, oh where is the toggle class inside review, right? Because this is the only place where I probably will toggle that button. So I will not need this anywhere else. So don't abstract the whole page just to be able to test it using PageObject. Refactor your code as necessary. And remember, just JavaScript. Okay. Let's code together, deleting an item, right? So I kind of answered the question about recommending PageObjects. No, I recommend the small functions like this. I think they're much easier to reason about than PageObjects. So, can you share the code of refactoring? Well, it's not really required here. So I would say, just like code it yourself. Okay. So let's write the second, or the third test, right? We can delete an item. Okay. Add a couple of items, and I will confirm that there are two of them. Again, I have to delete everything before it passes. So Lindsay, I'm cleaning the items like manually, okay? Before rerunning the tests. So if I wanna rerun, we'll learn how to clear the state of application in like 15 minutes. Okay, so I have my items, and let's say I wanna delete the first item. I have to find the first item, so I'll use the same thing. Now I need to click on this button. Notice that this button, it becomes visible only when we hover. Unfortunately, there is no hover in Cypress unless you use a plugin, because it's a native event, which is fine. We don't need it. So, I will inspect my markup. I can see the button has a class Destroy. Okay. So, what I can do, I can say, once you found the first item, find button with class Destroy and click. And after we perform an action, we want to add an assertion to make sure only the one item remains. Okay. Even better, we want to confirm that the first item. So, mouseover can work, cannot. For example, if it's a CSS class on hover, it won't work, right, because mouseover event is not the same as setting a hover state. A hover state. But we'll have native events anytime soon and there's already a plugin to do that. So, we confirmed that the number of items is the same, but maybe we deleted a wrong item. So, what we can do is say contains to do with class first todo, second. And, let's say the first todo should not exist. Okay? Now, Vistas fails. See how it doesn't, it refuses to click a button that's invisible. So, remember side visit command. It has all these built in assertions. Right, the server has to respond, it has to respond with, like HTML 200.

11. Simulating User Interaction and Queuing Commands

Short description:

Cypress has built-in assertions that simulate how a human user interacts with a website. The time-traveling debugger allows us to track changes in the application. Cypress does not come with built-in native events like hover, but there is a plugin available for simulating real clicks. When writing tests, it's important to cover the main use cases and perform basic checks. Cypress commands are queued up and executed, allowing for retries and dynamic interactions.

On page load event has to fire. So, Cypress, in every command has built in assertions. For example, if you want to click on a button, it says Cyclic failed because the element is not visible. So, imagine a human user. If I don't see a button, I can not click on it. So, Cypress behaves the same way. It first scrolls an element into a view port, it makes sure the element is not covered by something else, it's visible, it's not disabled. So, all these checks are built in. And they're trying to simulate how a human user would use your website. So, in this case it says it's not visible. All right, to fix this problem, if you really wanna, like, just use force true. Okay, I will use force true.

So, onClick I'll say force true. Okay, so what happened here? Again, we can use time traveling debugger. So, we found two list items. Okay, we found the first one. We found the destroy. We clicked on it. And you can see how Cypress noticed that the list items changed. So, it shows before and after. Right, we can see the execs calls that application is making, right, to the backend. We see Li, to do, right, has now length of one. We don't see the first to do, text. But we still see the second to do. It still exists. So, we confirming that we're deleting the right item. And again, Olga, so the hover is a native event and Cypress doesn't come with built-in native events yet, but there is a plugin that you just add and you can simulate, like, real clicks. Not simulate. You use Chrome debugger protocol to send the real event to our page, just like a real user, so where there's a hover as well. Okay, we can extend this test. Does the app return the second to do, if we reload, right? If we reload the page, like it should, so we can say, Cy reload. Perfect, we can see what is there. We just have to confirm, so we'll say there still should be a single item. So the interesting thing is now you can kind of see what are all the possible things that might go wrong. You don't have to necessarily write like exhaustive tasks for everything that can go wrong. I'll do, go through the main use cases of your application, make sure they work, right? And the most basic checks. Then if you find that very, some kind of mistake and something fails, then you can add the tests as needed. Right? And this will be your regression test. Again, no, the mouse over doesn't really replace the native hover because it doesn't trigger the CSS class changes. Like all the active and focused, and hover CSS classes, pseudo classes I would say. Okay? Okay. One more test just to kind of finish this is, because it's just JavaScript, if you want to create multiple items, like write for loop. Now, here's a for loop, right? So I'll just say this thing. And I'll say to do, and I'll just use this variable which is right here, K plus one. And now I'll just confirm that for where it's expected number of items. So I'll clean it. So here's what that's right. I will add five items. Each item will be named to do one, two, three, four, five. And when I'll confirm for our five items, so the test should pass. Now, K is not defined. It's not K, it's N. Okay. So, I think Eric asked this question, where are all the awaits? Notice with our tests we don't write asynchronous JavaScript so to speak. We kind of write commands and assertions but they kind of look like synchronous code. There is no, let's say, like await here. In fact, if you try this thing, it would fail miserably and would not work and would be very confusing. And most our test runners, they actually use this. We don't. So when you use async await, right? So if you declare a function, you know, as async, or if you use, let's say await here, it's exactly the same as you use promises. So if you use like await here, and it would be exactly the same as add item right here and then, and then like continue, it's harder to type, right? So this would be the equivalent code. Even worse would be... This is fine, right? This is fine, but what happens here? So I have this assertion. First, it's a command and then we run assertion. We wanna make sure that there are an items. So if we use async await, like ours, right? We could say, like all these elements will just await. And this looks simple, right? And I agree. This is more explicit, less confusion. But then we would say, okay, let's say, expect li to have length, let's say n. So we would do something like this. So these are promises, right? So this is exactly the same as saying, where did this go? As saying, get me, and then you will get li and you will do something like this. So these are two equivalent. Here's a problem. If we did this await syntax, right? These are promises. For promises in JavaScript, execute just once. Okay? Just once. It's a single shot attempt. So if we run this once, and we get the list items, well guess what? None of this, like if list items has a different name, right, if we have to retry, we cannot go back to this promise and execute it again. Okay? So if you do this, using async await, once you've got this list of items, that's it. If it's the wrong length, if the element is still not there, if it doesn't have a class, right, like we write all these assertions. Well, you cannot retry it. Like all those spinners would be impossible. That's why every test runner has this weird syntax where they say like expect, you know, or like await, kind of like, so I get to have like weird syntax for doing operation and also then checking assertions immediately. Just to get around the thing that await only executes once. So Cypress commands are completely different bits. When they run, all right, so let's say this syntax, right, that's like really simple. You kind of write instructions to a human, like add item, add item, add item. What we do instead, we cue them up, right? So we queue a command, like, Cy get input to do, type. Right, like this is what it really is. So when you execute this thing, you add all these commands five times to the queue, then you add this to the queue, and then you start running.

12. Cypress Commands and Viewport

Short description:

The browser opens and executes the first commands. We have the entire list of commands before opening the browser, allowing us to go back and redo steps if needed. The syntax used in Cypress allows for declarative test writing. The return of an element is not possible as the command is scheduled to be executed. The viewport command can be used to change the size of the application.

Then the browser opens, and the first commands I visit executes. We have all the whole list of commands before we even open the browser, which means that if this command, for example, fails, after it goes, we can go back, re-execute again, like much smarter stuff than Promises. Promises, single execution, we are reactive stream of events where we can go back and redo things because we know we have to retry those steps. Right now, if this assertion fails, we go back to previous command and retry it. We probably should do it to retry the whole thing and so on. But that's why these are not promises, right? And middle-news async away, because then it would be really, really limited and this syntax, like declarative test writing, would be impossible. Which also is why it's impossible to assign the return of an element on. So, let's say we do this. And instead of this, we do like Cy constant ele equals. Okay? By the time when this executes, right? It doesn't actually do get elements. It just schedules the command to be executed. Which means, so here, li is still undefined. Okay? So if you really want the number of elements, right? You would say that. This is a special thing we do, which kind of looks like promises, but this is not. So this runs as many times as necessary, and then it passes the results to that command. So that's why you can just say, constant text equals get title. Right, because when this executes and makes the assignment, none of it is there. Okay. So it's 1154. Let's see if I have anything here. Oh, there is this command called viewport, which is kind of cool. Let me, you can try it out. So right now my test, right, passes. As you can see, I'm running my application at 600 by 800. How does it look when like the viewport is smaller? You can change it and say viewport, and say, I don't know. You can give dimensions or you can say iPhone, or you can say four. And now this is how your app would work. So in this case, everything is fine. Done, done.

13. Conditional Testing and Selecting Elements

Short description:

When writing tests, it's important to add assertions to the commands. Assertions help ensure that the expected behavior is met. The site pause command allows for stepping through each command and inspecting the application. For longer tests, it's recommended to use end-to-end tests. Cypress can run tests in subfolders and allows for organizing tests by feature. Selecting elements can be done using the selector playground or the experimental Cypress Studio. The Studio mode allows for recording test commands based on user actions. However, the selector suggestions may not always be perfect.

So question, can I do something if element like is present or not, right? Can I do something like if I get, say, button, right, else, so for that we call it conditional testing. So if you go to docs and you say conditional and we have whole discussion like why you should not do that. You never wanna not know what to expect in the page. If you have to, we kinda give walk arounds, right? But you always wanna go from data, right? And always know what you wanna expect on the page, okay?

You can go from what is one discussion about before we go to a break. So these are unit test, right? If you ever use just a MockA, they also just that you kinda like get your function or code under the test, you perform a single action and then you have a single assertion. And this is important because if a test fails you only have really the name of a test. So if you have multiple assertions and one of them fails well it's hard to understand usually which part failed and why because there is no time traveling debugger. For end-to-end tests like I'm showing it you can write longer tests. Jennifer, try just searching our docs for this link. Okay, we have to probably. So notice this is a typical test. It goes for where you use the story, step by step and it has multiple assertions because every command usually has built-in assertion. If something fails you have video, you have screenshot you can pop the test and start running it yourself and kind of see what it does. So it's much easier to debug a long test and log test really corresponds to the whole story. Another thing for longer tests is to do the following which is kind of cool and like my favorite thing to do after I learned about it. Check this out. I'm gonna delete those items. I'm gonna remove this. I'm just gonna do the site pause and you can do it anywhere. So right now it just did site visit, right? And now I can step through every command one by one and I can see what it does. I can open DevTools, right? I can investigate what my application does versus. So site pause is really good cause it will allow you to write longer tasks, understand them, right? And then use time traveling debugger to understand maybe what has happened as well. So my personal rule of thumb is if you're describing like little piece of code just write a unit test, longer like a user story it's end to end. You can split, no, specs. You can organize them by folders. Cypress can run on the subfolders. And then we were writing like individual tests, right? But you can also group them, right? You can say, this, let's say, describe, let's say, toggle. And then you can have a series of tests inside, a particular, describing a feature. And you can have common before each hooks, so you can set up the data for that particular thing.

So Lindsay, if I understand correctly, the side-pause is a command you can add to your test to pause at a specific place and then step through the test, okay? So I've shown how to write a test that goes for your user interface of your application and executes the same thing as the user would to add an item, delete an item, toggle, right? And then make sure when you add those commands, don't just add command, command, like check, get, type, click. You also want to make sure you add assertions. If you add an item, there should be more items, right? Like, we expect a number of items. If you complete an item, there should be a class added or class removed. Don't just do actions, vary actions and assertions.

So Eric, I definitely recommend KitPitch, right? It's, notice what, this is what it takes to actually write KitPitch slide deck. You just write markdown like it's shown right here. Right, you just separate slides and then you include images in all in VectorRepo. And then if you use their URL, the same file is displayed as a slide deck. The simplest thing. Now they are moving away, so I'll have to find something else. So I, for my needs and for the company, we actually use Slides.com because they are amazing, right? They know what they're doing. They know like the UI, the experience is just unbelievable. They use Cypress to test them, we use them to show off. They can also import markdown. So we probably will just, it's the same people behind reveal.js. So we probably will switch them because git pitch is moving away, but it was good while it lasted. So I think it's pretty close. You can probably will be able to just take the markdown and generate slides a couple. That, but I don't know, haven't done it yet. Do Cypress end-to-end tests reduce the importance of integration test and vice versa? So integration test is a test where you take, let's say, a couple of components and try to see their work together, right? Maybe with some other parts of the stuff. So, yes and no, right? But I would start with end-to-end tests because that's the only test that matters to the users. And what we'll see really soon is that you'll be able to stop parts of your application, even from Cypress, for example, like network calls and so on. So I would say start with end-to-end test because they don't reduce the importance of integration, but I think they're more important than integration when you start, especially. And when you can add integration tests, as you see, like things that are hard to test for end-to-end things. Okay, let's continue.

So a real short section, select a playground and Cypress Studio. So I have this as very short chapter, so it doesn't even care. It's not important to kind of try it yourself. But here's the thing. So, we were discussing selectors. I use DevTools elements, right, to find the selector. So for example, this input, even Chrome suggests input with a class new to do. Okay. But where does open, we can open select a playground. So here's how it works. Let's say, I have this test and I need to add, right, an item. All right, so what is this box? So I'm gonna click on this open selector playground. And now, I can just hover over elements and it will suggest. So for example, see how if I use data side, the test ID, it will speak back. If not, it will pick, you know, a class. So here, once I pick that, it even tells me command, I can copy it and let's see, paste it here. And I can say type, text plus enter. So this is how I would pick, you know, an element. The problem with that selector, right? So, if I, for example, try selecting this element, I don't think it makes much sense. Right, like this selector. So it still is imperfect, I would say. But here is something else that many people ask about us, like for a long, long time. Let's say I don't have anything here. Okay? Can you just click around the app and see if you can record the test from the user actions. Okay? So in Cypress 6.3.0, so basically, like last week, we released an experimental feature. So in order for you to see this, you have to go to a Cypress JSON and say experimental studio true. That's how we control experiments, right? We don't load them by default. But if you enable it in your project, then once the test is finished, you'll see this thing right as you hover over the name of test. So add command to a test. So you click that. So now this is called Studio mode, right? So interact with your site to add test commands. So I want to say first to do, enter, second to do, enter. So notice that it actually correctly interpret the commands and it doesn't allow everything, like only a few commands are observed. But when I click save. Wait.

14. Recording Tests and Adding Assertions

Short description:

When recording tests in Cypress, it's important to manually add assertions after recording actions. This ensures that the application responds correctly to the recorded commands. Cypress Studio can be used for this purpose. While Cypress may not have all the features of other tools, the team is open to feedback and aims to meet the needs of users.

Again. Notice the test executes, all right. And those commands are right here. And notice with it doing combined first to do and second to do because they have the same thing, right? It's the same element I kept typing. So you can try that, right? And you can give us feedback. Like, you know, where's the link, everything. But the one thing that I would say, notice that when we recorded actions, there was no way for us to record assertions because you see it, right? And we have no idea if you as a human, right, what you do. What you do. So when you record your tests, make sure after you done to go inside and say add assertions. Should have length too, because otherwise your test will blindly do things, but you have no idea if the application is doing the right thing in response to those commands. So definitely try Cypress Studio and see what happens, okay? I agree other tools have Chrome extensions and plug-ins. I think it's cool, right? I'm not sure if we'll be able to satisfy everyone's requirements, right? To have good tests, but we'll figure it out. We'll listen to your concerns.

15. Resetting Data in Cypress Tests

Short description:

In this section, we learn about resetting data in Cypress tests. The speaker explains that the todos are stored on the server and can be reset using a special endpoint or commands provided by Cypress. They demonstrate how to reset the data before each test using a side request. The speaker also discusses other methods of resetting data, such as writing to a file or using scitask to connect to a database. They highlight the benefits of setting up complex data before tests and separating tests by feature. The section concludes with the speaker addressing common questions about XHR requests, websockets, and when to reset data using before-each or after-each.

So a couple of quick questions. Do we have a second session if we didn't finish all the chapters? No, unfortunately, right? So we have three hours. I'll cover the most important basics, but everything that I'm covering, right, everything is available in the slides and in this repository, everything that I'm showing. So it's not like there is anything. It's just an opportunity to ask questions. And another thing, why do we call our tests integration rather than end-to-end? Just historical reasons by now, right? We probably should rename it to end-to-end and drop the name integration. Okay. So next session, our next chapter is resetting data, okay? So we kind of did everything manually. We removed all to-dos in order for us to type new to-dos and confirm for the two of them. But it's kind of a pain.

Okay, so let's take a look at the test number four. So let's back. Okay, so notice, right, but all the tests fail because none of them reset the data. So what do we do here? Okay. So the to-dos, the to-dos fetch from the server, right? That's where they're stored. So we visit the site. That's where they get them and so on. So we know that the to-dos are saved somewhere and I'm using JSON server, so I can control the server, right? And I inserted a special middleware there, so I can execute a POST, right? So check this out. So I can execute the POST using curl or something, right? So right now, I have all the items. So from command line, I can say, Reset, and boom, they're done. So I did HTTP request to a special endpoint, I introduced just for the purpose of resetting the data. I can do the same thing before my test. Okay? We have a special command. So usually you can not just do arbitrary resets, but in Cypress, there is a command, right? That can do it. So here's what we can do. I'm working with full spec. So I'm just gonna take the first one. Okay? The problem is, when do we want to reset it? Before or after the visit. So we know that as soon as application opens, right? It starts, it does a get request. So if we don't want to raise condition where I reset too late after application really asked for it, what we have to do is, before we do a site visit, we do side request. So side request is HTTP call that you can use. So I'll say reset, all right? And I'll say method POST. And I have to say to do is just set when you want. Okay, so let's see how it is. Okay, so now, notice I'm requesting this, right? I can open my console, click on a command, see what we send. I can see what the server responded. Okay? So now, every time I start the task, it's all the same because we reset the data, right? Okay? We can also, instead of reset, we could have used something else. For example, we have sciwritefile, where we can just write a different file to overwrite to do MVC data JSON. We could do that, right? Just make sure that you're writing the right file. You can see the path to a file that you've written. You can also use scitask, and this is the most powerful thing. So imagine you don't have a server where you reset it, but you have a database on the same host where application is running, okay? If you want to connect to a database and maybe truncate a table, right? Or check the table, maybe during the test with the record is great, you can use scitask. That's a piece of JavaScript code. It runs in Node. That means it has access to your operating system, file system, connect to a database, right? And you can use scitask, call it from your spec file and it goes to the plugins file, connects to a database, queries, and so on. So I can reset this. I can use scitask. Here is something else that we can do. So right now, every time we reset, we send an empty object, right? We're setting empty to this. But what if you don't want to do that, right? Maybe you want to set the data, right? And they immediately initialized more complex situation. Okay, so I have this example right here. So I'm gonna remove this and I'm gonna run this test. Okay. So here's in this test. I have a fixture file, so two items. Okay, so I can load that fixture, side fixture, I can say two items. Right now nothing interesting. Then I have to do this. I can even bring them into a console to make sure they're loaded correctly. Okay, so we're loading the JSON file. We have the items. Now I can copy this code and say reset it. And just sent, but to-do is to load it. And now look how cool it is. If I run the test it will always start and already immediately have a couple of items. So now I can delete an item, add an item, whatever I do. So this is pretty nice. Because this means that I can set up complex data before particular test, before every test. And the test itself will be very simple. Because it doesn't have to, for example, add items, mark them completed. So, for example, if I want to delete items I might as well reset the database from this test, and immediately go to deleting the item. Because my other tests will test if adding the items works. So my tests will be separated by feature rather than combine everything into one. And this separation helps out because if I refactor how I add an item, I will just have to update the test that adds an item. And my test that uses this fixture to create an item immediately will never have to be modified because we didn't modify how we delete an item. If we modify adding items. Okay, so every test will have its purpose and they will not be overlapping as much.

Quickly answering a couple of questions. XHR request and marking websockets? No, Cypress cannot do it for websockets yet. So, in the future maybe. Why would you reset in a before-each instead of after-each? Let's see if I have this. Here's why you would do it using before-each. So, let me just remove it and just go here. So, I suggest resetting the data using before-each. We could also say, when the test finishes, it will clean up after itself. So, we can have after-each. We can do this and kind of move it here. Aha, see the problem? We moved it, but there were already results from the test when it ran before. Our test can clean up after itself, but what about other tests? Are you sure they clean up after themselves all the time, correctly? Maybe not. So, I recommend using before-each, because you don't know what other tests are doing, if they really clean up.

16. Cleaning up and Network Control

Short description:

We recommend using before-each in our best practices. Resetting data within before-each involves executing the request before the data is needed. Tests where you don't know what to expect are considered anti-pattern. It's important to prepare the test so that you know exactly what the application will show. The next section covers network control, one of the best features of Cypress.

And that means you introduce dependencies. Now, here's another thing. What if the test crashes completely? Like browsers down, completely crashes. Well, the after-each will never run. And so it will crash other tests that assume everything is clean. For these two reasons, we always recommend to clean up and set everything your test needs using before-each, and never use after-each. After-each is okay for some weird stuff. When maybe you want to close database or send a message, right? But don't assume that will work, because your test runner can just crash and never do that. And so you don't want to affect other tests. So that's why we recommend using before-each in our best practices.

So answer this... How can I use the reset within before-each? Just like I showed, you just execute the request inside, before the data is really needed. Really quickly, Karim, so all the slides that I'm showing, they are already there. They're just markdown documents, so they're present, so you never have to download anything. If you look at all the chapters, everything that I've shown, these links, they're just showing these markdown documents already in this repository. So this will stay there forever. A quick question from Dmitry, if I want to check the difference between the old value and the new value, how would I do that? I'm just going to really quickly. Imagine you have a value when you click a button, and it's modified, and it's different, but you don't know what's the new value, but you know it should be different. I'll just send this. This is an example of a test that adds an item and then checks that the list has a great item. You can see because of the Cypress channel model, if you want to get the number of items, you do a command, you use then callback. That's where you get the value. Save it in a local closure variable. Click a button and then you can use the new length right here. It's not as straightforward. The important thing here is that this kind of test where you don't know what to expect is anti-pattern. You should know — especially if you can reset the data or as we will see in network stubbing we know how to stop network — you should prepare your whole thing so that you know exactly what application will show. Because then you can confirm everything and not have tests that maybe there are no items and in that case do one thing and maybe there are items that do another thing.

I think we have half an hour which is exactly the time for the last section which is the network control. I personally think this is one of the best features of Cypress and we have just improved it tremendously. So, you'll like it. Our application is making network calls to fetch the items, it's making network calls to delete items, add new items etc. So we want to make sure that those calls are happening and happening correctly. So, what can we do? I suggest we all open 05-xhr-spec. So, this has a bunch of tasks that right now are pretty much empty and do nothing. And here, I'll close everything. And I'll go to 05-xhr-spec. So, I'm prepared.

Okay, so we're going to start with a problem. And the problem is annoying. So, I have this test. It starts with zero items, right? Because we think, like, yeah, when replication loads, it should have zero items. Okay? Now, the test passes. It's all green. And yet, I don't think this is right. I can definitely see two items right here. So, what has happened? Well, here's the problem, right? And this is where understanding the test runner and the application behavior is important. Think about the sequence of events during the test. So, the app loads, it makes a call to the server, right? So, it goes and fetches the items. What does it do while it's fetching? It might show a loading indicator, maybe, but basically it shows no items, right? So, our test, immediately, because it has no idea what has to wait, shows get me all to the items. There should be none, right? So, no items found, boom! The assertion passes, and the test completes, because there are no other commands here. So, as soon as that assertion passes, right, the test completes. So, application returns some items. It shows them, great, but the test is already done, so it will never fail. You can see what happens, right, if we add a built-in wait. So, by the way, this is really anti-pattern, but if we have to, we have to. In Cypress, because of command retrace, you don't want to wait for one second or five seconds. You want to say, wait until there are two items in a list, or wait until there is a class and element. All right, so you do it by using CyGet and Assertion, not by using wait. Wait can wait for other things. So, now the test is failing correctly. But the problem is, you don't know how long you should wait for. Should I wait for 10 milliseconds? That seems to work, right. Should I wait for one millisecond? That should work, right? But the thing is, even if you say, wait for a second and a half, it might be okay on your local machine, right? See how this is actually incorrect? It passes too quickly. So 50, 150? Okay, that's good. Maybe just 50. In fact, why don't we look how long this takes? We can look at this network request. It took 25 milliseconds. So locally, if our test finishes within 25 milliseconds it finishes incorrectly. And if it's 30, then it actually catches. Okay, the failed test is correct. That's what should happen. Anything that passes is incorrect. It passes for wrong reason. So, when running locally, it could have one wait period. When you run on CI, it could have another one. Maybe longer, right? Because now the server is somewhere else, for example. Or the data is somewhere else. And this is very annoying because now you are having flake. When running on CI, sometimes it passes sometimes it's not. Because it's like right on the edge of that threshold. And so what do we do? Well, we keep increasing the threshold and pretty soon every test has built in 30 seconds just in case to avoid flaky test. So, in this case, first of all, you can say in Cypress if a test fails, you can say retries and let's say retried up to three additional attempts. Alright, so I'll say, I'll fail after 100 milliseconds. So if it fails, it will retry one more time. So if there's a little bit of flake and you cannot solve it, there are built-in test retries that you can try. You can try in Cypress open or just Cypress run mode. That's fine. But let's actually fix the flake in this case. So in our case, we don't want to wait for hard-coded one second.

17. Waiting for Application Updates

Short description:

We can write multiple assertions attached to the same command using should. For example, we can assert that the list items with the class 'to do' exist and have a length of zero. When multiple assertions are attached, they all have to pass with the same element at once.

We want to wait for something application does. So usually, our application updates with dum UI. So what we want to say for example, get me list items with class to do should exist, and have linked one. So you can actually write multiple assertions all attached to the same command by using either should, multiple shoulds or it's a synonym and is the same as should. It just reads nicely get list items. It should exist and have length zero. So notice in this case, it correctly does things because first, it says it should exist in a DOM. So this will take care of waiting for the app to actually return. It cannot be undefined, and then we say length zero. So you can add more assertions to wait for the DOM to do something. Let me remove where it tries. And the thing is notice when we attach multiple assertions, they all have to pass with the same element at once. So this passed, but this one's always failed because there's always two instead of zero.

18. Spying on Network Requests with Cypress

Short description:

To spy on network calls in Cypress, use the Sciintercept command to create intercepts before visiting a page. By giving the intercept an alias, you can save it and see it in the command log. You can also specify the type of request to intercept, such as GET or POST. To wait for the intercept to happen, use the cy.wait command. With intercepts, you can spy on network requests and ensure they happen before working with the application. Additionally, you have full programmatic control over the requests and responses, allowing you to modify them and add assertions.

Okay, I'll answer it later. Okay, so we can wait for the DOM to update. But in this case, we also know that our application is doing this request. So the first thing we wanna do is make sure that that request's finished. That's where we can start working with app. So not just the DOM, not just with document and browser and elements is observable. That's what we can, from Cypress query and so on. The network is something else that will browse the sense that we can observe from Cypress, and wait. So, what we wanna do when we visit the page, we wanna spy on network calls. And we have a command called Sciintercept where it can spy or stop. The most important thing is to make sure we make the spy or stop before it happens. Which means, if you wanna spy on something, right, so, I can not just intercept. To those. Actually, I'll remove. So, this is my intercept. If I do this when it's too late, okay? It might be, you know, caught, but it's a race condition. Okay? You wanna intercept. You wanna create it before you visit a page, before it happens for sure, right? So, this is the correct way. You can give you, you know, this intercept an alias, so you can save it as, let's say, loading. You can give it a name. And then, you can see that it actually shows up in command log. So, you can see how it happens. Okay? When you create those intercepts, you can see this new table. So, we are looking at all URLs, but go to URL, todos. We're not stopping, we're just spying. We just wanna know when it happens, right? And we gave it an alias, and it happened one time. We can be more specific and we can say, get. Because adding an item also will go to the same URL, but using post, right? So now, we are more specific. Okay. And instead of waiting for one second, once we have an alias, we can say, side wait. Okay, now it fails correctly. Because we waited for application, notice now like how it used to before. Notice here, we got the items before the network happened, but by adding wait, we have to visit first, wait for network happens, and then we'll try getting all these items, right? So we reorder the commands and the actions. So now we've waited, now we're getting it, and now there is no more confusion about zero items, unevent items. So this is how you can spy on network request and make sure it happens, right? Before you incorrectly assume you can start working with application. Okay, so this is good, right? Can you also specify parameters of a network request in the intercept? You can do whatever you want, right? So a good thing about those network intercepts, right? Not only... I mean, let me just show it, right? So this is correct, right? Let's make sure that initially, right? And we're gonna reset the thing. So request first reset. So, before we run, we make sure there's no data. So we loaded the data, right? And now application loaded the data. Let's make sure that actually, like returns the right thing. So if you click on this request, you can see what Cypress has done, right? Like it says this is the URL that you are interested in. Right? So this is this thing. If you click on the wait, it actually prints the whole intercept. Right? Into a command unit. So this is where you can see what was the request from my application. Right? All the headers and everything. What was the response from my server? And if you can wait, right? You can say it's... So look at this. We are and we call it yielding. So once you get this command, it gives you a big object. Inside the big object, you have response property and it has body. So we can say it's response body should be equal empty. So this is we're spying on intercept. I guess maybe it's not. So we can drill down with network requests and make assertions against things we're sending or things we're receiving. The request is pretty complicated command. Not only you can just specify parameters, you also have programmatic control which I can just briefly show here. But it's up to you to kind of look for examples because there is a lot of things that intercept. Wrong command, okay. So for example, you can have you can write your own logic where you can inspect the thing that your application is sending and add assertion you can modify what your application is sending. So application sending one thing you intercept, modify and when it continues you can reply, which means application is sending a stuff you look at that, make assertion and then like reply immediately, so you stop the network so it doesn't go to the thing. You can also, once replication replies, right here let me see. Once application response, I mean, application sends the request, you intercept it, allow it to go on it goes to the server response and now you can modify response or add assertions. So for example, if you wanna make sure that your application sends like my project text, you can do that, you can modify it, okay? So you have full programmatic control of wherever is sent by the application to the server and wherever application receives back. So it's pretty powerful. So if multiple requests are sent one after another, right, I already forgot this syntax, to be honest. I think it's something like, I can do something like this. Like the sec, no, no, it's not this. I forgot, we have to look up how to get to separate request from a separate call. So if insertion fails in your intercept, it should fail the test as well, right? So for example, here, if we add something like this, right, and you say like expect rec body to include, right? So it should fail, if it's not, then it's our bug, okay? And if there is a way to combine multiple waits like promise all, I think yes, but you have to look at our docs. So can you kind of do like something like this? And imagine where it's like, I don't know, post-it, like multiple Alice's. So site intercept, as supposed to do, right? I think, yes, but you have to look at documentation. Okay, so what else is intercept is useful for? So we were resetting the data, right? Every time before the application is loaded, we would request it. I mean, request, reset, okay? But here's something else we can do. Instead of doing this, we can say, whenever application makes a request to get to those, just respond with empty list, okay? So here's how it works, Okay, one second. So something is happening here, maybe so this responded with body, okay. Actually no, this is correct, why doesn't load? So if I don't do this, Let's see, One second. So this is weird, because it actually shows the things. I'm already kinda starting to do this correctly. I'm just trying to understand because this is what we want to do. We want to stub and intercept. And when application is making requests, we want to respond with an empty list. So let's see, we can wait. Let's see. Okay, so this time our routes table is saying there's one call from application to a server. That matches. And we stubbed it. That means we did not allow that call to actually go to the server. We intercepted returned an empty list.

19. Intercepting Initial Data Load and POST Requests

Short description:

We intercept the initial data load and replace it with a JSON file. We can also intercept POST requests and send an empty item as a new todo. By confirming the request body, we ensure that the application sends the expected data. Additionally, we can perform multiple assertions to validate the data being sent.

Here's something else that we can do. All right. Why do we start with an empty list? We can say fixture, right? And what are the good fixtures that we have in this folder? Maybe two items. OK, two items JSON. In this case, we have to modify the assertion. All right. So application is trying to load to-dos at the start. We intercept the call. And instead of going to a server, we say, here's the JSON file. Here you are. Right? Very convenient. Now, in this case, we are not allowing for a full end-to-end test to happen. Right? Because we're intercepting initial data load. Our other calls, right, they go to the real server, because we're not actually intercepting the boss. We could, right, for example, we could say, typefirst or like one more, enter. Right? Before we do that, we can intercept boss. So every time there is a boss to slash to dos, we can just send an empty item as new todo. So let's see. And type input new todo, select. Okay? So now we actually have two intercepts. And each one was called. And we can confirm. We can say, Cywait, new todo. It's the quest. So we're getting from what the application is sending, right? We're getting request. Okay? And, for example, we have a body. So why don't we say, it's request body should deep include, because it's a big object. It's an object. And we can say title. So we type one more. And completed, false. So we're confirming that when we operate application through its UI, right, and then we... application sends the expected data. And we can have more assertions here. For example, we can say should and... So this is body. Another thing we can do is have a should call back. And here's where we can do multiple assertions. For example, expect body to deep include. And whenever we passed it here, title completed. Okay. And we can say expect body to have property ID. All right. Because we want to make sure that we're sending ID from front end as well. This is also nice, because it actually shows me particular assertions, right. And it is false. So why did I think it was. Okay. So we confirming everything about this.

20. Testing Error States and Intercepting Requests

Short description:

How to test error states with Cypress using mock data? Each chapter in the workshop has a spec with placeholders. To run the answers, remove the 'answer' folder. The answer files contain different test cases, such as testing the app's loading state and simulating error responses. You can intercept specific requests by creating aliases dynamically. Starting from Cypress 7, the methods 'CyServer' and 'CyRoute' are no longer needed. Use single intercept and ensure it is set up before the action that triggers network requests. Manage dependent requests by only observing the ones needed for each test. The network request guide provides more examples and discusses the impact of stopping some network requests on end-to-end testing. You can easily simulate edge conditions with signed intercepts that cannot be achieved through the UI. Feel free to explore other sections and examples, and reach out for any questions.

So quick questions from the chat. How would you test your error states with Cypress, would you test your error state with Cypress with mock data? Absolutely. For example, if like how does my app handle failing to load, to do it. Okay. So one thing you probably have noticed already, every chapter here has a spec with placeholders. Right. If you learning Cypress and you might like doing exercises, you would actually go through the slides and implement this things by looking up our documentation. Each file has an answer, each chapter has an answer. So in order for you to run the answers, because right now they are not here. Notice they are not in Cypress. Here's what you do. And I will answer all the questions after this. So we can ignore test files in our integration folder. So I will remove answer. And notice now all the files are there. So our section is this. So for example, the answer, right, spec in this case has all different cases. I think this one has to be reset. Okay. For example, how does my app load data? What does it do while it's loading the data? All right, so in this answer file, there is a test that shows how do you make sure, how do you slow down a network request so that you can verify the loading thing. So let me show this test. Kind of interesting. Before I show this one. So we're going to intercept things. Right? We're going to intercept initial GET TO DOs. We're going to respond with empty body. Right? But we're going to slow down. Okay? So now this test clearly shows the loaded indicator. And now this test first checks for the loading element to be visible. The network call happens. We wait for it. And then it should be invisible. So we can slow down our network to make sure things happen. And now I think in the equation, what happens on error? For example, if my server for some reason responds with 404. Right? And says test doesn't allow it. And here we can spy on console error because our application, the only thing it does, it prints a message into a console error. So let's run this test. Okay. So our application printed the error message, and our test simulated an error state and confirmed that it's happening. Okay. Another thing that happened, how do you intercept only POS, you know, with specific tests? Yes. One thing that you can do, and this is useful for GraphQL as well. So you can create an alias on the fly. So let me just start with this one. Okay. So this one, we're going to intercept things, and we're going to say request. And here's where you can say, I don't know, if request body, like includes, or body, let's say operation name, right? So imagine if this were GraphQL code. If some particular condition was true, you could say alias, let's say, to this. So instead of assigning everything, you assigned it dynamically. So this works exactly the same way. So we can wait for this to happen. Alias is not set, it's set dynamically. So you can inspect the request and then say, oh, I'm interested in this, I'll give it an alias, and then I can wait for that alias. I can get the alias later and do network assertions on that as well. With intercept function, don't we have to start CyServer? So it used to be that we had this method, CyServer, CyRoute, but those are super limited. We duplicated them and they'll be removed in Cypress 7. That's why it actually shows in VS Code as duplicated, because we no longer need them. So, bye-bye! But most importantly, use single intercept. Please make sure you set it up before the action that triggers network requests, so there is no race condition. That still is required. So, if you need JW token, you know, in order for, for example to... Let's say... I don't know. If you're making site request and you need the token, you have to get the token somehow. Maybe from the window, from local storage, and then... So, get the token somehow. And then you call.then token. Look at our recipes because we have a lot of examples of using tokens and setting cookies and so on. If I have many dependent requests per page, how should I manage that? Only observe requests that you really need for the test. I've seen people setting up 150 intercepts for every test using before each, because... Then they would have the intercepts in case they need it. Every test needs a couple of them. But they always set up 150. Know what your test requires and only set up what you need. We're five minutes from the start. Let me just make sure that I haven't forgotten anything important. You can do the same thing. You have a very good network request guide. It's kind of a discussion of is it still end-to-end if you stop some of the network requests? So look at our guide. More examples. Those network requests, signed intercepts, you can easily simulate edge conditions that you cannot achieve with just going through the UI. Because the UI might have checks and validations that don't even allow you to create the data that you need for edge case. So that's pretty much it. And I want to finish with a couple of things. So feel free to look at other sections, and other slides. All the content is there. Feel free to look through examples. So I have more complicated things shown in the answer files. Feel free to go through other sections. You can ping me, email me, ask questions about it.

21. Final Remarks and Testing Tips

Short description:

We have a chat channel. This is more complicated and I want to go through this. For end-to-end testing in Cypress, we suggest setting everything you need for a test before it starts. You can intercept network requests and speed up tests. Avoid using hard-coded time periods and instead wait for the application to update the DOM or make a network request. You can access the application object and perform various actions from the dev tools. Thank you for attending. Check the docs for any questions and updates on GitHub and Twitter.

We have a chat channel. I want to finish with a couple of last slides. Daniele, weight and element might be detached. You have to look at our documentation. I blogged about this. This is more complicated and I want to go through this.

And the most important thing I would say is that this is just JavaScript. Whatever makes your test readable, keep using this. Right. That's pretty much it.

For end-to-end testing in Cypress, we really try to mimic how the human user uses the page, right. That's why there are all these checks, like for elements to be visible and actionable and not disabled before we click a button. We also suggest that you set everything you need for a test before it starts, right. If you need specific data in a database, set the data using requests or site tasks. If you need to set up cookies so you can login immediately, get the cookies, set them up, and then the test will be logged in. If you want to intercept a network request and have a user object with user list of projects and all the data, intercept it, set it up, and then your test can continue from there. You can spry and stab API calls that your application is making. That's one of the ways you can speed it up. If your complex, expensive operations, expensive, long-lasting calls to API can be stopped, and then the test goes really quickly. Notice that I advised against using silo-wait, where there is a hard-coded time period. And instead just say, wait for the application to update the DOM or make a network request. That means your test will be as fast as your application. But will never slow, or will never wait unnecessarily for something just because you want it to. So the test will run as fast as the application runs.

I always have my dev tools open. Sometimes I can access the application object and maybe do something like call it from the dev tools. So in my example here, I can access my app iFrame, that's for my application, and I can say app. So I could expose things and maybe call methods on my application. Maybe I can inspect things and validate the internal state of the application after adding it. Anything you can do from the dev tools, you can do from the Cypress test as well. Because Cypress test, look, this is where your iFrame, where your application executes. This is the iFrame where your test lives. They can talk right to each other and can access everything. That's how Cypress works under the hood.

I want to thank you very much. It was my pleasure. For any other questions, first, check the docs. You can always give Cypress a star. If you want to talk to us, we have a chat channel where I try to answer people's questions, usually by posting links back to the docs. And if you want to find out about our releases, we post them on GitHub and we also tweet about them on our Twitter account, so feel free to ask questions or follow that account. Thank you very much. I really appreciate it, everyone. Happy testing.

Watch more workshops on topic

React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Top Content
Featured Workshop
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn
TestJS Summit 2022TestJS Summit 2022
146 min
How to Start With Cypress
Featured WorkshopFree
The web has evolved. Finally, testing has also. Cypress is a modern testing tool that answers the testing needs of modern web applications. It has been gaining a lot of traction in the last couple of years, gaining worldwide popularity. If you have been waiting to learn Cypress, wait no more! Filip Hric will guide you through the first steps on how to start using Cypress and set up a project on your own. The good news is, learning Cypress is incredibly easy. You'll write your first test in no time, and then you'll discover how to write a full end-to-end test for a modern web application. You'll learn the core concepts like retry-ability. Discover how to work and interact with your application and learn how to combine API and UI tests. Throughout this whole workshop, we will write code and do practical exercises. You will leave with a hands-on experience that you can translate to your own project.
React Summit 2022React Summit 2022
117 min
Detox 101: How to write stable end-to-end tests for your React Native application
Top Content
WorkshopFree
Compared to unit testing, end-to-end testing aims to interact with your application just like a real user. And as we all know it can be pretty challenging. Especially when we talk about Mobile applications.
Tests rely on many conditions and are considered to be slow and flaky. On the other hand - end-to-end tests can give the greatest confidence that your app is working. And if done right - can become an amazing tool for boosting developer velocity.
Detox is a gray-box end-to-end testing framework for mobile apps. Developed by Wix to solve the problem of slowness and flakiness and used by React Native itself as its E2E testing tool.
Join me on this workshop to learn how to make your mobile end-to-end tests with Detox rock.
Prerequisites- iOS/Android: MacOS Catalina or newer- Android only: Linux- Install before the workshop
React Day Berlin 2022React Day Berlin 2022
86 min
Using CodeMirror to Build a JavaScript Editor with Linting and AutoComplete
Top Content
WorkshopFree
Using a library might seem easy at first glance, but how do you choose the right library? How do you upgrade an existing one? And how do you wade through the documentation to find what you want?
In this workshop, we’ll discuss all these finer points while going through a general example of building a code editor using CodeMirror in React. All while sharing some of the nuances our team learned about using this library and some problems we encountered.
TestJS Summit 2023TestJS Summit 2023
48 min
API Testing with Postman Workshop
Top Content
WorkshopFree
In the ever-evolving landscape of software development, ensuring the reliability and functionality of APIs has become paramount. "API Testing with Postman" is a comprehensive workshop designed to equip participants with the knowledge and skills needed to excel in API testing using Postman, a powerful tool widely adopted by professionals in the field. This workshop delves into the fundamentals of API testing, progresses to advanced testing techniques, and explores automation, performance testing, and multi-protocol support, providing attendees with a holistic understanding of API testing with Postman.
1. Welcome to Postman- Explaining the Postman User Interface (UI)2. Workspace and Collections Collaboration- Understanding Workspaces and their role in collaboration- Exploring the concept of Collections for organizing and executing API requests3. Introduction to API Testing- Covering the basics of API testing and its significance4. Variable Management- Managing environment, global, and collection variables- Utilizing scripting snippets for dynamic data5. Building Testing Workflows- Creating effective testing workflows for comprehensive testing- Utilizing the Collection Runner for test execution- Introduction to Postbot for automated testing6. Advanced Testing- Contract Testing for ensuring API contracts- Using Mock Servers for effective testing- Maximizing productivity with Collection/Workspace templates- Integration Testing and Regression Testing strategies7. Automation with Postman- Leveraging the Postman CLI for automation- Scheduled Runs for regular testing- Integrating Postman into CI/CD pipelines8. Performance Testing- Demonstrating performance testing capabilities (showing the desktop client)- Synchronizing tests with VS Code for streamlined development9. Exploring Advanced Features - Working with Multiple Protocols: GraphQL, gRPC, and more
Join us for this workshop to unlock the full potential of Postman for API testing, streamline your testing processes, and enhance the quality and reliability of your software. Whether you're a beginner or an experienced tester, this workshop will equip you with the skills needed to excel in API testing with Postman.
TestJS Summit 2023TestJS Summit 2023
148 min
Best Practices for Writing and Debugging Cypress Tests
Workshop
You probably know the story. You’ve created a couple of tests, and since you are using Cypress, you’ve done this pretty quickly. Seems like nothing is stopping you, but then – failed test. It wasn’t the app, wasn’t an error, the test was… flaky? Well yes. Test design is important no matter what tool you will use, Cypress included. The good news is that Cypress has a couple of tools behind its belt that can help you out. Join me on my workshop, where I’ll guide you away from the valley of anti-patterns into the fields of evergreen, stable tests. We’ll talk about common mistakes when writing your test as well as debug and unveil underlying problems. All with the goal of avoiding flakiness, and designing stable test.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Remix Conf Europe 2022Remix Conf Europe 2022
23 min
Scaling Up with Remix and Micro Frontends
Top Content
Do you have a large product built by many teams? Are you struggling to release often? Did your frontend turn into a massive unmaintainable monolith? If, like me, you’ve answered yes to any of those questions, this talk is for you! I’ll show you exactly how you can build a micro frontend architecture with Remix to solve those challenges.
TestJS Summit 2021TestJS Summit 2021
33 min
Network Requests with Cypress
Top Content
Whether you're testing your UI or API, Cypress gives you all the tools needed to work with and manage network requests. This intermediate-level task demonstrates how to use the cy.request and cy.intercept commands to execute, spy on, and stub network requests while testing your application in the browser. Learn how the commands work as well as use cases for each, including best practices for testing and mocking your network requests.
TestJS Summit 2021TestJS Summit 2021
38 min
Testing Pyramid Makes Little Sense, What We Can Use Instead
Top Content
Featured Video
The testing pyramid - the canonical shape of tests that defined what types of tests we need to write to make sure the app works - is ... obsolete. In this presentation, Roman Sandler and Gleb Bahmutov argue what the testing shape works better for today's web applications.
Remix Conf Europe 2022Remix Conf Europe 2022
37 min
Full Stack Components
Top Content
Remix is a web framework that gives you the simple mental model of a Multi-Page App (MPA) but the power and capabilities of a Single-Page App (SPA). One of the big challenges of SPAs is network management resulting in a great deal of indirection and buggy code. This is especially noticeable in application state which Remix completely eliminates, but it's also an issue in individual components that communicate with a single-purpose backend endpoint (like a combobox search for example).
In this talk, Kent will demonstrate how Remix enables you to build complex UI components that are connected to a backend in the simplest and most powerful way you've ever seen. Leaving you time to chill with your family or whatever else you do for fun.
JSNation Live 2021JSNation Live 2021
29 min
Making JavaScript on WebAssembly Fast
Top Content
JavaScript in the browser runs many times faster than it did two decades ago. And that happened because the browser vendors spent that time working on intensive performance optimizations in their JavaScript engines.Because of this optimization work, JavaScript is now running in many places besides the browser. But there are still some environments where the JS engines can’t apply those optimizations in the right way to make things fast.We’re working to solve this, beginning a whole new wave of JavaScript optimization work. We’re improving JavaScript performance for entirely different environments, where different rules apply. And this is possible because of WebAssembly. In this talk, I'll explain how this all works and what's coming next.
React Summit 2023React Summit 2023
24 min
Debugging JS
Top Content
As developers, we spend much of our time debugging apps - often code we didn't even write. Sadly, few developers have ever been taught how to approach debugging - it's something most of us learn through painful experience.  The good news is you _can_ learn how to debug effectively, and there's several key techniques and tools you can use for debugging JS and React apps.