Advanced Testing for React with Vitest, React Testing Library, and Playwright | Babak Mehrabi | Skillshare

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Advanced Testing for React with Vitest, React Testing Library, and Playwright

teacher avatar Babak Mehrabi, Teaching difficult things in simple way

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Course Introduction

      1:49

    • 2.

      Course Pre Requirements

      1:27

    • 3.

      Why Testing Matters

      3:18

    • 4.

      Different Types of Testing

      1:35

    • 5.

      Testing Pyramid

      1:59

    • 6.

      Introduction to Testing Tools for This Course

      1:43

    • 7.

      Simple Blog Repositories and How to Run Them (Part 1)

      1:50

    • 8.

      Simple Blog Repositories and How to Run Them (Part 2)

      2:11

    • 9.

      Simple Blog Project Tour

      2:36

    • 10.

      Introduction to Vitest & It's Features

      2:11

    • 11.

      Vitest Installation

      2:55

    • 12.

      Writing First Unit Test

      3:31

    • 13.

      Configuring Vitest and Completing Our Unit Test

      5:08

    • 14.

      Code Coverage Definition and Metrics

      3:30

    • 15.

      Code Coverage vs Test Coverage

      2:58

    • 16.

      Adding Coverage Report to Vite

      2:54

    • 17.

      Digging Deeper in Code Coverage Report

      8:11

    • 18.

      Adding Unit Tests for QueryKeys

      6:30

    • 19.

      What is Mocking?

      3:24

    • 20.

      Writing Unit Test for FetchPosts with the help of Mocking

      12:47

    • 21.

      Writing Unit Test for usePosts

      12:52

    • 22.

      Writing Unit Test for fetchPostById

      3:32

    • 23.

      How CreatePost Mutation works?

      5:27

    • 24.

      Writing Test for useCreatePost (Part 1)

      8:28

    • 25.

      Writing Test for useCreatePost (Part 2)

      6:49

    • 26.

      Unit Tests for useEditPost & useDeletePost

      3:02

    • 27.

      Test Factories and Their Benefits

      6:53

    • 28.

      Introduction to FakerJs

      2:47

    • 29.

      Using FakerJS with Post Factory

      6:35

    • 30.

      Unit Testing Module Summary

      2:14

    • 31.

      Introduction to Integration Testing

      1:37

    • 32.

      Seting Up Environment for Integration Testing

      4:16

    • 33.

      Writing the First Integration Test

      3:22

    • 34.

      JSDom vs Browser Environment

      2:39

    • 35.

      Finishing the Integration Tests for PostComponent

      6:35

    • 36.

      Code Coverage Report for PostComponent

      0:52

    • 37.

      Writing Integration Test for Footer Component

      3:33

    • 38.

      Writing Integration Test for Contact Page

      8:52

    • 39.

      Writing Integration Test for About Page

      1:47

    • 40.

      Writing Integration Test for Blog Page (Part 1)

      12:59

    • 41.

      Writing Integration Test for Blog Page (Part 2)

      14:01

    • 42.

      Introduction to Writing Test for the Admin Section

      2:24

    • 43.

      Different User Event Methods and Actions

      2:05

    • 44.

      Writing Test for the Admin Table (part 1)

      10:13

    • 45.

      Writing Test for the Admin Table (part 2)

      14:10

    • 46.

      Testing Edit Action Item

      10:52

    • 47.

      Testing Delete Button (case 1)

      3:47

    • 48.

      Testing Delete Button (case 2)

      6:29

    • 49.

      Getting Coverage Report for Admin's ListPosts Component

      2:21

    • 50.

      Introduction to CreatePost Section

      1:57

    • 51.

      Looking at CreateOrEditPost Component

      3:21

    • 52.

      Testing Rendering of Correct Form Elements

      11:55

    • 53.

      Writing Test for Post Creation

      10:47

    • 54.

      Testing createPost Parameters

      9:08

    • 55.

      Analysing Code Coverage for createOrEditPost Component

      2:32

    • 56.

      Adding Test for the API Failure Case

      8:48

    • 57.

      Adding Test for Edition of the Post

      15:41

    • 58.

      Adding Validation Test for Image Selection

      3:21

    • 59.

      Integration Testing Module Summary

      1:29

    • 60.

      Introduction to End 2 End Testing

      2:08

    • 61.

      Installing Playwright

      4:28

    • 62.

      Running Playwright Example Tests

      4:11

    • 63.

      Playwright Methods and Helpers for Testing

      4:05

    • 64.

      Writing Our First E2E Test

      1:45

    • 65.

      Testing the Blog's Header

      1:19

    • 66.

      Testing Click Event and Navigation between Page

      8:07

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

1

Student

--

Projects

About This Class

Master React Testing: From Vitest to Playwright – Build Rock-Solid Apps with Confidence!

Are you building modern React applications and want to ensure they’re robust, bug-free, and production-ready? Look no further! This hands-on course takes you step-by-step through the most advanced testing strategies using today's most powerful tools: Vitest, React Testing Library (RTL), and Playwright.

Whether you're a frontend developer, QA engineer, or full-stack pro, this course equips you with in-demand skills that top tech companies are actively seeking.

What You’ll Learn:

  • Why testing matters – and how it saves time and money

  • Unit, integration, and E2E testing using the modern Testing Pyramid

  • How to set up and use Vitest for lightning-fast unit testing

  • Mocking network requests and React Query using Vitest

  • Writing real-world tests for custom hooks and API logic

  • Test-driven development (TDD) with React Testing Library (RTL)

  • Code coverage: metrics that matter, and how to improve them

  • End-to-end testing React apps with Playwright

  • Efficient test architecture for real-world React projects

Tools & Technologies Used:

  • Vitest – A blazing-fast Vite-native test runner

  • React Testing Library (RTL) – For testing UI from the user’s perspective

  • Playwright – For full browser testing (E2E tests)

  • Mocking – Learn to test network and async logic with confidence

  • Code Coverage Tools – Gain insights and boost test quality

Project-Based Learning

This course is 100% practical! You'll work with a real-world blogging app repo, writing tests that mirror what you'll do in a professional setting:

  • Test fetching and mutating posts

  • Cover all edge cases

  • Master mocking strategies

  • Apply best practices for organizing test suites

Who This Course is For:

  • React developers who want to go beyond basics and write reliable, testable code

  • Engineers preparing for tech interviews or transitioning to senior roles

  • QA professionals looking to add automated frontend testing to their skillset

  • Anyone building production apps who wants confidence in their code

By the End of This Course, You Will:

  • Write unit, integration, and E2E tests like a pro

  • Understand testing from theory to real-world implementation

  • Create robust, maintainable test suites using modern tools

  • Build the confidence to refactor and scale apps safely

Enroll Now!

Start mastering testing in React today and build bulletproof apps that users (and your team) can trust. Your future self—and your next employer—will thank you.

Click Enroll Now and take your React testing skills to the next level!

Meet Your Teacher

Teacher Profile Image

Babak Mehrabi

Teaching difficult things in simple way

Teacher
Level: Intermediate

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Course Introduction: Hello, and welcome to the course Advanced testing for react with V test, react testing library, and playwright. This is a very comprehensive course. I will teach you all of the concept about testing in the react. We will first start with unit testing with V test. I will talk about the test factories. We will implement FACRes with the help of ACG library. And then we are going to go to the next step which is integration testing. We are going to use react testing Library. I'm going to teach you everything about react testing library and we are going to use user events for simulating the actions that users, for example, clicking, submitting for entering information, and then we will go and we will test our whole application with the tend testing framework, which is playwright. I already created two repositories for this project. I will show you how you can set up a simple block with react and all of our tests and all of the lectures will be done for this blog and here you can see that we have an admin dashboard and I will walk through you about the setting up the project in every step, you will do the coding with me. You can sit and watch the videos and also implement them yourself. And at the end of the course, we will have a complete tested application with all different kind of testing like unit testing, integration, and end to testing. I'm really excited to see you in the course and please join me in the course, we will have so much fun in this course together. 2. Course Pre Requirements: And what will be the course pre requirements? I have designed this course to not require a lot of things. A basic knowledge of typescript and Javascript and also a basic knowledge of react would be enough for this course. And everything that you need to learn about the testing, I'm going to cover in the course so you don't need to know anything about testing. You can learn everything in this course, just a basic knowledge about how JavaScript works and how typescripts work and what is react, how react components work would be enough for this course. There is a section good to know. I have used TNSAquery or Rea Query for the communication between the rea client and our No J server. But if you don't know it, it is not mandatory to have it. I will inside the videos, I will tell you how it works and how you can use it. But if you already worked it, it would be easier for you to follow the course. But if you have not worked, I already I'm already going to teach you everything that you need for this course. As I said previously, it doesn't need, you don't need to know a lot before starting this course. Just start this course with me and I will teach you everything in the duration of the course. Let's start together. 3. Why Testing Matters: Let's talk about why testing matters. Testing will help us to make sure that the code is working as expected. Also, testing will help us to prevent regression. And what does this mean regression? Any changes to the software can break the existing functionality. And if we do some kind of coding and this coding changes some part of the code, but it breaks another part of the code, we will call these kind of errors as regression. Testing will help us to prevent regressions, and testing will also help us to ensure better code design. When the code has been when we are adding more tests, it helps us it helps developer and us to better understand the code and it helps us to have a better code design. And also it increases the product reliability. It increases the product quality, and it will bring confidence for the whole team because the team knows about the quality of the product, and this gives the team confidence. And it saves a lot of time in the long term because when you want to add new features, there are a lot of tests that will make sure that the old functionalities won't break. And also, if something happens, you can detect it immediately at the first step. So it will also help you to save time in long term. And what is the difference between manual testing and automated testing? So in manual testing, it requires a team. Manual testing usually will be done by humans. So a software tester usually be higher and then he he or she starts testing every possible flow that in software can happen, and this is the process of the manual testing. But manual testing requires team and it requires a lot of time every time that the software development team changes something into the software, the A team needs to do a lot of tests, and this requires a lot of time. As it is not error prone as we all human can make mistakes. So maybe in the first time, there is a bug and somebody finds it, but maybe the next time somebody forgot that he or she should check a flow and then he misses this flow and then the bug is not detected. So the whole process is not error prone. And also it can be a boring job. Usually, when a team works over six months or one year and they are every day testing the same flows. Sometimes it's getting boring for them, and also when it gets boring, it means that they don't put 100 person attention on this job, and it makes it that some of the bugs cannot be found, and we are returning back to the item that it is not error pro. And let us talk about the 4. Different Types of Testing: In automated testing, we have three different types of testing. First is unit testing, second is integration testing, and the third is E to E or N to N testing. What is unit testing? In unit testing, we are focusing only on one unit. For example, a function or a class, and our purpose is to test this unit separated from all of the other functionalities and all of the other components of our in integration testing, we are going a level higher, and then we are testing the integrity been different components and modules. First, with unit testing, we are sure that every unit is working as expected. In integration testing, our focus is to see how these units work together. So for example, if the API adds a new field and the front end is not aware of this new field, then we can have an integration test to make sure the integrity between our front end and our BC. And the last one is end twin testing. Into end twin testing, we will see the suffer as a whole. We will test the whole suffer from the perspective regardless of how many components, how many modules, and how these components and these modules interact with each other. We are testing it as a whole and as a system. 5. Testing Pyramid: Let's talk about the testing prompt. As I mentioned previously, we have three different kinds of testing. The first one is unit testing, integration testing, and end two testing. And if we look at these three kinds of tests as a pyramid, on the top, we have unit testing, which is we have a lot of tests. They are fast when we want to run them and they are cheap, so they don't require a lot of time and we can easily write unit testing. They are easy to maintain, and they are easy to change. And as a result, we have many of the unit testing. On the bottom of pyramid, we have end ten testing, which means they are usually in production environment, there are few TN tests, and running this kind of tests, it is slow, and it is also expensive. So it requires a lot of time for writing this kind of tests and also maintenance of these tests are really difficult and time consuming. And as a result, we don't have so many end TN testing relative to the unit testing. Not saying that you should not have it in your project and your production, the more that you have TN testing, it is better so you can provide more quality for your software. But relative to the unit testing, which is easy to write and they are so much faster for running, we have in practice in production environment, in staging environment, usually a lot less NTN testing relative to unit testing. And between them, there are integration tests. So there are more than two t, fewer than units. And from the cost, they are also in between, so they are not as cheap as unit test, but they are also not as expensive as the end two testing. 6. Introduction to Testing Tools for This Course: All right, let's get our hands dirty. In this module, I'm going to talk about the testing tools that we are going to use for this project and also I will show you how to set up them and how to install them and how to run them. Let's get started. The testing tools that we are using for react for this project is V test react testing library and playwright. And we are using V test for unit testing, and for integration testing, we are using react testing library or RTL, and for TN testing, we are using playwright. In this course, I'm going to show you step by step, and we will first start by writing unit test with VTS and then we are going to write integration testing with RTL, and then at the end, we are going to write TN test with playwright. So let's get started. I already created two repositories for the project. These are the links to the front end repository and server repository. And then the next video, I'm going to show you about the project setup. So we want to add test for a project which is already running. I will show you the features of this project, and then I will talk you what components we want to test and how will be our testing process, and I will also show you how you can run these projects locally on your machine, so you can also follow with me step by step during this course. 7. Simple Blog Repositories and How to Run Them (Part 1): So I have created two repositories for this project. One is called Simple blog, which is a reactor application, and the other one it is called simple Blog server, which is a packing service for this block. In order to run this project on your local, you need no JS, and first you have to clone these repositories. So here, when you press on this button, you will get a URL, and you can copy this and then inside your terminal, you can write Git clone and then you can write this. I already did that, and here I have two folders. One of them is simple blog, one of them is simple block packing, let me open a new tab. And when you've done that, you can easily go to there and to run the projects, you need NodeJS. I'm using NodeJS version 22. So I also suggest you to use the exact same version so you will make sure that everything that I am doing, you can also do it on your local machine. So if you run node version, I have version 22.14. I also suggest that to use the exact same version. And here I will going to the first thing that you need to do is run NPM install to install the dependence of the project. I will pause the video and I will continue after that. 8. Simple Blog Repositories and How to Run Them (Part 2): So I did the NPM install, and then after that, you can easily run NPM Stop. Just one note that you should notice, I'm going to change this project and I'm going to add codes as we go in this project together. I'm going to add some test. In order to check out the start of the project, I have created a tag, which is called start for both the front end and both the back end serve. And when you want to check out the repository, you can run Git tags, and here you will see that sorry, Gits tag. And here you will see that I have a tag, and then you can check out this specific tag so you can return back to the start of the project and you can continue your work with me step by step. And when I do the changes, you can also do the changes. After adding all of the tests, I will leave the repository at the final estate, so you can also use it in the future. Okay. Let's start. We already have the dependencies and also let us go to the back end. And here I will go to the simple blog. I and here as also I also need to run in PAM install. I already did it, so my packages are up to date. And here you have a file which is called server dot JS. The only thing that I need to run is node server dot JS. And you will see that the server is running and local host 3,001 now that our backend service running, let us go to the front end and let us run NPM start and now you will see that the client is running in this pot. I'm going to copy this link and I'm going to open it in my browser, wonderful. Now you will see the project. 9. Simple Blog Project Tour: So let's talk about what is this project. I have created a simple blog that when you come in your homepage, you will see a simple blog. Every block has a photo, has a picture, a title, avatar of the creator of the post. And then when you click on that, you can see the details of the post, and then when you go back, you will see you can back to the home page. As you can see, we already have a box, so I already have my icon here and but when in the home page, this is a default icon. So this is one of the things that the testing can help us. This is an intended that we will fix it in this course together and also we will provide the test for. We have the About page, which is tell that this is a log that I have created for this course and also, these are the details for me if you'd like to contact me. And this is the blog site, and we also have an admin tunnel which I can write slash admin. And here, I will see the number of the posts that have been published. And to be accurate, you should write slash admin slash. And we can also see the post here. We can create a new post, we can edit posts and we can remove posts. So for example, if I go and if I edit this post, and then I just had a two at the end of the post, I can see that this has been changed. If I go to the simple blog, I can see also this has been changed. If I return back to the admin home section, I'm going to the post and I'm going to return this back to what was before. And we don't have authentication. Here it is not important right now for us. Usually in the production environment, you should hide the admin and user should login. You should have a usernPassword, and this area should be protected. But for this course, it is not required for us. We got this project and now we want to add tests for it. We are starting with unit test and then we are going to integration testing and then at the end we are going to write some test with plat. 10. Introduction to Vitest & It's Features: In this course, we are going to use V test for unit testing. But what is VTS? V test is a fast unit testing framework and it by default, supports typescript. The react project that I have created with TypeScript and most of the modern projects are also with typescript. This is a really good feature of the test that we can use V test with TypeScript. And also it is just compatible API. If you have previously worked with react, a lot of react developer previously were using Jest for unit testing, and VTS and T are nowadays more modern tool and a faster tool that we are using. And VTS is also compatible API. VTS has the compatible API with J. So it is really helpful for the developers who have already experience with the JS learning VTS is so much easier because we have the same API like describe it, expect, and all of these APIs are the same. The learning care for VTS for the developers who have previously worked with Jess is so much easy and so much, it doesn't require so much time. One of the features of VTS is that it supports code coverage out of the box. I will discuss about the quote coverage in the future lectures. But for now, just know that test by default provides us with the Code coverage report and it also provides the parallel test execution. Our test doesn't need to run a sequential in one by one test, run them in parallel, which makes them faster and we can run our test faster. Let us go and set up our test environment. In the next video, I'm going to show you how to add the test to our project and we are going to write our first unit test. 11. Vitest Installation: I have opened the project inside my ID. I'm using webstorm. You can use whatever ID that you are more comfortable with it. Webstorm is a commercial product. You can get a 30 day trial if you want to use it and if you like it, you can purchase it. I am enjoying a lot with working with it, so I already purchase it, but you don't have to purchase it. You can use Atom sublime or any other text editor or ID that you are more comfortable with it. And so let us see the project structure. We have an SRC folder here. We have an admin folder which is related to the admin section of the web log, which is post addition post removal adding post. We have a folder called API for the API communication. We have a constant folder for the constant and the site is the block part that every user can see the post the shared is some components that are shared between the website and admin. Let us open the constant folder and here we have one index file and here three variables have been defined. Let us set up test and let us first write our first test for this file. To install test, I'm going to my terminal and I'm going to write in pristall dash DSD means that this is for only dev dependencies, and this dependency is not part of our production dependencies. It is only for the development. When I run this command, you will see that package package that Jason has been changed and if I see what file has been changed, now inside our dev dependencies, we have V test. What is the difference between depth dependency and the normal dependency depth dependencies will be only used for the local development because the tests we write tests to only run them when we are developing and they are not part of the production environment, so we install VTS as a depth dependence. Now we have VTSt and let us go and here I want to create a first test. By default, by convention, I will name it as a test, I would say index the test, the ts let us write our first test. 12. Writing First Unit Test: To write our first test, we first define a describe block and a describe block will tell what we are going to test. Because I'm going to test a constant file, I'm going to call this constant and inside, second parameter will be a function that I am passing. And here I will write it and here I can define what condition I want to be tested. The first parameter is an string that, for example, let us write the test and let us make sure that the course name is stay always and the correct value of which is this value. Let me then write my first, then I would say should return the correct value for the host name. The second parameter is also a function that I can pass and I will define my test here. Here, we have what we are going to expect from the test and what we are going to expect. We have a expect function from B test that we can give a condition and then it will check if this condition is true or false or what should it be? Here, I'm going to use course name and I'm going to import course name. I'm expecting the course name to be this advanced testing with react and Test. I think here also, I have a problem because this course is not about est, but I should write it with playwright, but we will fix it together now. With this, this will be our first test. What does that mean? That means I'm going to first define a describe lock and describe is a collection of the test and every test will be inside it block, the first parameter will be a message that if the test is failing, it should it will tell us this message so we can identify which one of the tests is failing. And here I'm going to write exactly what I am going to expect. As you can see in my vastorm ID already detected and I have two bottoms here, and this is a cool thing about gastrom that also provides with support for TS. But if you are using another ID or something else, you can just inside your terminal write NPX V test. As you can see, it's automatically detected and it is running my test, but I have an error and it says that describe is not defined. The reason is that we have not configured V test yet. In the next video, I'm going to configure V test. 13. Configuring Vitest and Completing Our Unit Test: So let's configure our test. Inside this project, there is a file called it dot JS. This is a configuration for the T. In order to add the configuration for test, I will also add a parameter here. Here, you will see that we are saying that our project is a a project. And also for our imports, everything which is sorted up, please replace it with SRC. Here I'm going to add a section and for the test, and I will set the globals to true and environment to the J Describe, these are the global keywords, and here I'm telling VTS that to understand describe and it. As you can see, the error is that describe is not defined. With this configuration, we are saying that we want to have the globals. For our testing, which is describe it and also our testing environment will be Jz. Let us go to the terminal. As you can see, it automatically re run my test. I didn't have to start and stop it again. This is also another cool feature from VTS, which is automatically re running the test when you are changed. Now, you will see that my test is failing and it says that our expected value is advanced testing with reacts test and the received value is something else. Let us go and see what was actually the value. The actual value is here. Now, I didn't add the playwright section, so I only said that I'm expecting this value to be this p, which is definitely wrong. I'm going to replace this value. Now when I say we will see that it automatically run it again and this time I'm expecting my test to pass. As you can see now, my test is passing. I can also let me press Control C and also run and pick test. Now I have one failed test and one past test. This is the default test by react. Let me also go and remove this at the Ts five. I have created this project with create react up and this test has been created by react let me also remove that and let us go. Now our test should be clean. We have one test and this test is passing. Amazing. And know what is the benefit of having this test? Where do we see this string inside our web blog. You see here I have a simple block created for the course advanced testing we react. If we do only manual testing, this text is in the footer and when the blocks gets more complicated and a lot of people working with different elements and the tester, can easily ignore this part. As a result, a developer may come and start writing and maybe he wants to write something, but he doesn't notice that he's actually typing, so he will do this and when he will do this, you will see that our web log is broken. But with this test, immediately, we will see that one of the tests is failing. So I can see exactly in which file and which line test is fake. Let me first remove just because this test for the course line will be atlas testing for react with test, RTL and Plavt. I changed the test, but I didn't change the actual value, so let us go and also change the actual value. From these moments that I have this test, I know, I am sure that this part of the text will always be correct. Nobody by mistake if anybody by mistake comes and for example, at the G, immediately, we have a test which is fail. Wonderful. Let's continue our work by adding more tests. 14. Code Coverage Definition and Metrics: As previously I mentioned, one of the benefits of VTS is that it provides the code coverage report by default. And what does code coverage means? Code coverage is a measure for the quality of our test. I said that we are going to improve the quality of our software with automated testing. And now, how we can make sure what is the quality of the test? Actually, what is the quality of our automated test. And here there is a new concept which is called code coverage. And the code coverage is the percentage is a number based on the percentage, and it is the percentage of the lines and the code that will be executed when you are running the tests. So if I have a function, if I have a class and this class has ten lines of code, and if I write a test for this class and during the execution of this test, eight lines of these ten lines will be executed, then my code coverage will be 80%. And this is the definition of the code coverage. And but code coverage also have different metrics. In the next videos, I will show you on its and we can actually see these numbers. Here I want you to give you the definition of this matrix. We have five numbers from its when we add code coverage report to it, first is the lines. The second one is a statement. The third one is branch, functions and uncovered lines. The lines actually shows us how much percentage of the lines has been covered. So like I said before, if I have a function and this function has ten lines of code and during the execution, eight lines will be executed, then the code coverage for the metric of the lines will be 80%. Statement is similar to the lines. The only difference is that I can write multiple statement in the single lines. In the lines calculation, this will be calculated as a one if I have three statement. But in the statement number, this will be calculated as a state. And branch means whenever I have an IL condition or a switch case that based on different condition, my program goes in different direction. This is called branch and actually its also provide many percentage of our branch has been covered during the execution of the test. And the function, also the number of the functions that have been called during the running of the test relative to the whole number of the functions that we have in our code bias. And at the end of the report, also VTS provides us uncovered lines, so we can actually see which lines of the codes have been covered by execution of our tests and which lines have not been covered. And by seeing these lines, we can improve and we can also add more tests for those lines that have not been covered to increase good coverage and increase the quality of our tests. 15. Code Coverage vs Test Coverage: There is also another concept which is called test coverage, and usually it will be discussed when we are talking about the code coverage, code coverage and the test coverage. These are two important concepts. Sometimes they have been used interchangeably, but if we want to be accurate, code coverage is actually the percentage of the code base that is executed when we are running our test. And the test coverage is a more general term and more broad term referring to actually how much our application behavior has been covered by the test. So maybe there are some cases that our application we didn't even implement in our application, and because we didn't even implement it in our code base, even if there is no test for them, it doesn't affect the code coverage because this part of the application logic has not been even seen. This can be this can happen that, for example, a product manager hasn't seen some functionality that existed and we didn't even implement those part of the code. This coverage is a more general term which also tries to address and those condition and those scenarios. Here I wrote a simple example. I have defined a divide function as a arrow function in just one single line. I said that the first parameter is number and the second parameter is number and please return A divided by B. And if I add a test, and if I say, for example, I am expecting that when I am dividing a four by two, the results will be two. Then my code coverage will be 100% because I only have one line and this line will be executed during the test. So the code coverage will be 100%. But here, I didn't check if B is not zero. So if I call this function with A and for the value of the B, I will pass zero, then I will get an exception, and this first, I should check that B should not be zero. And this is a definition. This is the concept of the test coverage. And actually, I haven't seen the behavior that B should not be zero, and my code actually doesn't even consider this option, and this condition has not been checked. But my code coverage is 100%. So having a good code coverage is a really good thing. It's something that you should try to have it, but it doesn't mean that our application doesn't have any issue or any bug or any error. 16. Adding Coverage Report to Vite: Now that we have learned the concept of the code coverage, let us add our code coverage report and let us see the code coverage report for our test. To run the code coverage, I will run test, I would say NP test run coverage. As you can see, it says this is missing dependence cannot find VD coverage, V, do you want to install it? I would say, yes. And let us wait until this dependency gets installed and now we have it. Let us go and re run the cover. Here you will see that no I will get a table. And these numbers are the numbers that I have explained in the slide assessment, branches, function, lines, and uncovered lines. Now for our index that is file, we actually see the code coverage report. This is inside SRC constant. If I go and if I find this folder, you will see that SRC constant, I have the 100% because this statement and these branches have been covered. You will see that this actually is green, and the others are red. After that, after running this command, I also have a coverage folder. I can also open this coverage folder and I can also see the code coverage report by running this index that GML file. Let me click on this. Let me right click on this file, and then I would run it and u. It has opened column and let me just copy this link to my brave browse. Let's see it in our breve. You will see that here I have none of these files have been tested, so I don't see any value here and here I will see my index at Ts five. Because this is an import, the moment that this file has been imported, the lines all of these variables have been initialized and all of them have been executed. The coverage is 100%. Uh, 17. Digging Deeper in Code Coverage Report: Let us dig a little bit about the code coverage concept and let me change this file and add a function as I defined it in the slides that I'm expecting and function which A and B will be number and it returns and it returns a value, which is number and this is A divided by B. Now I added the function and I don't change my test, and let us run and see the coverage again. Because I am using webstore, webstore has a good integration with test that's actually here, if I write click on the test file, I can run it. I can devugate and also I have this option run index with coverage. And I will press this. However, if you don't use webstom, you can always run the coverage report with the terminal. But for easier explanation in this course, I'm just running this. When I do this, actually, it will ask me, do you want me to replace the suit or do you want to not apply any changes or replace it? I'm going to press replace and then I'm going to refresh the page page that I have here you will see that actually now the states when we have 100%, the branches, 100%, the function where we have a function which has not been covered. This is I will get a zero, if you go to here and you can also see here, that now we have a function that has not been covered. Let us go and let us also implement the if condition let me expand this and I would say, I want to return a divoid baby, but if be equal zero, then I want to, for example, true exception. New error that division by zero is not possible. On de, I will go and I will return. I have a typo here, so let me write division. I have an link tissue, express. I also have an link tissue here. Now, I added a new condition here and I'm checking if B is zero, then I'm going to through an exception. Let us go and let us rerun our test. I'm going to replace. Sometimes there is an issue with coverage that in the first time it doesn't work, so I'm going to read on it twice to make sure that I will get the correct number. Now you will see that change, the coverage report has been changed and let us see it in our HT. Now, we will see that actually the statement, we have nine statement, only four of them have been tested. Branches is 100% function zero and lines is only four nines have been. All right. Let us go and let us add a test. I don't need this test, I don't need this function, but I'm just using it as an example. In the next video, I'm going to add some tests for this function. Let me add a test. I can add a test by writing and it's here, but since this is a different function, and it is one of the best practices to actually separate the things that are connected to each other. I'm going to define another describe block and I would call it divide and here I will pass a function, an arrow function, and then I would say, I should return the divide value of A by B. Then in my test, I'm going to add, I'm going to expect that if I call this function divide with four and two, then it should be two. This will be my test. By intention, I didn't test the zero parts, so let us see what will happen. I'm going again, I'm going and run the test with coverage and I'm going to replace and you will see that this number has been changed to 77%. Let us also see it here. So actually, now you will see that previously it was red, which was not good. Now it is yellow, so we are not a sil green. We are not on a good statement on a good status, but it is a little bit better. So seven of nine statement have been covered branches. Now now we have a function. If you remember in the previous video, the function was zero because we didn't call the function at all, but the branches was 100% because the function has not been called, the branches has not been calculated because except the function, we don't have any branches. We just define three variables. But now that the function is executed and we have the 100% coverage for the function, only one of our Is is being executed and because of that, the coverage for the branches is 50%. Our lines and statement are the same. The coverage report for these two are the same. Let us go and let us also add another test and let us a test that we are expecting when this time I'm going to pass zero and I am expecting that this time I should receive an error as an exception. In order to test that we can use a provider from test which is called to throw. I can pass with this, I can actually say that when I want to this function should throw an error. I will also wrap it into an arrow function because now that this function throws an error, if I don't wrap it, then the execution of the whole file will be interrupted. I'm wrapping it into an arrow function, but I am saying I am expecting that in is arrow function. Be executed, I am exciting that an error to be true and that error the message relative to that error should be this strength. Let me paste this value and let us now run the test again. And let us replace the suit and amazing. Now we'll get 100% coverage. Let us go to the coverage report. Let us refresh the page. Now we have a green. Fantastic. All of the nine lines have been covered, all of the statement have been covered. We had an if and s, both of the branches have been covered. We had one function that has been covered and all of the lines have been covered. Amazing. We did a really good job. Let's continue our work. 18. Adding Unit Tests for QueryKeys: Let us continue our work by adding more test. I already wrote a test for the constant folder and we will see that the code coverage is 100%, which is really. In this video, I'm going to add tests for the API. Inside the API, I have one folder for the models and one folder for the post. And the models is the actual data definition of the post. So if we take a look at this, we have a post type and this post type has a ID title description and has an image, author and the published date. And this is a simple type. So I don't need to write tests for the interface because this is just a type definition. And if I go to the post, I have some tanstaquery the hooks, and I have the query line and query que. So if you are not familiar with Tanstaquery or re aquari, it is no problem. I already have another course which you can take a look at if you are interested introduction to Tanstaquery or aquari. But for this course, it is not mandatory to understand and know all of the features of the Tansta query. And just to give you a small overview about what is actually doing. So if I go here, I'm reading this blog posts from the API. To do that, I can show you, for example, if we go to the site, we have a page and here if we go to the blog page, here we are using a hook which this is the syntax of the rea cor, and I defined use pose which has been defined here. And this function actually uses rea query to call a function, which is called query function, which is fetch post. And what does this fetch posters? It actually uses Axios to get a network request to the API for the API that has the list of the post, and it will do a get request and then at the end, returns the data. And because this is an async action and I have here a weight and here a sync with rea query, we can use an external hook with this four that I am saying, I need a query key, which will be an string, which here is posts, and then a query function, which is this function. I will define this as a custom hook and here inside my component, I can easily just call this custom hood and this will handle the Async operation of the calling the API fetching the data. I can map this data to a variable which is called pause and it also return me a bullion, which is loading and also error. Is loading shows if this hook has been resolved, this API call has been resolved and if there is an error in the API, then the error will be set. And here inside the component, I'm checking if this is loading, I'm returning just a loading component, simple in a simple paragraph. If this is error, I will return error. And these two and if this is loading, it's false and error is also false, it means that I have the list of the posts. So here, I'm going to map. The post and I show them inside this page. For this course, the only thing that we need to know is that actually a query uses a query client and we have these kind of hooks and I use posts, I created this custom book to return all of the posts. This one returns one post with the ID. And this one is for the addition, deletion of the pose and creation of the post. However, if you are interested in learning more about rea query, you can see my other course introduction to Tana Sta query or Ra query. But for this course, we don't need to know a lot about rea query. The only thing that we need to know is actually just how this function works. And for this video, I'm going to add write test for this query. And here you will see this is a really simple file. I just define query key as an object. It has a key pose and the value is post. Let us go and let us create a test file for this and let us call it query keys, the test, the ts and I'm going to write a describe block. And I will have one as written, correct, query key, and I don't need async, I just need. I'm going to add expect and expecting that query that posts to be posts. And let me run this test. This is a easy test also let me run it with coverage and the coverage should be 100%, which we can see. If we return to our brave browser, if I return to old files, now you will see that inside SLC API. For this file, I didn't add any test, but for this file, we have 100% code coverage. 19. What is Mocking?: But the more challenging part would be actually to write test for these custom hooks. Let us see the first hook. So we have use post. And for simplicity, first, this is a function fetch post, and then we have use post, and then we are using this function as a query function and we are exporting this cons as a default. This function is private, and there is no export. For simplicity, I'm going to export this function for now and we are going to first write a test for this function. What does this function do is called the axis that get and then passes the URL for the post and returns the data. But remember that in unit testing, actually we are not interested in the interaction with our back end and our APR and if I want to write a test for this function and I don't want to run an instance of the back end for my testing. And this test should be because I'm testing only this unit. And inside unit testing, we have the assumption that all of the other units are working as expected, we are focusing on just this unit. So how we can do that, and here it comes a really important concept in unit testing, which is mocking. So what is the concept of the mocking? Mking means replacing a unit with a fake unit. And this fake unit actually mocks the behavior of the original unit. And this is the reason that we are calling it mocking. When we are talking about mocking, it means that we are not interested in the actual behavior of a unit or a component, and we just want to have a fake unit instead of the original unit. And remember that in unit testing, we are focusing on one unit. So we are not interested about how the other units works. And because of that, because we want to add a test for one unit and we will use mocking for the other units and we will make them as a fake in order to just act as we expect instead of running the real code behind them and we only focus on the unit that we are actually writing test for it. How can we do marking in its? It is so much simple which can just write dot Mk then we will pass the name of the module that we want to mark. In this example, I have used axis. V is also the short form for VTS and the mark is actually the function, so I can easily mark an axis module with dot Mg. Let's see it in practice. 20. Writing Unit Test for FetchPosts with the help of Mocking: So in order to write test, I'm going here, I'm creating a file. I will call it use post test dots. I will add a describe block, and call it use post and the function inside it. Inside because I have two function, I will create a describe block for every function. The first one will be fetch post. I just for the part for the E, let us just make it empty for now. I will explain it later what we want to write here. But what we actually expect for this function to happen. When we are calling this function, we are expecting what can go wrong if a developer changes this URL, and we expect this function to call the correct URL and then returns the correct data. Let's do it. I'm going and let us add expect lock and we want to import fetch Bs instead of this, I want expect fetch to be to to a strict equal. When I say equal, usually it will be used for primitive types like integer numbers. But when I have an object and because in Java script, the objects will be compared by the references, I'm interested in actually the properties of the objects. I want to just have strict equal. Let me just run it to see what will have. So as you can see, this shows an arrow, expected promise because this function is an ASN function and I am just calling it. Let us first fix this. Let's call it the response and let us wait for the result and let us say that we are expecting that response to be something response. Because I'm using a weight, so here I should also add an ASN keyboard here and let us ignore it. Because this is an array, actually I should pass an array of object. Let us fall now, pass an empty array. Let us run the test. Now, you will see that actually It is called the actual IPI, but this is not what I am expecting. If I stop the server, let us go and stop the server. Let us stop the server and let us know run the test. And now you will see that actually us cannot run. This is not actually we are looking. We don't want to have a server running. We don't want to have an interaction with the API. In the end twin testing, yes, but in the concept in the scope of unit testing, we just want to have to just work with one unit. And for that, I'm going to use marking and I would say dot Mk xS. With this line, I'm telling that actually, I I don't need axis itself. I need only a marked version of axis. Now that I wrote this line, you will see that this part is red. Let's see what you're saying. It says cannot find name at file globals Ts config. Let me do it and now I can do it. Let's see what has been changed inside our Ts config file. It added the types for the VTest. Also TypeScript understands that we are using VTS because these are the keywords from VTS. Know that I added this, actually the exxus has been replaced with the marked version. After that, I can pass and I can say that whenever you are calling the exxus with the G, I want to get a response instead of having a having a real response. Let's just define a response. What we want? For example, we want a marked pose to be an array of the post type. For example, ID would be no this variable would be an array of post type the post tip has so many parameters. Let's see what it says. Let us ask our ID to place where it should provide us with some automatically fill in data more action. No and I'm passing an empty object using the properties IT title description. Unfortunately, it doesn't appear in it, so let me just type ID would be one, title would be a string of title and description would be a string of description, what else I am missing created image author published. Created t will be an empty string, Auor will be an object. Over you will be an empty string and the name will be a string. Let me just use my name. Now we are missing image and published dates and the image also lets us go with an empty object and the published date also empty string. Now let us fix the whole file with the preta m. And current file. Now I want to use this as a response for the API call. I can do that by saying that's marked. I am saying every time that axis that gets has been called, I'm expecting to get a result value, which is an object and the data will be marked post. Let me also import axis source. So here we added dot Mg which we are telling actually we don't need axio and here we are telling that whenever axiusG has been called, this is exactly what this function does is calling this function. We need to get this data. And now when fetch post has been called, what does fetch post cause? If we replace this line with that value, it returns the data property, it returns this object. I'm expecting and my condition should be that this response should be this marked post that I have defined. Let us run the test and it should fail now because now I added this object, so let me replace it and marked post and after that, this test should pass. Wonderful. What is happening, let me summarize it again. I am defining an array of some objects and I am telling whenever Axios has been called, please resolve because this is an ASN function, I am using marked result value. We have also a mark return value, which is for synchronous operation for ASN, I'm using mark result value. Please return an object which has a key which is data and the response should be. Whenever we call the fetch post, we are expecting that to get this. Here, if I start the server, now you will see that still the test is passing because it doesn't have any interaction with our node JS server. It is just a completely replace axis with the marked version. There is also another thing that I want to test here, which is actually when we call this function, we want to make sure that actually XS get has been called and has been called with this correct parameter. To do that, I will also add another line for the expect. I would say I'm expecting that axus dot called and T provides us with the function, which is called have been called WT here I'm expecting that it should have called with this UR. I'm going and I'm going to pass this value. Let us run the test again and the test is passing. If a developer by mistakes come and change this to, for example, APURA let me also import this No, we have a test that actually tests that fetch post should be called with the correct URL. Now, this test is failing because it says that you have been expected to be called with a slash post, but this value is not correct. Now we are sure that any changes to that function will be tested. Now let us write the description of the I what I am testing, I would say returns the correct data from API. Let us also see the coverage code coverage report, let us run it with coverage. Let us see our let us go one level up. We have the API fold there and let me go to SRC API posts. We didn't add any tests for these files, but I have used posts and this function has been tested. These red lines means this *** has been tested, which is not the function that we wanted to test. But now it is amazing. All of this function has been tested. 21. Writing Unit Test for usePosts: So let's continue our work by writing unit tests for this function, which is use posts. And what do we expect? We expect actually use query comes from react query, so it is an external library. I don't need to write units for external library. What I am doing is actually I should make sure that I am passing the correct query key and query function. And when this hook will be resolved, I'm expecting to get the data that I am expecting from that. And in order to do that, first, we need to let me go to the describe block and let me add another describe block. Here we are going to add another described block and this will be for use post, and I'm going to pass a function, and here I'm going to add new it. For the message, I would say it is good returns the correct data from the APA. Let us because this is a custom hook and I need to render this hook and I need to wrap this hook inside the provider. How we can do it. I will define to using a rea query, as you can see here, we have a query line first, we should first initialize a queric line. Let us come here. This is also an interesting part that I want to show also some of the definition. Like it, we have another block which is called before each and this before each will be run before every test will be executed. If we have some variable initialization and stuff like that, we can also put it here and but for this test, I don't need it, I will define my variable exactly above of this test. Let me put this inside the other describe block because here I don't need this. But let me put this here. Let me also create a wrapper function that's actually a strapper and it expects an intro turns as a JSX element, aquatic client provider Aquatic clin provided. And our clients will be. Let's also close this. Now because I am using TSIX, I should also rename the file to TSX. Let's import this query client provider then you also need to import this from the a que our client will be the quer client and everything else will be going inside this I'm just ping everything that I am passing to this I will pass children properties here and I will say that hilern is a type of react nut and the ton will be react elements then I have a type here. This will be the wrapper. Now I am expecting that returns the posts from the APA. Let us start writing this. What we expect if we're going to render this hook, we if you get the results here, I'm expecting this result. I'm going to use react render Hook which will explain it in a second and I will go use post, and then I will also pass the rapper here. I will import use post and also I will import from testing library react. Testing library is the react testing library, and we are going to discuss it in the next module which is integration testing. For this video, I'm just importing it. For now, the only thing that you need to know is actually, I have a custom booking react and in this way, I can render this book inside this wrapper. Let me also fix this pretty. When this is happening, the result will be set up. But this hook is Async hook and how can I make sure that this has been resolved? Because this is also an ASN function. We have a function which is wait for again in the react testing library that it will block our execution until one condition has been met. What is the condition? What is the condition we are expecting that the result that current is success to be true? What does this line means? We are saying that because this is an AC and this is when the current success is true, please wait until that moment. What does that mean? That means that react renders this hook and then rea query calls the API, which we don't want the API, we are replacing it with the mark version. But when the successful that promise has been resolved, we can add an extra condition here and after that, we will make sure that fetch post has been completed, we can get the data from that with current data, and we are going to expect this data to be equal by the marked posts. And I should do exactly what I did with the marking of the posts that I did here there. Because this variable is the same, so I will bring this up into this level so I can use it in both and I'm going to also use this line. Exactly like the previous example, I'm making I'm marking the axis that gets and here I'm expecting that after that the results should be this value. Let us run the test amazing. Now the test is running, to make sure that we are doing it properly, I can just change it to something like an empty array and now this test should fail, of course, because we are expecting to get this array of object. And also the other condition that I like to check here is that fetch posts to have been called actually with the proper message. And But for now, we can just ignore that. I do it in the next video. Now we added the test. For this video, it is maybe it is too much. If you like, please return if it was difficult for you to follow, please rewash this video. Now let us run the coverage and see the whole coverage. Now we have two describe blog, one for fetch boost, one for the boost and both of them are running and now you will see that all of the red lines are gone. So amazing. We have 100% coverage for this. By writing this test, we learned a lot of concepts. First of all, we learned about the mocking. Second of all, we learned about how we can actually render a custom hook inside the wrapper. Then we also learned another function which is wait for, which is for Async operation, we can block our execution of the test until we make sure that the reacquery response is ready. And we know that it has been successful and it is true, and then we can check our condition that actually if we mark exusgs if you are saying that whenever exxous that get has been called, then when this hook has been resolved, then the value should be marked process. Let us do a little bit cleanup. As you remember, I added this export to this function just for the explanation purpose because it was easier to test this function. If I wanted from the beginning to test the hook, then you should know everything about the marking, everything, but it was easier to first explain it. Just for this, which is easier and then for this hook. But you will see that function, most of the tests that we wrote is similar. Actually, we don't need to export this function and this function should be kept private inside this. The only thing that we need to use is actually to test the actual hook. I remove that. I will let me also remove fetch post here. And let us run the test to make sure that actually we didn't break anything and now I have one described lock in the post in the top level, so I don't need this described lock. I can remove it and also I can do a fread here for the whole file. Now it is easier to understand marked we have a marked object, we have a querc alliance and we have a wrapper and then we marked it and then we expect that I can also bring this inside the test, it lock this is related to the to this test. In this test, we mark the axis that get and then when we render the hook, we expect the results to be this value. 22. Writing Unit Test for fetchPostById: Congratulations. We added a really complicated test, and I'm happy that you are with me here. So now that we have this test, adding a test for other files will be so much easier. Let us do it. Let us also see the use post. This is also similar. We have the axis that gets the difference is that here we are getting a post by ID, and then here we also returning this function as a query function for this Hoch, and we also have it as a as a query key, we have two parameters post D. Let us go and create a test file. I'm going to I can also just copy and paste this file, use post, and I can call it, this one, this one. Use post that test 65 and I will inside my descri, I will go with post and these parts will be similar. I would say returns the post by ID from the APA. This time I'm expecting if I have this time I expecting that as that gate will return me a single object, not an array of the mark pose. We can also change this instead of an array to be only one object and I will return this remote these lines and let us fix the pret here for this file. Here we are going to expecting that we will return one object and then we are going to instead of use posts, you are going to render use postcode and then we are expecting the data to be marked post and you can also replace this because this is not an array so let us also use a single form for this variable. And we don't need to use post, let us run these tests, wonderful. Let us also run with the coverage. Let us also see the coverage report. And here, amazing, we also have 100% code coverage. This is a really important thing that I want to tell you that this is happening with testing. Maybe at first, it will require a lot of time. But when you have a little bit of test when you already your project structure is good and you have other tests, you can easily easily add more tests. Sorry, I just forgot here that I can also should as a number as a parameter to this. This is really easy. Now, I added another test and I also let us go and run the coverage for the whole files. I can run it with rung coverage. Now that we have both of our tests now we will see that we have 100% test coverage for most of these files. 23. How CreatePost Mutation works?: In this video, I want to write test for create post. This is a real query custom book that allows us to create post inside our weblog. But first, let us see it in our dashboard and let us see what is happening. So here inside the admin dashboard, I have C post, which is meno which I can see all of the posts that have been published on the weblog. And I can create a new post here by writing, for example. Title, test description and I can also upload the picture. I will use a docure if I submit the post now you will see that immediately I have four posts and if I go to my dashboard, as the number of the posts, I will see four here. If I remove this admin section and if I go to the web log, we also have a new post here. So how did I implement this? I implemented this with a mutation in a query. Let us see the source code. One of the really good benefits of rea query is that all of these actions can be done without having a store. This is a different a component. This is a table. I have a new form inside this page, which is a different rea component and how these components interact with each other. Because now as you saw, when I created an element here, this table has been updated immediately and also this number has been updated immediately, and this is happening, for example, with deletion, if I delete this post, now, if I go to the phone, you will see that this number has been updated immediately. Rea query provides function in validate queries, which inside that when I am using mutation, mutation is being used when we want to change data on the server, for example, addition, creation, deletion, and all of these three are mutation. And when we want to read the data, we will use query and when we want to change the data on our API, we will use mutation. And here you will see the code. The code is simple. I'm just calling a post on the post endpoint and I am passing a form data which is all of the title description on the image with the header and success, I also forgot what call it here common. On success, when this API has been resolved and this API has been fixed, I'm asking rea query to invalidate the query, and what are the queries that I want to invalidate the queries which is related to the posts. And with this, I'm telling rea query that you need to refetch and recall all of the hooks which is related, which have these query keys, which is, for example, use posts because this is also you will say that the query key is the same. So when we do that and when we know that we added a new post, the list for the post should be updated. Then Ra query does this for us. The only thing that I need to do is to say invalidate query, and after that rea Query understands that this list has been updated. We can also see together. If I come here, if I go here, if I go to the Netfox section, I create ATPost when I press here, when I add a new entry, you will see inside my NetforxtpF I have a post request, which is for the creation of this No blog, and the payload is the parameters, the thing that I have entered. The interesting thing that I have get request for the post, and this is happening by invalidate queries. So rea query understand that now this query this query key has been invalidated, so it will recall the API and this time the API returns four object. So this table will also be updated. And this is happening. We can also see, for example, for deletion, we will see two requests. One first for the deletion and this is now, again, the request for the G and now we have three objects. And this is happening by this line. So to write this mutation, I need to add two tests first to make sure that I am calling the correct API endpoint, and the second one is actually when we are happening when we finish success is happening, I want to make sure that I am invalidating the queries and I'm also invalidating the correct query key. The 24. Writing Test for useCreatePost (Part 1): So let's start writing test for us create post. I can do the testing like we did for us post by marking the axios, but in this video, I want to show you another way of the testing that we can do. To do that, I want to move this upload post to another file. Let me create a file and call it api. Let me move this const to that, let me import export default upload posts. Why am I doing this? Because I want to show you another way of the testing. Now that I did this, now we are importing upload posts from these APIs. We also need the comma here. Now I want to write units for this and I want to treat this upload post as an external dependency that it outside of this module. There are two ways that we can do marking on test versus with dot mark that I showed you in the previous videos and another way is with the method of spy. And for this video, I want to use this new method. Let us go and I will copy this use post test and I will call it use create pose and I will also change my describe to use Create Pos. Here I want to add a new test that that actually, I want to make sure that when my mutation, when I use create pose, it calls the API with the correct parameter. So I will call it calls upload pose when mutate is called. Instead of marking axios, I will remove this line and let us see use create post. I want to completely mark this function because now it is an external dependency to this unit and in unit testing as we discussed previously, I'm not interested in what other units do. I want to completely replace this upload post with the marked version. To do that, I will go and I will call I will remove this line and instead of this line, I will call Spire. As the first parameter I will call it, I can let's also go and change. Let us import stars AVs from up a slash post slash aps Ts. The first parameter will be the module that I want to mark. The second one will be actually the default exports which I want to mock, which in this case, is this upload post. With this, I am saying that whenever the default module of this APIs module, which is upload post has been called, I don't want to run the actual code inside it. I just want to return a mark value for me. What does this function do when the API calls, it will be successful, it will return the post. I will just pass the mark post that I have created. And in this way, I can say that whenever this API has been called, please don't go to Axios, don't execute the code, return me this object. And with the spy on, we can actually see if this method has been called, how many times has been cut with which parameters have been called. So it returns in spy version, a very well, which I stored and I will call it upload post Spy. And now I want to actually call and actually call my mutation. Instead of use force, I will change this to use create force and I will import this and the wrapper with the same so I'm rendering this hook. In order to call the mutation, I will call results that current that mutate and I will pass it mark Post. And I will need the weight for block, but there will be a difference. I am going to test is that I'm going to expect that my SPI to have been called and also its provides us to have been called times. I'm expecting that it has been called one time. I have an error here because I'm passing the mark time. Let us see the create post. So when we are calling when the mutation has been called, the parameter is four data, so I should pass the four data. So let us fix that. Let me create mark post data, which will be type of form data. And let me attached to this a title, an ID, which will be one and a description, which will be description. And when I'm calling the mutate, I need to pass this Mk post data. Let us see together what is happening. I'm creating a form data object. I am replacing the default import of the APS, which is Upload force upload post with the Spy version and I am saying please return me the Mk post that I have created previously, and this is the Spy. Now I want to render my mutation. Whenever the mutate will be called with this form data, I'm expecting that the API should be called. Let's run the test. And wonderful. The test is passing. So if I change this, for example, to two, this is definitely should fail because there should be, as you can see, it says that you have expecting it to be called two times, but it has been called alta. And my condition for this test should not only be also that this function has been called, but I'm expecting also to have been called with the proper parameters. So there is another function, and to have been called VD. In this way, I can also test that actually which parameters, function spy version of this function has been called. I will run the test and now the test is passing 25. Writing Test for useCreatePost (Part 2): So the first, the first part of the test has been done, we wrote the first test regarding the use create pause, which was related to the mutation function, which is upload pause. Now we want to test this success. What does this do? This actually reads the query client from this file and then calls the invalidate queries with this query key. We want to make sure that first of all, whenever this mutation has been called on success of this mutation, invalidate queries will be called and also it will pass the correct parameters. Let us do it. I will just copy this test and then I will start changing what I need to change for this. Let me also change the description. I will write invalidate queries and success. The form data stays, the render hook stays, the mutation stays. Here, instead of testing, I also want to create an spi for this quercline because we are also importing from a API quercine. Let us go at the top file and let us import ts query client I am importing this query client and here I will also create another spy here. For this spy I'm going to I'm going to use this module and the method that I want to create an Pi is the invalidate queries. Here I can also write return value, mark result value, but for this test, I'm not interested to what is returning with this function. I just want to have an SPI as the name suggests Spy means spying on something. I just want to make sure that after this mutation, this invalidate query has been caught and has been called with the correct parameters. I will define it as invalidate queries spy. Inside my expectation, I'm expecting that invalidate query spy to have been called one time. Let's run the test. And now we will see that the test is failing, so let us debug it together what is happening. Here I have success, here we have the invalid query. My bad, this was a mistake. When I see the reference of this query line, this is actually it is going to this variable that I have defined here. It is also always good to sometimes show errors that we are facing. It is not like that whenever I start coding, everything works perfectly. You will see that this line has been covered because by mistake, I have used the same. Let us go and let us call this queric client module, for example, inside our Spi we expecting to to actually expire on this module and then let us run the test. Now wonderful it is passing. Now I also have a typo here. Now I am sure that this is getting cut and we also want to make sure that a it has been called with the correct parameters. I will just let the test fail because we are sure that this is not one. Let us see the error message. So now you see that the test is failing because it expects actually to receive an object from query key to posts. So as you can see, the passing object is query key posts. So I will change this, let us fix this by query client and not query client, query key, and the value should be posts. And let us run the test again and let us see query and also it should be an array because we are also passing an array and not just string. Let us see amazing. Now our test is passing by writing this test, now I am make sure that if any developers come by mistake, for example, adds something to this. Now I have a test that will fail and will prevent this to happening. And this is the benefit of having unit test and automated testing. If for example, another developer comes and by mistake removes these lines of code or changes that, this test will also fail. We are always sure that everything will work as expected. Now that we have the test also let us go and run the whole block with the coverage to see our code coverage report. And let apply and let us go fresh this. Wonderful. Now, you will see that actually use Create Post has a 100% coverage, this test all of this file has been covered by our tests. I will come in and push my changes and I will continue my work by writing tests for use edit and use delete. 26. Unit Tests for useEditPost & useDeletePost: I added two other tests for the other hooks, use edit post and use delete post and most of the codes were similar. So I strongly recommend you to pause the video, try to write the test. You can use the other tests that I wrote, use Epos and then learn it from it and write the test. For example, there are some small changes, but it is also a really good practice that you do it for yourself. For example, here in edit post in our sucton we are invalidating two queries. First is the relative to the list of the pose and the second is the relative to the ID of that specific post that has been edited the way that we can test this is that I can call I can ask that I want this to be called twice, and I want it to be called one time with the posts as an array and also one time with the post and ID one, which is ID one is the ID of this post. And now we have a really good test for all of these folders. So let us go and let us run all of our tests and let us and to see the whole coverage of the project. I can also do it on the terminal. So if you are not using Web store, we can run NPEgs with Rundah coverage. And here if I return back to my browser, I can also see on my terminal. But if I return here, now you will see that actually our API is 100% covered, our constants and hostile, all of these these hooks that I have created, all of them have been 100% covered. So all of the statement, all of the branches, all of the lines and everything has been covered. And for this module, I didn't create external tests for these files, and that's the reason that they have not been covered. And for now, we can ignore it and this is not important for us right now. But there is an issue with the test, and we can improve our test a little bit more. Now it is really good that we have 100% coverage for almost everything and we can also run this here so you can also see it inside our ID. Here you will see that all of these files have been 100% covered with the tests. But there is another improvement that we can do to make our tests better. In the next module, I'm going to talk about that. 27. Test Factories and Their Benefits: There are some improvements that we can do to have better testing. Imagine here, we have added so many tests, for example, for use created. Use create post, I have a marked post, which is type post type and I have a hard coded object here. Inside use edit post, this is also the same inside, use post. Again, we have a marked post, which is a hard coded object inside, use posts have an array which contains only one object and this object is also a hard coded object. This is a type definition. Imagine that you are working on the production product and after sometimes there is a new requirement for customer, from business development team or from support team that every post should have another field. For example, number of the likes or number of the comments for this post or an array of the comments. And in order to support that, we should and the API first will provide that data and imagine if we want to implement that. Then for example, number of comments. The way that we will implement it is that we will change our type and we will add this parameter to that. But now, all of our tests we have this problem that because these values, this has this field didn't exist in the time that we wrote the tests, now we should update all of the tests again, the property does not exist and we can also see in use create pose. This is a problem that we can solve it by using test factories. With test factories, instead of hard coding an object, I'm going to define a function that returns to me one object, and this is the test object, and then we can change our implementation in a way that these tests only use that factory and they are not dependent. They are not hard coding on the fit. Let us do it. I will create a folder, I will inside SRC, I will call it test factories. Inside test factory, I'm going to create a new file and I'm going to call it post factory dot ps. Inside this file, I will define a function. I call it I will call it, for example, get test post, which is a function which returns a post type and the return value for this function will be the post type. The definition would be, I can simply return this object, for example. I will also need to import post type. I can even make it really simple one line with this because I only return one object. Let us go and for now, let us first remove this type to get rid of this error. And now I have a function which actually returns a test object. I will go and inside all of the tests that I have created for the API. I'm going and instead of this, I will just call this function. Test post. Inside my factory, I also need to export default test post. Here I will just call this function. H. And inside my edit post, I will do also the same thing. Inside use post, I will also replace this hard coded object with KD test post and also import it. Here I think I forgot to import it. Let us also import this one inside my use post, I will also replace this with get test boost and also need to import it. They can also simplify this to this let's us run all of the tests to make sure that we didn't direct anything and wonderful. Now all of the tests are passing now if the API is changing and for example, if we need to add a neopl, the only place that I need to add this will be here. For example, I will go. Now again, none of my tests need to be updated. None of these changes. Need to be done. I will just put the value here. Let us keep it as it is. Perfect. This is the concept of the factory and factory is a design pattern in software engineering and the test factor is called when we are using factories, some functions that generates us an object and we will use this object inside our tests in this way, we are separating the domain definition from our test. If anything inside our domains need to change in the future, we don't need to update all of our tests. We just need to update our factory. 28. Introduction to FakerJs: Another improvement that we can do for our test is that as you can see here, I hard coded some values as the test object. But in real life and in production environments, users will use our software with different dataset. This dataset can have some special characters. So H cases might happen with the string with numbers and a lot of these cases can happen, but if we only have one object with hard coded values, and this cannot test all the possible solution, all of these possible situations that can happen. In order to address that issue, we are going to use fakare library, and FakreGS is a library that generates data that mimics real world values like names, addresses, date, anything about email, anything about, for example, a name of the person, a name of a company and stuff like that. And are going to change test, factory to use faker in order to generate and get a test object which actually is a real world object instead of coding value. There are benefits. The first thing is we can have dynamic and realistic data. And also there are benefits with face that we can easily create arrays and have multiple entries that these entries are not oplicated. In my case when we have use post when we create a test for use post, I just created an array with one element. But with Faker Js, I can easily create multiple objects and multiple arrays, which is more realistic to the thing that I want to test. And also it provides us with better test coverage because the data is random. It may contain a special character, it may contain Hcases. If you are working with numbers, it provides us negative numbers, positive and all of these things can be put into our test and actually our test is testing the real world data. Also it provides us with a way to avoid hard coding values. In the next video, I'm going to install faker Js and I'm going to change our test to use Faker. 29. Using FakerJS with Post Factory: So let's start with working with Facare. You can see the official website of facare in fakjs dot v. Here, you will see they have different modules for person, location, date, finance, commerce and localization. I will go to get a start and here for installation, I'm just going and copy this and this is what we need. I'm going to our terminal. Again, because the whole testing is for development only, this will be installed as only a dev dependency. Now that Facure has been installed, I'm going and I'm going to import fac so I can import it from the package. I'm going to write FacimportFakre, from Fakre Js. Instead of hard coding number one for ID, I'm going to use fare, that data type, fare data type, umber or fare number. That's it. This line actually returns me a random number. I have a weather storm issue which is not important. I didn't understand that. I already install it, but we can ignore it. For Titan, I'm going to use random string. I'm going to use Fac Lorem that sentence for description, I'm going to use to generate a random paragraph and this time, I will go with paragraph. For created that faker provides a lot of helper for working with dates. I'm going with faker, that dates and because I want to use a recent time, there is a helper function recent which returns a recent and I'm going to convert it to Iosring because our type definition is a swing. And for our tR URL, we need a random image URL, so I'm going to use the image of the image or module of the faker, and for the name, the name should be name of the person. I'm going to name and I will just use first name. I think this has been deprecated let us see I think it says use person instead instead of let us go and pick the first name and you can also use the full name for this. For the image, again, the only thing for us is important is URL, so I'm going to just create an URL for published date. I will go and I will date. This time I will use a past. A past means that it has been passed in some date in the past. Because it is String, I will convert it to ring and for number, I'm going again to use an integer. Also we have some options. For example, I can provide mean and max because for example, I know that the number of the comments is always a positive number, so I will use a minimum value of four Z. And now you will see that every time this function when this function is getting called, we are getting a new object and this object does not have hard coded values and it is with some real data and it has been filled with real data. Now that we have the fake, I can also go inside my use post and here instead of hard coding only one value, I can use an array of the faker. Faker also provides an easy way to actually generate multiple data. In this case, I'm just going and I'm using array dot From. I'm going to pass an object which the length would be, for example, ten and inside and I will pass arrow function and inside that I will use this. In this way, I can also actually, when I have an array, I can also replace this with a more realistic data. Let's run this test and make sure that this test is also working. I can also make it better instead of having a fixed length, I can also go and I can use with faker and then can go to number and ink with something, for example, minimum one and let me also import fake. And maximum would be, for example, 20. I just need to fix it. In this way, I am actually testing my code with real data and every time I'm getting a random array which contains all of the random objects. Let us go to the terminal and let us run all of the tests to make sure that everything is still running. Perfect. Okay. 30. Unit Testing Module Summary: All right. Congratulations. You have finished this module, which was relative to unit testing. We have covered a lot of topics. First, we start talking about VTSt, we installed and configured VTS, and then we talked about the code coverage, different metrics that exist in code coverage like lines, branches, statement, function, and also we discussed about the differences between the code coverage and test coverage. And then we dig into the coding, and then we added some unit test. First, we wrote some simple unit test, and then we talked about the advanced concept in unit testing like marking and also using Spy with the method of spy on invites, and we added some unit tests. Also for each unit test, we calculated the quote coverage to make sure that we will test all of the possible options. And then after that, we started to improving our test with using of the test factories. We talked about the factory. What is the definition of a test factory? And we have created a post factory for our project. And at the last module, we also talked about faker Jes, and we used faker to generate realistic data for our test cases. This module was a really, really good module that you have finished, and now you have a really good understanding of the unit testing. I also encourage you if some of the parts were not clear for you, you can always return back to these videos and watch them again. Or you can also finish the course. And when you have seen all of the videos for the future references, you can always return back. Maybe some of the parts will be more clear for you if you finish the course first. But congratulations to you. You did a great job. So maybe you can take a coffee and get a break, and then I will be happy to see you in the next lecture. 31. Introduction to Integration Testing: Congratulations for the finishing of the last section about unit testing. In this module, we are going to talk and work about integration testing. Let us do a summary about what is integration testing. As we said previously, unit testing focuses on one unit like a function or a class as we did in the previous module. For example, we started writing tests for a single unit, and for the other units, we used marking and spying to replace them with the marked and spied version. So our focus was only one motion. And in the integration testing, we are going to test the integrity between different components and different motions. And if we return back and if we look at the testing pyramid, integration testing is in the middle. So they are not as many as the unit test. They are still faster than testing, but slower than unit testing, and writing them is a little bit more challenging. So they are not as easy as cheap as unit testing, but they are still easier for writing two testing. In this module, we are going to use react testing library for writing integration tests. And first, we will set up this tool and then we will work with this tool to write integration test. 32. Seting Up Environment for Integration Testing: So let's start writing our first test. First, we need to install the dependencies required for the react testing library. I'm going to show the package that Jason filed and here I'm going to test I'm going to search for testing library. From the previous video, we added the testing library dump. Just don't react and user events. So we already have the dependencies inside our project, and we can start writing our test. But for the configuration, we also need to change our IT configuration. Let us see our with conf. Here we added a test section, we set global suturu and we set the environment to the JS. Here I will also add another line and I will add a key which is setup files and I'm going to pass it to SRC slash Setup Ts. Inside my setup, I'm going to create a file, creates a typescript file with setup. Inside the setup file, I'm going to import testing library JSA. I'm going to put this line. This is the this actually helps that when we are using some matches like to be in the document, it makes it globally available, so we can ID our ID understand and we can also use them. And for our first component, for our first test, let us go and let us write inside our share folder. We have a components folder. We have an index file, and I want to write my first integration test for this component. And what does this component do? Actually, when we are visiting our website, when we are on the home page of our website, we have a post component, and when I click on that, you will see the picture of this post, the description of the pose and the person who wrote this post. As you can see, we already have a bug here. Here, the image is wrong and this is if I am the writer of this post, then the image should be corrected. For this one, I'm going I want to add a test for this component. Let us see at the source code, it's going to we have a cospose which is a type of pose type and here we are reading image and title from the post and then we have a style card, which is a and design element. Then here we are setting Avatar, avatar is a hard coded value and the title of the post. What am I going to test, I'm going to test that actually when I visit this test, I want to see an image with the t. I want to see I want to make sure that this post URL, the image URL is the correct value and I also want to make sure that I will see the correct avatar and I want to also make sure that I will see the correct title for this test. So let us do this in the next video until now I describe how we are going for which component, we are going to add a test and in the next video, I'm going to write test for this component. 33. Writing the First Integration Test: In order to write the test, I'm going and I'm going to create a file, which I call it index that tests that Tsix. I will use the exact describe block and we are going to test our post component. Then I will add describe, I would say, renders the post image or post title. Probably here I'm going to add this. What we are going to do is we are going to first get this component and render it inside the page and then we will see what is going on with this rendering. For that, we are going to use a render function which is provided by the react testing library. I'm going to import render from testing library react. Inside the render, I can actually as a a complete react component, and I will also need to import this. My condition for the test would be I also can have another function from react testing library which is a screen. Here I can ask from screen that I'm expecting get by text to be in the document. I'm going to put this into an expect and then I'm expecting to be in the document. What I am expecting to see, I'm expecting when I am rendering a post component, I'm expecting when I see the source I'm expecting that I should have the title of this text to be shown. I will also see an error here because our post component actually expects a post object to be received. Let us go and first create a post object and we can use our factories to get a random post here I'm going to pass this to this component, and now I am expecting that post the title to be inside this document. React testing library renders this component with this variable and then my condition for test would be that I am expecting that the title of this text to be sin Let us run the test. Now we will see an arrow that actually says windows that match media is not a function. Let us first fix this arrow. 34. JSDom vs Browser Environment: So what is this error and why does this happen? For rendering the component, we need a browser. Actually, when we deploy a react project, browser executes our Javascript source code and then it renders the component. But when we are doing testing with react testing library, we don't have the browser and because of that, we are using JSTO. And JSDOM is implementation is a JavaScript implementation of Dom and HTM, and it simulates a browser like environment. But there are some cases that not all of the functions that exist inside Browser also exist inside the JST here is the case that when I am running from browser, we are expecting to see a match media and why this is happening because I am using t design as a UI library and Aunt design uses this function internally and when it works inside the browser, it is fine. But when I am running this test against JS Done in a simulated environment, this variable doesn't exist. How we can solve this problem. We already learned this from the previous videos. We can mark this function, which means that we don't actually need this function, we just need to pass something that mimics the behavior of this function. And in order to do that, as you remember, I have created a set of the Ts file, which we are importing just done. Here I can also define a mock version of the function. Here I added this code and I'm saying if windows that match media is not equal function, which means if this doesn't exist, I'm going to define this function. This function returns an object and most of these objects are null, the functions, I have replaced them with empty functions that does do nothing, but it just gives this when As design wants to use, it just makes it available inside the JStO. Let us add this and let us return back and let us run our test. And wonderful. Now our test is passing. 35. Finishing the Integration Tests for PostComponent: So until now, I just tested that I can see the post title properly. So let us see the component, what do actually this component does. It has a cover which is this image as a featured image. And this image has a title as alt attribute that if I Sorry, if I move my mouse over it and if I inspect on this, I can see that here I have the title of the post as a alt attribute. It also has the SRC of the image. I also want to test that my post component also renders the image properly. Let us add also a test for it and let us right renders the featured image of the posts, and I will also add. For the start, I will also again use the I will get a factory for my post. I'm going to render my component with react testing library. Here now we can use another helper function from react testing library, which is G by Alt text. I'm going to say get by Alt text, which means get by alternative text. I'm going to expect I'm going to call this as an image. First of all, I'm expecting this image to be inside the document. To be in the doc. I'm expecting that my component renders an image and second of all, I'm expecting that this image to have attribute for the SRC. For that, I can also use this helper function to I am expecting the SRC to be post image dot R. First, I want to make sure that the image has been rendered properly and also I want to make sure that the post has the correct image. Let us run this test. And wonderful now our test is failing. If I come here and if, for example, remove these lines. Now, I am sure that there is a test that will fail because now when we render these components, testing library says unable to find an element with the alternative text. And here you will see a random value and this is exactly what we discussed about features and about the values. Let us also test the metal that actually we are expecting to see an overture. We already tested this one, so I'm going to copy this block. And I'm going to render the utter avatar ter avatar and I choose slash Te and let us make it with prettier, better. Let us use double codes here and that's what you're saying your code. Here now I am expecting again, what I am going to search. Here I can use another helfare function I can use to fetch a post by its role name. There is another another function, get all by role. Here I can pass an image. I would say I want to see all of the images. When I am using get all by role, it means that I am I'm getting all of the images and as you can see first, I have this image and also there is another door. This will be an array. I am expecting so let's us call these images, and I am expecting that the images to have length of two. I'm expecting first to see two images and for the 01, I already add a test for the first one, I am expecting that this one to have the post right what was it? The at that avatorR. For the SRC, for the second image, which is the index of one, I'm expecting to see the avatar uR. Let us run the test. And now you will see that the test is failing. So let us see unable to find an element. Here are the accessible. Sorry, I had a mistake. The role name should be IMG. I will replace it. Let us run the test again. And now we will see that actually our test is failing, so the element that SRC, this condition is not met. This is because we know that we already have this bug because the URL is something else. This is the hard coded URL. First, let us fix our code. Let us replace this with post, AatorRN and let us see that actually our website has been updated the aur ing is correct. Let us fix this with prettier. Let us bring this to online. Now this time the test should pass. Wonderful. 36. Code Coverage Report for PostComponent: And exactly like unit testing, we can also calculate the coverage for this test. So I'm going to expect it. And here, I'm going to run post with coverage. And first, it will run all of these three tests, and all of them are passing. And I will run it again. Sometimes there is an issue that in the first time it doesn't calculate the coverage. So let us just make sure that I will get the correct value for the coverage, and we are in the SRC shared postfolo. Let us go to the coverage report, let us back to the old file. We are in the SRC shade and here you will say that fonder we have 100% coverage for this file. 37. Writing Integration Test for Footer Component: Let us continue our work by writing a test for the foot component. What is a footer component? It is just a style foot is a foot that has been wrapped with the text Ali center and it shows a simple message. If we want to see it inside our web page, we will see this is the footer component. I'm going to create a new file for this. I will call it index test. T six and I'm going to describe block and the describe block would be for the full component and I need an arrow function here, and I also need a block here, so I will say renders full properly, and I also need a arrow function here. And I have a type here. It is always good that when you are learning a new technology, a new library or new framework to practice the same concept twice. For testing this component, this is a simple component, so we only need to make sure that this line and this will be showed properly. For that, I'm going to use render footere and I'm going to import footer component. I'm going to import it from my own folder not from there. Design and I'm also going to import a screen render from react testing library and also the screen. My condition for this test would be simple. I am expecting to see this text inside my document to be in the document. I'm going to copy this text and I'm just going to pass it here. Let us run the test. Now you will see that actually the test is failing because this has been rendered as we have inside our component, we have a bolt and in order to make sure that it is writing properties, so I will use these two sections. I'm expecting to see this text and I was expecting to see this text. Let me just duplicate this line and for the first condition, I'm expecting to see this text and for this one, I'm expecting also to see this line. Let's fix it pretty here and let us red on the test. And wonderful. Now, the test is passing. As always, if a developer by mistake comes and puts here something, we are make sure that we will find the error related to this test and also let us run the coverage and I'm expecting a 100% coverage because this is just one line of code. If we see it here, let us return back and let us go let's refresh this page. We have the footer component and here we will see a 100% code coverage. And 38. Writing Integration Test for Contact Page: So until now, I added a test for this component for this post component and also for the Foote, but I didn't test the whole page. The integration test that we wrote for the post components make sure that the component will be rendered correctly. But this page, if we want to test this page, we want to make sure that when we are on the root of our website, we will see all of the posts that are coming from the API, and then we will also see the footer components and also we want to make sure that this also works. It is a little bit more complicated, let us go and first write for the test for the about page and for the contact page because they are simpler static page and it is easier to write test. Let us first, for example, let us go and start writing a test for contact page. Inside contact page, you will see that I added a text that if you have any suggestion, please add me a text. I think I have a I have some ES link and typos and stuff like that. I added an email address to me and my Github report and also my link. Let us go and create a test for this. Let us call it contact page that tests that six, let's describe and describe will be about contact page? I don't know I heard. I will add shows the peop linked in links correctly. For this, I'm going to render my contact page component. I'm going to import this component. I also import render function from the testing library, and I'm also import a screen and here my condition would be that I am expecting to get my email address inside the text and what will be to be inside the documents. What I'm going to say, for example, I want to see my LinkedIn URL here. I want to make sure that inside my contact page, I have the linked in URN and the URL is correct. Let us run this test and let us also see that actually we have the Github link so let me also add this one for the GTub Also I have an text for the email address. Let us also make sure that the text will be rendered. Correct. Apart from that, I also have one paragraph. I also have a contact which is an H two, I also can add a test for that. I can say spring screen get by roll heading when I'm expecting a heading to have this and I'm expecting this to be in document and I'm going to expect this to be in documents. Here get by roll except heading role and the first parameter is the name, but I think it will fail, so that's assist Because actually this tech doesn't have the title, it doesn't have the name, but what I am searching actually would be actually if I search heading, and I want to have this text, which is contact. C. I can test it with this function to have text cont. Now the test is passing. I am sure that I can also use it by screen that text and expected to be in the document. But here I am adding another condition. I'm also checking that actually this text exists and also this is a heading. I can test the whole paragraph for this. I would say it is not necessary, so we can and we can ignore that. Until now, I just tested that these tes exist, but actually all of them are buttons and they have links and they have some icons, so I can also add some tests for that. I can come and say, I can again use screen get by roll and this have the butthead roll. I am expecting to see actually the three buttons. Let me separate this, let us run the test, it is fading. Let us see us unable to find an accessible element with the role. Let us see what actually react testing library is rendering. As you can see, they have been replaced with anchors. They are links, they are links. When we have the anchor, the role will be link. Let me just slip link. And found multiple, I should say get by row. Now the role name is correct, but because there are multiple elements, so I should say get word. Now I am sure that there are actually three anchors to be set. There are three anchors inside this page and also now I can start testing them. I can define this as a variable. And I can say, first, I need to see three links, and then I can actually test the links to make sure that they are correct. Then I can expect links and for the first link, to have instead of, I would say to have attribute and I am expecting the attribute of H ref for the first one would be mail to that contact at one programmer D. Let us run this test first to make sure that I wrote it correctly. Perfect. It is passing. Let us also add tests for the second and third link. The second link should be my Github link and the third link should be linked. I also Let us run the test. I'm wonderful the test is passing. Let us run the test with coverage to also see the code coverage report. Let us see the coverage inside our folder. We are in the SRC side pages folder and here we have the contact page and all the force lines have been covered. The code coverage is also good. With this test, I am actually making sure that always my contact page is valid and correct page. 39. Writing Integration Test for About Page: I also added a test for the A page. In this video, I don't go and I will not write it because it is also similar to the previous video. I encouraging you to write the test yourself. Please pause the video, write the test yourself and you can compare it with my solution. It is an aesthetic page. The only thing that matters for us is this text to be shown properly, and as you can see, I have two header here relative to the contact page that it has only one header and for some of the test, it wasn't so much important, so I add, but I just wanted to make sure that, for example, this paragraph is this paragraph is also exits. If you see the test like previous, I will render the page. I will get all of the headings because now we have two headings for the first one. It should be about this project as we can see inside our A project for the second heading, it should be the course ta then I am expecting to see the text and the goal and the code base and also all of this stuff. Actually, I already did the test for this one, so I can remove this because I already had this test for the heading so I can also remove this test. Let us run the test. It is an easy test, so all of them should be passing and let us also run into coverage. And let us see the cost coverage report. Now we also see that we have the 100% coverage for the about sage. 40. Writing Integration Test for Blog Page (Part 1): Until now, the integration tests that we wrote didn't have any interaction. We were just rendering a component or rendering a page and then we were expecting to see the correct test text inside the page or inside the components. Let us now go and write a test for a component which is a little bit more complicated with the block page. As you can see inside our block page, we have a list of posts and when I click on this, when user clicks, you can see the details of this post. And now I want to add a test that actually also tests this behavior. So we want to write a test for a block page. That makes sure that the components will be rendered correctly and also involves a user interaction and that user interaction is clicking on one post and making sure that actually this page will be rendered. When we click, we are expecting to go to a page which is slash post slash two and this involves the user interaction. Let us go and let us write this test. Let us create a file. I will call it. Log page, the test six let us describe log. For the first one, I would share renders posts correctly. Let us see the component. Here again, we are using react query. So in order to do that, we should do the marking again and we should also provide some post and here we can actually test to see if we see the post element and we also see the link and also we will see it properly. Let us go and let us remove the unit test that we added for the API. Here we had a post and we had a use post. The way that we did this, it was what we marking, we created from Faker, we got a number of 1-20 and for each of them, it was this test factory that was generating a test post, and then we wrapped the whole component inside the reacquery and then we were testing that. Let me just copy this as post values and let us go to the blog post page. Let us do it step so you will see everything that is happening. First, let us run there our blog page. Let us run for now this test and see what will happen. Let's turn back here, let's close this. As you can see, the first will be no query client use query client provider. We already know this error, so I'm going to return and I'm going to use actually to use a wrapper and I'm going to copy this whole line and inside my post component, I need to first render a query client provider. Because this page uses this component and for the client, I'm going to use clients and what have we done previously? It was like we were using this as a query client. Let us create a query client and let us pass it to this. Let us now run the test again. Let us also fix it pretty, let us run the test. And now you will see the test is passing because we don't have any expect. So now, let us go and add a condition. What do we want to expect because the first time component will be inside the loading estate, so I'm going to expect to see this text. So let me add expect here screen that gets by text, and I'm expecting it to be inside the document in the document. So let us run the test. And the test is passing, but this is not my purpose. This is not my goal. I want to actually make wait until this API call will be resolved, and then I want to make sure that I will see all of the posts. And of course, I'm not interested in the actual API call and the API call with the interaction with the server. I want to mark this use post in a way that it returns an array of this marked post, and then I want to test that actually if this function returns the collect value, do I see the proper page or not? So let's do it and let us actually mark this us post. I'm going to import this. I'm I'm going to use D as much as we previously used, and I'm going to mark this whole file and post USPost. Inside my test, I'm going to say that actually after I have defined this variable, I'm saying that I'm expecting use posts. As a mark to always return a fixed value. I also import mark from its what would be the return value for the return value as we expected the data, which we need a data, which will be marked for we are reading is loading an error and is loading should be false and error should be no. So I'm replacing the whole use voice, replacing the whole line with something fixed. And here, I'm going to mark the whole module with this value. Another thing that it is important because at page actually is a page that has been post sorry, block page is a link and we have links inside this component. I also need to wrap the whole component in the memory router. I will also add a memory. Router here and I'm going to use the component inside because when you want to use a link component, you should always have a router as out of scope and I'm going to put a memory router here. Now, I'm expecting that actually this time, I'm expecting this line to be not in the document because I'm expecting that this condition wouldn't be run and I'm actually rendering this for component. Let us first test this part. And the test is failing, let us it is saying that unable to find a text, and this is exactly what we expected. But here now, I should replace this with query by text. I'm just expecting this or to have length zero. Because when I'm saying expect, then get my text, it searches for this text. Now I am saying that actually if you query for this whole text, and query or if you are searching for for this test and inside the render component, you should not see anything and this should have length z. Now the test is passing. My purpose was to actually test to see all of these components and first, I want to make sure that actually the post will be rendered and also I want to make sure that the links are correct. And how many links should I see inside? It will be the number of the posts that I have. I'm going to set and I'm saying get all my role and for the role I'm going to use Link, and I'm expecting this to have the number of these marked posts. I would say marked posts, that's it. Because what is happening, I'm telling the react query. I'm telling this line to return the fixed value which is this fake, the number of the fake posts 1-20 and this iterates over all of these tests. I'm expecting to see this number of these links inside my component. Let us see this and this should also be passed. Now that I have this, let us make sure that, for example, the first post actually has a correct link. Let us copy this line and here I'm going to get the first element. I'm going to test that this test actually have the SRC and HR attribute and the HR attribute should be a post and the ID of the post. Let me also use templates screen. I should be post and the first post that ID, I'm sure this link should have this extra attribute. Let's run the test again and this should also pass. Now I am making sure that actually there is a link. If somebody comes and changes this source code to something like this, still users see the posts. But this is not calculable, and this test that we added is actually making sure that there should be links and the links should also have a correct Hf attribute. Let us return we have removed now, the test should be passed Also, I want to make sure that actually this post component will be also rendered. If we saw it in the previous video that we had some test, I can also bring all of that, or I can easily say because I have another test for the post. I already tested that, so I only need that, for example, to see actually the title. The title of the text should be in the document. Let us just test the tight. I would say get by text and I'm expecting the market posts. The first one that's title to be in the document. With this, I'm making sure that actually post components has been rendered. Wonderful. Now this is passing and this works as expected. If you want, you can also go and also add more conditions for the oatory URL and also the image. This makes the test even better to test that. 41. Writing Integration Test for Blog Page (Part 2): Until now, I have tested that actually, I can see the contents of this page, but I did a test that actually user can interact with the page. In order to do that, we are going to use user event from react testing library, which is a library which allows me to simulate and mimic the behavior of a user, for example, clicking, inputting a form and stuff like that. So first, let us go to our package, Jason. It's already existed, so we're testing library user event, but it is an old version. Let us install the latest version of this library and let us go to the terminal and let us run NPM install. First, I'm going to update this library and then I'm going to add a test that actually tests the the click of the user on the test. Most of the test will be the same. I'm going to create a set of function here and I'm going to let us create a set of function and we want to mark the whole post and we want to have the same random method. Let me put everything here and let me just call the setup here. Let me just return this multi post because I need this from this function, I'm going to render and then I'm going to turn kips. For the second test, I'm going to write a test like navigates to the ID page after clicking on the items. What I am going to test, I'm going to actually test that when user clicks on one button and when user navigates, then he will see this page. For that, I'm going to use again the setup, I'm going to get the marked post. Now, I will get an user object from user events library, from react testing Library. I will call the setup method. I will give us a user that I can do something like click. Something that click. This actually simulates an interaction of a user with an element until the page. What I'm going to click on, I'm going to, for example, click on the first link which is related to the blog post. Let us make sure that first we have all of the links. Let us define a variable. I would say all post links which will be and I'm getting all of the links inside the page after rendering my components. And I'm expecting first the length to be the length of Mc post because for each post, I have a link, so I'm expecting the first link to be done. Then I'm going to click on the first link. First, let us make sure that until here, everything is correct. Let us run this. Now we will see missing setup index specifier. Let us go and see if I did the import wrong. Let us fix this. We need just to import user event. Let me just remove this and then let us import it again. I don't need the index but I just need to branch this from user events. Let us run the test again. Good. Now it is passing and let us make sure that actually this clique works. To test that, actually, I need to create the links correctly. For the first because we didn't need the test, we didn't need the links. I just added a memory router and I just flapped it because the only thing that we wanted to check was to make sure that the link is correct. But now that we have actually the interaction between the links, let us see how also our app works. We are using memory router and this is a browser router and whenever we are in the slash, we are going to have the block page and then whenever we are going to slash post ID, we are going to see this page. I will also need to bring these routes inside my test. I would say that I want to have these two routes and also I want to wrap it inside the route element. And we also need to import routes from react router Dom and I will also remove this blood page and then I will put this to here. Now, actually, I have a router which has an slash which shows the render page and post show this page. Inside our memory router, I can actually say initial interest, which means what I am currently, what the user is there we can say we are already slash to render the block page. Now that actually user click this thing, it means that we started from the block page. The memory router render these components. Now, you are expecting the post details page to be rendered after clicking. This is the content that I want to test. For now, because this page again, uses a query, which is a different query that we marked, I'm going to just test that actually we are seeing the loading. I'm going to add expect here and when this happened when we are clicking on the post, we are going from the blog page, we are going to develop details page and first, we will see a loading, but then this will be resolved to a response and then we will see the whole thing. But for now, I will just add this because I'm expecting it to be inside the documents. Let us run the test. Now the test is fasting because the click the click is Acnc action, so I will also add an here and I will also make this function acing. Let us give it time until the link and the click and everything works to make sure that this is working. Perfect. Now, the test is passing and now I am sure that actually this navigation, this click on this page is working. If you want to make sure 100% because this loading is also exists inside the block page. We have also here a loading. Now, I can show you something, for example, change this to load posting details. And then inside my test, I can say that actually I need to see this to be sure that actually I am testing the correct thing because maybe maybe this is coming from the thing or the other way which will be better would be actually to say that before clicking, I'm expecting to not see the loading test. If I change this with query alba text, I'm expecting it to be have length zero. And it means that here I am sure that the mock value for the use post has worked. I'm seeing the block page, all of the block has been loaded, so there is no loading page. But when the user clicks on it, then I will see the loading test. Let us run this test, and this is also passive. The correct way actually would be actually to also have a mark value for this one, this book and to make sure that, for example, the difference between this page is like that, we will show the writer name here. If I want to test that actually after clicking, we are on the right page, I should search for the writer of this author of this post. Let us do that. Let us also go and let us exactly like what we have. Let us mark the use post here. I just use post which brings all of the list. Let us now march the single one. In order to do that, I'm just copying this line, I'm going to also map this the post. I'm also going to copy all of this mark. I'm going to say that actually for this time, let us always return the first post. The parameter is not important here I'm going that now I don't want to see the loading, but I want to see actually the author of the first post. This is the first and now I'm expecting that to see this. So let's run this test and now we will see that posts that map is not a function. I have a typo here, I should get use post and also I should import use post. I also really always love to show these errors to my students because this is not like that I am writing code and it works for the first time. It always happens that we don't see something. Now I have an actual realistic test that I am testing, that I have created a memory router, I have created these pages, I have linked them and I am starting with slash and now I am involving in user interaction. And when I click on that, I'm making sure that the page has been changed and because I know in this new page that this element exists. This is also one of the best practices to not check the URL. I can check that, for example, the URN should be a slash Postm, but this is something internal and in integration testing, we are interested in actually what is happening. So what is happening when the user clicks, he should see the name of the person and he should, for example, also see the description of the test and you can also add a condition, and I would say gets that description. But because description has multiple lines, I will also need to add one condition I would say, if only the first ten lines first ten character is there, it is fine. Let's run the test. Probably it's going to fail because description has a lot of enters. Okay, no perfect. No, it has been working. And now I am sure that actually this works because if I come before clicking on this page and I say query all by text, I'm expecting to not see the not see the description because when I am in the Blog page, I only see the title, the photo. If I add this, then I am sure that actually if this test passes that I am testing the correct scenario. You can also remove this loading. First, we are in the Blog page, we don't have any description. Now, user clicks on it. I'm expecting to see the author name and this time I'm also expecting to see description. And congratulations. This was a really complicated test. We had to do a lot of stuff, we have to work with memory router, we had to mark some of the queries that we had but we did it and this is a real good test that we can use it inside our project. 42. Introduction to Writing Test for the Admin Section: We already added tests for the blog pages and all of the blog pages have tests and we also run the tests with the coverage, we will see that all of them are completely covered, which is wonderful. In this section, I want to go and I want to start testing the admin section. For the block side, we wanted to see that the blog page is working, so we will see the post and when the user clicks on that the navigation changes and we can also see the description of the post. And now I want to write test for the admin section. If we go to the admin and home, here we have a number of the post as a card. Inside the post, you can see the list of the post. Here user admin has an option to add a post. I can write something and I can at the post or I can come here and I can press Edit and I can change the description and the content of this post. These scenarios are more involved with the user interaction. Actually, if you want to test this, first user Admin should visit this page, then he should come and click on this it and then he should change something in the title, change something in description and then probably change a photo, submit the post, and then we can make sure that actually something it is working correctly. These tests are a little bit more complicated than the tests that we had in the previous section. But the interesting part will be that we will use more react testing library and we are going to use more functions and more methods from react testing library. And so in the next video, I'm going to show you a little bit about the methods and functions that react testing library for user interactions provide, and then we are going to add tests for our admin section. 43. Different User Event Methods and Actions: So let's talk about user events. User event is a component from testing library from react testing library that we can import it like this, import user event at testing library, slash user event. The purpose of this component is to provide interaction of the user. For example, we can have different actions. The first one, I can go and I can type inside an input element, hello. And with these helpers, we can actually test the user interactions with our four element. In the second example, I can clear what I already wrote in the test element. And with click and DBL click, it's double click. I can click on a button or I can double click on a cell element. Imagine you have a table, and the table if you use a double click goes to the edit more, so you can change the content of itself. And for testing that we have DBL click, which is double click. We can test hovering of the mouse over an element to see if a tool tip is happening. If we have a select that have multiple option, we can use method select option to select a value from this option. If you have a checkbox to make it check, we can also call again, click with the checkbox elements and for the upload, we can call user events upload and then we will pass the file that we want to upload and also the inputs that it is allocated with this action. These are the different actions and I find it really interesting that with the help of react testing library, we can test all of these kind of actions and we can see what will happen in our app when we simulate the actions that users are taking when working with our application. 44. Writing Test for the Admin Table (part 1): So let's start by going to our admin folder. Inside our admin folder, we have two folders, components pages, and I'm going to first write test for the components folder. And you will see that we have a sidebar and the sidebar is a menu element that this is the menu that is showing in the left side of our page. And we have a post which here we have create or edit post. This is the component that when we create a post or edit a post shows this form and we have the list post, which is this table component that renders list of the post, and we have the delete button which when user presses on it, I can it shows a first, it shows a confirmation and if user presses yes, then it deletes the post. So let's start writing test with the first for the list post, and let us see the component, what does the component do. It uses, again, we are using here reac query to fetch the posts, and if it is in the loading, it returns, and then if there is an error, it returns, and then we are going to have a columns, which is an array of of objects. And this is actually the table that will be rendered and every column is the first column is a number, so we are just rendering an index in it. The first column the second column is the feature image, and we are reading from the post the property of the image and URL, and the rendering will be an image with the alternative text of the post title and image URL, and then this is the second column. The third column will be the title. Which we are just reading the title of the post, and the first column will be the actions. And inside the actions, we have first a link to an edit which goes to this link admin post edit, and we have a dite button that we are rendering and we are passing the post ID to that. And actually, we are rendering a table with these columns that I showed you, and our data source will be actually the objects that will be rendered inside this table, which are the posts that we have read them from reacquire so let's start writing test. I'm going to create a file. I will collect List posts. The test test and I will add a describe block and it will be for the list post component and inside that I will add a block. As a first test, I just want to make sure that if the page is loading, we are going to show this loading. I'm just write randoms loading if the posts have not been loaded. Yet. I'm going to pass a function here and my expectation will be actually, let us also import. Let us render the list component and let us Let us import post, let us import render, let us also import Screen from react testing library and our condition would be screen that gets by text loading to be inaccurate. I am sure that you know that the first time this test is not going to pass because we need to actually mark use posts. We already did that, so I'm going to the pages, I'm going to site and I'm going to pages and I'm going to the blog page. We did it like this. Use post. I'm going to copy this that we had previously. I can put it before here. We also need to first mark the whole module. I need also to bring this line for this one, I want a data to be nothing to be an NTR and I want here to ease loading to be true. I want to make sure that this component shows the loading. Let's run these tests. And one point that I want to mention here is it is the most important thing about the testing. You see now how easy I added the test because I had previously the same solution, and I just use the same solution here. And a lot of developer at first, when they start learning about testing, they think it is complicated. It requires time. At first, yes, but when you set up your project and you are setting when you are writing the first test cases, after sometimes you can always use the helpers, use the marks, use the spice that you have previously created, and it will make it a lot easier for the future to write tests. So now you will see that I just copied something from my previous test, and now I have my first scenario, which is to make sure that actually this testing is loyal. And now let us go and let us change and add another test that actually we are expecting renders a table with a list of posts. And now, I'm going to test that actually if if I change this mark to returns to loading would be false and returns a list of marked posts, I'm expecting to see a table. And this table should have an index. This table should have and all of the columns that we have seen. And for this marked post, again, I'm going to use the thing that I have created previously. I'm going to just copy this line. We already have the faker. We are generating a number with a faker and for each of them, we are going to use the helper function, the test factory that we have created for this test. I'm going to render this time, I'm going to expect not to see anything. I'm going to query all by text and I'm expecting this to have length of zero. I'm expecting this to not be shown. Let us run this test. We already saw this error previously. This is happening because if I go to the list post here, we also have a link element. In order to fix this issue, I should wrap my component inside the memory route. I'm going to wrap it in a memory route and I'm going to fix it with prettier. Let us read on the test again. And now we will get another error that we also saw previously, we have not provided query client provider, let us go and also let us bring this from our other test and let us wrap it. We also need the query line, let us also bring this line from the other test. I will put it inside my decried block so all of the tests can use it. Remove these. Let us rerun the test. No and this error actually is not related to our test. This is coming from our component that react expects that when we have a list, which is like, for example, a table, every row should have a unique ID. And design provides us with a property row key that we can say, every pose has a ID and please use that ID as the key for this. And because we know that the IDs are unique, this will be unique. So let us add that and let us run the test again. And now we will see that the previous warning has been gone, and now we have a new error, not implemented window that computes style. And this is the same situation with the JSTOm and browser that inside JSTOM we don't have all of the functions, so letter to solve that let us go to our setup set of file. And like that we did previously with the match media, I'm also going to add a new mark here. So I'm going to just write this as a windows that get computes style, and and I'm just going to mark this with something that always returns and a string. That was come and return and run the test. Now the test is passing and we don't have any warning and error, so it is clean. 45. Writing Test for the Admin Table (part 2): But actually, to make the test realistic, I need to make sure that the table will be rendered and I will see all of these rows and all of these columns. So in order to do that, I will define a variable for rows, and I would say screen that gets all roll row. And I'm using Ant Design for the UI library and ntsign a row row for every row. So here we have one header row and three is for the post. So I'm expecting to C, the number of the rows should be the number of the marked posts that's length and one also for head. If I have three rows, then I should see a table with a row with four rows. Let us run its test. And now it is passing. But let us run the test again and let us run the test again and now you will see that the test is failed. I wanted to show you because this is also a really interesting subject in the testing and now we will see the benefit of having the faker and benefit of generating random numbers. If here I had an array of fixed length of three elements, this test would always be passed. And I couldn't see this case. Why this case is happening. Let us see I ran the test for the first two times it was passing for the third time, it is failing. It says that we are expecting 21, but the actual is 11. What is happening here is nsdsign. This table from ntsign by default provides a pagination with the size of ten. Oh, I I have more than ten posts, it will show a page ination. We can test it by setting a pagination to be an object to be an object. I think I should pass the page size of one. Let us imagine that if I have the page size of two or two, you will see that now, it shows me a pagination, for the if I change this page size to one, now I will see three pages. By default, this options exist and it is for the ten rows. When it's happening when the number of the marked s are more than ten, and design only shows the first ten row and we have one header row so it should be 11. In order to make this test work, I have to test this that if marked length greater than ten, then I am expecting to get an 11 to see an 11. Otherwise, I am expecting to see the length. So if the number of the poster I have more than ten, I am sure that the page ination will happen, so I am expecting to see 11 records. But if it is less than, it should be actually the number of the post plus one. Now let us run the test again. Now it's passing. Let us run it again and let us run it again, and now we will see that it is always. In order to make sure I can change also this number to 12 to make sure that actually my test is covering with the pagination. Or we can change it to the. It is even better if I separate this test to two categories. Let me just copy the whole test. Let us first also create a setup file because I don't want to copy and paste everything. Let us create a setup and this setup will be a function that I will put all this thing inside setup and I'm going to return Mark post like we did previously here I'm going to call setup I'm going to say that and I will define also marked posts here for the first test case, I'm expecting that it shows them. I will copy the whole test and I will also make it sure that I will call it renders a table B Hagenation if the number of the posts are more than ten. And for this test case, I'm expecting to always get 11 if I know the number of the posts are more than 11. And to simulate this, I'm going to pass a parameter to setup, which will be number of posts, which will be a number. And here I'm going to let us let's just call it min and max. I want to also min max number of posts. Let's call it number of posts. Instead of always one and 20, I'm going to pass these parameters here. For the first test case, I'm going to always pass a test and I can also make it the default value for one and on 20. For the first test case, I want to make sure that it is less than ten, so I will go with one and nine. I want to get a number of the posts 1-9 and I have expecting to see. For the second test case, I'm going to fix something 11-12. For this one, I want to make sure that the test is actually the table shows a pagenh. Amazing. Now, I have two tests specifically. For two condition which is happening. With this, I can also make sure that my table shows the pagination and how we can make sure that it is running. I I just come here and change the pagination. For example, to false, that means that the page table doesn't show the pagination here, then this test should fail. And you will see that this is failing because it actually renders all of the rows and not only the first. Now I am sure that I am rendering a table, and this table has enough the correct number of the rolls. But I want to also show that I am rendering the correct table. And what does this table has? This has a header, so I want to make sure that I will get all of this these headers correctly. I want my first condition to be get by text, and I'm going to use a hash tag to be in document. Let us run this test. And it is passing, so I'm going to test and I'm going to add a comment here testing the table headers. And the second will be a featured image or you're expecting to see this text inside my table, I also expect to see a title and an action. Now, I am sure that actually the table also has the correct headers. Let us also test that. For example, the first post will be shown properly. Let us go and copy this line and let us testing the table content. For the first one, for example, I will get the first post. And I'm expecting the title of this text to be inside the document. I also want to see the edit and delete button. For now, let us remove this because I have always multiple buttons, let us get them by all by role. The first one is actually a link, so I can use the link row. Let us get all by rod and get all by roll and let us then get the first link and what do we want to check? We want to check that actually the link has a correct value. You have attributes Hf it should be Admin post edit and the post ID, admin post Edit also get the ID from the first post. Let me just remove these two. Let us fix this with prettier and let us run the test. And now the test is failing, actually expect the element to attribute admin post. I have one S here extra. I can also replace this with the template testing. Instead of having a plus, I can also replace it to be like that. If I do that, I think it will be possible in well I know it is. Let's return it to what it was previously. But I had a typo and now I am expecting this time to pass so now I see, I am sure that the title is here, the edit is here and also for the delete, we have a buttoF this one, I can also make sure that the buttons exists, so I can also get expect screen that gets all roll and here I'm going to say button, I am expecting to see exactly as the number of the posts for the button. If I have three posts, I also want to see that my table renders three and three. Now we have two an error because I think the pagination is also here. Let us make it more clear that to make the test more specific for the button, I can pass a second parameter when I am using get role and I can say I want to get only the buttons that the name of the button is delete. Because if we look at the component, if we see I have, this is a confirmation and two options are yes and no, and the text is delete. I'm telling them, please give me only the buttons that are the name is deleted so I don't want to be confused with these buttons. Let us read on the test. And now it is passing. Let us read on it multiple times to be tested with different datasets, so we are actually make sure that our test is correct and we are testing the correcting. Wonderful. Now I have the test for the table. I have the test for the pagination, and in the next video, I'm going to actually interact with the Edit button. I want to actually click on this Edit button and I want to click on this Eit button and I want to add scenarios for these two cases. 46. Testing Edit Action Item: Now that we have added tests for the rendering on this table, and we are making sure that the title is rendered, the number of the rows are correct and the table renders properly. I want to add a test for edit and delete Actions button. And in this video, I'm going to add a test for edit. And what I am going to test, I want to make sure that when user clicks on this edit, then users will see this page and this page have an input, have a text area, has an upload button and submit button. But the interaction of users for this page, it is not important for me for this page. I just want to make sure that when I am pressing the Edit button, this will go to the correct page and user will be redirected to the correct page to do that, I will call and I will create a new describe block and I would say shows the edit post page when user clicks on the Edits Edit action. I'm going to pass a function to it and let us remove this. Like previous, I'm going to set up my post and I'm going to just limit the number to 1-5. I will say cons marked posts equal this post. What I am expecting, I am expecting to see the links, so I'm going to the first condition would be actually that this link has a correct attribute, it should be a slash admin, if you see on the left bottom corner of the page, the link should be admin, slash post, edit one. Let us get links and I would get them by a screen that gets all by roll. For the first link, I'm going to expect that links zero to have attributes Hf links. The href should be admins ID, post Edit. Let me replace this with the templates string and let me add also exactly a marked post. I'm expecting to get the ID of the first post will be inside the f of this link. Let us run this test and it is passing. After that, I want to click on this link and we can do that with the help of user event from React testing library. I will define a user and I would call user events that setup and I'm going to click on the first link. Because I added evite, now I should also change this function to be async. And after this edit, I'm going to expect and I'm going to see the edit post. I will add the condition, but I know that the test will fail. Let us do it together and I will tell you why this is fail. Let us go here. Let us click on the edit. I'm going and I'm telling you that I expect this to be seen inside this page, and I'm going to expect this text to be inside the document. And let us run the test. As I said, it will fail. We already faced this problem before. I want you to pause the video, think about it, and guess what is going wrong here. All right. If you remember, we had the same issue inside the blog page, and the reason is that because if I come back to our setup, here, I just added a memory router and I just render the list post components. And why did I do that? Because inside our list post component, we had a link, and in react, every link should be wrapped inside a router and I just added this. But I didn't define the routes. I didn't define the links. I didn't define the navigation between them. Where does this has been defined? If we go to our after tier 65, the routes have been defined here. I also need to define them for the test. I don't need all of them. I only need for example, here I thought when we are in the admin slash post, please load the post page. When we are in the edit page, please load the Edit page. So I'm going to bring this and I'm going to have a routes block here, routes block, and I'm going to bring this and I also need the post space. I only need these two routes. And I will also add an admin prefix. I would say if you are in the admin posts because this page is slash admin slash posts. Please load the post page. If you are in the admin post delete, please render the edit post page. Where do we start? We are starting from this page. I'm also going to pass this parameter as initial entry. So now, I have actually a memory router. I have a router that has two routes and we are starting here. Now then I press the edit, there is an element and there is an index for this route. Let us go down and let us re run the test. And the tests are still failing, let us see what is happening. You will see that inside, no, I haven't loading component and what is happening? Actually, the navigation has been done, but because we went to the edit post, let us go and let us see this page. When we are going to this route, this page will be loaded and this page, we have this line. So because it tries to fetch the post from the server and then it goes first to the loading state. So we are still seeing the edit post, we are not seeing this title. So let us go and let us mark this use post inside our test. And to mark post, we already did this also previously. I'm going to just remove just going to copy the test that we had from the block page. We did it like this. I'm going to just copy the whole block. And inside my admin page, I'm also going to add this and we are saying that actually the first post should be returning always in the perura use posts, return all of the posts in the short form, return the zero. I also need first to also mark the whole module that's so with this, I am marking this module and here I am defining that if this mark has been called, this fixed object should be returned. Let us return and let us run the test. And wonderful. Now the test is passing. I always like to have a clean warning and arrow section. Let us also fix the error that we are seeing here. You will see that I have one warning here. The test has been passed, so the user sees this page, but we also have a warning. What is happening when user presses on this and clicks. In this area, I have used CK Editor, and the error that we are seeing is related to that. And in this test, I am not actually interested in CK Editor. I am not interested in interacting with that. And this is, again, one of the usefulness of features of mocking that I can completely ignore CK Editor and I can mock it. And let us do this to not see a dirty console like this. Let us go and let us see our edit postage and let us see inside our edit post page. We have the header, we have a component and this component has a CCA Eeditor which is probably here, exactly. Let us see where this has been imported. This has been imported from Editor five and Editor five. I'm going to mark the whole module. Let us go and let us duplicate this line and this time I'm going that I want to mock Ckditor and let us return back and let us read on the test and wonderful. Now the test is working and also don't see any warning and any message 47. Testing Delete Button (case 1): So wonderful. We have a really good progress, and I am really happy that you are with me here. We are testing every piece of our software and we are making it a really high quality software with this effort. Right now, we test at the table, we tested the edit fcton. And in this video, I want to test the delete button. And what will happen when users press the delete button? First, they will see a pop up and then they can decide to see yes or no. If they say no, then the post stays. But if they say yes, then this test, this post will be removed. If you did this by mistake and you want to return back the post, you just need to restart the server. So if you just stop the node J server and restart it, and if you refresh the page, you will get again back the same post. So let us go and let us write the test for this scenario. I will create two tests because first, I want to make sure that I will see this confirmation box and then I will start writing tests for the scenario. Let us add a block here, I would say shows a confirmation box, let users click on users click on deletes action item. And again, because I need the user, I can pick most of the lines from this test and 1-5 posts will be enough. This time, I'm interested in buttons. I'm going to get all of the buttons and because I'm only interested in the delete button, I will add a second condition here. I will say I only want to see the delete button. I'm going after that, I'm going to click on this button on the first button that I'm seeing, and then I am expecting to see this text. Let us add a condition to expect a screen that gets by text to be in the document. If this is happening, then my test should pass. Wonderful. Order to make sure I can also add another condition, I can add also this line before and I can say query all by text. First I want to check that actually this one have length of zero. I want to make sure that this doesn't exist inside the document. When I press on this click button, then this is happening. Let me also bring this a little bit down and I also don't need the return value for the setup function. First, I am checking that I should not see this text, then if I press one of the delete buttons, then this text should be displayed. And wonderful the test is passive. 48. Testing Delete Button (case 2): Now let's go and let's test the second scenario, which will be that if I press the yes button, and what will happen if I press the yes button? Let's read the source code together. We have a list post and inside we have two action buttons. This is the link, this is the button. What is this delete button code button? This is first this conformation and then it has two text, yes or no. And when we are confirming, actually the delete post will be cut. And what is this delete? This delete is a mutation from rea query, which will call an API call and then actually deletes the post from the server. But for this test, we are not interested in the interaction with the server. We are the only thing that condition that I want to test to make sure that this function has been cut. So if the user clicks on the yes, I want to make sure that this function has been called and this function has been called with the correct parameter, which is the test le. Let us write that test. I will copy the whole this block and I will call I will change this. I will say delete the post or let us be more calls delete post. If user confirms the the deletion. What do we expect? Again, I'm creating pi pos. This one I already tested so I don't need it. I will get the delete button, I will click on it, and I'm I'm expecting to see this text. This time, I'm going to get the yes button. Instead of this condition, I will define a yes button and I'm going to say a screen get all by roll. And with the button and this time I'm targeting the yes button and I will get the first button. I'm going to click on this but this time I'm going instead of I will change this. Here it should go my expectation and my expectation would be that actually that function, this delete posts to be cut. But this delete post first in order to make sure that it is getting called, we should first mark it. This is coming from this module and in order to be able to check it, I also need to mark it. Let us go to the top of the page. Let us duplicate this line and let us replace the passes up API posts, use delete posts. Let us go up API post, use delete post. What does it do? It returns an object which is the mutate is delete post and it has an E pending. We already did this, so I'm just going to copy this and I'm going to bring this Inside. I can put it also inside the setup section, I will put it all together here. I will use DiltPst and I would say a mutate. The key will be mutate. And pending, I will pass the E pending fogs. For this one, I will define spire call it delete post. I'm going to also delete the delete post here. I would say const post equals t fn. As you remember, dot fn is a spy function. It doesn't do anything, but I can just make sure that this function has been cut. If I come down, my expectation would be that this function to have been called one time to have been called times one. I am saying that whenever this happens, this yes button clicked, I'm expecting that this delete function to be cut. Let us run this test. And it is passing and to make sure that I am actually testing the correcting, I can bring this also here and I can say this function should have not been called. And whenever we are getting this yes button and when we are clicking on this yes button, we are expecting to be called. And now I am make sure that actually the action of this button has caused this button to be cut. I will also add another condition. I'm saying that I am expecting to have been called and with which parameter, if I check the code, we are passing the ID of the post because here I'm also getting the first post with these links and with these buttons, we are expecting this to be called with the marked post and we also need the marked post. Let us first get the mark posts here. And I have a type of marked post. I'm expecting this has been called with the ID of the first marked post. Wonderful. Now we also have a test for the delete scenario. 49. Getting Coverage Report for Admin's ListPosts Component: As the last step, let us run the whole describe block and let us see the whole code coverage code coverage. We have an error here, sorry, I forgot to remove the lists posts here. And now two of all tests were failing so we run the tests and now all of them should pass. Let me run the tests with coverage and let us see the code coverage report for this component. So let us go here and let us refresh the page and let us go to we were in the SRC admin slash posts. Wonderful now we will see that the post page has been tested with the coverage of 100% and we have also covered all of these. This is a really also good tests. We can also see the coverage for the actual components. If we go to the admin components post, the list pus components has been also completely covered and as a side effect, delete button has been also covered, but our purpose was not to cover this from the edit component, we will see that these red lines means that they have not been covered and these are actually relative to the actions which is happening, for example, submitting form and uploading something. But because we just have the navigation and because of the navigation, we rendered this form and these lines have been covered, but the action because we didn't have any interaction with that form, those parts has not been covered, and of course, it was not our purpose. We will create a separate test for that component. But for the list post now we have a really good coverage and all of the thing that is happening inside that has been covered, which is really good. And 50. Introduction to CreatePost Section: We added test for the list posts component inside the admin page, and in the previous videos we already tested that we could see the title, we could edit and go to the edit page and also we could delete the post by pressing this button. Now we are going to actually test creating a post. And here when I want to create a post as a user, I can enter, for example, post title, and I have an editor here. I can write my content inside this and then I can select the photo and then when I press submit post, then this post will be shown in this page. And let us refresh the page and make sure that post is there. In this video, I'm going to write test for this component. As you see, it requires a lot of user interaction which we are going to use react testing library for that first, I need to enter the title inside this input first and then second, I need to enter the content of the post that I want, and then I should be able to simulate a click and then selecting a file and then uploading it with this button. Then I should be able to send all of these parameters to the API with this pose and then my test should check that actually it is happening and it is work. Let us get a start with coding and let us implement this test. It will be so much fun. Let's start it together. 51. Looking at CreateOrEditPost Component: As the first step, let us see this component, create or edit post. So this is a This is a react element, and here we have a form. We have an state variable for the description. We have an state variable for the image oil and we have two mutation from RaqueryO for create post and one for edit post. And here, handle API call is responsible to to do the API code. And this component, the same component has been used for adding a post and also for the edition. So if you see the URL, if we go to the edit, this is the same form and same element. The difference is that it will show you the content and the title of the post which is already load. And if you are going to add new post, then we will see the same component, just everything is empty. The way that it's handle is here we are in the admin post create. But when we are editing a post, we are in admin post edit form. We have the post ID here inside the URL. The way that it works, we are using navigation and here we are reading in the post object. If the post exists, it means that we already have a post, then we are going to edit this post with the ID and also the form data. Otherwise, we are going to create post, and for this we need only the form data. The handle submit also for it as a validation message to make sure that we already selected the files and then he uses the form data, we are appending title description, and then we are adding the image and then we are calling the previous method, which was handle API card and if we are successful, then we are going to add in slash post. Here for the JSX, you will see that we have a item. The first one is the title. If the posts exists, we are using an initial value. Of the post title, this feed should be required and if the user does not enter the title, we will show a message. Please enter the title. Then we have a content. Here we are using a Ck Editor and we have an unchanged which when user enters something inside this form, then it will be called. And then we have an upload button, which user can select a file for the image, and then we have the subject button. In this video, in the next video, I'm going to write test for this component. 52. Testing Rendering of Correct Form Elements: So let's get started. The first thing that I will do, I will create a new file. I will call it creates or edit post the test that T six Let us a describe block, we are going to test, create or credit post component, and here we will have it. Then I would say, first, we can just make sure that the form is rendering properly. We can just say renders an empty form. For this, I'm going to render create or edit most component. I will import it. I also need to import render from react testing library. I will add a screen. I will also import a screen. Then what do I expect? I expect to see an input. I'm going to or I can also make sure that I will see only one input. I can use get all by roll and then I can say that I'm expecting to see one row. I'm going to expect a screen and I will change this get all by row input to have length what. Let us first run this test and let us see what will happen. As you can see, encounter or use navigates maybe you use inside a router component. Like previous tests, we also need to wrap our testing component inside a router and inside a memory router. I'm going to bring all of these since a since we don't actually need navigation for now, I'm going to just wrap it inside a memory router. I will define a set of function. Inside this set of function, I'm going to return render here I'm going to use a memory route. I will pass this parameter here and instead of this, I will just the I will just call the set function. We need to cover here semicla com here. Let us run the test again. We will see the query client. We also need the rea query. Let me also bring this and we need to close it. And we also need the query client parameter. Let us also copy from here. I like to show it to you that first we start with nothing, then the error will come and then we will fix the error. I could completely copy and paste from this test, but I like to see you how I am approaching, I am writing a test and whenever something doesn't work, how I debug it. Now actually we see that the previous errors have been solved, but now we have a new error. The CK editor component requires you say editor, we can ignore it for now, unable to find a row. We will first see testing library unable to find an x seven element with the role of. But we have our input and I need to the title input is here. I think the role is just textbox. Let us change this to textbox and let us see what has happened. And wonderful. Now the test is passing. Now I am sure that I am actually seeing an input inside the textbooks. For the testing of the CK editor, actually, I don't need to load the whole CK editor. For the purpose of this test, the only thing that I am interested that this component should be rendered. And when user types something on it and press submit voice, this data would be transferred to the APA. CK editor for us is an external dependency, so we don't need to actually test an external dependencies. We can just mark it. To do that, I'm going and I will just add this at the top of my file, I'm going to replace I'm going to mark CK Editor with a in this object, which I am just replacing it with the text area. This text area has a test ID that whenever I want to get this editor, I will use this ID. It has some different value if you pass it and it has an unchanged value. Here I'm going to but now that I am marking this and I have a text area, now I have two text boxes. So this condition will be failed. For checking the existence of the CC editor because I have replaced it with the marked version. The only thing that I need to do is to just check that this element with this test ID exists. I'm going to expect screen that gets by test ID. This is also another helper function from the testing limate that we can assign the elements, a test ID, which we can use it in the future to getting help. I'm expecting it to be in the document. And now I'm expecting this condition to run, but this condition will fail because now I have two inputs and I also expect not to see the warning message because I am replacing it with the I am replacing CK and this one with the mark sure. Let us replace this with two and let us ran on the test. And now the test is passing and I don't also see the error message and how do I make sure that I am testing the correcting if I come to the component and if I remove this section, now this test should fail because I have not rendered the CK ditor. If I return this back to one and if I re run the test again, because I have not loaded the CK editor inside my phone, so this mark has not been executed and this condition is failing. So I am actually making sure that an element of the CK editor has been rendered and because I am replacing a CK editor with a marked text area which just has test ID and I am testing that this element exists. I am sure that this test is actually functional and it works as expected. And to make it better now that we have two text box, I can return back to here and to make sure I can also specify and I can get this first one with the label or with the title. For that, I can also add another condition here, I would say explain that gets by texts and the text is title. I'm expecting this one to also be in the document. Now I am actually making sure that I am rendering the correct textbox inside my create for postage. Now let us test the buttons, we already test this. First item, we tested the Ckeditor and now I have two buttons here. I want to make sure that this form also has a upload button and also has a subit pose. I can also do that with expect screen that gets all by roll and this time I will use roll button and I am expecting to see two buttons inside my phone. Let us run the test. The test is passing so wonderful. Now I would define this as a buttons. I will define as a variable buttons and I will assign it to this. Now I am expecting the first button to have text content of click to upload. For the second button, I'm expecting it to show submit posts. Let us lay on the test. Wonderful. Now the test is passing. You can do it like this, with defining a variable or I can also use it by something like this that, for example, I'm expecting submit posts and elements with the idea with the text of sub cost to be in the document. This is also another way of testing this. But for now, I will just keep it as this is. Now I am I have a test that makes sure that the form is rendering properly and rendering correctly. I need to run at another test for the interaction of the user with this form. For that test, I'm expecting to enter a title. Enter a description for the post and also select a file and upload it and then it should actually calls to create post mutation from reacquiri. 53. Writing Test for Post Creation: So let us write test for that. Users can create a post form. Or I can just make it simple. My test would be to make sure that users can create a post. But I will make it better when I write the test. For now, let us ignore it. Again, I will call the setup to render the components, render everything from the previous test, I know that I have two textbooks, so I'm going to get this and I will call them inputs, and for the first one, I also need ear user events. I will also call Hs user call user events setup. Because for this test, we need the interaction from the user, so I'm going to call the type method on the first input and then I'm going to use post title. For the second one, I'm going to type content of the post. Now I need a file and I because here I have an upload button. In order to that, I'm going to use and this has a label so I can get this form element with this label, but I only interested in the input of this image. Let us get it together. I will say a screen that gets by label text and my label text will be feature image. And then I'm going to for now, let us just test this to be in the document. I want to do it step by step. Let us run the test. And it is failing. Let us see what is unable to find an element with feature image. Let us see we have the content, we have the feature image here, the title is feature image so that we make sure that I can also make it and then I'm interested in this actually input. Or I can just directly input it because this is the type is a file. I can also get it from that. Let me just change this and get it by that. I would say cons file because that's my role and I would say I want an input, but I don't want all of the inputs. I want an input which the type is it's the type is five. And testing library does not provide this, so again, I need to get it from the container. I will get this I will get the container back from my setup file and here I'm going to call containers queries selector, and then I'm going to expect file to be in the Natural. Let us run the test um, and wonderful not is passing, so I have it, and now I want to upload a file inside this file input. Let me call this file input. I'm expecting this file input to be in the document, then I'm going to define an actual file. As a constructor as the content of the file, I will say just sample file content is not important for the file name, I would say feature image that's PNG and for the options, we can also pass option process, for example, type this image, pH. Testing library provides us with a function which we can actually upload. Inside an element, a file and the first argument will be the HTML input elements which will here is file input, and the second part will be file. Actually, the file that we want to upload, because I have used a weight, so I should change ACN. I can also add a weight for these two because these two user types also AC to make sure that my test works as expected, I will also add a weight to this. I can also bring this top, let's make it a little bit cleaner. And now here I have because now I have an error, the argument of type of null is not let us also tell type script that we know that this value exists. Now what will happen, I already input something in the post, I already input something in the file. Now I'm going to press the submit button and I will user click and I would get all of the buttons. I know there are two buttons, so I would I can also get it by roll and passing a name. Let us pass it in the name and the name will be something post. This is also a sync, so I will also add an Avight here at the end, I need to check that actually the upload has been called. But I added so many lines, so let us for now just run the test to make sure that I didn't break anything. For now, it looks good. What will happen when actually when we are submitting the post this form has a handle submit and inside this handle submit, first, I want to make sure that this has been called and it will create a format object, it will put all of the values and then it will call the API. We are expecting and because we don't have the post object because this is a creation, I'm expecting this create pose to be called. And we already did this in our previous test. I need to mark this mutation from reacquery and I want to make sure that this has been called and this has been called with the correct parameters. Let us go to what we already did. We did this for the same with the deletion. Let us go and let us bring this. But for this test, I need to I need to import, not use delete post but use Create post. For this line to be executed first, we should mark the whole module and then we can actually test. We can tell what we want to be executed. I'm going to mark up API post, use create post. For the use creat pos, we are going to create a spy here. I'm going to call it create spy equals FM. I'm just creating an empty function that I can test if this has been called and which parameters aspect. Our condition would be that after clicking of the submits, we are expecting that this create a spy to have been called one time. So let us run the test. Actually, I have a mistake here. If you look at the code of the component, when we are use create force, here we are reading the property of the mutate async and here I am marking the mutate function. I should replace this to be mutate sync. Now that I am using an async option, so I should also need to wrap this inside the wait for block. I will also wrap it inside the wait for block. Let me also import wait for. We can also add eight here and weight. Let us read on the test again. Wonderful. Now the test is passing. 54. Testing createPost Parameters: But for this test, I also want to make sure that this function has been called with the correct parameter. This is really interesting here and I want to use this opportunity to also teach you something else. I cannot simply use it the previous methods that I have been using. For example, I would say to have been called W. Because if I pass, for example, a new form data, what is this form data, it is an object. And if I do it something like this, but this comparison doesn't exist in form data. How we can test actually that, we can ask our react testing library. We can ask this Spy all of the calls that has been called, and then we can make our own comparison for the title, description, and also for the image. Let us do that. For that, I can get all of these parameters that this function has been called I will call it for data arguments with this. Now this is an SPY. I can every SPI has a function mock and then I have an array of calls, which is a two dimensional array. The first argument is the first time that it has been called because it has been only called once, I will use zero and the zero will be actually the first parameter that this function has been called. If we had, for example, create a spy with something else, then that would be the index one. The number of the calls will be actually the first index. These are all the parameters that has been called and this object I can iterate over this and I can create a dictionary for myself for all of the parameters that this has been called. For example, I will call it for data entries. And then I would say, I will define a dictionary, which is a record of the ring to an unknown object. And then I'm going to iterate on this form data argument for the arguments that this function has been called, and I'm going to expand this with value which should be no and the key, which will be string I'm going to fill my dictionary with this value. What I am doing here is just a simple flo that I am reading all of these parameters that this SI has been called and I am creating a dictionary with a key and value for this. Now, I can make sure that actually here it starts my assertion. For that, I can expect that now that I have four data entries, now I can actually test the tight, for example. And here, because this is now the string, I can just say I'm expecting to be host tight. So let us first run this test to make sure that this is actually working and wonderful. Now I am actually make sure that the value that user enter inside the first input has been passed inside my create spy function, which is an spy version of the create mutation of the reacquery which actually calls the API. I am making sure with this test that the whole form, the submission part of the form works correctly. I will also do this for the description. Let us make sure that it is failing because now it should fail because then it should be the content of the post. Exactly. Now we are expecting post title. This should be content of the post and Now, I am sure that the description is also there for the image foil, I'm going to use and I can read this with the image and let us also make sure that this is image. Yes, because we are appending an image. I want this just to be an instance of a fil. We expect it to be a file. Also we want to make sure that, for example, the file name and also has been passed correctly. Import, when I am creating this file, I am also calling a feature age. Let us also test that as well. Let us also expect this image to have name of feature image dot page. Let us run this test this is passing, I have an issue with the type script because doesn't know and I can just use it like this as an object. I know that this is an object which has the name is string so I can just to make it type script doesn't complain, I can also change this. Now I am making sure that actually test, this form has been submitted with all of the values that the user has been entered. Now, let us make our test better. I added some hard coded values, but we already have the fake care. Let us create these values here. I will define the post title here. I would say fake Let me first import fake care from our faked library and I'm going to use a sentence for the post title and for the post description. I'm going to use a paragraph. For the image name here, I added a hard coded image name. I would just also define as a image name I would get fake from system module of the fake and I will get the file and here I can also pass an extension which will be, for example, pH. Extension cons I don't need this, let us make it simple. Here, instead of a hard coded value, I'm going to use an image name and here I'm replacing this value with post title and here I'm replacing this with post description. Inside my test now I am expecting that the post title would be the post title. And the description would be the post description and also the name of the file should be file. What did I name it? I name it image name and this should be image name. Let us read on the test. I know that every time that I am running this test, some random values will be generated for the post title description and file name and it looks exactly like how users interact with our system because everybody uses different things, different characters and different values. Now I am sure that actually my API call, my mutation has been called with the correct parameters. 55. Analysing Code Coverage for createOrEditPost Component: Now, let us see the code coverage report. We added one test for rendering the empty four and we added one test for creating the post. Let us come in here and run the code coverage report. The first test is failing and this is because we added a mock. We mock this create pose and now for the second test, I added this Spy but for the first test this doesn't exist. Let us move this to a before each block and let us define this as inside before each block and let us also define this outside Aslett and let's us override it before each with the spy version. Now I don't know I cant the first and let's call it, or we can also call it with e's just completely bring this out. The first test doesn't have any interaction with it should be fine. Now the first test is also passing, let us run the coverage report. Let us go onto our browser. Let us go to all files. We were on the components post. Now we are under 90% coverage, let us see it. As you can see, the edit section has not been covered. Also the catch section has not been covered and these three lines of code has not been covered. For this, in the next video, I also go and I will also create a test for this case. 56. Adding Test for the API Failure Case: Just before starting writing tests for these, there is one point that I should mention. You don't have to, for example, write tests for everything. Right now, we have a coverage of 90%. In a lot of resources and books, one of the best practices is to have a coverage more than 80%. Oh. And actually, we are already there, so I can ignore this. But because this is an educational video and I want to show you all the power and all of the things that we can do with react testing library, I'm going to add this line I'm going to add test. But technically, after this test, I will test only one single line of code. And it is sometimes you should think you can think maybe it is too much. If you don't want to do it, feel free to not do it. I'm just want to show you that if you wanted to do it, how you can do it. So let us write the test, and this test is similar to the previous test. The only thing that here we want to do is like that if this function fails and if the API calls fail, we want to make sure that users will get one error message. For that purpose, I'm going to copy the whole block and I'm going to replace it users message if creates post mutation phase. We want to add a test for the case that it is failing. And now that I have a before each block that marks this and this is all successful. For this case, I want to make this to fail. And because this test has a lot of duplicates, we can also refactor this kind of duplicate, but I will do it and then. Let us first come here. Instead of returning a mark result value instead of saying that this is working fine, let us reject this with an error that for example, create mutation failed. Now for this case, I'm going to tell vitas that I want this mark to be failed. I want to simulate an API error and a failure in the APA. What I am expecting to see when this happens, I'm expecting that this will this message that error to be called, and this message should be shown to the user. Also, in order to do that, let us create an SPI for it. I will say error. I call it error spot. I would say that FN, we spy on message and error. I'm creating a mark for the message that's error because I want to test that this has been called. Now, at the end of the test here when we are clicking on the submit button. Again, we are expecting that this has been called. I already tested all of these conditions so I don't need to test it. But this time, I know that this will fail. I'm expecting that I'm going to add an expect B to my errorspiT time to have been called one and I am expecting it to have been called to have been called with this error message that error and creation of the posts. I don't need this line anymore, so my weight for command will be that this error message should have been called and should have been called with the correct paramet. Wonderful. Now the test is passing, let us re run all of the tests together again and let us see that I didn't break anything any previous test by adding this new one, all of them are testing, all of them are passing, wonderful now let us run it with coverage. And this time, I'm expecting when I come here and when I refresh the page, this line should not be read. Let us see together and wonderful. Now this line also has been covered. Now our coverage has been increased 90-93%. I still have two conditions. I use I will test this in the edition and I will also write we can ignore this or we can also write a test for this one. Just another thing that I want to do this video because I have a lot of parts or are shared between these two tests, I can also create a helper function for that. For example, call it, I can copy all of this function and I can call it I can call it interact or fill create post for. After my setup, I can define this as a feel can define this function and we put all of this block here. And because all of these actions are the same, so I have a typo, let me fix this typo and here I can also remove all of these lock parts and I just simply replace it with this. Now it is easier to understand what is happening inside the tests. Let us re run the whole tests again to make sure I didn't break anything. And now the function should also be a sync because I added. I'm using a weights here, that was on the test. Inside my tests also, I should also add an evade here, I should also add evade here. Now I also need these tests needs actually these values. We can also extract these from this. Instead of returning nothing, I can return an object of post title, post description, image name and I can get them here. I would say cos post title, post description and image name. I am writing them here. I also have a typo here. Let us read on the test again. I also have semicol on here. Let us read on the whole describe. Wonderful. Now my tests are passing and also it is easier to understand if another developer wants to read the test and see what is happening here, it is so much clearer that we are spying on message that error, we are rejecting the promise, and then we are filling the form and then we are expecting to be called a spy here, we are expecting here we are filling the form and we are expecting that the creative spy have been called and also we are expecting this form data to be passed with correct parameters. 57. Adding Test for Edition of the Post: Now I want to add a test for the addition. So if we have, for example, because we didn't test this part of the code, this part of the code is the same, but this component can accept the post object. If we pass it a post object, then we are expecting it to we are expecting this edit function to be called. Let us go and let us bring all of our rendering function. This time I want to pass a parameter, so I would say calls what did we use, we use users can create a post. Let us also make this message better. Let us say calls calls, create post mutation when users fill the form. Here I would say calls the other mutation, which is it calls, edit post mutation. If a post is cast. Again, this will be an acing, so I'm going to render this time and for the post, I'm going to use our test factory that we have created, get test post. And here I'm going to pass the post object here. I would say post equals to post. I also need a query client. Let us also bring a query client for this one. This will be our render function. I have a need also on this for Now I am rendering the same thing with the host. I can use the same helper function that I have created. I can then do all of the interactions that I had with the four but now I need a new spi also I will bring all of this block here. But then I just don't need create spy, I will also create a function phon Edit posts, spy I also here spy the whole spy the second mutation which is use Edit posts. I'm going to copy this block. I'm going to this time I'm going to use Edit post, call it a mark and this time for the task for the spy, we are going to use Edit post. Of course, if I am doing this first, I should mark the whole module, so I'm going to the top of this file, I'm going to also mark use Edit post. And then after that, these lines will be executed. I have the edit post. Now I am expecting that this time, I am expecting my edit postpe to be cut and the parameters that I am reading from it will be from this time. Let us run the test and let us see what will happen. We have an error, let us debug it together, found multiple roll element with the name button of the submit posts. Now we have a before each block and inside before each block, I think I already had the setup submit post, submit post then we have the content. We have the feature image inside our contents and but I didn't call the setup in this function. I think we have the setup here. Usually we set up container equals. Because I have the container here which is calling the setup now, I am rendering the four twice and this field form actually also does this. For now, let us just let us For now, let me just simply copy the whole block. Here inside instead of this line, I'm going to use this. It has so much duplication, but for now, we can ignore it. Let us see if this will solve our problem. Because now I am rendering my component here. The test again is failing, and I should also remove this line, the whole purpose was to remove this line and bring the function call here. We also the container. Let me also bring the container here. Again failing form data arguments that for each is not a function. Let us see here we are getting an edit ppi. The form has been called once, so this function has been aligned. Let us from now remove these codes and let us re run the test. Now, I am sure that actually my edit spy has been called because if it was failing, it should have failed on this log let us debug it, so let us see what is happening. And Okay, wonderful. Now, let us debug it together. When the edit post is calling, actually, it will receive an object which has an ID and has a property of the form data and the ID is the ID of the post and the form data is for theta. Previously, we were just passing the first argument as the whole form data. Now that I am doing this, actually this this is the ID because I'm using the first posts, and then let us duplicate this line. I need and sorry, this is the whole object. This is the whole object that has been called, which is this one, ID. So let us go and let us instead call this as like this. Instead of say, I would say an object, and I'm reading a form data. The first call will be this object for the form data, then I'm going to iterate over this. This time, it should not be a problem. Actually, no, it is failing because it is also another interesting thing that I can discuss it and I can teach you. Now that we are passing a post object here, so this input, the inputs that we already have has a value. And when I am going and when I am typing something inside this, it will be appended to that. For that, I'm going to first clear the input, and I would the user input that clear to make it a to make it empty and then adding something to it. Or I can simply remove all of these object, and then I will say, for this test, I just want to add a two. How do we test it manually if I come here and if, for example, press edit here, if I want to test manually, sometimes I will just add a number and then here I will see it has been changed, so this is good. For this test, I'm going to just inside the title, I'm going to add this and then I am expecting it instead of this random value, I'm going to expect it to have my title of the post plus this new value that I have added. For now, let us remove these lines. Let us make sure that just to test if this is work. And wonderful. Now my test is actually passing. For this test, I can also do the same thing for the image name. I can also do this for the same thing. Let us go and instead of passing actually a value just append description to the value that is already there and it is also it says us that it prefers to use a temple item. Let us change this to be like this and let us also change to be post the previous description that the post had, and then we are adding a description. We are appending a description for this one, for the image because this is an upload button, the image will be replaced so I can leave the image as it was before, so I can just go and I can bring the same fake line here. And now I'm expecting this test to be passing. Let us see it together. Wonderful. I didn't check ID, so let us also test that actually the edit post will be called with the correct ID. I was adding an expect and I'm expecting it to be post ID. Let us run the test. I'm also expecting this to be passed. Now let us run all of the tests together to make sure that I didn't break anything during these changes. So wonderful it is passing. Let us rerun the test with the coverage to also see the coverage report. This time, I'm expecting that these two lines also have been covered. And wonderful. This has been covered. Also I can exactly like what I did with the message that error. I can also test that. When the edition is successful, we are seeing inside our source code that we are showing message that success. Let us also test that. Here before rendering, I'm going to call message. Instead of spying on message and error, we are going to spy on success. So and I'm going to call it success spot. When this has been finished, when all of this has been done, we are also expecting that success spy to have been called once and also we are expecting to have been called with this message which is post has been updated successfully. Let us rerun all of the tests. And wonderful. Now my test is passing. Also the coverage has been increased. I also added this test for these two lines. The coverage has been increased from 93% to 96%. And in the next video, I will put this as an exercise for you. You can also add test for this. Here, we had a condition that if the post doesn't exist, it means it is an create post file. And we are not editing it because we are creating. If users doesn't select a file, we will show an error message and if you want to see it inside our blog, if I write title here and if I write content, but if I don't select a feature image and I try submit, then we will see this error message. You can also add a test for this. This will be fun. Please stop the video and add a test yourself. 58. Adding Validation Test for Image Selection: So let us come to the solution part. Let us add the last test and let us finish this lecture. For the last test, I would say shows an error message if users have not selected a file. After sometimes writing tests will be so much easier because I already created everything that I need from the previous examples. The only thing that I need is just to copy and paste all of the things that I already have. Let us go and let us bring Actually, this one is easier to copy this time because we need to spy on the message that error, so I'm going to replace all of these things. I will bring all of these values from my setup file, I don't need the return value, I will just bring them for this last test here instead of I won't enter the image name. I will remove this line, I remove the creation of the file. I remove the file input, getting the file input, I remove the uploading file and I am just submitting the form with this empty value because I don't need upload file, I also don't need this container, let us make it. Simple here I'm just generating a post title post description. We have a before each plot which always marks the create with a successful message. For this test, we want it to be successful we don't want to enter we don't want to enter the file output. After that, we expect it to be error message to be called with this error message. Let us go and first time, let us try to let it fail to make sure that actually we are testing the correct thing. Let us run this test. And you see that exactly it is calling, it expects it to be called with this message. So I'm going to add this and I'm going to run the test. This was easy 2 minutes to write this test because I added already all of the other cases. And this is really interesting with testing that when you have some at first, it looks complicated. It looks like time consuming. But after sometimes it's just getting so much easier because you have everything that you need for your test. I'm running the test with the coverage, I'm refreshing the page and wonderful. Now these lines have been also covered and now I have 100% for this component. All the lines, all of the branches, all of the function, and everything has been covered for this test. 59. Integration Testing Module Summary: All right. Congratulations. You have finished this module. This was a tough module. I know we have covered a lot of topics with writing test for create and editing post. Actually, we learned a lot. We learned how we can actually input something into the text area with user that type. We have learned how we can write tests and simulate the uploading of the file for a form. We also learned about marking complex editors like CCA Editor and just replacing them with a normal a text area. Also we have learned about the success and failure API because we wrote tests for different situation if the API works and how we can simulate an error in the API that we are showing the error message to the users and also we implemented tests for validation logic like that. If the user has not selected a file and he wants to create a post, then the app shows a morning message, and we also wrote test. This was a really advanced module, so I'm really happy that you finished it. It's time. Let's get your time and do a quick break. I'm really proud of you, and I'm hoping that you will use all of these things that you have learned in this module in your future projects. 60. Introduction to End 2 End Testing: So let's get a start with end ten testing. Congratulations for finishing the previous sections. I'm really proud of you that you came this long way. And in this module, we are going to talk about end ten testing. And what is end twin testing, let us go and let us do a review. We talked about the unit testing. We said that unit testing focuses on one unit, which is a function or class. And in integration testing, we are testing the integrity between different components and modules. But in end twin testing, we are seeing the software as a whole. So it doesn't matter for us in which technology it has been written. It can be react, angular, view or anything else. We don't know what back end technology is using. It can be CSO, Java, JS or anything else. And in in term testing, we are seeing the software as a whole, and we are testing the expected behavior of this software. And let us again return and think about the testing per bit. So first, we started with unit testing, which they were many fast and cheap to write. And now we want to write end Twin tests. And doin tests from the number, there are fewer, a lot fewer than the unit test, and they are fewer also than integration testing. And running this kind of test is slower relative to the unit test and relative to integration testing. And usually for developers and for the companies, they are expensive. So from the time the developers need to put from the resources that they require and from the time for execution. And now we want to start with this module with the end twin testing and with playwright. So let's get it started, and let's start with installing playwright. 61. Installing Playwright: For writing unit tests, we are using playwright. Playwright is a tool for ten testing, writing, and what does it do? It actually open a browser, a Corum He Firefox or Safari and then it renders it visits the website that you want to test, and then it is acting like what a normal tester does. It opens the page and then you can have different condition that, for example, this text should be visited or this link when I click on it, something should happen. If I submit this form, I should see this message and then the page should be redirected to this page. All of these conditions, we can test it with playwright. So let's start by installing prey right. I'm inside my terminal, and here, if I do an LS, you will see that I have two folders. One is for the simple blog and one is for the back end. I'm going to create a folder and I will call it TN test, and then I'm going to go to this folder and to install playwright, I will run this comer NPM ElenPlaywt at latest. I will pray. And it will ask me, do I need type script or Javascript? The default option is type script. I will pick the type script and where to want to put your twin test, the default is a test folder, so I will accept also the default. And the next question is at the Git of action workflow. And what does this mean? Usually in the companies and in the production environment, we are using heat of action that whenever merge is happening into our main branch, a pipeline should be run and that pipeline it's running all of our Twin test. For now, we don't need that, so I will go with the no option. And the next question will be what playwright browsers, do I need to install? I will pick the default option that will by default install all of the three main browsers. I will just change it as true, I set it and then now it is actually installing and it is downloading the browser. As you can see here, for example, first, it starts by installing Colombio. This is also interesting for you to see that it actually download the browser, it is actually testing the whole software in the exact same way that a browser and a user and a tester works with the software. And and now in the next section, it is trying to download Chromium headless, Chromium headless is the Chromium version that doesn't have the user interface that a normal user works. So as a normal user, when we are working with a with the room, we have these windows. We have all of these things, and Corobu headless only has the APIs for Corom that renders and for the testing, we only need the headless part of the browser. And here you are seeing them, it starts to download the firefox and then it starts to download the web. And these are the three major browsers that playwright does. This is also again, interesting that when we write tests with playwright, actually, we are testing our software with different browsers. And this is also really important that we are sure that our website works and our web application works properly in different browsers. 62. Running Playwright Example Tests: So it has been installed, and you will also see this is the icon of the playwright and we can also see it here. Playwright comes with some default tests in order to run them, we can run this PX playwright test. And these are some predefined test just to make sure that we have installed the playwright correctly, and you will see that all of this test has been passed, and now I can confirm that actually my installation has been successful. It generates an HML report, and we can see that by running this command and pigs playwright show report. Here, when you run that, you will have a page page and I will open it on local host. You will see that I have one test which has been run against Combo. The second, this is the same test has been run against Firefox and this is the same case has been run against bk. Then I have another test which is get a started leak and the same has been run against different browser. Here you will also see the time that each of these tests took to run. If I click on it, you will also see the steps that, for example, it has a before, which is a setup and installation and then it visits this web, which is the official page of playwright and then it expects to see the text of the playwright and then it will do some kind of afterhoks Let us see the other test. The other test is, again, it visits the playwright website and then it is searching for a link which is get started and then it clicks on it. Let us also see it. Here we have this link which is get started. This test is actually for this button, then it clicks on it, and then it expects that to see a page with the heading of the installation. Let us see together. If I click on here, you will see that I have a page with the header of a installation and this is exactly what does this test do. And for running tests in playwright, there is also another option, which is running them inside a UI mode. And I can also show you here. So if I run the same covered and NPxPat test, and if I add UI, it opens the test mode in the UI form of the playwright. And here you will see that I have a window and I have two tests. I can see my test, and here I can run them. And here you will see that actually what is happening. So it first visits a playwright website and then it expects to see this playwright text and then it will do some kind of cleanup. For the second test, you can also run it here, and you will see that it first came to this page and then it clicked on this button, and then it expects to be going to this page and see this installation text. 63. Playwright Methods and Helpers for Testing: And let us see the playwright methods that we have used in the previous example tests. We have some basic methods, page dot GT, for example, this is the first thing that actually with this, we can tell the browser that playwright is using to visit a URL. And then like react testing library, we have G by role and we can query from the HTML of the page based on the link button, inputs, text o and we can get this element. And for conditions exactly like we test that we had in the previous videos, we have an expect. We have some matchers like to have title, we can test that an element, a title exists ins the page. We have to be visible, which is which is similar to be in the document of react testing library. And now that you have learned test, now that you have learned react testing library, learning playwright will be so much easier because you know the terminology, you know what is the purpose of the testing and what we are going to test, and it will be so much easier to also implement T test. And I also opened the project in my ID, so I have created this T test. Let us go and let us see the test examples. And here you will see you can also go to the test folder. So let us first see this one. This is actually the example test that we have run. And as you can see here, I have two tests, but we will see six because every test will be run regarding three browser, Chromium, Firefox, and web kit. And here you can see that I have the test keyboard and this comes from playwright and the test exactly like what we saw in the test and reactesm library, we have a description for the test and we have the function, which is most of the playwright tests are AC because when we go to when we are visiting a page, this is an AC Gas action. So we have this AXI from playd we will receive a page object, which we can do methods on it. For example, we can call the go to to visit a page, and we can expect also this page. So here we are first awaiting for this to make sure that this action has been finished. So browser open this page because this requires a network request. It can be async and so we added an await here. And then here, I'm expecting this page to have this title. When we write it like this, it is look it's a rejix so it is not exact strength but it is a rejix. And for the second test, I'm again seeing this URL. Again, I will receive a page as the parameter and then I am visiting and you already know you already have seen syntax. First, it will get a link. But if you are getting link, there are many links, so it will also add another condition for get started and then it clicks on this link. Again, we have the await here and then we are expecting to see to visit a page that has a heading and that heading should be installation. This is the two example test cases that we saw in the area. 64. Writing Our First E2E Test: All right. Let's start and let's write our first test with Playt. And I'm going to test my page, and I'm going to implement the exact same test that I want to visit this website, and then I want to see some elements in it. So I opened the browse I opened the project in my ID, and I'm going to copy the whole test here. I'm going to name it blog section. Here I'm going to define a variable for the URL. I'm going to use. I'm going to store this as a variable here exactly like the example test, I'm going to visit this page. I'm expecting what title I will see the title is the thing that we will see here, simple block page. I'm expecting when I visit that to see the simple block page and language. This is an easy test, so let's run it and let's see. As you can see, now I have this window and I will see the chromium web cube, firefx tested against different browser and all of these tests have been passed. Congratulations. We did our first test in playwright. 65. Testing the Blog's Header: And let us also see and make sure that we will see a correct header for our website. I'm going to add another test. I'm going to copy all of these sections and I'm going to call it has correct heading. Like the previous page, we are going to visit the page. Here now I want to get this element, which is an H one element. I will get it by page dot locator. Here I can pass H one, I can get a selector and this will give me the H one for this page. Then I can say that I'm expecting this H one to have text. The text will be something that I am expecting to see here. I'm going and I'm saying that for this test, I'm expecting it to see simple blood created by. Let us run this test, wonderful. Now it is also passing. 66. Testing Click Event and Navigation between Page: For the next test, I also want to visit this page and then get the first element and then click on it and make sure that I am actually seeing the title of that post article inside my page. It is a little bit more complicated. It requires multiple steps, so let us do it together. Let us change this test and let us call it users can see a post by clicking on it. As the first step, again, I'm going to visit the URL. I'm going to get a I'm going to get all of the leaves, and for that, I'm going but I don't want to limit based on the title or based on any condition. So I will remove this condition, and I will also remove the action button and I will change this to call it gets links and I will store the results into the variable. For the first condition, I actually expect to have three links and let us see if this is working or not. Let us just add an expect condition. Let us say that we and let us define we are expecting the count links to be three. Let us also define these count links, which will be the links dot card. I want to store I want to store the number of the links, and I want to test if I see three links. Let us run this test. Actually, it is failing, and you will see that I am getting three but I am expecting three, but I am receiving six. Because I also have other elements here, I also have, for example, these meno elements. They are also links. Let us make it more specific. Let us inspect and see the H t of the page. Here I have one A and inside, and this is inside a DV and I have the main section. I can actually narrow my selection to be only searching inside the main area. Oh, let's do this. Instead of searching inside the whole page, I just want to get the links that are inside this main tag. So let me first get the main section. Let's be come here and let's get main section. And I can do that by page dot locator. And here I will pass selector, and this will give me a subset, all of the H table inside this main tag. So instead of getting all of the links and instead of query Get by role in the page, I'm going to change this get in main section. And I will change this to main. So I'm running the same requirement, same query, get by roll, but I'm not running it inside the whole page. I'm going to run it only for the main section. Let us run the test, and this time I'm expecting the test to be passed and wonderful. Now my test is passing, I am here inside this area and and now my next step would be actually to click on the first one and make sure that I am seeing the correct title. And so I will add two conditions. The first condition would be actually to see this text five mounts wearing receipt. And then my second condition would be when I click on it, I'm expecting to see a page that has this title. Let us do that. I'm going to expect that my first link turns links to have text. Let me just change this. I'm expecting links. I'm going to get the first link by this method NTH and I'm passing an index. I'm saying that I'm expecting this to have the text that I am expecting five bound watering receipts, you need to try this way. I also need to add ant because every time when I am actually calling a method and counting or getting a method, this is also an azing operation. Let us rerun the test and the test is passing so good, I will see this text and now I'm going to click on this on the first link. And what will happen when I click on is, I will go to a page and let us see what is this. I also think this is an H two. So I'm expecting also to be on a page that these t exists there as an H two. And we already did that here. So I'm going to copy the same thing. I'm going to use it here. This time, I will just use an H two locator and my condition would be exactly like this. So I'm going to expect H two to have text, this will be the text that I am this one this is the text that I am expecting to see. This is also a. Let us also add an Image and let us also add an ps and let us run the test. And wonderful. Congratulations. We need a test. We did a really good test first what we are going in this sense, first, we are visiting our homepage. Then we are getting all of the links that are inside this main area. Then we are testing to see three posts, and then we are testing that the first link should have this text. And then we are going and we are actually clicking on this text, and we are expecting to have an H two tag, and this H two tag should also have this text. So now we are making sure that all of our users can click on this element, and when they click, they will go to a page that has an H two tag and the title of the post is there.