{"id":18750,"date":"2023-01-26T05:00:00","date_gmt":"2023-01-26T04:00:00","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=18750"},"modified":"2024-01-31T18:11:04","modified_gmt":"2024-01-31T17:11:04","slug":"playwright-why-should-you-get-interested-in-the-microsoft-tool","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/en\/playwright-why-should-you-get-interested-in-the-microsoft-tool\/","title":{"rendered":"Playwright \u2013 why should you get interested in the Microsoft tool?"},"content":{"rendered":"\n<p>For a while now I have been using one of the best growing tools for automating UI tests (but not limited to), which is Playwright. In this article, I would like to show you how to start using Playwright, why it is worth it, and what automated tests in Playwright look like in practice.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Playwright beginnings<\/strong><\/h2>\n\n\n\n<p>Playwright was released by Microsoft in 2020. It is an open-source tool created by Andrey Lushnikov, who previously worked on another popular automation product, which is Puupeteer, developed by Google. Playwright is used to automate actions in the browser, but also allows API automation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Playwright&#8217;s strengths<\/strong><\/h2>\n\n\n\n<p>The tool has numerous interesting advantages, which is why it is worthy of your interest. I will outline them below.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Auto Wait<\/strong><\/h3>\n\n\n\n<p>If you have ever worked on automatic UI tests, you probably know what a problem it can be to handle waits for various dynamic elements located on the page. For Selenium WebDriver, it is recommended to use the so-called Explicit wait, which should solve this problem. However, finding the right wait is not that easy sometimes. It affects how much JavaScript and asynchronous operations are used on the site.<\/p>\n\n\n\n<p>Playwright uses the so-called auto-wait mechanism. What does it mean? In most situations, we do not need to add additional wait for elements, as Playwright itself waits the elements and actions by default. Of course, in a more complex situation, when we need to wait for an element, Playwright provides methods that can be used.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Using different programming languages<\/strong><\/h3>\n\n\n\n<p>Currently, Playwright is supported for several popular programming languages. They are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Java,<\/li>\n\n\n\n<li>C#,<\/li>\n\n\n\n<li>JS\/TS,<\/li>\n\n\n\n<li>Python.<\/li>\n<\/ul>\n\n\n\n<p>As a result, the solution in different language versions is finding wider use on the market.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Documentation<\/strong><\/h3>\n\n\n\n<p>Playwright\u2019s documentation is excellent. The use of methods is described on the basis of practical examples, which help to take advantage of the tool&#8217;s capabilities. Also, the documentation that appears while invoking a method in the IDE is often enough to make real use of it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Popularity of the tool<\/strong><\/h2>\n\n\n\n<p>It is worth noting, that the number of Playwright users is growing, as you can see in the graph below.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large is-resized\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-1-2.png\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-1-2-1024x535.png\" alt=\"Ranking of framework usage in terms of the audience size\" class=\"wp-image-18752\" width=\"838\" height=\"437\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-1-2-1024x535.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-1-2-300x157.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-1-2-768x401.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-1-2.png 1445w\" sizes=\"(max-width: 838px) 100vw, 838px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 1 <a href=\"https:\/\/2021.stateofjs.com\/en-US\/libraries\/testing\/\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Ranking of framework usage in terms of the audience size<\/a><\/figcaption><\/figure>\n\n\n\n<p>Playwright, among the libraries used in tests, improved its score from 3% usage in the community in 2020 to 10% in 2021. This ranking relates to the Playwright JS\/TS version, however in my opinion, it is a noticeable popularity jump, that will be also likely noted for other language versions of the tool.<\/p>\n\n\n\n<p>Awareness of Playwright in the community has also improved, from 19% in 2020 to 34% a year later.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-2-2.png\"><img decoding=\"async\" width=\"1024\" height=\"533\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-2-2-1024x533.png\" alt=\"Ranking on tool knowledge and awareness\" class=\"wp-image-18754\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-2-2-1024x533.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-2-2-300x156.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-2-2-768x399.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-2-2.png 1421w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 2 <a href=\"https:\/\/2021.stateofjs.com\/en-US\/libraries\/testing\/\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Ranking on tool knowledge and awareness<\/a><\/figcaption><\/figure>\n\n\n\n<p>While choosing the tools, it is worth paying attention to their popularity and positive reception by the community, which is something that Playwright has already established for itself.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>New versions delivery frequency<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"721\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-3-2-1024x721.png\" alt=\"Playwright \u2013 new versions delivery frequency\" class=\"wp-image-18757\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-3-2-1024x721.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-3-2-300x211.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-3-2-768x541.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-3-2.png 1273w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Fig. 3 Playwright \u2013 new versions delivery frequency<\/figcaption><\/figure>\n\n\n\n<p>It is undoubtedly worth mentioning how fast Playwright is evolving. Every two weeks or so, a new version is added with some kind of improvements (you can check the frequency of changes on GitHub).<\/p>\n\n\n\n<p>When choosing a potential tool, I always pay attention to the size of the community behind it. In this case, it is Microsoft and its employees, but also a growing number of engaged people outside the company.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Browsers supported by Playwright<\/strong><\/h3>\n\n\n\n<p>Currently Playwright supports all of the most popular web browsers, such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Chrome,<\/li>\n\n\n\n<li>Edge,<\/li>\n\n\n\n<li>Firefox,<\/li>\n\n\n\n<li>Opera,<\/li>\n\n\n\n<li>Safari.<\/li>\n<\/ul>\n\n\n\n<p>Also, solutions based on Electron have the experimental support for the JS\/TS versions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Projects using Playwright<\/strong><\/h3>\n\n\n\n<p>More and more projects are admitting\/bragging, that they use the tool in their UI tests. They are popular open-source initiatives, but also commercial solutions. A few examples below:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"274\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-4-1-1024x274.png\" alt=\"Example of a project using Playwright\" class=\"wp-image-18760\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-4-1-1024x274.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-4-1-300x80.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-4-1-768x205.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-4-1.png 1301w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Fig. 4 <a href=\"https:\/\/github.com\/adobe\/spectrum-web-components\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Example of a project using Playwright<\/a><\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-6.png\"><img decoding=\"async\" width=\"1024\" height=\"328\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-6-1024x328.png\" alt=\"Example of a project using Playwright\" class=\"wp-image-18762\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-6-1024x328.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-6-300x96.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-6-768x246.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-6.png 1097w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 5 <a href=\"https:\/\/github.com\/mui\/material-ui\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Example of a project using Playwright<\/a><\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Playwright&#8217;s weaknesses<\/strong><\/h2>\n\n\n\n<p>As with any tool, there are times when a method does not work properly in a particular situation. As a Playwright user, I encountered problems only occasionally, but always managed to find a solution. However, I cannot exclude the possibility that in some specific case we may come across circumstances in which the solution will not be found. In that case, it is worth talking to the creators of the tool &#8211; they are available and are actively taking part in responding to the reports on GitHub.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Let&#8217;s write the first test!<\/strong><\/h2>\n\n\n\n<p>After a brief, theoretical introduction, let&#8217;s move on to writing the first automated test in this tool.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Implementation of the automated test<\/strong><\/h3>\n\n\n\n<p>The test that I have prepared will consist of automating a simple test case for a store created for the test purpose. The test scenario looks like this:<\/p>\n\n\n\n<ol class=\"wp-block-list\" type=\"1\">\n<li>Go to the website: seleniumsklep.pl<\/li>\n\n\n\n<li>Click on the selected product based on its name.<\/li>\n\n\n\n<li>Go to the cart and check if the price in the summary section matches the price in the product details.<\/li>\n<\/ol>\n\n\n\n<p>Go to Visual Studio and start by creating a package library project. This is the preferred type of project. The next step is to add the needed packages using NuGet packages. In our case:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Playwright,<\/li>\n\n\n\n<li>Playwright Nunit.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-7.png\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-7.png\" alt=\"Adding needed packages\" class=\"wp-image-18765\" width=\"672\" height=\"461\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-7.png 672w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-7-300x206.png 300w\" sizes=\"(max-width: 672px) 100vw, 672px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 6 Adding needed packages<\/figcaption><\/figure>\n\n\n\n<p>Playwright Nunit includes useful classes, which help the tools work together, e.g. in the context of running tests concurrently.<\/p>\n\n\n\n<p>The next step is to create the necessary catalogs, to organize the solution from the beginning.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-8.png\"><img decoding=\"async\" width=\"318\" height=\"152\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-8.png\" alt=\"Creating catalogs\" class=\"wp-image-18768\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-8.png 318w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-8-300x143.png 300w\" sizes=\"(max-width: 318px) 100vw, 318px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 7 Creating catalogs<\/figcaption><\/figure>\n\n\n\n<p>First, create the \u201cPages\u201d catalog, in which all page objects needed for the automated test will be placed. The next essential catalog, which needs to be added, is the \u201cTests\u201d catalog.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-9.png\"><img decoding=\"async\" width=\"1024\" height=\"614\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-9-1024x614.png\" alt=\"code\" class=\"wp-image-18771\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-9-1024x614.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-9-300x180.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-9-768x461.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-9.png 1229w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>In the BaseSetup class, there are two methods that will be used in all tests inheriting from this class. The \u201cSetup()\u201d method at the beginning initializes the Playwright object. It should be done in line 17. Before it, declare three fields that will be needed in further work.<\/p>\n\n\n\n<p>These fields are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Playwright,<\/li>\n\n\n\n<li>Browser,<\/li>\n\n\n\n<li>Context.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-10.png\"><img decoding=\"async\" width=\"315\" height=\"65\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-10.png\" alt=\"code\" class=\"wp-image-18773\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-10.png 315w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-10-300x62.png 300w\" sizes=\"(max-width: 315px) 100vw, 315px\" \/><\/a><\/figure>\n\n\n\n<p>In the Setup() method, initialize the Browser field, which should be defined to set which browser will be used in the tests. If the Headless parameter is not entered, you will not be able to see the course of the tests &#8211; they would run without the graphical mode. It is a helpful option to avoid screen pop-ups with tests.<\/p>\n\n\n\n<p>Another thing that can be set here is the Channel. Playwright allows you to decide which version of Chrome will be used in our automated test. In a very simple way, you can define that you want to use e.g., Chrome beta or Edge in this version. It can be very useful for checking the operation of our application with the upcoming browser versions.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-11.png\"><img decoding=\"async\" width=\"639\" height=\"98\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-11.png\" alt=\"code\" class=\"wp-image-18775\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-11.png 639w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-11-300x46.png 300w\" sizes=\"(max-width: 639px) 100vw, 639px\" \/><\/a><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-12.png\"><img decoding=\"async\" width=\"709\" height=\"97\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-12.png\" alt=\"code\" class=\"wp-image-18777\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-12.png 709w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-12-300x41.png 300w\" sizes=\"(max-width: 709px) 100vw, 709px\" \/><\/a><\/figure>\n\n\n\n<p>Next, we move on to defining the Context. What is Context? Initialize the Context field, which allows session handling of a given browser. What distinguishes Playwright is that it can handle more than one browser session at a time. Additionally, each screen has a &#8220;Focus&#8221;, so you if you want to perform an action, you do not have to switch between them.<\/p>\n\n\n\n<p>Also in the Browser object, you could immediately use the NewContextAsync() method, but Playwright&#8217;s creators recommend that you create a context every time. Each &#8220;Context&#8221; stores a separate cache and cookies.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-13.png\"><img decoding=\"async\" width=\"753\" height=\"204\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-13.png\" alt=\"code\" class=\"wp-image-18779\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-13.png 753w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-13-300x81.png 300w\" sizes=\"(max-width: 753px) 100vw, 753px\" \/><\/a><\/figure>\n\n\n\n<p>The next step is defining the so-called Tracing. This method allows collecting logs while the automated test is running. We can trace:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Screenshots \u2013 creating a screenshot after each action,<\/li>\n\n\n\n<li>Snapshots \u2013 collecting DOM contents after each action and collecting information from the network, so all requests and information from the console,<\/li>\n\n\n\n<li>Sources \u2013 collecting information on which code line was activated in a particular moment.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Automated test source code<\/strong><\/h2>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-14.png\"><img decoding=\"async\" width=\"836\" height=\"466\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-14.png\" alt=\"code\" class=\"wp-image-18781\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-14.png 836w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-14-300x167.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-14-768x428.png 768w\" sizes=\"(max-width: 836px) 100vw, 836px\" \/><\/a><\/figure>\n\n\n\n<p>Moving on to the automated test source code, begin with defining the method name. In this case it is<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; gutter: false; title: ; notranslate\" title=\"\">\nEnterToShop_AddProductToBasket_CheckProductPriceInSummary()\n<\/pre><\/div>\n\n\n<p>Define \u201coption\u201d as a parameter, so that the name of the article chosen by the test can be passed dynamically. The \u201cTestCase\u201d attribute responds to it. Each next line in a form of the TestCase attribute with an argument, defines the next test case.<\/p>\n\n\n\n<p>Begin with defining the page object. It is responsible for controlling a single tab in the browser (associated with the context, of course).<\/p>\n\n\n\n<p>HomePage<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-15.png\"><img decoding=\"async\" width=\"965\" height=\"543\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-15.png\" alt=\"code\" class=\"wp-image-18783\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-15.png 965w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-15-300x169.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-15-768x432.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-15-555x312.png 555w\" sizes=\"(max-width: 965px) 100vw, 965px\" \/><\/a><\/figure>\n\n\n\n<p>Define page object for the HomePage. The site itself contains a products of interest list.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-16.png\"><img decoding=\"async\" width=\"1024\" height=\"524\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-16-1024x524.png\" alt=\"The site with the products of interest\" class=\"wp-image-18785\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-16-1024x524.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-16-300x154.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-16-768x393.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-16-1536x786.png 1536w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-16.png 1571w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 8 The site with the products of interest<\/figcaption><\/figure>\n\n\n\n<p>Start by creating a constructor for this class. The constructor will take the page object as a parameter, which contains methods to control actions related to this page. The next step is defining the ProductTitles fields with a selector corresponding to the name of each product.<\/p>\n\n\n\n<p>You still need a SelectDefineProduct method, which is responsible for clicking on a given product based on its name.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-17.png\"><img decoding=\"async\" width=\"910\" height=\"298\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-17.png\" alt=\"code\" class=\"wp-image-18788\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-17.png 910w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-17-300x98.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-17-768x251.png 768w\" sizes=\"(max-width: 910px) 100vw, 910px\" \/><\/a><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-18.png\"><img decoding=\"async\" width=\"984\" height=\"137\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-18.png\" alt=\"code\" class=\"wp-image-18790\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-18.png 984w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-18-300x42.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-18-768x107.png 768w\" sizes=\"(max-width: 984px) 100vw, 984px\" \/><\/a><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>QuerySelectorAllAsync method \u2013 allows downloading all of the elements on the basis of a given selector,<\/li>\n\n\n\n<li>InnerText method \u2013 allows downloading the text from a given element,<\/li>\n\n\n\n<li>ClickAsync method \u2013 clicks on an element of your choice.<\/li>\n<\/ul>\n\n\n\n<p>An interesting Playwright feature is that most of the used methods have additional uses, that expand the possibilities.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-19.png\"><img decoding=\"async\" width=\"1024\" height=\"183\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-19-1024x183.png\" alt=\"\" class=\"wp-image-18792\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-19-1024x183.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-19-300x54.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-19-768x137.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-19.png 1219w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>One of them is the ClickAsync method. It allows defining how many times you want to click or determine the wait after the click.<\/p>\n\n\n\n<p>There are a lot of methods, which can be used on a given object. Here are some of them:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-20.png\"><img decoding=\"async\" width=\"566\" height=\"302\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-20.png\" alt=\"Choice of methods available\" class=\"wp-image-18794\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-20.png 566w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-20-300x160.png 300w\" sizes=\"(max-width: 566px) 100vw, 566px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 9 Choice of methods available<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Waits<\/strong><\/h2>\n\n\n\n<p>As I have mentioned, for most of the operations there is no need to add any additional waits. However, if the site is more complicated and adding the wait for an element is desired, you can use these methods.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-21.png\"><img decoding=\"async\" width=\"617\" height=\"306\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-21.png\" alt=\"Methods of waits for an element\" class=\"wp-image-18796\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-21.png 617w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-21-300x149.png 300w\" sizes=\"(max-width: 617px) 100vw, 617px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 10 Methods of waits for an element<\/figcaption><\/figure>\n\n\n\n<p>You can wait for such a pop-up or a specific request shows up. This method is useful when switching between pages and you need to wait longer for the page to load.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-22.png\"><img decoding=\"async\" width=\"1024\" height=\"508\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-22-1024x508.png\" alt=\"code\" class=\"wp-image-18799\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-22-1024x508.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-22-300x149.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-22-768x381.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-22.png 1065w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>But back to the test code.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-23.png\"><img decoding=\"async\" width=\"1024\" height=\"288\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-23-1024x288.png\" alt=\"code\" class=\"wp-image-18802\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-23-1024x288.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-23-300x84.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-23-768x216.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-23.png 1097w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>The next step in the line 18 is to use the GoToAsync() method, which will go to the specified page. Save the page address in a separate class TestSettings.EnvUrl. Values such as the address to the environment are best stored in separate classes\/files. The GoToAsync method also has an ability to add an additional wait to load the page. The page address should be saved in the property of TestSettings class.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-24.png\"><img decoding=\"async\" width=\"761\" height=\"190\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-24.png\" alt=\"code\" class=\"wp-image-18804\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-24.png 761w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-24-300x75.png 300w\" sizes=\"(max-width: 761px) 100vw, 761px\" \/><\/a><\/figure>\n\n\n\n<p>After this step in the test, go to invoking the SelectDefineProduct(option) method. It is the one, that clicks on a specific product. Next, add the DetailsProdcutPage class, where I start by creating the fields needed for the methods, I will be using in the later stages of this test.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-25.png\"><img decoding=\"async\" width=\"624\" height=\"319\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-25.png\" alt=\"The AddToBasketBtn field corresponds to the button on the page\" class=\"wp-image-18806\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-25.png 624w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-25-300x153.png 300w\" sizes=\"(max-width: 624px) 100vw, 624px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 11 The AddToBasketBtn field corresponds to the button on the page<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-26.png\"><img decoding=\"async\" width=\"864\" height=\"266\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-26.png\" alt=\"The ProceedtoCheckoutBtn corresponds to the button on the page\" class=\"wp-image-18808\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-26.png 864w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-26-300x92.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-26-768x236.png 768w\" sizes=\"(max-width: 864px) 100vw, 864px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 12 The ProceedtoCheckoutBtn corresponds to the button on the page<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-27.png\"><img decoding=\"async\" width=\"247\" height=\"59\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-27.png\" alt=\"The CurrentPrice field corresponds to the current price of the product, which is located on the product details page\" class=\"wp-image-18810\"\/><\/a><figcaption class=\"wp-element-caption\">Fig. 13 The CurrentPrice field corresponds to the current price of the product, which is located on the product details page<\/figcaption><\/figure>\n\n\n\n<p>Next, add a constructor that through the argument will take the page object, allowing to perform actions related to the page.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-28.png\"><img decoding=\"async\" width=\"963\" height=\"543\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-28.png\" alt=\"code\" class=\"wp-image-18812\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-28.png 963w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-28-300x169.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-28-768x433.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-28-555x312.png 555w\" sizes=\"(max-width: 963px) 100vw, 963px\" \/><\/a><\/figure>\n\n\n\n<p>Define the AddToBasketBtn fields. To add and element in Playwright, use the _page.Locator(\u201cselector_name\u201d) method, which allows getting access to the element in Playwright on the basis of the specified selector. The next element, defined in the class, is the equivalent of the \u201cProceed to checkout\u201d button.<\/p>\n\n\n\n<p>The following field, needed for the test to work, is the \u201cCurrentPrice\u201d field. It allows retrieving the current price for the item.<\/p>\n\n\n\n<p>After defining all the fields required for this test, move on to defining two simple methods:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>AddProductToCart() method contains the click on the add to cart button,<\/li>\n\n\n\n<li>ProceedToCheckout() method is analogous to the click on the \u201cProceed to Checkout\u201d button.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-29.png\"><img decoding=\"async\" width=\"682\" height=\"151\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-29.png\" alt=\"code\" class=\"wp-image-18814\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-29.png 682w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-29-300x66.png 300w\" sizes=\"(max-width: 682px) 100vw, 682px\" \/><\/a><\/figure>\n\n\n\n<p>Define the GetCurrentProductPrice method, which is responsible for retrieving the current value of the price from the details of this product. You still need to add the ParseEuroToDouble method. It is a method that applies a simple so-called parsing, which, in this case, removes the \u20ac symbol from the text. In this case, it needs to be done, because the element is so defined in the HTML of the page.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-30.png\"><img decoding=\"async\" width=\"521\" height=\"78\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-30.png\" alt=\"code\" class=\"wp-image-18816\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-30.png 521w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-30-300x45.png 300w\" sizes=\"(max-width: 521px) 100vw, 521px\" \/><\/a><\/figure>\n\n\n\n<p>Of course, this is one way, you can approach it in many different manners. Another idea could be to use some regular expression to retrieve a numeric value from the text. The ParseEuroToDouble looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-31.png\"><img decoding=\"async\" width=\"1024\" height=\"201\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-31-1024x201.png\" alt=\"code\" class=\"wp-image-18819\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-31-1024x201.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-31-300x59.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-31-768x151.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-31.png 1065w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>Go back to the test source code. Invoke the methods, which allow adding product to the cart.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-32.png\"><img decoding=\"async\" width=\"454\" height=\"46\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-32.png\" alt=\"code\" class=\"wp-image-18821\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-32.png 454w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-32-300x30.png 300w\" sizes=\"(max-width: 454px) 100vw, 454px\" \/><\/a><\/figure>\n\n\n\n<p>In the next line initialize the summaryCartPage object. It is an object representing the SummaryCartPage class.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-33.png\"><img decoding=\"async\" width=\"647\" height=\"274\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-33.png\" alt=\"code\" class=\"wp-image-18823\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-33.png 647w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-33-300x127.png 300w\" sizes=\"(max-width: 647px) 100vw, 647px\" \/><\/a><\/figure>\n\n\n\n<p>In this class, apart from defining the constructor, add a field, which corresponds to the amount element on the cart summary.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-34.png\"><img decoding=\"async\" width=\"421\" height=\"123\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-34.png\" alt=\"total VAT incl.\" class=\"wp-image-18825\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-34.png 421w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-34-300x88.png 300w\" sizes=\"(max-width: 421px) 100vw, 421px\" \/><\/a><\/figure>\n\n\n\n<p>Here I also use the ParseEuroToDouble method, because they are comparable in this situation. After adding this method, return to the test code and compare the value of the currentTotalPrice variable with the productPrice. This comparison uses the FluentAssertations library, which is added via NuGet. It is an assertion library that allows more readable record, than the standard methos from the Assert class. Moving on to the test run. It can be done either using a dotnet test from the VS level or from the VS and R# level.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-35.png\"><img decoding=\"async\" width=\"640\" height=\"275\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-35.png\" alt=\"Test run\" class=\"wp-image-18827\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-35.png 640w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-35-300x129.png 300w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 14 Test run<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-36.png\"><img decoding=\"async\" width=\"870\" height=\"295\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-36.png\" alt=\"code\" class=\"wp-image-18829\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-36.png 870w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-36-300x102.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Ryc.-36-768x260.png 768w\" sizes=\"(max-width: 870px) 100vw, 870px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Summary<\/strong><\/h2>\n\n\n\n<p>In this article, I have showcased Playwright in practice and demonstrated a few fetures that may interest you and convince you to try working with this tool.<\/p>\n\n\n\n<p>In the next part, I would like to present how to use a helpful feature, which is Trace Viewer that allows to view the collected test logs. I will also present other interesting features of the tool.<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/sii-poland\/PlaywrightCSharp\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >The code can be found in the prepared repository.<\/a><\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;18750&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;9&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;5\\\/5 ( votes: 9)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Playwright \u2013 why should you get interested in the Microsoft tool?&quot;,&quot;width&quot;:&quot;139.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 139.5px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            5\/5 ( votes: 9)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>For a while now I have been using one of the best growing tools for automating UI tests (but not &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/en\/playwright-why-should-you-get-interested-in-the-microsoft-tool\/\">Continued<\/a><\/p>\n","protected":false},"author":215,"featured_media":19842,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":11,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1321],"tags":[1793,1706,1639,1603,1604,1590],"class_list":["post-18750","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-testing","tag-zalety-i-wady-en","tag-playwright-en","tag-przeglad-narzedzi-en","tag-playwright-2","tag-pros-and-cons","tag-tools"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/01\/Playwright-\u2013-dlaczego-warto-zainteresowac-sie-narzedziem-od-Microsoftu.jpg","category_names":["Testing"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/18750"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/users\/215"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/comments?post=18750"}],"version-history":[{"count":2,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/18750\/revisions"}],"predecessor-version":[{"id":26775,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/18750\/revisions\/26775"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media\/19842"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media?parent=18750"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/categories?post=18750"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/tags?post=18750"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}