React is one of the most popular frontend JavaScript frameworks. If you want to make sure that your React apps work as intended, it is important to write comprehensive tests.

We just published a React testing course on the YouTube channel that will teach you how to build, deploy, and test React applications.

Nikolay Advolodkin created this course. Nikolay Advolodkin is a seasoned IT professional, test automation expert, and popular testing instructor with Ultimate QA.

In this course you will learn how to use React Testing Library, write end-to-end visual tests, and develop comprehensive test strategies. You will also learn how to use testing tools such as, Cypress, and Jest.

First, you will learn how to create a basic React app and deploy to Microsoft Azure. Next, you will lean how to create a birthday reminder app with full testing. Finally, you will learn how to build and test a portfolio website.

Watch the full course below or on the YouTube channel (2-hour watch).



In this three part course, you will learn how to code, deploy, and test three react applications.

Nikolay is the founder of ultimate QA, and is a popular instructor on software testing.

Consider leaving a comment with any react testing tips you learned in this course, we're going to start the first tutorial by creating a very simple react application using create react app.

Next, we're going to use React testing library to write a few unit tests.

Afterwards, we're going to learn how to write end to end visual tests.

And then finally, we're going to take that application and deploy it to Microsoft Azure.

In the second part of the tutorial, we're going to learn how to create a beautiful birthday reminder application with some static data.

It's going to be very simple, but we're going to build upon the skills that we learned in the first tutorial.

Next, we're going to think about a comprehensive test strategy for this web application.

And then finally, we're going to write those tests and run them against our birthday reminder webapp.

In the third and final tutorial, that's actually my favorite one.

And I think you're really going to enjoy it as well, you will build a beautiful dev portfolio website that you can use to show off your developer skills.

We're going to code a lot of different components for this web application.

But the tutorial is mostly going to be focused around a testing strategy, you will learn a lot of very cool tools like how POJO, Cypress and jest for component testing and unit testing.

My name is Nikhil Avalon skin, and I'm a Senior Solutions Architect and I create tutorials at ultimate QA YouTube channel on that channel.

That's where developers come to learn how to test and testers come to learn how to develop.

So what are you waiting for, let's dive right into the tutorials.

Alright, so let's go ahead and start creating our React app, you can see that I'm here in a folder called react web up, we've only got a license and a readme.

So let's go ahead and do an NPM in need to set up this directory.

And so now we have added our package dot JSON.

If you don't already have it installed, be sure to install create react app, it's a easy way to create react applications from Facebook.

Once you have create react app installed, you can actually use create react app to create a new React application.

So let's go ahead and do that.

And we're calling this app my app.


So once that's done downloading and installing, you can see a bunch of commands that create react app provides for us to get started and they tell us exactly what we can do is to CD to my app.

And then in my app, you can see now if we open this up, we now have a my app folder, has its own node modules, has a bunch of code here that we will explore in a moment.

So let's actually go ahead and start up our app and see what that looks like.

And here is the start of our wonderful little application running on localhost 3000.

That's also pointed out in the logs here.

So the really wonderful thing about create react app is not only does it build us an application that's ready to go and ready to be modified.

It even comes with a test that we can execute.

If we look at package dot JSON, we can see that if we run a NPM test command, it's going to run some tests.

And so what we can do is open up a new tab here and do NPM test.

And that's going to execute a unit test here that we have an app.test.js.

And this test is actually using React testing library.

But what you can see here is we have a test and that will render the Learn react link.

Here we use a method called render and we are rendering our app component and next you can see that we are using the screen to get an element by text called Learn react.

And then finally we are expecting that link element to be in the document.

This is a just expect and to be in the document is the React testing library assertion.

That's fantastic, because now we have a unit test that's already ready for us.

And it can run, regardless of whether our application is up or not.

So if I close down our app, and then come back here and rerun the tests, they will still continue to work because they don't need a server, we are actually going to go ahead and push this up into CI.

So the easiest way to get started with GitHub actions is to come over here to the Actions tab in your GitHub repo, making sure that you have one created.

And then you can come and say, a new workflow.

GitHub actions will provide you some suggested workflows, and then it notice it notices that we are obviously using no J S.

And so then it can recommend us a potential workflow.

And this one right here looks fantastic.

So let's go ahead and click it, it already comes with a bunch of steps that have been configured for us.

And the other nice thing about creating your Yamo file here is that you also get a little IDE that you can use, for example, you can see that if we don't do something, right, like, let's say we do something like this, the UI automatically highlights anything that may go wrong.

And so it says that we're missing a runs on here.

And so then we can do runs on and then now it says that the value cannot be null, and then that's where you supply the value.

So this is what our CI pipeline should look like.

And let's go over it step by step, by the way, you can see it's automatically gets created in a dot GitHub slash workflows folder, and then you give your file a name, I'm calling our CI, pipeline CI, you can call it of course, anything you want.

And then at the very top, I am setting three environment variables.

These environment variables are the screener API key sauce, username, and sauce access key, they are coming from Secrets variable that is part of GitHub actions, and then coming from the key called screener API key here, sauce, username and sauce access key, so the value from here is retrieved and stored in the environment variable on the left hand side.

So where are these values coming from? Let me show you that it's very intuitive in GitHub actions, you come to Settings.

Scroll down to secrets, you can see I have three keys that have been created here and inside of them, they have the corresponding values that will then be set in here.


Next, we are saying that we want this CI to run on push requests and pull requests whenever we do that to the master branch, main branch.

Next, here, we are defining the jobs that we want to execute, we're saying we're going to run on Ubuntu latest, there are multiple types of different kinds of VMs available for you to execute on.

And I'm going to be running on Node version 14, you can execute on other node versions if you want, of course, and then we are using the steps.

A lot of these steps were previously provided for us.

And I've made some modifications to help you get started faster with your CI pipeline.

So the very first thing we want to do is install dependencies.

And here we are doing exactly what we were doing in our command line for our application.

And so we would have done CD my app, right and then done a npm install.

However, I'm simply using an NPM CI, which is actually faster in GitHub actions because it ends up caching our dependency.

So this is the recommended action to take in CI.

Next, we're going to build the app, right, this was just seeding to my app and doing an NPM run build to make sure we have a production version.

Because whenever we do an npm start here.

And our application comes up here in localhost 3000.

And we take a look at our React developer tools, we can see it's red, and it says this page is using the development build of React, which we obviously don't want to use for production we want to use this year.

We want to use the production build.

And so that's how you do with NPM run build.

Next, we're executing our component tests.

After our app is built, we simply do the same thing by navigating to that directory and running the tests exactly as you saw before.

And then finally, we are starting up our application actually starting the server by doing npm start, and then we're doing a wait on command that will wait for the app to start up for up to 60 seconds before erroring out.

And we will expand this pipeline as we expand our testing.

So once it's ready, the only reason I recommend that you use the UI was to help you with the IntelliSense.

But ultimately, the best way to do it is to come to my app, and then make sure we're going to add a GitHub repo going to do that GitHub slash workflows.


And then we're going to add a new file here.

If you're enjoying this tutorial and want to support this channel, be sure to hit the thumbs up button for the video.

And if you want to be notified of every time a new tutorial is released, hit the subscribe button.

Let's call it CI dot Tamil.

It will look exactly as I showed you here, I actually named the two CI two so that we can see, let's quit our tests and do a and do a push.

And once we do a push, that should start executing our CI pipeline.

Let's come and take a look at that.

We'll see that I have this new branch open.

So let's go ahead and do a PR with this branch.

I made one mistake here, I should have put GitHub workflows in the very root, not inside of my app.

So what you'll see is I moved that to the correct location did another push.

And so now we have a CI pipeline that started executing here's the name called CI to exactly the name that we gave it in the Yamo file.

And it did fail after nine seconds.

So let's go ahead and take a look at exactly what happened.

So the error says that we can only install packages with a package lock JSON, or NPM, shrimp crab JSON.

So let's go ahead and fix that.

In order to do that, what we need to do is come to my app and do an npm install.

Which will create a package lock dot JSON.

And then let's go ahead and add it.

And we can watch our c ci rerun.

Here you can see we just committed 14 seconds ago, here's a little yellow circle that shows that our CI pipeline is running.

Let's go ahead and take a look at the details.

Wonderful, so there is our CI pipeline that is not only able to build our app and start it up, it's also able to even run some component tests against it.

So if we take a look of where we are in our testing journey, you can see based on this table that we've actually got a pretty long way to go before our app is fully tested.

It's a really tiny app that we haven't even made any functional changes to.

And so far, the only thing that we know about this application without testing it manually is that a URL with the correct text does exist in the DOM of the application.

We've validated that with a component test, which came with our app create react app.

And we did that using React testing library in jest.

How about actually knowing whether the URL is correct, right? It may be there with the right tags but doesn't go to the right location.

So let's go ahead and write up another test for that.

The very first thing that we want to do is make sure that we are running our test suites here in and then we can add a test that looks like this, where we say where we're testing that a URL is correct rendering our component is before getting our link element as before.

However, now we are going to validate that the href of the link element will contain ultimate, because that's where we want our URL to navigate to.

And then once we hit save, watch this window in the bottom right.

It's going to execute all of the tests in this file.

Here, the first one passed, which makes sense, but the second one failed, the URL is correct.

It's saying that we expected ultimate

But we got react J

And that's because we need to make an update to our application to go to ultimate

So let's come here and go to app Jas.

And we will change the URL to ultimate

We're going to hit save, our tests are going to rerun, and now both of them have succeeded.

Also, while we're here, we this link text is no longer correct, because we're not going to learn react, instead, we are going to learn testing.

So let's put let's learn testing, and the above and hit Save now.

And our tests both have failed.

And the reason that they both have failed is we can take a look at our logs.

And it seemed that it's unable to find an element with the text, learn react.

And then it spits out the DOM for us here showing everything that is visible.

And of course, this is the text that exists.

However, the this exercise also showed us that having text as a check in our test is not really a good strategy because we can often change the text of our links.

And so we can instead use a better strategy such as supplying a data dash attribute.

And so here we can do a data dash Test ID.

And we can call it a learn link.

We'll hit save here, we'll come back to app dot test.

And now instead of getting by text, we can get by ID.

So let's go and do that.

Let's give this a run.

And now everything passes because we are getting our element by Test ID.

And of course, if we decide to change the text our tests continue to work.

Let's go ahead and push this up into our CI.

Here's our commit.

And here is our check.

We can check on it back in a moment.

So our CI pipeline has executed successfully, which is wonderful.

So let's see where we are in our testing journey.

So at this point, we are we have now tested that the URL is correct.

Now how about making sure that our application actually renders correctly that we can do a this test as well as making sure that our application looks correct on web and mobile using two different technologies.

We're going to use WebDriver.

Io and shift right by testing our rendered application later in the stage of the development cycle.

And we're going to use visual snapshots to check our application in different resolutions in the browser to make sure that our app is responsive and that it looks correct on different types of devices.

And for that we are going to use WebDriver IO lessons.

All WebDriver IO let's configure WebDriver IO, you're gonna get a nice handy menu that allows it allows you to decide what you're going to do.

So we're going to execute in the cloud using Sauce Labs.

Yes, this will be our username, and this will be our access key.

No, we don't want to do that which is the default.

Once you've selected all the options, now you're going to wait for WebDriver IO to install all the appropriate packages.

So once all the installation is done, the only other thing that you'll need to install is the WD IO sync service.

And so once you have everything installed, this is what our package json looks like everything that we added.

If we look at the diff, you can see we've got a few WD i o services added for our testing purposes.


Io tests by default, go to test specs directory, and in here I created a visual.spec.js file.

And in here, we are going to have our visual test.

This visual test uses a standard describe it format.

And then the commands come from the browser object which is a global object from webdriverio.

We navigate to a URL, and then we execute two important commands.

First, we do it, which will provide a name for the app that we're testing.

So we can say, my react app, for example.

And then the next one we're going to do is a snapshot.

This is capturing a snapshot of the page that we want to test.

And so in this case, it's our homepage.

And so we are calling it home page.

So the config file for WebDriver.

Io lives over here.

And there's a lot going on in here.

But that we can take a look at only the important components.

So here I've created two constants called visual options and sauce options where I am setting some API keys.

Here, I'm setting the screener API key, I am providing a project name, I'll show you how that correlates to the actual UI.

And then I'm saying to scroll and stitch screenshots to enable that to true so that when my apps are pulled up, the entire page is scrolled and stitched together.

Next, I am enabling a sauce Connect, which is an HTTPS proxy that allows me a secure connection from a local host into the cloud execution environments for screener and Sauce Labs.

This is telling us where the specs are for our tests.

And then finally, the most important part of this, I would say, is the configuration to run on multiple different browsers and operating systems.

So I'm running this on two of the most popular browser resolutions.

The very first one is this one here, on this viewport size, which is the most popular desktop and running on Windows, 10, and Chrome, and then the other type of browser that we're running on is MacOS Safari on this resolution, which is an iPhone X viewport size.

And of course, we can have a lot more resolutions here.

And what's going to happen is, our visual spec is going to run on both of these platforms at the same time.

We can of course run it.

We can run our tests using this command here.

But instead let's add a test script to our package json.

We can come here and add.

And then ensuring that in a separate terminal, you have the application actually running on localhost 3000, because it has to be up for us to do end to end visual testing, we can now run our visual testing command.

At this point, we can see that it's executing two specs.

And of course, that's our Safari and Chrome specs.

Let's go take a look at the screener UI to see what's going on over there.

So we can see that Here is our new app dash two that we started.

There are currently tests running.

The build has failed.

And the reason why it failed is because we have two brand new snapshots that we've never accepted before.

What screeners currently telling us is that, hey, I've got these two snapshots of these resolutions of this page here of the homepage.

And I don't know whether they are acceptable to you or not.

So we can open each one up and take a look.

Does this look good to Austin? Correct? Yes, it does, we can come here and set this as a baseline.

From this point forward, every single automated test will validate against this version of the baseline.

And this was the bigger resolution here.

And this one looks fantastic to us as well.

Let's go ahead and accept it.

And so now from this point forward, and new executions will run against this baselines.

Let's also now add this visual step to our CI pipeline and see that execute.

Here we are back in our CI Yamo.

We've added a brand new step our after after application has rendered to run Visual tests and performing the following commands.

Let's go ahead and check all this into Ci and see what happens.

We've got a new command here for adding visual test.

And here is our CI pipeline executing.

So here's our pipeline after execution, we can see our visual tests have executed successfully with a checkmark.

And if we scroll all the way down, we can see that two tests have passed.

So the current version of our application, it's a little boring, right, let's make it a little bit better, and actually see the power of visual testing.

So we're going to replace this logo with another logo by coming into app dot j s.

And we can see that up here at the top, we're pointing to an SVG, let's change this SVG.

And instead, we're going to point to me dot jpg, which is a nice file that I've uploaded.

So let's save that and watch her application ran there.

And here is the cutest little dog in the world.

Her name is Mia.

And of course, we can also even change this link right here to his channel B, instead of learn testing, we can change it to something else, we can say, learn testing, with Nikolai, and Mia.

Fantastic, our application rebuilt.

And this is what it looks like.

And we can even run our tests to make sure that everything is working as before our component tests, both of them working successfully, because remember, we added that nice Beta Test ID attribute.

And now we can check in these changes and see what happens to our visual test.

Here's our change in GitHub.

Let's see what's going on.

So now if we look at the screener UI, we can see that our new app two has two changes, let's click Take a look and see exactly what happened.

And so what screener shows is two visual changes that have occurred as screener users a smart hybrid div meeting, meaning that it analyzes the DOM and element shifts, and identifies exactly the two elements that we have changed.

And so now as far as to decide whether this is a valid change or not.

And yes, this is a valid change.

And it looks fantastic.

And we want to use this as the new version of the baseline.

So we're going to accept this one.

Looking at this page here.

We like all of the changes here as well.

And we can accept that as well.

And with all that said, we are pretty far down in our coding and the testing journey.

We validated pretty much everything about our application.

We validated that the app renders correctly and that the app looks as expected on the web and mobile using our visual DOM to database tests, also known as Antwuan test, and we did it with the following technologies.

So how awesome would it be if we can actually deploy this application and then test it in a real production environment? Well, we can actually do that using Microsoft Azure.

And we are going to use their Azure static web apps feature, their Azure static web apps feature is basically a simple way to deploy applications without having to worry about infrastructure and regions and a bunch of other stuff.

As you'll see, it's a very easy way to make this possible.

So we're gonna go ahead and do that, in order to do this, you're gonna need an Azure account, you can get your Azure account by going to

And it's absolutely free, you can sign up for free, and then you can follow along in the tutorial.

Next, you're going to need to install an Azure static web apps extension.

So here in your Visual Studio code, you're going to come to extensions, and install Azure static web apps extension.

Once you have add your static web apps, you will have this little icon Azure, you will come in there, you will come into static web apps, and you will click the plus symbol to add a new Azure static web app.

So here is asking for us to provide a name a unique name for our web app, let's call it my react web app.

Nexus, it asked me to select the configuration, we obviously have a React project.

Next, it's asking where is the source code of our application, and ours is not at the root, but it's inside of my app.

That's where all the code goes.

And then finally, tasking, where will your application get built to.

So when we come here, and run NPM build, that's the final production version of the application that goes here into the build folder.

And so this here is correct.

And that's what we're going to supply.

Inside of our GitHub project, we see that we have a new action that was added.

And it's called Azure static web apps workflow.

And basically, Microsoft Azure added a new Yamo file, that it's calling right here, Azure static web apps, blah, blah, blah.

And so then this has a configuration for building and deploying our application.

And so once we open it up, we can take a look at everything that happened here, the longest and most important step was actually building and deploying our project.

If we open it up, we'll see a bunch of stuff that was executed.

But ultimately, the most important part was this at the end here, where our web app was actually deployed to this URL, which was dynamically generated for us.

And if we click on this URL, we will see that here is our beautiful and wonderful application alive in production.

I did have to add one other thing here, when I checked into the code is there was a settings dot JSON that came along.

Let's see if I can find that here.

That came along.

And so what was very, I needed to push that up into my pull request as well.

And that settings that JSON just has these three things configured as well.

And then once I push that up the bill to work successfully, we can also talk about that file here that was added for us.

It has a lot of stuff going on, which is not really anything important.

What the most important part here is basically that these three parameters talking about where our app is located and where the build output is created.

And so in this instance, it basically just builds and deploys our job.

I didn't set up any of this, it was done for me automatically, which is really fantastic.

And then here at the end is just a close pull request the job which basically once a pull request is closed.

It'll basically close out the job for us.

So that's really all that was added here for us all automatically using using Azure static web apps.

Now, how do we actually write the tests for our production environment, let's go ahead and do that.

So the very first thing that I want to do here is actually update our app.

So if you run npm start this this was an okay picture, it can definitely be better.

And so let's make it better in our app.

So what we're going to do here is come to my app in the source, we will change the picture to a better one.

So here we have Mia I'm going to read name this one to me old.

And rename this one to meow, you can see this one is much better of my cute little dog being violently attacked by her boyfriend.


So obviously, that's going to now load up in our app.

So there it is a much better image.

And so then with that change done, we also need to update our Azure pipeline for being able to handle all over the testing.

And so to do that, we simply do everything that I did in this file.

And so it's basically a merge of the Azure file that we had before that was automatically created for us by Azure static web apps, and the CI file that we have before.

And so all of this you've seen before setting environment variables, all of this configured here, however, now, we have a built in Deploy Job, I kept a bunch of the logic that was there from Microsoft Azure.

And then we did all of our local testing here.

So installing dependencies, building the app, running component tests, starting the app, running visual tests on localhost, this is a new step we were doing it before, but I just simply renamed it, calling it our run Visual tests on a local host.

And you can see we are running NPM, run test visual, which if we look at that, here you can see NPM run does points to this config here.

And then we're also going to have test visual prod, which is going to run the same config is going to have a debug higher log level.

And it's also going to point at a base URL.

So let's continue here in our Azure, Azure Yamo.

So here is the build and deploy step that we got from the Azure static web apps, I literally just copied and pasted this in here, everything all the same.

And then the only part that I needed to add was adding visual tests to be executed on prod.

And so that's that script that we were using before, however, we need to point to a different URL, and which URL are we going to use? Well, this one, now that we know our production URL, we can use it for testing production purposes.

So let's go back to here.

And we're going to go to our package json.

And we're going to update our script.

So we're going to change our base URL to this right here.

And so if we're using WebDriver IO, so that's how we're able to pass on this parameter here.

And we're setting it to our production URL.

And then this close pull request job remains just as before.

And so now, let's go ahead and give this a run.

Let's stop this, let's see our changes.

And don't forget that I renamed our job to Azure CI.

And let's push this up.

If we come back here to pull requests, we see that we have some checks being executed.

Let's take a look at those.

So here we have our Azure CI pipeline that we just created by updating the Yamo file.

Let's click on the details.

And now we are going to see all of the steps.

And let's watch them execute, and then see the final outcome.

Oh, something happened to our CI pipeline looks like visual tests failed on localhost.

Do you know why that is? We're going to figure that out in a moment.

So the reason that our tests failed on localhost is because remember, we made the change to the image.

And so now if we come back here to screener, we see that two have changed.

If we look at the changes, we obviously see that the image has changed.

So this is good for us.

We don't need to worry about it.

It's absolutely the new version that we want in our application.

We're going to accept everything that was selected.

And then we are simply going to rerun this job and now everything should pass successfully.

Wonderful our build has finished successfully.

So let's go ahead and actually take a look at every thing that that's happened.

Here was just some actions that we've already seen.

We've seen installing of dependencies building the app, running Component Tests starting the app.

And then here is the visual tests on localhost.

Those have succeeded, because we finally accepted a new baseline.

Right, we can see that one has passed on Chrome and windows and the other one on macOS.

Next, we have the build and deploy task here that was using the Azure static web apps, action.

And that all succeeded successfully.

If we scroll down, we'll be able to see the URL to which it was displayed to.

And then finally, we run our visual tests on production, which is pretty much the same thing.

Except we are just running a different script, write a test of visual prod.

And you can see the WebDriver i o configuration that was enabled here pointing at that URL to which we published and the tests there passed successfully.

And that's pretty much it, we've successfully created a CI pipeline that not only tests our application, but then deploys it to production and retests, you can now go ahead and make $100 million on this application.

So just to summarize, in this tutorial, we created a very simple react web application using create react app.

We then created component tests using React testing library.

Afterwards, we shifted right, by creating automated visual tests, using screener and WebDriver.

We added the code to a CI pipeline using GitHub actions.

And then finally, they use Azure static web apps to easily release all of that code into the Microsoft Azure Cloud.

So that's our application lives in the production environment.

And we can test it.

My name is Nikolai Bulacan, you can learn more about me at ultimate

And it's been a true pleasure being able to show you all of the skills to have a wonderful day.

Hey, and welcome to building a birthday reminder application with React js.

In this tutorial, we're going to code a React application from scratch.

Next, we're going to consider a wonderful testing strategy for application.

And finally, we're going to implement a single test that's going to provide us a ton of coverage on our web application.

My name is Nikolai adelakun.

And on this channel, I help as that all over the world build, test and deploy applications in a continuous manner.

If you want more amazing content like this, be sure to smash the thumbs up button, so that I continue creating content for you.

So grab your computer, grab your coffee, and let's do this.

Alright, so you ready to get started, let me put on my magical coding glasses.

And let's begin.

So the code base that we are going to be working on is going to be coming from this project right here.

You can see it's a fork of this other project that has a bunch of React web apps.

And we're building on top of those by teaching about how to test and deploy them.

We're going to be working on this birthday reminder, there are two folders here, there's a setup folder.

And there is a final folder.

The final folder is basically what the code is going to look like at the end.

And the setup folder is what you're going to be working from.

It's a blank folder to get you started.

And it's going to have some boilerplate code in there.

And then we are going to code out the rest.

So let me show you exactly what that looks like.

So of course, first step, you're gonna get clone.

You can if you want, you can fork my project, and then do a git clone.

And once you have that down, you'll navigate to the final directory.

So I'm just going to do that and then I'm going to do an npm install and start so that we can see what the final version of the application will look like.

Alright, so there it is, you can see our application is running, of course, and localhost 3000.

And this is what it looks like.

It shows the birthday.

So we have today, the people whose birthday it is.

And if you press the Clear All button, it clears all of the birthdays.

That's really about it, the app is super simple.

However, we have to get started with somewhere simple and build up.

And along the way, we're going to figure out not only how to code it, but also how to test it.

So now that we know what the application looks like, let's go ahead and implement it together.

And then afterwards, we're going to talk about the testing strategy.

So I'm gonna cue this over here, and you're gonna follow along with me.

So you're gonna navigate one route off, you're going to navigate into setup.

And that's where we're going to be working from also, I am going to change to a new branch.

We're going to work from birthday tutorial.

And if you want to follow my commands, you'll see those in that branch.

So obviously, we have the source folder.

If you're in setup, you'll also need to do an npm install.

While that installs, we can talk about in app J S, you can see there's nothing here except this h2 that says reminder project set up in this data dot j s, you'll see it's just an array of metadata about each one of our users, just again, keeping it simple, not needing to pull it from anywhere right now.

Our index, CSS already has all the styling, right, we don't want to spend hours, putting together all the styling for our application.

So it's already here and ready for you, all we have to do is implement and I'd rather spend more time actually implementing projects and less time worrying about CSS in index.js.

This is our entry point for our application.

And then our list.js will contain the list of users.

And we're going to iterate over them.

And you'll see exactly what we do in here.

But in the meantime, everything should have installed and if you do npm start, it'll pull up our app.

And I am actually going to pull this out we'll put this side by side with our editor.

So it makes life easier.

And we'll put this over here just like that.

So you can see what this is showing right now.

It's just a our app J S.

It's just a simple pink background with a header that says reminder, Project Setup.

Let's go ahead and start coding.

Alright, so let's start doing some work on this application.

We're going to start working out of app J S.

Let me go ahead and close the window on the right just so you can see more space here.

And we'll close this down here as well.

So with that, we are going to get rid of this.

And we will return a much larger block of code.

And now we are going to add a main element and why it's main.

If we come into our index CSS, we will see that the styling for the main component is over here.

That's going to be the wrapper for our main portion of the application.

And inside of that, we're going to have a section and this section is going to get a class name.

And that's going to be called container.

So as soon as I save, you can see exactly what this looks like.

Again, if we look at the index, find container, you can see that CSS styling for the container is right there.

Inside of this section, which is the white part right? What are we going to have in there? Well, we're going to have an h3 and that's going to display the amount of birthdays So far, we're just going to do everything static and then make things a bit more dynamic.

So we'll do something like this, save it, boom, see that come up right there.

Next, we're going to import our list components.

So you can see the import is already on top on line number three.

And that is going to be dynamically generated once we put the logic in there.

So for now, that's all that looks like because if you look at lists, you can see that this is all it has for now.

Next, we are going to add a button.

So button, and then we're going to do an on click method, right? What is it going to do on a click? So what is it going to do on click for now, again, always keeping it simple, let's zoo an anonymous function.

And that's not going to do anything.

And instead, it's simply going to do a console log.

Just like that.

And let's give this button a title.

And save that, and boom, there is our button.

And if we come here and inspect, scroll down.

Go over to the console, and click it, you can see that it says clicked because that was the method that we coded.

By the way if you're wondering how I quickly created an anonymous function, that was keyboard shortcut, a NFN.

So you can type this a and a fan.

And you can see it's an anonymous function.

And then when I hit tab, I get this automatically generated.

And that comes from there it is this extension right there.


So App J S so far is up and running.

Now let's go ahead and fill it with the actual users.

All right, so next step, we're going to work out of our list component.

Our list component is going to contain all of the birthdays that are coming from data Jas, right.

So you can see it contains the name, the age, the image, and an ID.

And this list is just going to basically iterate over all of that and list those components.

So with that said, let's get rid of this heading.

And instead, we're going to keep the fragment here, we are going to do a map.

And actually, what we'll want to do is inside of this list, we're going to pass in an object that we're going to call people, okay, using this object, we are then going to do a map.

And inside of there, we're going to do another anonymous function.

And then we're going to map over a person.

And for every single person, we can D structure that object have a deconstructed object, and this is going to take in each of the properties of our person.

So we got that D There you go.

Next, we're going to want to return the component.

That's going to be an article and inside of that article, we are going to have an image we're gonna have a source of image.

You can see automatically how those destructured properties are coming back here to give it an alt it's gonna have have the name of the person.


And then below, and then we're going to add a div.

And that div is going to have an h for.

And that's going to be the name of the person.

And then we're going to have a paragraph.

And then that's going to say that age and years.

Just like that.

And then up here in the article, we definitely want to have a key for the map, so that's going to be the ID.

And then we want to give it some styling, which is going to be person.

So again, if we look at index dot css, and we look for look for person, there is that styling for the person.

Let's go back, let's save it and see exactly what that looks like.

Oh, it failed.

Let's see what's wrong here.

And I think the reason for that is we haven't passed in any object to our list component.

And so that's why it's undefined.

And so now if we come back here, we can actually define it.

So the very first thing we're going to need is a D structured array.

So let's do that.

And that's going to be people set the people.

And that's going to do use state.

And it's going to take in the data that we are getting from here.

There you go.

And then using this information, what we're going to want to do is obviously update this one to a dynamic value.

So that'll just be people dot length.

So now we'll show that dynamically.

And then our list, we're actually going to want to pass in the value of people.

And that's going to be people.


And I think that's correct.

Let's give this a run a save, boom, there it is, there is our application, you can see exactly how it looks, and how each of the components came into play from the list.

So we've got everything wrapped in an article, each one of these is an article.

Inside of that we have an image, and then we have the person's name, and then the age and years, all that's left is to actually make the button work, which currently is just console logging.

While and making that happen is extremely easy.

And it only takes a single method.

So that's just setting the people.

And inside of that, we are just going to pass an empty array, which is going to clear everything right.

So if we save that, and now we should be able to click this button.

And you can see that now it says your birthdays today, obviously the counter being updated from this, the list of people values being passed in from here into here.

And then the onclick is using the Set people method from above, passing in an empty array.

Our application is done now, how do we actually test it? So we now have our web application is there and ready.

And the question is, well, how are we actually going to test it? What is the most optimal strategy, our web application contains multiple components that need to be tested.

There is, for example, the dynamic birthday counter that we coded in the logic for that obviously needs to be correct.

There's the clear all functionality of the button that needs to ensure that the list is clear.

And then probably the most important part is the look and feel of the entire application on web.

And obviously mobile is also important.

So how are we going to test our application to ensure that everything is functioning as expected, so let's start working through the testing period.

Amid and see which approach makes sense.

We're gonna start at the very bottom, the unit test layer.

Unit tests are really great for low level types of tests, right? If you're having like, functions to add integers, for example, or a function that performs some parsing of some data, those types of tests are really good for unit tests.

And honestly, for most react web applications, unit testing is rarely ever necessary, unless you have some deep JavaScript logic that you need to test.

So unit testing are not going to apply here because it's, we're going to need too many unit tests.

And also, they're not the right use case here.

What's likely better and more applicable for web applications, especially in React are components has components has are a level higher, they ensure that the look and functionality work together that the component that we created, such as the list component is functioning correctly tied to all of the backend code.

So if we had component tests, we could have a component test for a list.

And then that would ensure that when we pull in the data from the data that Jas that is being correctly pulled in and displaying the correct counter, we could also have a component test for the button and ensure that when we do the onClick method, that the button performs the correct operation.

But what about the look and feel of the application? How do we check that that is working? And looking correctly, we could definitely move up another level into end to end tests, right? And to answer is make sure that everything from the DOM to the base database is behaving correctly.

We can Yeah, click a button using a Antwan test and ensure that when the button is clicked, it's actually clearing all of the functionality.

However, still, how do we ensure the visual correctness of the application? And what if I told you that there was a really cool strategy that we can use is going to be two validation points in a single test, and we can ensure 100% Working functionality of our application? Let's go and make it happen.

All right.

So we actually no longer need to show the application here.

So we're just going to go ahead and stop it so that we have full screen.

And the technologies that we are going to use for our testing is WebDriver.

I O and screener.

So we're actually going to perform a visual end to end test that's going to allow us to render the entire application, make sure that it looks correctly.

And then we're going to clear the entire list and make sure that that looks correctly.

And with those two validation points, opening the application, make sure it's in the right state, clearing the button, make sure that it's in the right state, we'll ensure 100% coverage of our application not and leave us knowing super comfortable that nothing is wrong with our app.

So let's go ahead and get started installing the code.

So we're gonna do NP X, WD, I, O, and O.

And let me make sure I'm in the right directory for so let's CD to one.

And then we're going to CD to set up.

And then we'll do MPX WebDriver i o like that, and then it'll take us through a super user friendly installation process.

It'll let us pick a bunch of dependencies.

While it installs, I'll tell you a little bit about WebDriver.

Io WebDriver.

Io is, as it says here next gen browser and mobile automation test framework for No, Jas.

It's really good for end to end testing with browser and mobile.

So if you're looking for a solution that can tackle web and mobile at the same time, plus it has other capabilities like being able to plug in with visual end to end testing tools such as screener WebDriver.

Io is the right tool for you.

So next, we're gonna answer a few of these questions.

Where's the automation backend located? We are going to be used running in the cloud using Sauce Labs because Sauce Labs is integrated into screen and we're going to need Sauce Labs.

I have an account if you don't have Then go ahead and sign up at sauce

Grab your free account there.

And I'll show you how to set up that.

So it's already asking me about the environment variables for my username and access key for Sauce Labs.

And yes, mine are saved in sauce username and access key in my bash profile just like that.

No, we don't want to run headless tests.

In which region we're going to do us which framework Mocha is fine.

There's also Jasmine and cucumber options.

Now we don't have a compiler, our specs located that your default on just hitting Enter for most of these.

Yeah, let's have WebDriver IO generate some test files for us, just so we can look at exactly what those look like page objects.

No, thank you.

That's way overkill.

For our testing purposes here, spec reporter is totally good.

And then the services that we're going to install sauce service, we don't need the chrome driver service chrome driver services for running tests locally unnecessary for our purposes, because we're only going to be using a single visual end to end test to tackle all of our problems.

And then I'm going to hit enter here base URL and install I don't know what it is about typing on camera.

You guys make me nervous.

Whenever I have to type on camera, I forget how to type.

Okay, beautiful.

So it says successfully setup our project.

Alright, in birthday reminder setup, let me just show you a few of the things that were added.

Package dot JSON was obviously updated with WebDriver I O.

We also got the config for WebDriver I O.

And we got an example test.

Here, let's actually open that up so that we can see what that looks like.

It's a very simple test, navigate to this URL, and then looks like it logs in.

Let's actually give it a run using npm.

Run WD IO.

And we'll see exactly what that looks like.

So there it is starting up.

Pull up Sauce Labs here.

Alright, so we see that a minute ago, I had just executed called my login application.

And we can open it up.

And the coolest part is just running the video and seeing exactly what happened.

So there it is, there is our functional end to end test.

So we know our environment is set up, the next step we actually need to do is set up screener so that we can do visual end to end testing instead of functional end to end testing.

So let's talk about the configuration for WebDriver I O and how to integrate it with screener.

So at the very top, I've set up a visual options object.

And that's taking in an API key and a project name, the API keys coming from screener I'll show you in a moment.

And the project name basically just corresponds to the project that we're working on.

And I named that birthday reminder, we also have source options here as well.

And those are also taking in a username and access key.

You can see all I have three environment variables here.

If you want to get your environment variables in account, User Settings, you'll find your username and access key for sauce and screener, which is our visual end to end testing tool.

Once you login and then you go to your account and click my API key.

You'll get that API key as well save them all to your bash profile.

And now we can easily do CI CD and testing on our machines.

A bunch of this was already here.

I just cleaned it up some more.

You can actually even see in my diff.

What I've changed, just cleaned it up made it less verbose.

There's a bunch of descriptions that were in the WebDriver IO config to show you everything that was going on.

But the most important components are this service portion that I added.

This allows us to create a secure connection from the screen or cloud to to our local machine, right, our application is running in local host.

And so they need to be able to talk to each other to perform the appropriate validations.

So I enabled that service here, I added these capabilities to be able to point to the screen or hub.

And finally, I have an array here that will allow me to run across as many browsers and operating systems as I want.

Currently, I have it sets to desktop with this one is the most popular desktop resolution currently.

And so I set it to that resolution, set it to run on Chrome, Windows 10, and latest, and then passing that viewport size, we can add more of these capabilities to run across more browsers and operating systems.

And of course, we can also change this part off if we want.

So that's the configuration, what does the test actually look like? Let's come back to the test that have shown me let me show you that here.

Here's what the test actually looks like.

It's used as a standard describe it format, I'm saying describe my birthday reminder app that it should look correctly.

Next, we're navigating to a URL URL here, I'm not specifying anything, because the base URL is set in WebDriver.

Io config.

Let me show you where that's that's down here.

Next, we're having an init command.

By the way, all of this documentation is available here in Doc's, visual, and to Doc's, you can follow along there, it'll help you get set up.

But of course, I'm here to explain as well, this will just basically start the execution for the test.

And then this is one of the most important pieces is capturing the snapshot.

So here I am, capturing a snapshot and calling it the default state because it says initially when our application opens.

Next, after it opens, I am going to click on our button.

What I've done here to is add a data Test ID attribute to make our button more unique.

And so in order for this to be possible, we have to come back to app J S.

And in our button, we're going to add a data Test ID attribute, calling it clear.

So now our button has this unique Test ID that we can use for identification purposes.

And we're going to click it.

So now that obviously clears our application, and then we're going to capture another snapshot of the app.

And then we are going to end our test and ensure that there were no messages coming back in our results object.

Let's give this a run.

And I think you'll understand exactly what's happening.

Let me pull up the terminal here.

So we are just going to be we're just going to do NPM, run WD IO is going to start up here.

If I didn't break anything, it's going to start running.

I think it's already running, but give it a moment.

All right, there it is, it's executing.

Let's come back to screener.

And what we'll see here is a our birthday reminder, we're going to see that currently there is a session being executed.

It's running on this resolution.

Here's some information about it.

And in a moment, I'll show you what comes out of this.

I made a quick error, there should be two new states.

Let me show you what happened it see how here it can't click on element data Test ID because it wasn't found.

What I did was I actually modified the wrong app J S.

So we're going to grab this and put it in the right app J S in the setup folder here.

There you go.

And now we're going to add that button, which is exactly what's running, save that now rerun these tests.

And we'll be back in a moment.

All right, there it is.

Two new states just came in for our application.

What does that actually mean? Well, let's open it up and see what happened.

Look, here, you'll see that on this resolution, Chrome 95, Windows 10.

I have my birthday reminder app, this birthday reminder app has a default state.

If we open it up, we see our birthday reminder app here.

How does it look? It looks absolutely perfect.

We have the correct amount of birthdays.

We have all the right people and all the styling is absolutely correct.

That is the best and most powerful thing about visual end to end testing is that we can capture the state and the look of the entire application in a case single command.

And so that's exactly what we did here.

And so we validated anything that we could have possibly needed to validate in this default state, right.

And so this looks good, we are going to accept this, this will be used as a future iteration of our new code.

And then the next stage is the only other possible state of our application, which is the clear state.

And so you remember, I press the Clear All button.

And this looks absolutely correct here as well.

So not only do we know that the Clear All button functions correctly, which we could have done with a number of types of tests, this test also ensures that our application looks good as well.

All of this logic here is correct.

And so we can accept this as well.

And now what this means is that any future iteration of our tests against our application will validate against these baselines and check hey, does this look correct? Or has something changed? In fact, if we wanted to make a change, let's say we went into data, J, s, and doesn't matter, let's remove our very first element.

Save that, of course, now, we're not going to have five.

And we wanted, we can run our tests.

Actually, let's look at our application first.

And, look, it only has four people now.


And so if we rerun our tests, let me show you exactly what this will tell us.

Think about it.

If we read running our tests, and it's comparing to the baseline, which functionality has changed and which functionality remains the same? Well, the clear all remains exactly the same.

So that test is going to pass.

And then the default state that part has broken.

And we know we've broken it.

So I will see that individual tests in a moment.

There it is, check it out.


As I mentioned, one changed one accepted rule.

Let's review what's changed.

See that? Look, it's identifying exactly what happened.

One element removed.

And this, of course, has changed the text.

And so now we determine is this correct the correct state of our application? Or did we introduce a bug in this case, we introduced the bug.

This was rejected.

And now we need to go and fix our application and ensuring that it's looking and functioning correctly.

So thanks so much for joining me for this tutorial.

I hope you enjoyed building and testing a birthday reminder application.

I've been Nikolai as of Alaskan.

So if you enjoyed this content, and you want to see me build that application, go ahead and smash that thumbs up button.

And if you want to be notified of future video tutorials, hit the subscribe button.

And finally, if you want to learn something specific around react, building applications and testing them, comment down below and I'll be sure to bring those tutorials to your YouTube feed.

Thanks again.

Have an amazing day.

See you next time.

Today, we're going to build a beautiful next J S personal portfolio website.

This is what it looks like if you navigate to Nikolai dot tech, you'll be able to see a live version of the application.

You can see how beautiful it looks.

Everything here is functional.

These icons will take you to different resources that you want people to know about yourself.

And if you scroll down, you will see a collection of all of the projects that you've done.

You can put here your testing projects, your development projects, anything you've done with the community.

At the very bottom, you'll see the technologies that you are familiar with and show that off to your potential employers.

There is a little section to describe yourself and who you are, and even show a timeline of your experience and your accomplishments.

And at the very bottom we'll see a personal accomplishment section that describes some of the things that you've been able to do in your awesome career.

There's even a link that you can click and someone will be able to email you of course also importantly is this website is absolutely Totally responsive.

So mobile first world, it's absolutely unacceptable in today's world to have a website that is not responsive, and you can see how our mobile view looks, everything looks wonderful, it's easy to read, easy to see, you can interact with everything.

If you want to view an application, you can click on the application, and then it'll take you there.

Alright, so with all that said, let's jump into building testing this application.

So let's go ahead and actually grab the code.

So you'll be able to locate the code at this repository.

And while you're there, please give the repository a star.

And then you will be able to get the final version of the portfolio here in this dev portfolio folder.

This is where all the code lives.

So if you pull this down and start the server, you'll be able to see a live version of the application.

And I even created a starter version of the code for us.

So if you come to the branches, and search for dev, portfolio, start branch net, and then you can download this code, come to code and download zip, you'll be able to get a starter version of the application.

If you come in here, you'll see it's bare bones, it's not fully finished.

But it's a wonderful place for us to start and avoid a lot of the unnecessary boilerplate setup.

When you download that branch, you can start your own project, of course.

And once you start that project, just pulling all of the folders into your new project.

And this is exactly what it's going to look like.

In fact, what you can actually do is you can first do an npm install.

And then after you do an NPM, install NPM run Dev.

And what you'll see is, it's actually going to start up our application on localhost 3000.

So let's pull that up here.

And this right here is our starter application, what you can see is it just has bare bones styling, and it has all of the components that we are going to code out together.

So the header, the hero, so on and so forth.

You can see in our package json, we have all of dependencies that we are going to use throughout the tutorial already set up.

And then if we take a look at the source code, you'll see that the bare bones components have been written.

So for example, here's what an accomplishments component looks like.

Already, you can see all it says All it has is a Dave that says accomplishments.

And of course that corresponds to that component, and so on, and so forth.

So every single component already is created here, just with a bare bones, Dave that displays the text.

And what you'll also notice just to make this tutorial a lot more entertaining, and move a lot faster is we've already created all of the styles as well.

So you can see the styles for each of the components are set up here through CSS.

So all we're going to have to do is just code out the actual application and use the styles where appropriate.

And we're not actually going to have to be writing any of the CSS.

I'm also keeping a readme here for your personal portfolio with all of the relevant links and information such as the link to a personal website, how to get started and a lot of other information that we may be useful for your development and testing journey.

So with all that said, let's go in and start building our personal portfolio website.

So let's go ahead and create our very first component, which is going to be our header component.

Usually, it's easiest to get started with the simplest component.

So we've navigated here to our header J.

S file.

And let's go ahead and we're going to return a container.

And inside of that container, we're going to drop a div.

This is what that div will look like.

We'll turn this into a span.

And so this is a div that's coming from our styled components down here.

You can see here's the styling that's applied to this div one, and then we're going to have a link in here the link points back to this homepage.

And then we have this gi CSS check icon, which is coming from react icons For slash di, and then we're adding a span that's called portfolio.

If we save this, pay attention to what happens on the right, we now have this icon that's clickable.

If we click it, it takes us back to our homepage, because that's where our href is.

Next to that Dave, we're going to add a div to which also, of course, has its own styling, as you can see over here, and we're going to add a several items from that Dave.

And the we've got a project a technologies, and about each one of those having an href attribute here that doesn't currently exist.

But if we save that, we now see what this looks like.

Of course, in a mobile view, hovering over all the styling, you can see apply there.

And of course, clicking it should take each one to the appropriate section.

But we don't currently have the sections enabled.

So we'll need to come back and implement those sections in the future.

And then what we want to do is add one more thing, we're adding this social Details component, the component is going to look like this.

Let's save it, this component is going to contain all of our social details, such as our icons.

And you can see here that it's wrapped in a div three.

And then we have our social icons, and those social icons have, for example, a GitHub icon, LinkedIn icon, Twitter, icon, YouTube, and so on.

If you have other social media that you want to add, you can simply get any of these icons from react package, if you go to their website, you'll see all the different types of icons.

And then of course, if you wanted to add others, you would simply come here and add more depending on the type of social media that you have.

Next, the other thing that we are doing here is we are storing all of our social URLs inside of this constants file.

Let me take you there.

So if you go to social URLs, Jas, you can see it's just an object that contains a link to each one of our profiles, then we are simply referencing each of the links here, accordingly.

And so now if we come back to header and scroll down to the bottom, and below this div, we add our social detail.

So you can see this selection at the bottom is also going to automatically import for me.

So if I do that, and then I scroll to the top, you can see the import was pulled in for me as well.

And then as soon as we hit save, pay attention to what happens on the right hand side, boom, we got our social icons, you see.

And if we hover over them, you can see in the bottom left of my browser, it even highlights the URL, let me make this a bit bigger.

So you can see check it out.

So there's that URL, LinkedIn, Twitter, and YouTube.


And in fact, what I'm actually going to do just quickly, put YouTube up front, take this, put it here, save, and there we go.

Let's talk about our testing strategy.

For a moment.

Of course, we have a web application that we're building, and now is a perfect time to think about a testing strategy for this web application.

And in a web application world, it's really important to be mobile first, all our applications, now they have to be responsive, and they have to support mobile.

So that's the very first thing that we have to check is how does our web application respond to different mobile device resolutions.

And so a really good way to do this is to check that as we scale down our browser to see whether we are finding any issues, and I'm not seeing any at this point, I'm kind of seeing some interesting behavior at this resolution where these three are kind of getting clumped together, right.

And then as we keep scrolling, I see another issue over here where our logo is being put on top of this projects header, which of course is not good to have it's not professional at all.

So that's something that we're going to need to fix.

And then of course, we can actually get into actual mobile sizes by right clicking doing inspect clicking on this mobile device and then you can select your device from here I'm selecting iPhone 12 Pro, I'm gonna scale it up to 100% resolution and this is what it would look like on an iPhone 12 Pro.

looks absolutely fantastic.

There are no We should see here, everything is very readable.

And of course, we don't have anything else.

But besides that, that's what's left.

And of course, you can also check it on a non iPhone device as well.

So that's important.

And so what we're going to end up doing actually is writing automated visual end to end tests to ensure that our application looks good on different resolutions.

And we can continue testing through all those resolutions as we develop our application making sure that there are no regressions as we hold our application.

The other thing to remember is that we added URLs here in these icons, right, these are the URLs that we supplied ourselves.

And of course, it's very possible that these URLs can be fat, fingered and incorrect.

We of course, tested them manually already to ensure that they are correct.

But there is no reason to think that this can't accidentally fail in the future.

So we want to ensure that these URLs are correct.

And also that they're matching to the correct icon.

Right, then, of course, we have a navigation for each one of these items as well that we wrote in our header.

So if we take a look at our header, JS, right, we put an href attribute for each one of these here in the future, we'll need to ensure that they are matching up to the appropriate section that we're going to code out here.

And then of course, there's this portfolio section that is supposed to redirect us back to our homepage, which it has this href attribute.

And of course, that should be checked for as well.

Other than this, I'd say there is no other real testing needs right now.

And so this is what we're going to work on, we're going to write automated tests to make all of this possible.

So let's go ahead and do that.

We're going to use two tools that are going to assist us in our automated testing journey.

First, we're going to use Happo I O, which is a visual end to end testing tool that allows us to ensure that our application looks as it should, on different resolutions.

And you can even see here actually, this is kind of what happens, it allows you to take snapshots, and then those snapshots can be compared against baselines.

And then we're gonna run those tests with Cypress i o Cypress I O is a functional end to end browser testing tool.

And it'll allow us to run our tests.

And then of course, it will allow us to write our functional end to end tests as well.

So let's go ahead and make all of this happen.

So in order to save time, I've actually already installed and set up a bunch of information here.

However, if you're doing it on your end, the very first thing that you're going to want to do is open up Cypress we do have it already installed, right when we ran npm install, however, we're going to want to run MPX, Cypress open.

And then what that's going to do is open up a cypress UI that looks like this, you're going to have way more folders and files that come out here.

And it's also going to create a cypress folder that lives over here, inside of the Cypress folder is going to have several other folders and several other files that are important.

What we're going to do is delete whatever folders and files were in integration.

And we're going to create a visual dot spared dot j s file, that's where we're going to write our visual tests.

We're going to talk about those in a moment.

Then inside of the plugins, we're going to want to add this code to be able to use Happo.

With our Cypress tests.

Next in the support, we're going to want to import Happo, Cypress in our commands js file.

And with all of that done, what we can now finally do is go to Visual spec and write a test.

Let me show you exactly what this test looks like.

So here we have a describe block.

And we're saying that our visual tests will display the homepage correctly.

First, they're going to visit our application and ensure that our application is in a good state.

And finally, we're simply going to get the body of our page and take a full page screenshot.

In order to set all of this up and make it run we need a Happo J S file located in the root of our folder in the root of our project.

So you can see here it's right next to the package json and the Cypress JSON.

So this Happo J S file has a A number of important things such as your username and access key that you can get from your profile here, if you come here and go to your user profile, and accountants will be able to get that information, then we're supplying a project name.

So what we're going to do is update our project name and call it dev portfolio tutorial.

And here is the most useful part of this configuration is setting up our targets.

So we're basically saying we're giving the targets a name.

And then we're saying which browser viewport size do we want to run across, there are multiple other configurations that we can set.

In this case, we're saying, wait until the last animation has finished, in which case afterwards, we're going to take a snapshot, right.

So here we're doing our Chrome 10, ADP, Samsung Galaxy S 10, viewport size, we're doing iPhone 12, viewport size, and we are doing the viewport size that caused our bug that we saw previously, how I determined as viewport size was coming here.

And you can see as we scroll down and actually if we open up our developer tools, and get out of this view, you will see that over here in the upper right hand side, it shows us the viewport size that we scroll, so we scroll you can see the viewport size and then we're going to look for the problematic one happens that here, there it is, there's a problematic one.

So you see, it's about 656 65.

That's not important.

So I put in 650 by 415.

And that's where we catch that bug that we're going to want to work on.

And then the final piece of this with setting up Cypress is in the Cypress JSON, we set our base URL to localhost 3000.

And that's how in our visual spec, so if we come to visual spec, that's how we're able to just visit this forward slash here because of that.

So now with all of that said, we have a script added here that we're calling test visual running the following command.

Let's go ahead and run it and see what happens.

And looking down here, we see that our tests have finished.

And let's go take a look at our Hafele dashboard.

So we'll come back here, go to Happo dashboard.

And here we see that we have this new report called dev portfolio tutorial, which is exactly our project name, we're going to open up and we can see our snapshots here, right, you can see the different resolutions, of course, beautiful, you can see our bug over here recreated at this resolution.

And then you can see other resolutions and what our application looks like.

And so in these, everything looks good to me.

No huge issues, of course, except this part here.

And so now we basically set our baselines, and from this point forward, when we execute these visual tests, they're going to be compared against this.

And we're going to need to decide whether we broke something or we did not.

So those are our visual tests, ensuring our application is looking beautiful across different browsers and operating systems.

What about the functional aspects of our application? How do we actually test those? What are we going to do with all of these links? Let's tackle that next.

What about all of the links that we need to check? How are we going to do that, in the past, what I would have done would be to use official end to end testing tools such as Cypress, selenium, and I would have gone identified each of these locators and then clicked on them and then ensure that they will navigate me to the correct URL.

I learned along the way that that is not the most optimal approach, there's actually a better approach to doing that the better approach to doing that, that I learned along the way would be to do something like a component test.

A component test, also known as a unit test is something that we can do to simply check the href attribute of each one of these elements, right.

If we come here and inspect each one of these locators, what we see is that each of these has an href attribute.

And so if we know that this URL is correct, then we know that it's going to take us to the correct page.

Because why wouldn't it the click ability of a league actually comes from the a tag.

And so if the click ability over link inside of a tag is not working for you, it's not going to work for the rest of the internet.

And so clicking it is actually unnecessary.

What's important is just one time doing a check that the URL actually works.

And then after that, all we simply have to do is check for the href attribute for its correct value inside of our test.

Now, we can, as I mentioned, do that through a component test, a component test, what it actually would have done is, if we came to our social details, we see that we are passing in a bunch of URLs through our social URLs object here, right.

And so all of these properties are being set.

And then the social URLs they live here in constants, and this is just an object pointing to your right.

So we can simply do something like a snapshot test that ensures that all of these URLs are correct, that would actually be wonderful, it will take milliseconds to execute, it would basically just capture a snapshot of this file.

And then if anything changes about this file, it would let us know that there's a change.

And then it's for us to decide whether it's a breaking change or not.

The danger with that, and the risk that it doesn't cover is even though you can have these URLs, that doesn't mean that they are correctly hooked up to the correct social icon, right, we could very easily come here and to do something like GitHub, because we were copying, we created one, and then it'll be copied and pasted the rest.

And we forgot to change one of them.

I've done that a number of times in my life, and I'm sure that you have as well.

And so that connection piece is actually what's missing.

And so in this case, what I think is the best strategy, the one that requires the least amount of effort, and has the best coverage is a functional end to end test.

And so a functional end to end test, of course, as I talked about, was coming here, checking the href attribute, and then making sure that that is correct.

And so to make that kind of test possible, what I've written here is this social details spec J S file, if we take a look at it together, and actually, we don't even need either one of these, we're gonna save that.

So what you'll see here is we are visiting our URL as before.

And instead, we are saying that our social details should have correct social links.

And the way we're getting those attributes is, we're looking at each one of our locators, you can see I've used a data Test ID attribute which makes each one of these properties unique.

And so again, if we come take a look at social details, J S, we will notice that each one of these icons had nothing unique about it, except the href attribute.

So prior to adding this data, Test ID attributes, all of the social icons look like this.

And so how do we reference the correct one, and ensure that it's hooked up to the correct URL.

And so we do that by adding a data Test ID attribute and I named each one, right, I said GitHub, YouTube, LinkedIn, and so on correctly, matching it to the correct icon.

And so with that, I can now get each one and assert that each one has a href that matches the correct value.

If we come to our Cypress dashboard, and we click on social details, spet, it's going to execute for us.

And all look, it has actually failed.

And if we take a look, you can see that we're getting a GitHub and GitHub work successfully.

But then if you look at the YouTube, we see that it failed.

And why did it fail because we were expecting YouTube, but instead we got GitHub.

And that's of course, because I messed up aka fat fingered, aka, copied and pasted and correctly, this URL.

And so if we do YouTube, and then we save this, we come back to our Cypress test, we rerun it, and everything passes accordingly, right checking GitHub, YouTube, LinkedIn, and Twitter, everything is successful.

And so ultimately, the test looks like this.

And I'm not going to write the tests for the other properties such as these and the even the logo because you already know how they should behave.

And I'm gonna leave that as an exercise for you to do definitely send a pull request to the repository and share with me your solutions and I will let you know if you got them right or did it.

Alright, let's get back to coding the rest of our application.

And now we're going to go a bit faster.

All right, next, we're going to work on our hero component, which is going to work our way down.

The hero component is this section of our application right here.

So to make it happen, the code is relatively simple, I've already pasted it in, we're going to save it, and then you can see what comes out of it, you can see all of the styles that have been imported, they are being imported from global components, which we've defined in the appropriate folder, because we're going to reuse them everywhere.

And so here, you can see we've added a section title, right, that's where my name comes from, you can definitely feel free to add yours.

And then there's a section text element here that allows you to define the text.

And then also, you can define this button here, I put learn more, in fact, maybe we can even change it to about me, there'll be a better button, because it's redirecting us to about section of the page, which doesn't currently exist yet, but it will, in the future, probably we'll add it under here under accomplishments, it would be this section about that we would add in the future.

So let's go ahead and save this, see how that text updates.

And of course, all the styling is automatically coming from all of these components.

So now we got this version of the application, let's rerun our tests, right, so we can do two types of tests now that we have.

So we can go to package dot JSON, right, we can do visual tests like this.

And then we can run Cypress tests, I'll show you how.

So let's run our Cypress test, you can do MPX, Cypress run, it will actually run them in the background, and then produce an output or of course, you can run them through this UI as well.

So it looks like our social details are passing, which is wonderful, right? We haven't changed anything about our links.

So that's expected.

And then let's do NPM run tests visual, so that we can run our visual tests and see what comes out of that.

So there we go, our tests have finished running, let's grab this URL, and check out what's going on in our Happo dashboard.

So here we can see that this is a little bit of a different if you now because we're comparing one check to a pre to a current check, right.

And so we're checking previous state versus current state.

And what we see here is we have five days, of course, which is great, right, we can zoom in a bit so that they're easier to see, this is what our diffs look like, we can put it in swipe mode.

And you can see this is the before.

And then this is the after, right.

And of course, the after is we added an entirely new section.

And this is the before.

And so all of that has shifted down.

But in terms of that it looks good.

Of course, there's nothing wrong here.

Of course here in this view, down here, you can still see we still have this bug that we're going to fix in the future.

And then we have this section.

So that looks good.

On Galaxy S 10.

Everything looks good.

This is getting a little bit tight over here.

And this is getting cut off, you may want to take a look at that in the future to see what's going on and how to fix it.

And here everything looks good as well on iPhone 12 Pro, so no new bugs introduced in a visual aspect, no new issues added from a functional aspect.

So of course, we can test the button to ensure that it navigates us to the correct location.

But we don't have the botany section yet.

So we're gonna do that in the future.

One thing we can do, if we wanted to, we could write a test in, we can create a new file and call this one hero dot spec dot j s and we could have a failing test that would be doing something like this until we create that feature.

That's also one option.

But we're not going to do that today just because of a lack of time.

So next, let's move on to the project section.

Next, I've gone ahead and implemented the project section.

Let me first start running our visual tests right, we don't even need to manually test anymore.

We can simply just run our visual tests and ensure that everything looks good.

So I'll let those run while I talk you through the project component.

It project component is relatively large however, it's not so difficult that the main logic here is really on line 34, where we use projects dot map.

And basically that's like a for each loop where for every single project that we have stored inside of this array, and this array looks like this.

So you can see we're providing a title, a description, an image, the tags, the source code, where to visit the application, and then an ID.

And so you can add as many projects as you want here, right, you just keep appending, to the array of whatever you need.

And then this map function will basically use all of the values that are coming from that array.

So for example, each everything is inside of a blog card.

And then you can see we're supplying an image that's getting this source, then we are having a header that's getting the title.

And so the title, of course, is this title, we are getting card info, which is description, which of course it's coming from there.

And then the tags, the tags, we also have to do that for each loop, right to go over each tag, and then simply add the tags.

And then of course, the external link, and another external link with the corresponding source and visit attributes.

So that's really that.

And then that creates this beautiful view that you can see here on the right hand side, of course, totally responsive.

If you of course, want to add your own projects, you simply need to add all of the images to this public images folder.

And then of course, update the information for the project.

So you can remove projects, you can add projects, but leaving these properties in place, you just obviously changing the values of the projects.

So these tests executed just fine, right? We can come here and take a look at a moment, let's run our Cypress tests, what do you think are the my Cypress says gonna pass or fail? Well, of course, if they are good Cypress tests, they are going to pass because we've changed nothing about our URLs, right, everything is still exactly as it should be.

Let me go back and actually redo them.

And because we we've updated our application.

So having really good tests, it allows us to update our UI without breaking the tests.

That is really good solid testing.

So and then with all of that said, let's take a look at the Happo comparison.

So we'll see a new view that we haven't seen before.

So here is those here are those defs.

So again, the original, and the new one.

And of course, here it says we need to review it.

So we're going to review it, and here are the five diffs, 10, ADP, everything looks great.

Chrome 650, of course, still has the bug because we haven't fixed it.

But in least everything else.

Let's take a look here, everything looks wonderful.

So everything is being rendered correctly, everything is looking great.

There's nothing weird visually going on, and everything looks good.

And of course, then we can probably expect a similar thing here.

And so of course, at this point, let's just go ahead and accept all of these.

And now they're going to be used as a baseline for our future iterations, even though we have a few more sections to implement.

Alright, so I've gone ahead and implemented the rest of the application in the interest of time so that we can talk more about testing and of course, do the most fun part, which is deployed to production so that we can proudly display it to the entire world.

So I've implemented a technologies section over here, as you can see is just a bunch of static text here that's written that describes all of this information.

If we navigate to the technology section, you can see that all everything is pretty much hard coded here in this component.


So in terms of risks, what are the risks with this section that we need to tackle with new tests? Absolutely not actually, visual tests take care of all of the risks they are for us.

That's the beauty of visual tests.

We've written them once.

And now we can continuously use them to check on our application.

Speaking of which, let's run them now.

While we continue to talk through our application, so then we get to our personal accomplishments.

Our personal accomplishments also show A bunch of data here, if we take a look at the accomplishments, we will see that there is this data that's hard coded here, could be very useful to actually move it to our constants folder and just put it in there.

But you will see how we iterate using a mapping method over all of our data.

And that's exactly how we display it.

So what are the risks that we need to check for here, for example, in this case, should we write another functional end to end test that will validate that this part of our UI correctly reads the data in the back end? No, in this case, we don't need to do that.

Because this data is simply displayed here.

If there's anything weird, that comes out of this, like, for example, let's say we put one zero last here, and the amount of projects here, that will show up in our visual snapshot.

And we'll be able to see the differences.

And so that's the nice part about the static data is being reflected here.

And we can capture it again, with a visual end to end test that already exists, protecting us from all of these risks.

And then the footer down here is also very simple.

So let's take a look at the footer from the source code perspective.

So the footer is very simple, you will actually see that we are reusing our social Details component that we've not only written before, but we also have tested.

That's why we put it into an individual component so that we can use it down here.

And so of course, if we've already written and tested it to retest this down here as well, no, we don't, it's the same exact source code that we've written and tested before.

And so we're good here.

The only other risk here is this link that will do and mail to that could be double checked, we could ensure that this has the correct value.

And what would be the best way to do that, we could simply do a components test to ensure this has the correct href value.

And that would be good enough, we could do a functional end to end test with Cypress.

But I don't think that in this case is necessary.

Now I do have one interesting question for you.

In terms of a testing challenge, how do we ensure that these projects links are correct here? So right in the View app, if we take a look at the projects, right, they're iterating over two arrays, one of which gets us the source and the visit from our projects file? Here, here are all of our projects, right? How do we ensure that this URL and this URL, and so on and so forth, are correct, even as we modify these projects.

So one initial thought that I might have is to do a functional end to end tests like we've done with Cyprus, right? For example, if we come to our social details spec, we checked all of our URLs in this manner, right, in this case, making sure that the UI is correctly connected to our file and reading from it correctly.

However, what's going to happen when we add a new project.

So now we need to add another test.

And then the other challenge of that is now not only do we need to add a new test, we also need to then start adding unique data test attributes for every single button that we add.

I mean, I guess that doesn't necessarily have to be too much work, we could make it somehow dynamic.

But that seems like a lot of extra effort for testing, just the fact of testing these components here.

So instead, what we can actually do is use a components test is specifically a snapshot of our component to ensure the validity of these components here.

And let me show you exactly what I mean.

And for that, we are going to use just Jess which is a unit testing library that also allows us to do snapshot tests with the code.

So let's take a look at exactly what I mean.

So I've configured here a snapshot test.

You can see in our constants folder, I've added a projects dot test dot j s The reason it's called projects dot test because it's testing this projects file that contains all of the relevant resources.

And this projects test file is saying that we're going to have a test.

And it's checking that the project details are correct.

And we're importing our projects object.

And then we're expecting our projects object to match an inline snapshot.

So when we initially use this method, in fact, I can even show you here, what just is going to do is generate a snapshot of this project.

So of course, we can access different properties, and so on and so forth.

But we really want the entire object, and I'll show you what that looks like.

So if we come here, and of course, I already added a script, that's called NPM, run test jest.

It's going to execute this test.

And what you also see here is, is just filled in this entire object into our code.

So it's written here, everything about our objects, such as a description, the ID, the URL to the image.

But even better, it's captured our links to ensure that they are correct.

So similar as with visual testing, all we have to do at this point is ensure that all of this is correct.

One time manually.

And now from this point forward, we can use the snapshot as an acceptance criteria for any future changes.

And what may a future change look like? For example, let's say that for whatever reason, I was in here, and I accidentally messed up this value.

And I said, or I even Yeah, let's do this first.

And so then if we rerun NPM, run test chest, we're going to get a failure.

And the failure is going to tell us, hey, you expected us to match your inline snapshot.

But look at the difference I found.

I expected this, but I got this.

And so of course, that's a bug and we can reject it.

So I'm just going to go back here and save that and rerunning it, of course, it's going to pass it beautiful.

But then of course, even if you wanted to add a totally new section, give us give it a new ID, and then rerun just we're going to get an expected failure, because of course, it doesn't match our snapshot.

And just as gonna tell us, hey, I see this totally new object is this.

Okay, so of course, you manually validate that everything works here one time, and then afterwards, we now have this test to ensure that nothing breaks in the future.

And with that said, we're able to successfully check everything, all of the data about this section, especially the URLs, which are hidden, of course, everything that's visible, can be captured by our visual test.

But the URLs are hidden, but they can be checked by our snapshot test.

And so with all of that said, that captures this risk, and then we never revisited our Happo dashboard.

Let's take a look at those tests.

Let's take a look at our new snapshots.

We can see our brand new snapshots.

This is what they look like now, right? Much larger.

Everything here looks good.

Everything looks wonderful to me here.

So of course I'm going to accept and now any future changes, we can go in, review them and make sure that nothing is broken.

Thank you so much for joining me here today.

I've been Nikolai Adva lockin, founder of ultimate where I create training on coding, testing and deploying web applications.

It's been a true pleasure hanging out with you today.

And if you have any comments on what you want to learn next time, please go ahead and comment below.

And if you want to learn more for me, you can follow me on my YouTube channel.

Alright, see you next time.