{"id":14824,"date":"2021-10-20T06:51:44","date_gmt":"2021-10-20T10:51:44","guid":{"rendered":"https:\/\/qxf2.com\/blog\/?p=14824"},"modified":"2021-10-20T06:51:44","modified_gmt":"2021-10-20T10:51:44","slug":"end-to-end-ui-automation-using-testcafe","status":"publish","type":"post","link":"https:\/\/qxf2.com\/blog\/end-to-end-ui-automation-using-testcafe\/","title":{"rendered":"End to End UI Automation using TestCafe"},"content":{"rendered":"<p>For one of our clients, <a href=\"https:\/\/testcafe.io\/\">TestCafe<\/a> has been recently used for end-to-end(e2e) UI automation. <a href=\"https:\/\/testcafe.io\/\">TestCafe<\/a> has a number of significant features, including simple setup, no web driver installation, support for all main operating systems, various browser support, reporting and HTTP Mocking.<\/p>\n<p>In this article, I&#8217;d like to show how to create UI tests with TestCafe, as well as how to set up and write e2e tests with basic assertions using page object models. For this, we created a sample React Resume Builder Application, which we will use to write an e2e test in the sections that follow. If you are new to TestCafe, this article will help you understand the basic features of TestCafe as well as how to write selectors for a React application.<\/p>\n<h3>TestCafe Setup and Requirements<\/h3>\n<p><strong>Pre-requisite<\/strong>: Install <a href=\"https:\/\/nodejs.org\/en\/\">NodeJS<\/a> and <a href=\"https:\/\/docs.npmjs.com\/getting-started\">npm<\/a> and check if the installation is correct  by <code>node -v<\/code> and <code>npm -v<\/code><\/p>\n<p><a href=\"https:\/\/testcafe.io\/\">TestCafe<\/a> can be installed globally or locally in your project using npm.<br \/>\nFor Global Installation on windows &#8211; <code>npm install-g testing cafe<\/code><br \/>\nFor Local Installation on windows &#8211; <code>npm install --save-dev testcafe<\/code><\/p>\n<p>Check the installation by running the command <code>testcafe -v<\/code><br \/>\nThe output looks like this: <\/p>\n<p><code>$ testcafe -v<br \/>\nUsing locally installed version of TestCafe.<br \/>\n1.15.1<\/code><\/p>\n<p><strong>Note<\/strong>: If TestCafe is installed both locally and globally, the TestCafe command will run the local version.<\/p>\n<h3>About our Web Application and Setup<\/h3>\n<p>For this tutorial, I am using this sample <a href=\"https:\/\/github.com\/yashrajb\/Drail-Resume-Builder\">Resume Builder Application<\/a> created using <a href=\"https:\/\/github.com\/facebook\/create-react-app\">create-react-app<\/a>. This application is built for our internal training purpose. You can find the source code <a href=\"https:\/\/github.com\/yashrajb\/Drail-Resume-Builder\">here<\/a>. This react application is used to create a resume by entering personal, educational, and professional experience details. Begin by cloning the base project structure<\/p>\n<p><code>$ git clone https:\/\/github.com\/yashrajb\/Drail-Resume-Builder.git<\/code><\/p>\n<p>From the root directory run <code>npm start<\/code> to start the project. The application will be deployed at http:\/\/localhost:3000 and a list of UI fields should appear. Once you&#8217;re comfortable with the application, start writing tests. <\/p>\n<p>Before we get started, take a look at our sample Resume Builder application. It consists of two pages, main page with textboxes, drop down list, buttons etc., and a redirect page. In this tutorial, I am going to build a E2E tests for Resume builder application. For example, this test will go to the main web page, fill out the form, and verify if the filled in contents are displayed in the redirected page.<\/p>\n<p><figure id=\"attachment_15479\" aria-describedby=\"caption-attachment-15479\" style=\"width: 900px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/resume-builder-app-2.png\" data-rel=\"lightbox-image-0\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/resume-builder-app-2-1024x488.png\" alt=\"\" width=\"900\" height=\"429\" class=\"size-large wp-image-15479\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/resume-builder-app-2-1024x488.png 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/resume-builder-app-2-300x143.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/resume-builder-app-2-768x366.png 768w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/resume-builder-app-2-1536x732.png 1536w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/resume-builder-app-2.png 1874w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/a><figcaption id=\"caption-attachment-15479\" class=\"wp-caption-text\">Main Page<\/figcaption><\/figure><br \/>\n<figure id=\"attachment_15480\" aria-describedby=\"caption-attachment-15480\" style=\"width: 900px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/education-and-experience-details1-1.png\" data-rel=\"lightbox-image-1\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/education-and-experience-details1-1-1024x718.png\" alt=\"\" width=\"900\" height=\"631\" class=\"size-large wp-image-15480\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/education-and-experience-details1-1-1024x718.png 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/education-and-experience-details1-1-300x210.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/education-and-experience-details1-1-768x539.png 768w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/education-and-experience-details1-1.png 1269w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/a><figcaption id=\"caption-attachment-15480\" class=\"wp-caption-text\">Education and Experience fields in Main Page<\/figcaption><\/figure><\/p>\n<h3>Page Object Architecture<\/h3>\n<p>Using the Page Objects Pattern is one of the best pattern for architecting a testing project. Ideally, you should save all selectors or locators or any specific data that is unique to a specific page in a page object file. The main advantage of this pattern is that it will be easier to maintain the test because if some changes are required, the test itself will remain unchanged, and only the selectors or locators in one page will need to be modified. This pattern helps to make the code more understandable, maintainable, and reusable by writing the page methods. You can read here about <a href=\"https:\/\/martinfowler.com\/bliki\/PageObject.html\">page objects<\/a>. <\/p>\n<h3>Writing Page Objects<\/h3>\n<p>For this testing, I used the page object model and created classes for each web page in the application. The Test scenarios include <\/p>\n<li>filling out the basic information, educations details and experience details on the main page and\n<\/li>\n<li>\nasserting the data in the redirect page.<\/li>\n<p>In the project root folder, I created a folder called `\/pages` and a folder called `\/tests`, and started writing page objects and tests here. Lets start with a basic <a href=\"https:\/\/testcafe.io\/documentation\/402837\/guides\/basic-guides\/assert\">assertion<\/a>. The directory structure looks like this:<\/p>\n<figure id=\"attachment_15536\" aria-describedby=\"caption-attachment-15536\" style=\"width: 363px\" class=\"wp-caption alignleft\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/09\/Directory-Structure-2.png\" data-rel=\"lightbox-image-2\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/09\/Directory-Structure-2.png\" alt=\"\" width=\"363\" height=\"446\" class=\"size-full wp-image-15536\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/09\/Directory-Structure-2.png 363w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/09\/Directory-Structure-2-244x300.png 244w\" sizes=\"auto, (max-width: 363px) 100vw, 363px\" \/><\/a><figcaption id=\"caption-attachment-15536\" class=\"wp-caption-text\">Project Directory Structure<\/figcaption><\/figure>\n<h3>Create Main page model<\/h3>\n<p>Make a file called &#8220;mainPage.js&#8221; in the pages folder, then declare a Page Object Class as shown below. This page consists of all the element locators and methods that we will use in the main page. To begin, you must import the <a href=\"https:\/\/testcafe.io\/documentation\/402829\/guides\/basic-guides\/select-page-elements\">Selector API<\/a> from testcafe module. The TestCafe Selector function allows to use CSS selectors to locate the elements to test.<\/p>\n<pre lang=javascript>\r\nimport { Selector, t } from 'testcafe';\r\nconst { ReactSelector } = require('testcafe-react-selectors');\r\n\r\nexport default class mainPage {\r\n    constructor() {   \r\n         this.title = Selector('a');     \r\n    }\r\n<\/pre>\n<p>In the mainPage.js, I have simply added one Selector which will be accessed from the test.<\/p>\n<h3>Creating our first Test<\/h3>\n<p>Test scripts should be organized by module name under the &#8220;tests&#8221; folder. Each test is grouped into a <a href=\"https:\/\/testcafe.io\/documentation\/402831\/guides\/basic-guides\/organize-tests#fixtures\">fixture<\/a> in TestCafe. The fixture is essentially a test category, and each test might have multiple fixtures. TestCafe uses a proxy server to inject scripts to the page, which we can then inspect. <\/p>\n<p>I created a &#8216;\/E2ETest.js&#8217; file in the `\/tests` folder and this test starts by opening the application and checking the header of the page(we will extend this test further in our next sections). If you notice I have also defined a config file to store all the critical data required for the project. In automated testing, test data is usually a crucial component. Using hardcoded values in our tests, such as &#8216;url&#8217;, is not a good idea. So I have added these values to a config file and am reading from it.<\/p>\n<p>Our first test looks something like this.<\/p>\n<pre lang=javascript>\r\nimport mainPage from '..\/pages\/mainPage';\r\nimport config from '..\/config\/config'\r\n\r\nfixture`E2E Fixture - Building a resume`\r\n      .page`${config.testURL}`;\r\n\r\n\/\/ page header test\r\ntest('Assert main page header', async t => {\r\n      \/\/ The assertion      \r\n      await t.expect(await mainPage.title.innerText).eql(\"Drail Resume Builder\");\r\n});<\/pre>\n<p>After importing the required modules, declare a test fixture and name it as `fixture &#8216;E2E Fixture &#8211; Building a resume&#8217;.` and define the start URL for all the tests in the fixture. In our situation, the URL is http:\/\/localhost:3000. Use keyword <a href=\"https:\/\/testcafe.io\/documentation\/402831\/guides\/basic-guides\/organize-tests#tests\">test<\/a> to create a new test(). In our case, the test starts with asserting the URL of the home page header. <\/p>\n<h3>Run the tests<\/h3>\n<p>There are many ways to run a test in TestCafe. The simplest way is run using<\/p>\n<p><code>testcafe chrome .\/tests\/E2ETest.js<\/code><\/p>\n<figure id=\"attachment_15478\" aria-describedby=\"caption-attachment-15478\" style=\"width: 795px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/result-1.png\" data-rel=\"lightbox-image-3\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/result-1.png\" alt=\"\" width=\"795\" height=\"203\" class=\"size-full wp-image-15478\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/result-1.png 795w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/result-1-300x77.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/result-1-768x196.png 768w\" sizes=\"auto, (max-width: 795px) 100vw, 795px\" \/><\/a><figcaption id=\"caption-attachment-15478\" class=\"wp-caption-text\">Run Test<\/figcaption><\/figure>\n<h3>Add actions to the page models<\/h3>\n<p>Let&#8217;s now add some actions to the page object mainPage.js. Inside the page object functions, things alter a bit. This time we&#8217;re instructing TestCafe to select specific form elements and type using the typeText(). So our mainPage.js now becomes<\/p>\n<p><em><strong>mainPage.js<\/strong><\/em><\/p>\n<pre lang=javascript>\r\nimport { Selector, t } from 'testcafe';\r\nconst { ReactSelector } = require('testcafe-react-selectors');\r\n\r\nclass mainPage {\r\n    constructor() {\r\n        this.title = Selector('a');\r\n        this.resume = ReactSelector('LinkAnchor')\r\n        this.name = Selector('input[id=name]')\r\n        this.email = Selector('input[id=email]')\r\n        this.phone = Selector('input[id=phone]')\r\n        this.headline = Selector('input[id=headline]')\r\n        this.objective = Selector('textarea[id=objective]')\r\n        this.skills = Selector('input[id=skills]')\r\n        this.languages = Selector('input[id=lang]')\r\n        this.college = ReactSelector('EducationForm').findReact('Input').withProps('id', 'college')\r\n        this.degree = ReactSelector('EducationForm').findReact('Input').withProps('id', 'degree')\r\n        this.fromDateEdu = ReactSelector('EducationForm').findReact('Input').withProps('id', 'from')\r\n        this.toDateEdu = ReactSelector('EducationForm').findReact('Input').withProps('id', 'to')\r\n        this.educationSubmit = ReactSelector('EducationForm').findReact('Button').withProps('children', 'Submit')\r\n        this.redirect = Selector('h3')\r\n        this.position = ReactSelector('ExperienceForm').findReact('Input').withProps('id', 'position')\r\n        this.company = ReactSelector('ExperienceForm').findReact('Input').withProps('id', 'company')\r\n        this.fromDateExp = ReactSelector('ExperienceForm').findReact('Input').withProps('id', 'from')\r\n        this.toDateExp = ReactSelector('ExperienceForm').findReact('Input').withProps('id', 'to')\r\n        this.responsibility = ReactSelector('ExperienceForm').findReact('Input').withProps('id', 'responsible')\r\n        this.experienceSubmit = ReactSelector('ExperienceForm').findReact('Button').withProps('children', 'Submit')\r\n    }\r\n\r\n    \/\/ click the resume button for the given link\r\n    async clickResumeButton(link) {\r\n        await t.click(this.resume.withProps('children', link))\r\n    };\r\n\r\n    \/\/ fills basic details\r\n    async fillBasicDetails(name, email, phone, headline, obj, skills, lang) {\r\n        await t\r\n            .typeText(await this.name, name)\r\n            .typeText(await this.email, email)\r\n            .typeText(await this.phone, phone)\r\n            .typeText(await this.headline, headline)\r\n            .typeText(await this.objective, obj)\r\n            .typeText(await this.skills, skills)\r\n            .typeText(await this.languages, lang)\r\n    }\r\n\r\n    \/\/ fill the education details in the page\r\n    async fillEducationDetails(educationDetails) {\r\n        await t\r\n            .typeText(await this.college, educationDetails.college)\r\n            .typeText(await this.degree, educationDetails.degree)\r\n            .typeText(await this.fromDateEdu, educationDetails.fromDateEdu)\r\n            .typeText(await this.toDateEdu, educationDetails.toDateEdu)\r\n            .click(await this.educationSubmit)\r\n    }\r\n\r\n    \/\/ fills the experience details \r\n    async fillExperienceDetails(experienceDetails) {\r\n        await t\r\n            .typeText(await this.position, experienceDetails.position)\r\n            .typeText(await this.company, experienceDetails.company)\r\n            .typeText(await this.fromDateExp, experienceDetails.fromDateExp)\r\n            .typeText(await this.toDateExp, experienceDetails.toDateExp)\r\n            .typeText(await this.responsibility, experienceDetails.responsibility)\r\n            .click(await this.experienceSubmit)\r\n    }\r\n}\r\n\r\nexport default new mainPage();\r\n<\/pre>\n<p>In the above page, I have added the following:<\/p>\n<li><a href=\"https:\/\/testcafe.io\/documentation\/402666\/reference\/test-api\/selector\">Selector<\/a> and <a href=\"https:\/\/github.com\/DevExpress\/testcafe-react-selectors\">ReactSelectors<\/a> are used in the test in the mainPage class. TestCafe provides <a href=\"https:\/\/github.com\/DevExpress\/testcafe-react-selectors\">ReactSelectors<\/a> plugin which provides selector extensions which helps to navigate a component structure and select component by name and state. The ReactSelector function takes in a root component name. You can use findReact() method to select the subcomponent or the component&#8217;s children <\/li>\n<li>different page methods which will be used in our tests<\/li>\n<li>defined different page actions using Test API to fill up the Education and Experience fields. To do this, different API functions such as <a href=\"https:\/\/testcafe.io\/documentation\/402674\/reference\/test-api\/testcontroller\/typetext\">.typeText()<\/a>, <a href=\"https:\/\/testcafe.io\/documentation\/402702\/reference\/test-api\/testcontroller\/expect\">.expect()<\/a>, and <a href=\"https:\/\/testcafe.io\/documentation\/402710\/reference\/test-api\/testcontroller\/click\">.click()<\/a> were used.<\/li>\n<p>Similarly, the page methods for redirect page are to verify if the contents are displayed correctly.<\/p>\n<p><em><strong>redirectPage.js<\/strong><\/em><\/p>\n<pre lang=javascript>\r\nconst { ReactSelector } = require('testcafe-react-selectors');\r\n\r\nexport default class redirect {\r\n    constructor() {\r\n        this.resume = ReactSelector('Resume')\r\n        this.educationView = ReactSelector('EducationView')\r\n        this.experienceView = ReactSelector('ExperienceForm')\r\n    }\r\n\r\n    \/\/ resume with specific name\r\n    async checkName(name) {\r\n        return this.resume.withProps('name', name)\r\n    };\r\n\r\n    \/\/ check education details\r\n    async checkEducationDetails(educationDetails) {        \r\n        return this.educationView.withProps(educationDetails)\r\n    }\r\n\r\n    \/\/ check experience details\r\n    async checkExperienceDetails(Experiencedetails) {\r\n        return this.experienceView.withProps(Experiencedetails)\r\n    }\r\n\r\n};\r\n<\/pre>\n<h3>Complete E2E Test<\/h3>\n<p>Now our test needs to be extended to make use of the methods in the page objects. By importing and accessing its selectors, I can now use this page model in the e2e test.<\/p>\n<p>I have added different tests for filling in personal, education and experience details and asserting the contents. I first imported all the page object classes needed, such as mainPage.js, redirectPage.js, as well as the config and data files. If you notice, I have also created a data folder to store data-specific information. With this in place, we can access our selectors through the page model&#8217;s properties and our test becomes like this<\/p>\n<pre lang=javascript>\r\nimport mainPage from '..\/pages\/mainPage';\r\nimport redirectPage from '..\/pages\/redirectPage';\r\nconst data = require('..\/data\/mainPageData');\r\nimport config from '..\/config\/config'\r\n\r\nfixture`E2E Fixture - Building a resume`\r\n      .page`${config.testURL}`;\r\n\r\n\/\/ page header test\r\ntest('Assert main page header', async t => {         \r\n      await t.expect(await mainPage.title.innerText).eql(`${data.basicInfo.title}`);\r\n});\r\n\r\n\/\/ fill the education and experience details page\r\ntest('Fill the education and experience details', async t => {\r\n      await mainPage.fillBasicDetails(data.basicInfo.name, data.basicInfo.email, data.basicInfo.phone, data.basicInfo.headline, data.basicInfo.objective, data.basicInfo.skills, data.basicInfo.languages)    \r\n      await mainPage.fillEducationDetails(data.educationDetails)     \r\n      await mainPage.fillExperienceDetails(data.experienceDetails)\r\n      await mainPage.clickResumeButton('Resume')      \r\n      const name = await redirectPage.checkRedirectName(data.basicInfo.name);\r\n      await t.expect(name.exists).ok();     \r\n      \/\/ check that we have the correct education details\r\n      const educationDetails = await redirectPage.checkEducationDetails({\r\n            college: data.educationDetails.college,\r\n            degree: data.educationDetails.degree,\r\n            from: data.educationDetails.fromDateEdu,\r\n            to: data.educationDetails.toDateEdu\r\n      })           \r\n      await t.expect(educationDetails.exists).ok()\r\n      \/\/ check that we have the correct experience details\r\n      const experienceDetails = await redirectPage.checkExperienceDetails({\r\n            position: data.experienceDetails.position,\r\n            company: data.experienceDetails.company,\r\n            from: data.experienceDetails.fromDateExp,\r\n            to: data.experienceDetails.toDateExp,\r\n            responsible: data.experienceDetails.responsibility\r\n      })    \r\n      await t.expect(experienceDetails.exists).ok()\r\n});\r\n<\/pre>\n<p>Now, run the test and view the Test Results. There are many ways to run a test in TestCafe. This time I have added the testcafe command to the <a href=\"https:\/\/docs.npmjs.com\/cli\/v7\/using-npm\/scripts\">scripts<\/a> section in package.json as shown below<\/p>\n<pre lang=javascript>\r\n\"scripts\": {\r\n    \"test-resume\": \"testcafe chrome .\/tests\/E2ETest.js\/\"\r\n}\r\n<\/pre>\n<p><code>$ npm run test-resume<\/code><\/p>\n<figure id=\"attachment_15477\" aria-describedby=\"caption-attachment-15477\" style=\"width: 946px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/result_package-1.png\" data-rel=\"lightbox-image-4\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/result_package-1.png\" alt=\"\" width=\"946\" height=\"285\" class=\"size-full wp-image-15477\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/result_package-1.png 946w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/result_package-1-300x90.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/result_package-1-768x231.png 768w\" sizes=\"auto, (max-width: 946px) 100vw, 946px\" \/><\/a><figcaption id=\"caption-attachment-15477\" class=\"wp-caption-text\">Test Output<\/figcaption><\/figure>\n<h3>Running Tests using CLI commands<\/h3>\n<p>TestCafe supports modern browsers and automatically detects the browsers installed on your machine. Listing out few CLI commands<\/p>\n<p>1. Use below command to view the list of all available browsers<\/p>\n<p><code>testcafe --list-browsers<\/code><\/p>\n<p>2. Use below command to run this test on selected browsers<\/p>\n<p><code>testcafe firefox, chrome, safari .\/tests\/E2ETest.js<\/code><\/p>\n<p>In this case, testcafe will open three instances together in three different browsers.<\/p>\n<p>3. Running on Google Chrome headless<\/p>\n<p><code>testcafe \"chrome:headless\" .tests\/E2ETest.js<\/code><\/p>\n<p>4. Parallel Test Execution against multiple browsers<\/p>\n<p><code>testcafe -c 1 safari,chrome .\/tests\/E2ETest.js<\/code><\/p>\n<p>5. Set Test Execution speed<\/p>\n<p><code>testcafe chrome .\/tests\/E2ETest.js  --speed 0.5<\/code><\/p>\n<h3>Debugging the Tests<\/h3>\n<p>There are different ways to debug the TestCafe Tests. One way is <a href=\"https:\/\/testcafe.io\/documentation\/402639\/reference\/command-line-interface#-d---debug-mode\">Debug mode<\/a>. Using this mode, test execution is paused before the action or assertion so that you can open the developer tools and debug the state of the element and page. The execution is halted and you can resume test execution or skip to the next action or assertion.<\/p>\n<figure id=\"attachment_15475\" aria-describedby=\"caption-attachment-15475\" style=\"width: 900px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/debug-mode-1.png\" data-rel=\"lightbox-image-5\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/debug-mode-1-1024x52.png\" alt=\"\" width=\"900\" height=\"46\" class=\"size-large wp-image-15475\" srcset=\"https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/debug-mode-1-1024x52.png 1024w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/debug-mode-1-300x15.png 300w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/debug-mode-1-768x39.png 768w, https:\/\/qxf2.com\/blog\/wp-content\/uploads\/2021\/08\/debug-mode-1.png 1275w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/a><figcaption id=\"caption-attachment-15475\" class=\"wp-caption-text\">Debug Mode<\/figcaption><\/figure>\n<p>We can also enable Debug mode On Fail using CLI option, which will automatically enter into Debug mode when a test fails using below command<\/p>\n<p><code>testcafe chrome .\/tests\/E2ETest.js --debug-on-fail<\/code><\/p>\n<hr\/>\n<p>That&#8217;s all folks !! I have only touched the basics of what can be done with TestCafe, if you want more information on TestCafe you can visit <a href=\"https:\/\/testcafe.io\/documentation\/402635\/getting-started\">official documentation<\/a> <\/p>\n<hr\/>\n<h3>References:<\/h3>\n<p>1. <a href=\"https:\/\/devexpress.github.io\/testcafe\/\">TestCafe documentation<\/a><br \/>\n2. <a href=\"https:\/\/medium.com\/xebia-france\/end-to-end-web-testing-with-testcafe-766ddbd74924\">End to End testing with TestCafe<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>For one of our clients, TestCafe has been recently used for end-to-end(e2e) UI automation. TestCafe has a number of significant features, including simple setup, no web driver installation, support for all main operating systems, various browser support, reporting and HTTP Mocking. In this article, I&#8217;d like to show how to create UI tests with TestCafe, as well as how to [&hellip;]<\/p>\n","protected":false},"author":16,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[291,290,292],"tags":[],"class_list":["post-14824","post","type-post","status-publish","format-standard","hentry","category-nodejs","category-react","category-testcafe"],"_links":{"self":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/14824","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/users\/16"}],"replies":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/comments?post=14824"}],"version-history":[{"count":91,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/14824\/revisions"}],"predecessor-version":[{"id":15565,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/14824\/revisions\/15565"}],"wp:attachment":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/media?parent=14824"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/categories?post=14824"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/tags?post=14824"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}