{"componentChunkName":"component---src-templates-content-template-js","path":"/en/part5/end_to_end_testing","result":{"data":{"markdownRemark":{"html":"<div class=\"content\">\n<p>So far we have tested the backend as a whole on an API level using integration tests and tested some frontend components using unit tests.</p>\n<p>Next, we will look into one way to test the <a href=\"https://en.wikipedia.org/wiki/System_testing\">system as a whole</a> using <i>End to End</i> (E2E) tests.</p>\n<p>We can do E2E testing of a web application using a browser and a testing library. There are multiple libraries available. One example is <a href=\"http://www.seleniumhq.org/\">Selenium</a>, which can be used with almost any browser.\nAnother browser option is so-called <a href=\"https://en.wikipedia.org/wiki/Headless_browser\">headless browsers</a>, which are browsers with no graphical user interface. For example, Chrome can be used in headless mode.</p>\n<p>E2E tests are potentially the most useful category of tests because they test the system through the same interface as real users use.</p>\n<p>They do have some drawbacks too. Configuring E2E tests is more challenging than unit or integration tests. They also tend to be quite slow, and with a large system, their execution time can be minutes or even hours. This is bad for development because during coding it is beneficial to be able to run tests as often as possible in case of code <a href=\"https://en.wikipedia.org/wiki/Regression_testing\">regressions</a>.</p>\n<p>E2E tests can also be <a href=\"https://hackernoon.com/flaky-tests-a-war-that-never-ends-9aa32fdef359\">flaky</a>.\nSome tests might pass one time and fail another, even if the code does not change at all.</p>\n<p>Perhaps the two easiest libraries for End to End testing at the moment are <a href=\"https://playwright.dev/\">Playwright</a> and <a href=\"https://www.cypress.io/\">Cypress</a>.</p>\n<p>From the statistics on <a href=\"https://npmtrends.com/cypress-vs-playwright\">npmtrends.com</a> we can see that Playwright surpassed Cypress in download numbers during 2024, and its popularity continues to grow:</p>\n<picture><img src=\"/static/87e4862d9fdae02bf10ef09a105cb0ef/5a190/pwc.png\" alt=\"cypress vs playwright in npm trends\" srcset=\"/static/87e4862d9fdae02bf10ef09a105cb0ef/772e8/pwc.png 200w,\n/static/87e4862d9fdae02bf10ef09a105cb0ef/e17e5/pwc.png 400w,\n/static/87e4862d9fdae02bf10ef09a105cb0ef/5a190/pwc.png 800w,\n/static/87e4862d9fdae02bf10ef09a105cb0ef/c1b63/pwc.png 1200w,\n/static/87e4862d9fdae02bf10ef09a105cb0ef/29007/pwc.png 1600w,\n/static/87e4862d9fdae02bf10ef09a105cb0ef/2d86d/pwc.png 2578w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>This course has been using Cypress for years. Now our choice is Playwright.</p>\n<p>So <a href=\"https://playwright.dev/\">Playwright</a> is a newcomer to the End to End tests, which started to explode in popularity towards the end of 2023. Playwright is roughly on a par with Cypress in terms of ease of use. The libraries are slightly different in terms of how they work. Cypress is radically different from most libraries suitable for E2E testing, as Cypress tests are run entirely within the browser. Playwright's tests, on the other hand, are executed in the Node process, which is connected to the browser via programming interfaces.</p>\n<p>Now let's explore Playwright.</p>\n<h3>Initializing tests</h3>\n<p>Unlike the backend tests or unit tests done on the React front-end, End to End tests do not need to be located in the same npm project where the code is. Let's make a completely separate project for the E2E tests with the <em>npm init</em> command. Then install Playwright by running in the new project directory the command:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">npm init playwright@latest</code></pre></div>\n<p>The installation script will ask a few questions, answer them as follows:</p>\n<picture><img src=\"/static/b44d73b495d354aff353a99c18b905df/5a190/play0.png\" alt=\"answer: javascript, tests, false, true\" srcset=\"/static/b44d73b495d354aff353a99c18b905df/772e8/play0.png 200w,\n/static/b44d73b495d354aff353a99c18b905df/e17e5/play0.png 400w,\n/static/b44d73b495d354aff353a99c18b905df/5a190/play0.png 800w,\n/static/b44d73b495d354aff353a99c18b905df/e751c/play0.png 1123w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>Note that when installing Playwright your operating system may not support all of the browsers Playwright offers and you may see an error message like below:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">Webkit 18.0 (playwright build v2070) downloaded to /home/user/.cache/ms-playwright/webkit-2070\nPlaywright Host validation warning: \n╔══════════════════════════════════════════════════════╗\n║ Host system is missing dependencies to run browsers. ║\n║ Missing libraries:                                   ║\n║     libicudata.so.66                                 ║\n║     libicui18n.so.66                                 ║\n║     libicuuc.so.66                                   ║\n║     libjpeg.so.8                                     ║\n║     libwebp.so.6                                     ║\n║     libpcre.so.3                                     ║\n║     libffi.so.7                                      ║\n╚══════════════════════════════════════════════════════╝</code></pre></div>\n<p>If this is the case you can either specify specific browsers to test with <code class=\"language-text\">--project=</code> in your <em>package.json</em>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">    <span class=\"token string-property property\">\"test\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"playwright test --project=chromium --project=firefox\"</span><span class=\"token punctuation\">,</span></code></pre></div>\n<p>or remove the entry for any problematic browsers from your <em>playwright.config.js</em> file:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">  <span class=\"token literal-property property\">projects</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token comment\">// ...</span>\n    <span class=\"token comment\">//{</span>\n    <span class=\"token comment\">//  name: 'webkit',</span>\n    <span class=\"token comment\">//  use: { ...devices['Desktop Safari'] },</span>\n    <span class=\"token comment\">//},</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">]</span></code></pre></div>\n<p>Let's define an npm script for running tests and test reports in <em>package.json</em>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n  <span class=\"token string-property property\">\"scripts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string-property property\">\"test\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"playwright test\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string-property property\">\"test:report\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"playwright show-report\"</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>During installation, the following is printed to the console:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">And check out the following files:\n  - ./tests/example.spec.js - Example end-to-end test\n  - ./tests-examples/demo-todo-app.spec.js - Demo Todo App end-to-end tests\n  - ./playwright.config.js - Playwright Test configuration</code></pre></div>\n<p>that is, the location of a few example tests for the project that the installation has created.</p>\n<p>Let's run the tests:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">$ <span class=\"token function\">npm</span> <span class=\"token builtin class-name\">test</span>\n\n<span class=\"token operator\">></span> notes-e2e@1.0.0 <span class=\"token builtin class-name\">test</span>\n<span class=\"token operator\">></span> playwright <span class=\"token builtin class-name\">test</span>\n\n\nRunning <span class=\"token number\">6</span> tests using <span class=\"token number\">5</span> workers\n  <span class=\"token number\">6</span> passed <span class=\"token punctuation\">(</span><span class=\"token number\">3</span>.9s<span class=\"token punctuation\">)</span>\n\nTo <span class=\"token function\">open</span> last HTML report run:\n\n  npx playwright show-report</code></pre></div>\n<p>The tests pass. A more detailed test report can be opened either with the command suggested by the output, or with the npm script we just defined:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">npm run test:report</code></pre></div>\n<p>Tests can also be run via the graphical UI with the command:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">npm run test -- --ui</code></pre></div>\n<p>Sample tests in the file tests/example.spec.js look like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">// @ts-check</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> test<span class=\"token punctuation\">,</span> expect <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'@playwright/test'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'has title'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://playwright.dev/'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>\n  <span class=\"token comment\">// Expect a title \"to contain\" a substring.</span>\n  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toHaveTitle</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">Playwright</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'get started link'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'https://playwright.dev/'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Click the get started link.</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'link'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'Get started'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Expects page to have a heading with the name of Installation.</span>\n  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'heading'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'Installation'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>The first line of the test functions says that the tests are testing the page at <a href=\"https://playwright.dev/\">https://playwright.dev/</a>.</p>\n<h3>Testing our own code</h3>\n<p>Now let's remove the sample tests and start testing our own application.</p>\n<p>Playwright tests assume that the system under test is running when the tests are executed. Unlike, for example, backend integration tests, Playwright tests <i>do not start</i> the system under test during testing.</p>\n<p>Let's make an npm script for the <i>backend</i>, which will enable it to be started in testing mode, i.e. so that <i>NODE_ENV</i> gets the value <i>test</i>.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n  <span class=\"token string-property property\">\"scripts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string-property property\">\"start\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"cross-env NODE_ENV=production node index.js\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string-property property\">\"dev\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"cross-env NODE_ENV=development node --watch index.js\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string-property property\">\"test\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"cross-env NODE_ENV=test node --test\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string-property property\">\"lint\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"eslint .\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token comment\">// ...</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token string-property property\">\"start:test\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"cross-env NODE_ENV=test node --watch index.js\"</span></span>  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Let's start the frontend and backend, and create the first test file for the application <code>tests/note_app.spec.js</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> test<span class=\"token punctuation\">,</span> expect <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'@playwright/test'</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'front page can be opened'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:5173'</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">const</span> locator <span class=\"token operator\">=</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Notes'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>locator<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app, Department of Computer Science, University of Helsinki 2024'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>First, the test opens the application with the method <a href=\"https://playwright.dev/docs/writing-tests#navigation\">page.goto</a>. After this, it uses the <a href=\"https://playwright.dev/docs/api/class-page#page-get-by-text\">page.getByText</a> to get a <a href=\"https://playwright.dev/docs/locators\">locator</a> that corresponds to the element where the text <i>Notes</i> is found.</p>\n<p>The method <a href=\"https://playwright.dev/docs/api/class-locatorassertions#locator-assertions-to-be-visible\">toBeVisible</a> ensures that the element corresponding to the locator is visible at the page.</p>\n<p>The second check is done without using the auxiliary variable.</p>\n<p>The test fails because an old year ended up in the test. Playwright opens the test report in the browser and it becomes clear that Playwright has actually performed the tests with three different browsers: Chrome, Firefox and Webkit, i.e. the browser engine used by Safari:</p>\n<picture><img src=\"/static/80278f03dca663d9fb0dd627d85b6c45/5a190/play2.png\" alt=\"test report showing the test failing in three different browsers\" srcset=\"/static/80278f03dca663d9fb0dd627d85b6c45/772e8/play2.png 200w,\n/static/80278f03dca663d9fb0dd627d85b6c45/e17e5/play2.png 400w,\n/static/80278f03dca663d9fb0dd627d85b6c45/5a190/play2.png 800w,\n/static/80278f03dca663d9fb0dd627d85b6c45/c1b63/play2.png 1200w,\n/static/80278f03dca663d9fb0dd627d85b6c45/29007/play2.png 1600w,\n/static/80278f03dca663d9fb0dd627d85b6c45/61583/play2.png 1616w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>By clicking on the report of one of the browsers, we can see a more detailed error message:</p>\n<picture><img src=\"/static/2e1769340191bf7d26b055eba8d46405/5a190/play3a.png\" alt=\"test error message\" srcset=\"/static/2e1769340191bf7d26b055eba8d46405/772e8/play3a.png 200w,\n/static/2e1769340191bf7d26b055eba8d46405/e17e5/play3a.png 400w,\n/static/2e1769340191bf7d26b055eba8d46405/5a190/play3a.png 800w,\n/static/2e1769340191bf7d26b055eba8d46405/c1b63/play3a.png 1200w,\n/static/2e1769340191bf7d26b055eba8d46405/29007/play3a.png 1600w,\n/static/2e1769340191bf7d26b055eba8d46405/6f175/play3a.png 2036w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>In the big picture, it is of course a very good thing that the testing takes place with all three commonly used browser engines, but this is slow, and when developing the tests it is probably best to carry them out mainly with only one browser. You can define the browser engine to be used with the command line parameter:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">npm test <span class=\"token operator\">--</span> <span class=\"token operator\">--</span>project chromium</code></pre></div>\n<p>Now let's fix the test with the correct year and let's add a <em>describe</em> block to the tests:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> test<span class=\"token punctuation\">,</span> describe<span class=\"token punctuation\">,</span> expect <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'@playwright/test'</span><span class=\"token punctuation\">)</span>\n\n<span class=\"gatsby-highlight-code-line\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span>  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'front page can be opened'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:5173'</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">const</span> locator <span class=\"token operator\">=</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Notes'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>locator<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app, Department of Computer Science, University of Helsinki 2025'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Before we move on, let's break the tests one more time. We notice that the execution of the tests is quite fast when they pass, but much slower if the they do not pass. The reason for this is that Playwright's policy is to wait for searched elements until <a href=\"https://playwright.dev/docs/actionability\">they are rendered and ready for action</a>. If the element is not found, a <em>TimeoutError</em> is raised and the test fails. Playwright waits for elements by default for 5 or 30 seconds <a href=\"https://playwright.dev/docs/test-timeouts#introduction\">depending on the functions used in testing</a>.</p>\n<p>When developing tests, it may be wiser to reduce the waiting time to a few seconds. According to the <a href=\"https://playwright.dev/docs/test-timeouts\">documentation</a>, this can be done by changing the file <em>playwright.config.js</em> as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token function\">defineConfig</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token literal-property property\">timeout</span><span class=\"token operator\">:</span> <span class=\"token number\">3000</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token literal-property property\">fullyParallel</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token literal-property property\">workers</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span></span>  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>We also made two other changes to the file, specifying that all tests <a href=\"https://playwright.dev/docs/test-parallel\">be executed one at a time</a>. With the default configuration, the execution happens in parallel, and since our tests use a database, parallel execution causes problems.</p>\n<h3>Writing on the form</h3>\n<p>Let's write a new test that tries to log into the application. Let's assume that a user is stored in the database, with username <i>mluukkai</i> and password <i>salainen</i>.</p>\n<p>Let's start by opening the login form.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'user can log in'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:5173'</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The test first uses the method <a href=\"https://playwright.dev/docs/api/class-page#page-get-by-role\">page.getByRole</a> to retrieve the button based on its text. The method returns the <a href=\"https://playwright.dev/docs/api/class-locator\">Locator</a> corresponding to the Button element. Pressing the button is performed using the Locator method <a href=\"https://playwright.dev/docs/api/class-locator#locator-click\">click</a>.</p>\n<p>When developing tests, you could use Playwright's <a href=\"https://playwright.dev/docs/test-ui-mode\">UI mode</a>, i.e. the user interface version. Let's start the tests in UI mode as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">npm test -- --ui</code></pre></div>\n<p>We now see that the test finds the button</p>\n<picture><img src=\"/static/a35101d3c0cd850939891db91925c5d9/5a190/play4.png\" alt=\"playwright UI rendering the notes app while testing it\" srcset=\"/static/a35101d3c0cd850939891db91925c5d9/772e8/play4.png 200w,\n/static/a35101d3c0cd850939891db91925c5d9/e17e5/play4.png 400w,\n/static/a35101d3c0cd850939891db91925c5d9/5a190/play4.png 800w,\n/static/a35101d3c0cd850939891db91925c5d9/c1b63/play4.png 1200w,\n/static/a35101d3c0cd850939891db91925c5d9/29007/play4.png 1600w,\n/static/a35101d3c0cd850939891db91925c5d9/eff3b/play4.png 2072w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>After clicking, the form will appear</p>\n<picture><img src=\"/static/b2a3d1b8d09c9167cb8d0302649b3bf8/5a190/play5.png\" alt=\"playwright UI rendering the login form of the notes app\" srcset=\"/static/b2a3d1b8d09c9167cb8d0302649b3bf8/772e8/play5.png 200w,\n/static/b2a3d1b8d09c9167cb8d0302649b3bf8/e17e5/play5.png 400w,\n/static/b2a3d1b8d09c9167cb8d0302649b3bf8/5a190/play5.png 800w,\n/static/b2a3d1b8d09c9167cb8d0302649b3bf8/c1b63/play5.png 1200w,\n/static/b2a3d1b8d09c9167cb8d0302649b3bf8/29007/play5.png 1600w,\n/static/b2a3d1b8d09c9167cb8d0302649b3bf8/9efb3/play5.png 1894w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>When the form is opened, the test should look for the text fields and enter the username and password in them. Let's make the first attempt using the method <a href=\"https://playwright.dev/docs/api/class-page#page-get-by-role\">page.getByRole</a>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'user can log in'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:5173'</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">)</span></span>  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>This results to an error:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">Error: locator.fill: Error: strict mode violation: getByRole<span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span> resolved to <span class=\"token number\">2</span> elements:\n  <span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span>input <span class=\"token assign-left variable\">value</span><span class=\"token operator\">=</span><span class=\"token string\">\"\"</span>/<span class=\"token operator\">></span> aka locator<span class=\"token punctuation\">(</span><span class=\"token string\">'div'</span><span class=\"token punctuation\">)</span>.filter<span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> hasText: /^username$/ <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>.getByRole<span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token number\">2</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&lt;</span>input <span class=\"token assign-left variable\">value</span><span class=\"token operator\">=</span><span class=\"token string\">\"\"</span> <span class=\"token assign-left variable\">type</span><span class=\"token operator\">=</span><span class=\"token string\">\"password\"</span>/<span class=\"token operator\">></span> aka locator<span class=\"token punctuation\">(</span><span class=\"token string\">'input[type=\"password\"]'</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The problem now is that <em>getByRole</em> finds two text fields, and calling the <a href=\"https://playwright.dev/docs/api/class-locator#locator-fill\">fill</a> method fails, because it assumes that there is only one text field found. One way around the problem is to use the methods <a href=\"https://playwright.dev/docs/api/class-locator#locator-first\">first</a> and <a href=\"https://playwright.dev/docs/api/class-locator#locator-last\">last</a>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'user can log in'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:5173'</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">first</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">last</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'salainen'</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  </span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Matti Luukkainen logged in'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span>  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>After writing in the text fields, the test presses the <em>login</em> button and checks that the application renders the logged-in user's information on the screen.</p>\n<p>If there were more than two text fields, using the methods <em>first</em> and <em>last</em> would not be enough. One possibility would be to use the <a href=\"https://playwright.dev/docs/api/class-locator#locator-all\">all</a> method, which turns the found locators into an array that can be indexed:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'user can log in'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:5173'</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">const</span> textboxes <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">all</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\"></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">await</span> textboxes<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">await</span> textboxes<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'salainen'</span><span class=\"token punctuation\">)</span></span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  \n    <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Matti Luukkainen logged in'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>  \n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Both this and the previous version of the test work. However, both are problematic to the extent that if the registration form is changed, the tests may break, as they rely on the fields to be on the page in a certain order.</p>\n<p>If an element is difficult to locate in tests, you can assign it a separate <i>test-id</i> attribute and find the element in tests using the <a href=\"https://playwright.dev/docs/api/class-page#page-get-by-test-id\">getByTestId</a> method.</p>\n<p>Let's now take advantage of the existing elements of the login form. The input fields of the login form have been assigned unique <i>labels</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">// ...</span>\n<span class=\"token operator\">&lt;</span>form onSubmit<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>handleSubmit<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n  <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token operator\">&lt;</span>label<span class=\"token operator\">></span></span><span class=\"gatsby-highlight-code-line\">      username</span>      <span class=\"token operator\">&lt;</span>input\n        type<span class=\"token operator\">=</span><span class=\"token string\">\"text\"</span>\n        value<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>username<span class=\"token punctuation\">}</span>\n        onChange<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>handleUsernameChange<span class=\"token punctuation\">}</span>\n      <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>label<span class=\"token operator\">></span></span>  <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n  <span class=\"token operator\">&lt;</span>div<span class=\"token operator\">></span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token operator\">&lt;</span>label<span class=\"token operator\">></span></span><span class=\"gatsby-highlight-code-line\">      password</span>      <span class=\"token operator\">&lt;</span>input\n        type<span class=\"token operator\">=</span><span class=\"token string\">\"password\"</span>\n        value<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>password<span class=\"token punctuation\">}</span>\n        onChange<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>handlePasswordChange<span class=\"token punctuation\">}</span>\n      <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>label<span class=\"token operator\">></span></span>  <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n  <span class=\"token operator\">&lt;</span>button type<span class=\"token operator\">=</span><span class=\"token string\">\"submit\"</span><span class=\"token operator\">></span>login<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>form<span class=\"token operator\">></span>\n<span class=\"token comment\">// ...</span></code></pre></div>\n<p>Input fields can and should be located in tests using <i>labels</i> with the <a href=\"https://playwright.dev/docs/api/class-page#page-get-by-label\">getByLabel</a> method:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'user can log in'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:5173'</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'username'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'password'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'salainen'</span><span class=\"token punctuation\">)</span></span>  \n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> \n  \n    <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Matti Luukkainen logged in'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>When locating elements, it makes sense to aim to utilize the content visible to the user in the interface, as this best simulates how a user would actually find the desired input field while navigating the application.</p>\n<p>Note that passing the test at this stage requires that there is a user in the <i>test</i> database of the backend with username <i>mluukkai</i> and password <i>salainen</i>. Create a user if needed!</p>\n<h3>Test Initialization</h3>\n<p>Since both tests start in the same way, i.e. by opening the page <i><a href=\"http://localhost:5173\">http://localhost:5173</a></i>, it is recommended to isolate the common part in the <i>beforeEach</i> block that is executed before each test:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> test<span class=\"token punctuation\">,</span> describe<span class=\"token punctuation\">,</span> expect<span class=\"token punctuation\">,</span> beforeEach <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'@playwright/test'</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:5173'</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></span>\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'front page can be opened'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> locator <span class=\"token operator\">=</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Notes'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>locator<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app, Department of Computer Science, University of Helsinki 2025'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'user can log in'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'username'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'password'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'salainen'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Matti Luukkainen logged in'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h3>Testing note creation</h3>\n<p>Next, let's create a test that adds a new note to the application:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> test<span class=\"token punctuation\">,</span> describe<span class=\"token punctuation\">,</span> expect<span class=\"token punctuation\">,</span> beforeEach <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'@playwright/test'</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'when logged in'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'username'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'password'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'salainen'</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a new note can be created'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'new note'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a note created by playwright'</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'save'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a note created by playwright'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>  \n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The test is defined in its own <em>describe</em> block. Creating a note requires that the user is logged in, which is handled in the <em>beforeEach</em> block.</p>\n<p>The test trusts that when creating a new note, there is only one input field on the page, so it searches for it as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>If there were more fields, the test would break. Because of this, it could be better to add a <i>test-id</i> to the form input and search for it in the test based on this id.</p>\n<p><strong>Note:</strong> the test will only pass the first time. The reason for this is that its expectation</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a note created by playwright'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>causes problems when the same note is created in the application more than once. The problem will be solved in the next chapter.</p>\n<p>The structure of the tests looks like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> test<span class=\"token punctuation\">,</span> describe<span class=\"token punctuation\">,</span> expect<span class=\"token punctuation\">,</span> beforeEach <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'@playwright/test'</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ....</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'user can log in'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'username'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'password'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'salainen'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Matti Luukkainen logged in'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'when logged in'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'username'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'password'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'salainen'</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a new note can be created'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'new note'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a note created by playwright'</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'save'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a note created by playwright'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Since we have prevented the tests from running in parallel, Playwright runs the tests in the order they appear in the test code. That is, first the test <i>user can log in</i>, where the user logs into the application, is performed. After this the test <i>a new note can be created</i> gets executed, which also does a log in, in the <i>beforeEach</i> block. Why is this done, isn't the user already logged in thanks to the previous test? No, because the execution of <i>each</i> test starts from the browser's \"zero state\", all changes made to the browser's state by the previous tests are reset.</p>\n<h3>Controlling the state of the database</h3>\n<p>If the tests need to be able to modify the server's database, the situation immediately becomes more complicated. Ideally, the server's database should be the same each time we run the tests, so our tests can be reliably and easily repeatable.</p>\n<p>As with unit and integration tests, with E2E tests it is best to empty the database and possibly format it before the tests are run. The challenge with E2E tests is that they do not have access to the database.</p>\n<p>The solution is to create API endpoints for the backend tests.\nWe can empty the database using these endpoints.\nLet's create a new router for the tests inside the <i>controllers</i> folder, in the <i>testing.js</i> file</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> router <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'express'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">Router</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">const</span> Note <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'../models/note'</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">const</span> User <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'../models/user'</span><span class=\"token punctuation\">)</span>\n\nrouter<span class=\"token punctuation\">.</span><span class=\"token function\">post</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/reset'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">request<span class=\"token punctuation\">,</span> response</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">await</span> Note<span class=\"token punctuation\">.</span><span class=\"token function\">deleteMany</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> User<span class=\"token punctuation\">.</span><span class=\"token function\">deleteMany</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  response<span class=\"token punctuation\">.</span><span class=\"token function\">status</span><span class=\"token punctuation\">(</span><span class=\"token number\">204</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> router</code></pre></div>\n<p>and add it to the backend only <i>if the application is run in test-mode</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token comment\">// ...</span>\n\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/api/login'</span><span class=\"token punctuation\">,</span> loginRouter<span class=\"token punctuation\">)</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/api/users'</span><span class=\"token punctuation\">,</span> usersRouter<span class=\"token punctuation\">)</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/api/notes'</span><span class=\"token punctuation\">,</span> notesRouter<span class=\"token punctuation\">)</span>\n\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">NODE_ENV</span> <span class=\"token operator\">===</span> <span class=\"token string\">'test'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> testingRouter <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'./controllers/testing'</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  app<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/api/testing'</span><span class=\"token punctuation\">,</span> testingRouter<span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\"><span class=\"token punctuation\">}</span></span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span>middleware<span class=\"token punctuation\">.</span>unknownEndpoint<span class=\"token punctuation\">)</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span>middleware<span class=\"token punctuation\">.</span>errorHandler<span class=\"token punctuation\">)</span>\n\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> app</code></pre></div>\n<p>After the changes, an HTTP POST request to the <i>/api/testing/reset</i> endpoint empties the database. Make sure your backend is running in test mode by starting it with this command (previously configured in the package.json file):</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">  npm run start<span class=\"token operator\">:</span>test</code></pre></div>\n<p>The modified backend code can be found on the <a href=\"https://github.com/fullstack-hy2020/part3-notes-backend/tree/part5-1\">GitHub</a> branch <i>part5-1</i>.</p>\n<p>Next, we will change the <em>beforeEach</em> block so that it empties the server's database before tests are run.</p>\n<p>Currently, it is not possible to add new users through the frontend's UI, so we add a new user to the backend from the beforeEach block.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page<span class=\"token punctuation\">,</span> request <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> request<span class=\"token punctuation\">.</span><span class=\"token function\">post</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:3001/api/testing/reset'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> request<span class=\"token punctuation\">.</span><span class=\"token function\">post</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:3001/api/users'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token literal-property property\">data</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'Matti Luukkainen'</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">username</span><span class=\"token operator\">:</span> <span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">password</span><span class=\"token operator\">:</span> <span class=\"token string\">'salainen'</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:5173'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  \n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'front page can be opened'</span><span class=\"token punctuation\">,</span>  <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'user can login'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'when logged in'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>During initialization, the test makes HTTP requests to the backend with the method <a href=\"https://playwright.dev/docs/api/class-apirequestcontext#api-request-context-post\">post</a> of the parameter <em>request</em>.</p>\n<p>Unlike before, now the testing of the backend always starts from the same state, i.e. there is one user and no notes in the database.</p>\n<p>Let's make a test that checks that the importance of the notes can be changed.</p>\n<p>There are a few different approaches to taking the test.</p>\n<p>In the following, we first look for a note and click on its button that has text <i>make not important</i>. After this, we check that the note contains the button with <i>make important</i>.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'when logged in'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'and a note exists'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">        <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'new note'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">        <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'another note by playwright'</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">        <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'save'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  </span><span class=\"gatsby-highlight-code-line\">      <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'importance can be changed'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">        <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'make not important'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">        <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'make important'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></span>    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The first command first searches for the component where there is the text <i>another note by playwright</i> and inside it the button <i>make not important</i> and clicks on it.</p>\n<p>The second command ensures that the text of the same button has changed to <i>make important</i>.</p>\n<p>The current code for the tests is on <a href=\"https://github.com/fullstack-hy2020/notes-e2e/tree/part5-1\">GitHub</a>, in branch <i>part5-1</i>.</p>\n<h3>Test for failed login</h3>\n<p>Now let's do a test that ensures that the login attempt fails if the password is wrong.</p>\n<p>The first version of the test looks like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'login fails with wrong password'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'username'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'password'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'wrong'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'wrong credentials'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The test verifies with the method <a href=\"https://playwright.dev/docs/api/class-page#page-get-by-text\">page.getByText</a> that the application prints an error message.</p>\n<p>The application renders the error message to an element containing the CSS class <i>error</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Notification</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> message <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>message <span class=\"token operator\">===</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token operator\">&lt;</span>div className<span class=\"token operator\">=</span><span class=\"token string\">\"error\"</span><span class=\"token operator\">></span></span>      <span class=\"token punctuation\">{</span>message<span class=\"token punctuation\">}</span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>div<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>We could refine the test to ensure that the error message is printed exactly in the right place, i.e. in the element containing the CSS class <i>error</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'login fails with wrong password'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> errorDiv <span class=\"token operator\">=</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">locator</span><span class=\"token punctuation\">(</span><span class=\"token string\">'.error'</span><span class=\"token punctuation\">)</span></span>  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>errorDiv<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toContainText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'wrong credentials'</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>So the test uses the <a href=\"https://playwright.dev/docs/api/class-page#page-locator\">page.locator</a> method to find the component containing the CSS class <i>error</i> and stores it in a variable. The correctness of the text associated with the component can be verified with the expectation <a href=\"https://playwright.dev/docs/api/class-locatorassertions#locator-assertions-to-contain-text\">toContainText</a>. Note that the <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors\">CSS class selector</a> starts with a dot, so the <i>error</i> class selector is <i> .error</i>.</p>\n<p>It is possible to test the application's CSS styles with matcher <a href=\"https://playwright.dev/docs/api/class-locatorassertions#locator-assertions-to-have-css\">toHaveCSS</a>. We can, for example, make sure that the color of the error message is red, and that there is a border around it:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'login fails with wrong password'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token keyword\">const</span> errorDiv <span class=\"token operator\">=</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">locator</span><span class=\"token punctuation\">(</span><span class=\"token string\">'.error'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>errorDiv<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toContainText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'wrong credentials'</span><span class=\"token punctuation\">)</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>errorDiv<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toHaveCSS</span><span class=\"token punctuation\">(</span><span class=\"token string\">'border-style'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'solid'</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>errorDiv<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toHaveCSS</span><span class=\"token punctuation\">(</span><span class=\"token string\">'color'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'rgb(255, 0, 0)'</span><span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Colors must be defined to Playwright as <a href=\"https://rgbcolorcode.com/color/red\">rgb</a> codes.</p>\n<p>Let's finalize the test so that it also ensures that the application <strong>does not render</strong> the text describing a successful login <i>'Matti Luukkainen logged in'</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'login fails with wrong password'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span><span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'username'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'password'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'wrong'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">const</span> errorDiv <span class=\"token operator\">=</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">locator</span><span class=\"token punctuation\">(</span><span class=\"token string\">'.error'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>errorDiv<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toContainText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'wrong credentials'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>errorDiv<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toHaveCSS</span><span class=\"token punctuation\">(</span><span class=\"token string\">'border-style'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'solid'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>errorDiv<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toHaveCSS</span><span class=\"token punctuation\">(</span><span class=\"token string\">'color'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'rgb(255, 0, 0)'</span><span class=\"token punctuation\">)</span>\n\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Matti Luukkainen logged in'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>not<span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h3>Running tests one by one</h3>\n<p>By default, Playwright always runs all tests, and as the number of tests increases, it becomes time-consuming. When developing a new test or debugging a broken one, the test can be defined instead than with the command <i>test</i>, with the command <i>test.only</i>, in which case Playwright will run only that test:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// this is the only test executed!</span>\n<span class=\"gatsby-highlight-code-line\">  test<span class=\"token punctuation\">.</span><span class=\"token function\">only</span><span class=\"token punctuation\">(</span><span class=\"token string\">'login fails with wrong password'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span>    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token comment\">// this test is skipped...</span>\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'user can login with correct credentials'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>When the test is ready, <i>only</i> can and <strong>should</strong> be deleted.</p>\n<p>Another option to run a single test is to use a command line parameter:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">npm test -- -g \"login fails with wrong password\"</code></pre></div>\n<h3>Helper functions for tests</h3>\n<p>Our application tests currently look like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> test<span class=\"token punctuation\">,</span> describe<span class=\"token punctuation\">,</span> expect<span class=\"token punctuation\">,</span> beforeEach <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'@playwright/test'</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'user can login with correct credentials'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'username'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'password'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'salainen'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Matti Luukkainen logged in'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'login fails with wrong password'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span><span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'when logged in'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page<span class=\"token punctuation\">,</span> request <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'username'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'password'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'salainen'</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a new note can be created'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// ...</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  \n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>  \n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>First, the login function is tested. After this, another <em>describe</em> block contains a set of tests that assume that the user is logged in, the login is handled inside the initializing <em>beforeEach</em> block.</p>\n<p>As already stated earlier, each test is executed starting from the initial state (where the database is cleared and one user is created there), so even though the test is defined after another test in the code, it does not start from the same state where the tests in the code executed earlier have left!</p>\n<p>It is also worth striving for having non-repetitive code in tests. Let's isolate the code that handles the login as a helper function, which is placed e.g. in the file <em>tests/helper.js</em>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">loginWith</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">page<span class=\"token punctuation\">,</span> username<span class=\"token punctuation\">,</span> password</span><span class=\"token punctuation\">)</span>  <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'username'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span>username<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'password'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span>password<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token punctuation\">{</span> loginWith <span class=\"token punctuation\">}</span></code></pre></div>\n<p>The tests becomes simpler and clearer:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> test<span class=\"token punctuation\">,</span> describe<span class=\"token punctuation\">,</span> expect<span class=\"token punctuation\">,</span> beforeEach <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'@playwright/test'</span><span class=\"token punctuation\">)</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> loginWith <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'./helper'</span><span class=\"token punctuation\">)</span></span>\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'user can log in'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">await</span> <span class=\"token function\">loginWith</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'salainen'</span><span class=\"token punctuation\">)</span></span>    <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Matti Luukkainen logged in'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'login fails with wrong password'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">await</span> <span class=\"token function\">loginWith</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'wrong'</span><span class=\"token punctuation\">)</span></span>\n    <span class=\"token keyword\">const</span> errorDiv <span class=\"token operator\">=</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">locator</span><span class=\"token punctuation\">(</span><span class=\"token string\">'.error'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'when logged in'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">await</span> <span class=\"token function\">loginWith</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'salainen'</span><span class=\"token punctuation\">)</span></span>    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Playwright also offers a <a href=\"https://playwright.dev/docs/auth\">solution</a> where the login is performed once before the tests, and each test starts from a state where the application is already logged in. In order for us to take advantage of this method, the initialization of the application's test data should be done a bit differently than now. In the current solution, the database is reset before each test, and because of this, logging in just once before the tests is impossible. In order for us to use the pre-test login provided by Playwright, the user should be initialized only once before the tests. We stick to our current solution for the sake of simplicity.</p>\n<p>The corresponding repeating code actually also applies to creating a new note. For that, there is a test that creates a note using a form. Also in the <em>beforeEach</em> initialization block of the test that tests changing the importance of the note, a note is created using the form:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'when logged in'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a new note can be created'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'new note'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a note created by playwright'</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'save'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a note created by playwright'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  \n    <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'and a note exists'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'new note'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span><span class=\"token string\">'another note by playwright'</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'save'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  \n      <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'it can be made important'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token comment\">// ...</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Creation of a note is also isolated as its helper function. The file <em>tests/helper.js</em> expands as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">loginWith</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">page<span class=\"token punctuation\">,</span> username<span class=\"token punctuation\">,</span> password</span><span class=\"token punctuation\">)</span>  <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'username'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span>username<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByLabel</span><span class=\"token punctuation\">(</span><span class=\"token string\">'password'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span>password<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'login'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">createNote</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">page<span class=\"token punctuation\">,</span> content</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'new note'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'save'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\"><span class=\"token punctuation\">}</span></span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">export</span> <span class=\"token punctuation\">{</span> loginWith<span class=\"token punctuation\">,</span> createNote <span class=\"token punctuation\">}</span></span></code></pre></div>\n<p>The tests are simplified as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> test<span class=\"token punctuation\">,</span> describe<span class=\"token punctuation\">,</span> expect<span class=\"token punctuation\">,</span> beforeEach <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'@playwright/test'</span><span class=\"token punctuation\">)</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> createNote<span class=\"token punctuation\">,</span> loginWith <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'./helper'</span><span class=\"token punctuation\">)</span></span>\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n\n  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'when logged in'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">await</span> <span class=\"token function\">loginWith</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'salainen'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a new note can be created'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">await</span> <span class=\"token function\">createNote</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'a note created by playwright'</span><span class=\"token punctuation\">)</span></span>      <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a note created by playwright'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'and a note exists'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">        <span class=\"token keyword\">await</span> <span class=\"token function\">createNote</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'another note by playwright'</span><span class=\"token punctuation\">)</span></span>      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  \n      <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'importance can be changed'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'make not important'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'make important'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>There is one more annoying feature in our tests. The frontend address <i>http:localhost:5173</i> and the backend address <i>http:localhost:3001</i> are hardcoded for tests. Of these, the address of the backend is actually useless, because a proxy has been defined in the Vite configuration of the frontend, which forwards all requests made by the frontend to the address <i>http:localhost:5173/api</i> to the backend:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token function\">defineConfig</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">server</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">proxy</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token string-property property\">'/api'</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token literal-property property\">target</span><span class=\"token operator\">:</span> <span class=\"token string\">'http://localhost:3001'</span><span class=\"token punctuation\">,</span>\n        <span class=\"token literal-property property\">changeOrigin</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>So we can replace all the addresses in the tests from <em><a href=\"http://localhost:3001/api/..\">http://localhost:3001/api/..</a>.</em> to <em><a href=\"http://localhost:5173/api/..\">http://localhost:5173/api/..</a>.</em></p>\n<p>We can now define the <em>baseUrl</em> for the application in the tests configuration file <i>playwright.config.js</i>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token function\">defineConfig</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n  <span class=\"token literal-property property\">use</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">baseURL</span><span class=\"token operator\">:</span> <span class=\"token string\">'http://localhost:5173'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>All the commands in the tests that use the application url, e.g.</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:5173'</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">await</span> request<span class=\"token punctuation\">.</span><span class=\"token function\">post</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:5173/api/testing/reset'</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>can now be transformed into:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/'</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">await</span> request<span class=\"token punctuation\">.</span><span class=\"token function\">post</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/api/testing/reset'</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The current code for the tests is on <a href=\"https://github.com/fullstack-hy2020/notes-e2e/tree/part5-2\">GitHub</a>, branch <i>part5-2</i>.</p>\n<h3>Note importance change revisited</h3>\n<p>Let's take a look at the test we did earlier, which verifies that it is possible to change the importance of a note.</p>\n<p>Let's change the initialization block of the test so that it creates two notes instead of one:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'when logged in'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'and several notes exists'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span>    <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">await</span> <span class=\"token function\">createNote</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'first note'</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">await</span> <span class=\"token function\">createNote</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'second note'</span><span class=\"token punctuation\">)</span></span>    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'one of those can be made nonimportant'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">const</span> otherNoteElement <span class=\"token operator\">=</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'first note'</span><span class=\"token punctuation\">)</span>\n\n      <span class=\"token keyword\">await</span> otherNoteElement\n        <span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'make not important'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>otherNoteElement<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'make important'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The test first searches for the element corresponding to the first created note using the method <em>page.getByText</em> and stores it in a variable. After this, a button with the text <em>make not important</em> is searched inside the element and the button is pressed. Finally, the test verifies that the button's text has changed to <em>make important</em>.</p>\n<p>The test could also have been written without the auxiliary variable:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'one of those can be made nonimportant'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'first note'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'make not important'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'first note'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'make important'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Let's change the <em>Note</em> component so that the note text is rendered inside a <em>span</em> element</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">Note</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> note<span class=\"token punctuation\">,</span> toggleImportance <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> label <span class=\"token operator\">=</span> note<span class=\"token punctuation\">.</span>important\n    <span class=\"token operator\">?</span> <span class=\"token string\">'make not important'</span> <span class=\"token operator\">:</span> <span class=\"token string\">'make important'</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token operator\">&lt;</span>li className<span class=\"token operator\">=</span><span class=\"token string\">'note'</span><span class=\"token operator\">></span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token operator\">&lt;</span>span<span class=\"token operator\">></span><span class=\"token punctuation\">{</span>note<span class=\"token punctuation\">.</span>content<span class=\"token punctuation\">}</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>span<span class=\"token operator\">></span></span>      <span class=\"token operator\">&lt;</span>button onClick<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>toggleImportance<span class=\"token punctuation\">}</span><span class=\"token operator\">></span><span class=\"token punctuation\">{</span>label<span class=\"token punctuation\">}</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>button<span class=\"token operator\">></span>\n    <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>li<span class=\"token operator\">></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Tests break! The reason for the problem is that the command <em>page.getByText('first note')</em> now returns a <em>span</em> element containing only text, and the button is outside of it.</p>\n<p>One way to fix the problem is as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'one of those can be made nonimportant'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> otherNoteText <span class=\"token operator\">=</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'first note'</span><span class=\"token punctuation\">)</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> otherNoteElement <span class=\"token operator\">=</span> otherNoteText<span class=\"token punctuation\">.</span><span class=\"token function\">locator</span><span class=\"token punctuation\">(</span><span class=\"token string\">'..'</span><span class=\"token punctuation\">)</span></span>\n  <span class=\"token keyword\">await</span> otherNoteElement<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'make not important'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>otherNoteElement<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'make important'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The first line now looks for the <em>span</em> element containing the text associated with the first created note. In the second line, the function <em>locator</em> is used and <em>..</em> is given as an argument, which retrieves the element's parent element. The locator function is very flexible, and we take advantage of the fact that accepts <a href=\"https://playwright.dev/docs/locators#locate-by-css-or-xpath\">as argument</a> not only CSS selectors but also <a href=\"https://developer.mozilla.org/en-US/docs/Web/XPath\">XPath</a> selector. It would be possible to express the same with CSS, but in this case XPath provides the simplest way to find the parent of an element.</p>\n<p>Of course, the test can also be written using only one auxiliary variable:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'one of those can be made nonimportant'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> secondNoteElement <span class=\"token operator\">=</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'second note'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">locator</span><span class=\"token punctuation\">(</span><span class=\"token string\">'..'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> secondNoteElement<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'make not important'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>secondNoteElement<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'make important'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Let's change the test so that three notes are created, the importance is changed in the second created note:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'when logged in'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">loginWith</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'mluukkai'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'salainen'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a new note can be created'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">createNote</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'a note created by playwright'</span><span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a note created by playwright'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'and several notes exists'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">await</span> <span class=\"token function\">createNote</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'first note'</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> <span class=\"token function\">createNote</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'second note'</span><span class=\"token punctuation\">)</span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">await</span> <span class=\"token function\">createNote</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'third note'</span><span class=\"token punctuation\">)</span></span>    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'one of those can be made nonimportant'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">const</span> otherNoteText <span class=\"token operator\">=</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'second note'</span><span class=\"token punctuation\">)</span></span>      <span class=\"token keyword\">const</span> otherNoteElement <span class=\"token operator\">=</span> otherNoteText<span class=\"token punctuation\">.</span><span class=\"token function\">locator</span><span class=\"token punctuation\">(</span><span class=\"token string\">'..'</span><span class=\"token punctuation\">)</span>\n    \n      <span class=\"token keyword\">await</span> otherNoteElement<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'make not important'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>otherNoteElement<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'make important'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span> </code></pre></div>\n<p>For some reason the test starts working unreliably, sometimes it passes and sometimes it doesn't. It's time to roll up your sleeves and learn how to debug tests.</p>\n<h3>Test development and debugging</h3>\n<p>If, and when the tests don't pass and you suspect that the fault is in the tests instead of in the code, you should run the tests in <a href=\"https://playwright.dev/docs/debug#run-in-debug-mode-1\">debug</a> mode.</p>\n<p>The following command runs the problematic test in debug mode:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">npm test -- -g'one of those can be made nonimportant' --debug</code></pre></div>\n<p>Playwright-inspector shows the progress of the tests step by step. The arrow-dot button at the top takes the tests one step further. The elements found by the locators and the interaction with the browser are visualized in the browser:</p>\n<picture><img src=\"/static/46246983a4279f74c606a9adab941895/5a190/play6a.png\" alt=\"playwright inspector highlighting element found by the selected locator in the application\" srcset=\"/static/46246983a4279f74c606a9adab941895/772e8/play6a.png 200w,\n/static/46246983a4279f74c606a9adab941895/e17e5/play6a.png 400w,\n/static/46246983a4279f74c606a9adab941895/5a190/play6a.png 800w,\n/static/46246983a4279f74c606a9adab941895/c1b63/play6a.png 1200w,\n/static/46246983a4279f74c606a9adab941895/29007/play6a.png 1600w,\n/static/46246983a4279f74c606a9adab941895/3c2d4/play6a.png 2092w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>By default, debug steps through the test command by command. If it is a complex test, it can be quite a burden to step through the test to the point of interest. This can be avoided by using the command <em>await page.pause()</em>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Note app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page<span class=\"token punctuation\">,</span> request <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'when logged in'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// ...</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'and several notes exists'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">await</span> <span class=\"token function\">createNote</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'first note'</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">await</span> <span class=\"token function\">createNote</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'second note'</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">await</span> <span class=\"token function\">createNote</span><span class=\"token punctuation\">(</span>page<span class=\"token punctuation\">,</span> <span class=\"token string\">'third note'</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  \n      <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'one of those can be made nonimportant'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">        <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">pause</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span>        <span class=\"token keyword\">const</span> otherNoteText <span class=\"token operator\">=</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'second note'</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">const</span> otherNoteElement <span class=\"token operator\">=</span> otherNoteText<span class=\"token punctuation\">.</span><span class=\"token function\">locator</span><span class=\"token punctuation\">(</span><span class=\"token string\">'..'</span><span class=\"token punctuation\">)</span>\n      \n        <span class=\"token keyword\">await</span> otherNoteElement<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'make not important'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token keyword\">await</span> <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>otherNoteElement<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'make important'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBeVisible</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Now in the test you can go to <em>page.pause()</em> in one step, by pressing the green arrow symbol in the inspector.</p>\n<p>When we now run the test and jump to the <em>page.pause()</em> command, we find an interesting fact:</p>\n<picture><img src=\"/static/fe53c42e12bf889d6cb8179636f4fcbf/5a190/play6b.png\" alt=\"playwright inspector showing the state of the application at page.pause\" srcset=\"/static/fe53c42e12bf889d6cb8179636f4fcbf/772e8/play6b.png 200w,\n/static/fe53c42e12bf889d6cb8179636f4fcbf/e17e5/play6b.png 400w,\n/static/fe53c42e12bf889d6cb8179636f4fcbf/5a190/play6b.png 800w,\n/static/fe53c42e12bf889d6cb8179636f4fcbf/c1b63/play6b.png 1200w,\n/static/fe53c42e12bf889d6cb8179636f4fcbf/29007/play6b.png 1600w,\n/static/fe53c42e12bf889d6cb8179636f4fcbf/6274f/play6b.png 2098w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>It seems that the browser <i>does not render</i> all the notes created in the block <em>beforeEach</em>. What is the problem?</p>\n<p>The reason for the problem is that when the test creates one note, it starts creating the next one even before the server has responded, and the added note is rendered on the screen. This in turn can cause some notes to be lost (in the picture, this happened to the second note created), since the browser is re-rendered when the server responds, based on the state of the notes at the start of that insert operation.</p>\n<p>The problem can be solved by \"slowing down\" the insert operations by using the <a href=\"https://playwright.dev/docs/api/class-locator#locator-wait-for\">waitFor</a> command after the insert to wait for the inserted note to render:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">createNote</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">page<span class=\"token punctuation\">,</span> content</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'new note'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'textbox'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">fill</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'save'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span>content<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">waitFor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></span><span class=\"token punctuation\">}</span></code></pre></div>\n<p>Instead of, or alongside debugging mode, running tests in UI mode can be useful. As already mentioned, tests are started in UI mode as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">npm run test -- --ui</code></pre></div>\n<p>Almost the same as UI mode is use of the Playwright's <a href=\"https://playwright.dev/docs/trace-viewer-intro\">Trace Viewer</a>. The idea is that a \"visual trace\" of the tests is saved, which can be viewed if necessary after the tests have been completed. A trace is saved by running the tests as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">npm run test -- --trace on</code></pre></div>\n<p>If necessary, Trace can be viewed with the command</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">npx playwright show-report</code></pre></div>\n<p>or with the npm script we defined <em>npm run test:report</em></p>\n<p>Trace looks practically the same as running tests in UI mode.</p>\n<p>UI mode and Trace Viewer also offer the possibility of assisted search for locators. This is done by pressing the double circle on the left side of the lower bar, and then by clicking on the desired user interface element. Playwright displays the element locator:</p>\n<picture><img src=\"/static/d8d093b2848f86b49acdea39b56b3964/5a190/play8.png\" alt=\"playwright&#x27;s trace viewer with red arrows pointing at the locator assisted search location and to the element selected with it showing a suggested locator for the element\" srcset=\"/static/d8d093b2848f86b49acdea39b56b3964/772e8/play8.png 200w,\n/static/d8d093b2848f86b49acdea39b56b3964/e17e5/play8.png 400w,\n/static/d8d093b2848f86b49acdea39b56b3964/5a190/play8.png 800w,\n/static/d8d093b2848f86b49acdea39b56b3964/c1b63/play8.png 1200w,\n/static/d8d093b2848f86b49acdea39b56b3964/29007/play8.png 1600w,\n/static/d8d093b2848f86b49acdea39b56b3964/49ee2/play8.png 1618w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>Playwright suggests the following as the locator for the third note</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">page<span class=\"token punctuation\">.</span><span class=\"token function\">locator</span><span class=\"token punctuation\">(</span><span class=\"token string\">'li'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">hasText</span><span class=\"token operator\">:</span> <span class=\"token string\">'third note'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The method <a href=\"https://playwright.dev/docs/api/class-page#page-locator\">page.locator</a> is called with the argument <em>li</em>, i.e. we search for all li elements on the page, of which there are three in total. After this, using the <a href=\"https://playwright.dev/docs/api/class-locator#locator-filter\">locator.filter</a> method, we narrow down to the li element that contains the text <i>third note</i> and the button element inside it is taken using the <a href=\"https://playwright.dev/docs/api/class-locator#locator-get-by-role\">locator.getByRole</a> method.</p>\n<p>The locator generated by Playwright is somewhat different from the locator used by our tests, which was</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">page<span class=\"token punctuation\">.</span><span class=\"token function\">getByText</span><span class=\"token punctuation\">(</span><span class=\"token string\">'first note'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">locator</span><span class=\"token punctuation\">(</span><span class=\"token string\">'..'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getByRole</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> <span class=\"token string\">'make not important'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Which of the locators is better is probably a matter of taste.</p>\n<p>Playwright also includes a <a href=\"https://playwright.dev/docs/codegen-intro\">test generator</a> that makes it possible to \"record\" a test through the user interface. The test generator is started with the command:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">npx playwright codegen http://localhost:5173/</code></pre></div>\n<p>When the <em>Record</em> mode is on, the test generator \"records\" the user's interaction in the Playwright inspector, from where it is possible to copy the locators and actions to the tests:</p>\n<picture><img src=\"/static/ea807b1d85b7c1b5181b828fcbb6442b/5a190/play9.png\" alt=\"playwright&#x27;s record mode enabled with its output in the inspector after user interaction\" srcset=\"/static/ea807b1d85b7c1b5181b828fcbb6442b/772e8/play9.png 200w,\n/static/ea807b1d85b7c1b5181b828fcbb6442b/e17e5/play9.png 400w,\n/static/ea807b1d85b7c1b5181b828fcbb6442b/5a190/play9.png 800w,\n/static/ea807b1d85b7c1b5181b828fcbb6442b/c1b63/play9.png 1200w,\n/static/ea807b1d85b7c1b5181b828fcbb6442b/29007/play9.png 1600w,\n/static/ea807b1d85b7c1b5181b828fcbb6442b/59058/play9.png 2376w\" sizes=\"(max-width: 800px) 100vw, 800px\"></picture>\n<p>Instead of the command line, Playwright can also be used via the <a href=\"https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright\">VS Code</a> plugin. The plugin offers many convenient features, e.g. use of breakpoints when debugging tests.</p>\n<p>To avoid problem situations and increase understanding, it is definitely worth browsing Playwright's high-quality <a href=\"https://playwright.dev/docs/intro\">documentation</a>. The most important sections are listed below:</p>\n<ul>\n<li>the section about <a href=\"https://playwright.dev/docs/locators\">locators</a> gives good hints for finding elements in test</li>\n<li>section <a href=\"https://playwright.dev/docs/input\">actions</a> tells how it is possible to simulate the interaction with the browser in tests</li>\n<li>the section about <a href=\"https://playwright.dev/docs/test-assertions\">assertions</a> demonstrates the different expectations Playwright offers for testing</li>\n</ul>\n<p>In-depth details can be found in the <a href=\"https://playwright.dev/docs/api/class-playwright\">API</a> description, particularly useful are the class <a href=\"https://playwright.dev/docs/api/class-page\">Page</a> corresponding to the browser window of the application under test, and the class <a href=\"https://playwright.dev/docs/api/class-locator\">Locator</a> corresponding to the elements searched for in the tests.</p>\n<p>The final version of the tests is in full on <a href=\"https://github.com/fullstack-hy2020/notes-e2e/tree/part5-3\">GitHub</a>, in branch <i>part5-3</i>.</p>\n<p>The final version of the frontend code is in its entirety on <a href=\"https://github.com/fullstack-hy2020/part2-notes-frontend/tree/part5-9\">GitHub</a>, in branch <i>part5-9</i>.</p>\n</div>\n<div class=\"tasks\">\n<h3>Exercises 5.17.-5.23.</h3>\n<p>In the last exercises of this part, let's do some E2E tests for the blog application. The material above should be enough to do most of the exercises. However, you should definitely read Playwright's <a href=\"https://playwright.dev/docs/intro\">documentation</a> and <a href=\"https://playwright.dev/docs/api/class-playwright\">API description</a>, at least the sections mentioned at the end of the previous chapter.</p>\n<h4>5.17: Blog List End To End Testing, step 1</h4>\n<p>Create a new npm project for tests and configure Playwright there.</p>\n<p>Make a test to ensure that the application displays the login form by default.</p>\n<p>The body of the test should be as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> test<span class=\"token punctuation\">,</span> expect<span class=\"token punctuation\">,</span> beforeEach<span class=\"token punctuation\">,</span> describe <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'@playwright/test'</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Blog app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">await</span> page<span class=\"token punctuation\">.</span><span class=\"token function\">goto</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://localhost:5173'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Login form is shown'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h4>5.18: Blog List End To End Testing, step 2</h4>\n<p>Do the tests for login. Test both successful and failed login. For tests, create a user in the <em>beforeEach</em> block.</p>\n<p>The body of the tests expands as follows</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> test<span class=\"token punctuation\">,</span> expect<span class=\"token punctuation\">,</span> beforeEach<span class=\"token punctuation\">,</span> describe <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'@playwright/test'</span><span class=\"token punctuation\">)</span>\n\n<span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Blog app'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page<span class=\"token punctuation\">,</span> request <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// empty the db here</span>\n    <span class=\"token comment\">// create a user for the backend here</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Login form is shown'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Login'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'succeeds with correct credentials'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// ...</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n    <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'fails with wrong credentials'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">// ...</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The <em>beforeEach</em> block must empty the database using, for example, the reset method we used in the <a href=\"/en/part5/end_to_end_testing_playwright#controlling-the-state-of-the-database\">material</a>.</p>\n<h4>5.19: Blog List End To End Testing, step 3</h4>\n<p>Create a test that verifies that a logged in user can create a blog. The body of the test may look like the following</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token function\">describe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'When logged in'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">beforeEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token function\">test</span><span class=\"token punctuation\">(</span><span class=\"token string\">'a new blog can be created'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> page <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>The test should ensure that the created blog is visible in the list of blogs.</p>\n<h4>5.20: Blog List End To End Testing, step 4</h4>\n<p>Do a test that makes sure the blog can be liked.</p>\n<h4>5.21: Blog List End To End Testing, step 5</h4>\n<p>Make a test that ensures that the user who added the blog can delete the blog. If you use the <em>window.confirm</em> dialog in the delete operation, you may have to Google how to use the dialog in the Playwright tests.</p>\n<h4>5.22: Blog List End To End Testing, step 6</h4>\n<p>Make a test that ensures that only the user who added the blog sees the blog's delete button.</p>\n<h4>5.23: Blog List End To End Testing, step 7</h4>\n<p>Do a test that ensures that the blogs are arranged in the order according to the likes, the blog with the most likes first.</p>\n<p><i>This task is significantly more challenging than the previous ones.</i></p>\n</div>","frontmatter":{"mainImage":{"publicURL":"/static/b92f84fe9702a35b12f10af4588ba4c2/part-5.svg"},"part":5,"letter":"d","lang":"en"}}},"pageContext":{"part":5,"letter":"d","lang":"en"}},"staticQueryHashes":["3128451518"]}