--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ui-test-automation-playground",
3 | "version": "1.0.0",
4 | "description": "UI Test Automation Playground",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "Inflectra Corporation",
10 | "license": "Apache License 2.0",
11 | "dependencies": {
12 | "express": "^4.16.3",
13 | "pug": "^2.0.3",
14 | "shuffle-array": "^1.0.1"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/static/upload.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | UI Test Automation Playground
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/views/Upload.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p Modern web applications often include file upload functionality, enabling users to easily share and manage documents, images, and other types of files directly from their devices, enhancing user interaction and content management.
11 | h4 Scenario
12 | ul
13 | li Attach a file via drag&drop.
14 | li Attach a file using `Browse files` button
15 | h4 Playground
16 | iframe(src="/static/upload.html" width="800" height="500" frameBorder="0")
17 |
18 | include footer.html
--------------------------------------------------------------------------------
/views/LoadDelay.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p Server response may often come with an unpredictable delay. So a test must be able to patiently wait for page loaded event from a browser.
11 | h4 Scenario
12 | ul
13 | li Navigate to Home page and record Load Delays link click and button click on this page.
14 | li Then play the test. It should wait until page is loaded.
15 | h4 Playground
16 | button(
17 | type="button"
18 | class="btn btn-primary"
19 | ) Button Appearing After Delay
20 |
21 | include footer.html
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ui-test-automation-playground
2 |
3 | The purpose of this website is to provide a platform for sharpening UI test automation skills. Use it to practice with your test automation tool. Use it to learn test automation techniques.
4 |
5 | ## Live Version
6 |
7 | Latest version of this website is always available at [uitestingplayground.com](http://uitestingplayground.com).
8 |
9 | ## Prerequisites
10 | - [Node.js](https://nodejs.org)
11 | - [npm](https://www.npmjs.com/get-npm)
12 |
13 | ## Usage
14 |
15 | 1. Clone the repository
16 | 2. In the package folder run
17 | ```bash
18 | npm install
19 | ```
20 | 3. Launch with
21 | ```bash
22 | node app.js
23 | ```
24 | 4. In a browser navigate to
25 | ```
26 | http://localhost:3000
27 | ```
28 |
29 | ## Software Stack
30 | - [Node.js](https://github.com/nodejs/node)
31 | - [Express](https://github.com/expressjs/express/)
32 | - [Pug](https://github.com/pugjs/pug)
33 | - [Bootstrap](https://github.com/twbs/bootstrap)
34 | - [jQuery](https://github.com/jquery/jquery)
35 |
36 |
--------------------------------------------------------------------------------
/views/DynamicID.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p Modern applications often generate dynamic IDs for elements. In this case ID is not a reliable attribute for using in element selector. By default many UI automation tools record IDs and this results in tests broken from the very beginning. An automation tool needs a way to instruct it to skip dynamic IDs when XPath is generated for an element.
11 | h4 Scenario
12 | ul
13 | li Record button click.
14 | li Then execute your test to make sure that ID is not used for button identification.
15 | h4 Playground
16 | button(
17 | type="button"
18 | class="btn btn-primary"
19 | id=buttonId
20 | ) Button with Dynamic ID
21 |
22 | include footer.html
23 |
24 |
--------------------------------------------------------------------------------
/views/head.pug:
--------------------------------------------------------------------------------
1 | head
2 | meta(charset="utf-8")
3 | meta(
4 | name="viewport"
5 | content="width=device-width, initial-scale=1, shrink-to-fit=no"
6 | )
7 | link(
8 | rel="stylesheet"
9 | href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
10 | integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
11 | crossorigin="anonymous"
12 | )
13 | link(
14 | rel="stylesheet"
15 | href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
16 | )
17 | link(
18 | rel="stylesheet"
19 | href="/static/prism.css"
20 | )
21 | link(
22 | rel="stylesheet"
23 | href="/static/style.css"
24 | )
25 | title=title
26 | script.
27 | function byid(id)
28 | {
29 | return document.getElementById(id);
30 | }
31 |
32 | function setStatus(txt)
33 | {
34 | byid("opstatus").innerText = txt;
35 | }
36 |
--------------------------------------------------------------------------------
/views/navbar.pug:
--------------------------------------------------------------------------------
1 | nav(class="navbar navbar-expand-lg navbar-light bg-light")
2 | a(
3 | class="navbar-brand"
4 | href="/"
5 | ) UITAP
6 | button(
7 | class="navbar-toggler"
8 | type="button"
9 | data-toggle="collapse"
10 | data-target="#navbarSupportedContent"
11 | aria-controls="navbarSupportedContent"
12 | aria-expanded="false"
13 | aria-label="Toggle navigation"
14 | )
15 | span(class="navbar-toggler-icon")
16 | div(
17 | class="collapse navbar-collapse"
18 | id="navbarSupportedContent"
19 | )
20 | ul(class="navbar-nav mr-auto")
21 | li(
22 | class=homeActive ? "nav-item active" : "nav-item"
23 | )
24 | a(
25 | class="nav-link"
26 | href="/home"
27 | ) Home
28 | li(
29 | class=resourceActive ? "nav-item active" : "nav-item"
30 | )
31 | a(
32 | class="nav-link"
33 | href="/resources"
34 | ) Resources
35 |
--------------------------------------------------------------------------------
/views/Nbsp.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p There are cases in test automation when something should obviously work but for some reason it does not. Searching for an element by its text is one of those cases. Text caption may contain non-breaking spaces that have no visual difference from generic spaces.
11 | h4 Scenario
12 | ul
13 | li Use the following xpath to find the button in your test:
14 | br
15 | br
16 | pre //button[text()='My Button']
17 | li Notice that the XPath does not work. Change the space between 'My' and 'Button' to a non-breaking space. This time the XPath should be valid.
18 | h4 Playground
19 | button(
20 | type="button"
21 | class="btn btn-primary"
22 | id=buttonId
23 | ) My Button
24 |
25 | include footer.html
26 |
27 |
--------------------------------------------------------------------------------
/views/Scrollbars.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p An application may use native or custom scrollbars and some elements may be out of view. A test scenario may require to ensure that an element is visible on screen and this may require scrolling.
11 | h4 Scenario
12 | ul
13 | li Find a button in the scroll view and record button click.
14 | li Update your test to automatically scroll the button into a visible area.
15 | li Then execute your test to make sure it works.
16 | h4 Playground
17 | div(style="height:150px;overflow-y: scroll;width:300px;overflow-x:scroll")
18 | div(style="height:300px;width:600px")
19 | div(style="height:150px;")
20 | table
21 | tr
22 | td(style="width:300px;")
23 | td
24 | button(
25 | type="button"
26 | class="btn btn-primary"
27 | id="hidingButton"
28 | ) Hiding Button
29 |
30 | include footer.html
31 |
32 |
--------------------------------------------------------------------------------
/views/Click.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p Physical mouse click and DOM event emulated click are differently handled by browsers. There are still cases, with sometimes hardly identifiable reasons, when an event based click does not work. The solution for this problem is emulating physical mouse click. This page is specifically designed to ignore event based click.
11 | h4 Scenario
12 | ul
13 | li Record button click. The button becomes green after clicking.
14 | li Then execute your test to make sure that it is able to click the button.
15 | h4 Playground
16 | button(
17 | id="badButton"
18 | type="button"
19 | class="btn btn-primary"
20 | ) Button That Ignores DOM Click Event
21 |
22 | script.
23 | function ClickEventHandler(event)
24 | {
25 | if (event.target.id == "badButton")
26 | {
27 | if (event.screenX > 0)
28 | {
29 | event.target.className = 'btn btn-success';
30 | }
31 | }
32 | }
33 | document.body.addEventListener('click', ClickEventHandler, true);
34 |
35 | include footer.html
36 |
37 |
--------------------------------------------------------------------------------
/views/footer.html:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/views/Ajax.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p An element may appaear on a page after processing of an AJAX request to a web server. A test should be able to wait for an element to show up.
11 | h4 Scenario
12 | ul
13 | li Record the following steps. Press the button below and wait for data to appear (15 seconds), click on text of the loaded label.
14 | li Then execute your test to make sure it waits for label text to appear.
15 | h4 Playground
16 | button(
17 | type="button"
18 | class="btn btn-primary"
19 | id="ajaxButton"
20 | onclick="LoadLabel()"
21 | ) Button Triggering AJAX Request
22 | i(
23 | id="spinner"
24 | class="fa fa-spinner fa-spin"
25 | style="display:none"
26 | )
27 |
28 |
29 |
30 | script.
31 | function LoadLabel()
32 | {
33 | $('#spinner').show();
34 | $.get( "/ajaxdata", function( data )
35 | {
36 | var label = document.createElement("p");
37 | label.className = "bg-success";
38 | label.innerHTML = data;
39 | document.getElementById("content").appendChild(label);
40 | $('#spinner').hide();
41 | });
42 | }
43 |
44 | include footer.html
45 |
46 |
--------------------------------------------------------------------------------
/views/DynamicTable.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p Below you see a table where columns and rows change their position upon page reload. Values in cells are random. The table is based on DIVs with ARIA attributes. See WAI-ARIA table design pattern for details.
11 | h4 Scenario
12 | ul
13 | li For Chrome process get value of CPU load.
14 | li Compare it with value in the yellow label.
15 | h4 Playground
16 | div(
17 | role="table"
18 | aria-label=table.name
19 | aria-describedby="table_desc"
20 | )
21 | div(id="table_desc")
22 | =table.desc
23 | div(role="rowgroup")
24 | div(role="row")
25 | - for (var c = 0; c < table.columns.length; c++)
26 | span(role="columnheader")
27 | =table.columns[c]
28 | div(role="rowgroup")
29 | - for (var r = 0; r < table.rows.length; r++)
30 | div(role="row")
31 | - for (var v = 0; v < table.rows[r].length; v++)
32 | span(role="cell")
33 | =table.rows[r][v]
34 |
35 | br
36 | p(class='bg-warning')="Chrome CPU: " + table.chromeCPU
37 | include footer.html
38 |
39 |
--------------------------------------------------------------------------------
/views/ClientDelay.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p An element may appaear on a page after heavy JavaScript processing on a client side. A test should be able to wait for an element to show up.
11 | h4 Scenario
12 | ul
13 | li Record the following steps. Press the button below and wait for data to appear (15 seconds), click on text of the loaded label.
14 | li Then execute your test to make sure it waits for label text to appear.
15 | h4 Playground
16 | button(
17 | type="button"
18 | class="btn btn-primary"
19 | id="ajaxButton"
20 | onclick="CreateLabel()"
21 | ) Button Triggering Client Side Logic
22 | i(
23 | id="spinner"
24 | class="fa fa-spinner fa-spin"
25 | style="display:none"
26 | )
27 |
28 |
29 |
30 | script.
31 | function CreateLabel()
32 | {
33 | $('#spinner').show();
34 | setTimeout(function()
35 | {
36 | var label = document.createElement("p");
37 | label.className = "bg-success";
38 | label.innerHTML = "Data calculated on the client side.";
39 | document.getElementById("content").appendChild(label);
40 | $('#spinner').hide();
41 | }, 15000);
42 | }
43 |
44 | include footer.html
45 |
46 |
--------------------------------------------------------------------------------
/views/Resources.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | h4 Learning
11 | ul
12 | li
13 | a(href="https://www.w3schools.com") w3schools.com
14 | li
15 | a(href="https://developer.mozilla.org/en-US/") MDN
16 | li
17 | a(href="https://github.com/zeeshanu/learn-regex") Learn regex the easy way
18 | li
19 | a(href="https://devhints.io/") devhints.io
20 | h4 Standards
21 | ul
22 | li
23 | a(href="https://www.w3.org/") W3C
24 | h4 Articles
25 | ul
26 | li
27 | a(href="https://martinfowler.com/bliki/TestPyramid.html") Test Pyramid
28 | li
29 | a(href="https://testing.googleblog.com/2017/04/where-do-our-flaky-tests-come-from.html") Where do our flaky tests come from?
30 |
31 | h4 Community
32 | ul
33 | li
34 | a(href="https://ministryoftesting.com/") Ministry of Testing
35 | li
36 | a(href="https://www.utest.com") uTest
37 | li
38 | a(href="https://www.softwaretestinghelp.com") Software Testing Help
39 | li
40 | a(href="https://dzone.com/") DZone
41 | li
42 | a(href="https://stackoverflow.com/") StackOverflow
43 |
44 | include footer.html
45 |
46 |
--------------------------------------------------------------------------------
/views/DisabledInput.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p Sometimes elements become enabled after some time they are rendered on the page. A test should be able to wait for an element to become enabled.
11 | h4 Scenario
12 | ul
13 | li Record button click. Also record text input into an edit field.
14 | li Make a test that enters text as soon as the edit field becomes enabled.
15 | h4 Playground
16 |
17 | input(
18 | id="inputField"
19 | title="Edit Field"
20 | onchange="setStatus('Value changed to: ' + this.value)"
21 | class="form-control"
22 | placeholder="Change me..."
23 | )
24 | br
25 | button(
26 | id="enableButton"
27 | class="btn btn-primary"
28 | onclick="enableEditFieldWithDelay()"
29 | ) Enable Edit Field with 5 seconds delay
30 | div(
31 | id="opstatus"
32 | ) ---
33 |
34 | script.
35 | function enableEditFieldWithDelay()
36 | {
37 | byid('inputField').disabled = true;
38 | setStatus('Input Disabled...');
39 | setTimeout(()=>{
40 | byid('inputField').disabled = false;
41 | setStatus('Input Enabled...');
42 | },5000);
43 | }
44 |
45 | include footer.html
46 |
47 |
--------------------------------------------------------------------------------
/views/Overlapped.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p Entering text to a partially visible element may require scrolling it into view.
11 | h4 Scenario
12 | ul
13 | li Record setting text into the Name input field (scroll element before entering the text).
14 | li Then execute your test to make sure that the text was entered correctly.
15 | h4 Playground
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | script.
29 | var nameElement = document.querySelector('#name');
30 |
31 | nameElement.addEventListener('input', (event) => {
32 |
33 | var crect = nameElement.getBoundingClientRect();
34 |
35 | var centerX = crect.left + (crect.width >> 1);
36 | var centerY = crect.top + (crect.height >> 1);
37 | var elementAtPoint = document.elementFromPoint(centerX, centerY);
38 | if(!nameElement.isSameNode(elementAtPoint))
39 | {
40 | nameElement.value = "";
41 | }
42 | });
43 |
44 |
45 | include footer.html
46 |
--------------------------------------------------------------------------------
/views/VerifyText.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p In general inner text of a DOM element is different from displayed on screen. Browsers normalize text upon rendering, but DOM nodes contain text as it is in HTML markup. For example a browser may show the text as
11 | div
12 | p
13 | span(class="badge-secondary") Hello UserName!
14 | p and the text of the DOM element can be
15 | div.
16 |
17 |
18 |
19 | Hello UserName!
20 |
21 |
22 |
23 | p Take this fact into account when searching for an element using it's text value.
24 | div(class="container")
25 | div(class="row")
26 | div(class="col-sm") Does not work
27 | div(class="col-sm") Works
28 | div(class="row")
29 | div(class="col-sm")
30 | code //span[.='Welcome UserName!']
31 | div(class="col-sm")
32 | code //span[normalize-space(.)='Welcome UserName!']
33 | br
34 | h4 Scenario
35 | ul
36 | li.
37 | Create a test that finds an element with Welcome... text.
38 | h4 Playground
39 | include text.html
40 | include footer.html
41 |
42 |
--------------------------------------------------------------------------------
/views/ClassAttr.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p Class attribute of an element may contain more than one class reference. E.g.
11 |
<button class="btn btn-primary btn-test">
12 | p XPath selector relying on a class must be well formed. For example, the following will not work:
13 |
16 | h4 Scenario
17 | ul
18 | li Record primary (blue) button click and press ok in alert popup.
19 | li Then execute your test to make sure that it can identify the button using btn-primary class.
20 | h4 Playground
21 | button(
22 | type="button"
23 | class="btn class1 " + button1Class + " btn-test"
24 | ) Button
25 | button(
26 | type="button"
27 | class="btn class2 " + button2Class + " btn-test"
28 | ) Button
29 | button(
30 | type="button"
31 | class="btn class3 " + button3Class + " btn-test"
32 | ) Button
33 |
34 | script.
35 | function ClickEventHandler(event)
36 | {
37 | if (("" + event.target.className).indexOf("btn-primary") != -1)
38 | {
39 | alert("Primary button pressed");
40 | }
41 | }
42 | document.body.addEventListener('click', ClickEventHandler, true);
43 |
44 | include footer.html
45 |
46 |
--------------------------------------------------------------------------------
/views/Animation.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p Before clicking a button we may need to wait for it to become stable (not moving).
11 | h4 Scenario
12 | ul
13 | li Record `Start Animation` button click. Wait for animation to complete and record click on `Moving Target`.
14 | li Then execute your test to make sure that when Moving Target is clicked, it's class does not contain 'spin'. The class is printed on the status label below the buttons.
15 | h4 Playground
16 | button(
17 | id="animationButton"
18 | type="button"
19 | class="btn btn-secondary"
20 | onclick="startAnimation()"
21 | ) Start Animation
22 | span
23 | button(
24 | id="movingTarget"
25 | type="button"
26 | class="btn btn-primary"
27 | onclick="movingTargetClicked()"
28 | onanimationend="animationDone()"
29 | ) Moving Target
30 | div(
31 | id="opstatus"
32 | ) ---
33 |
34 | script.
35 | function startAnimation()
36 | {
37 | setStatus("Animating the button...");
38 | byid("movingTarget").className = "btn btn-primary spin";
39 | }
40 |
41 | function animationDone()
42 | {
43 | byid("movingTarget").className = "btn btn-primary";
44 | setStatus("Animation done");
45 | }
46 |
47 | function movingTargetClicked()
48 | {
49 | setStatus("Moving Target clicked. It's class name is '" + byid("movingTarget").className + "'");
50 | }
51 |
52 | include footer.html
53 |
54 |
--------------------------------------------------------------------------------
/views/HiddenLayers.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p Some applications use DOM caching techniques. For example, if a user follows a multi step process and each step requires filling data into a form then forms may be cached at the client side along the way. It allows to quickly navigate back and forward through the steps without requesting data from a server. When form is cached it just pushed on-top of z-order stack. It means that an element may be still present in the DOM tree but overlapped with another layer of elements. In this case it is important that a test does not interact with inactive elements becasue they are invisible to a user.
11 | h4 Scenario
12 | ul
13 | li Record button click and then duplicate the button click step in your test.
14 | li Execute the test to make sure that green button can not be hit twice.
15 | h4 Playground
16 | div(
17 | id="spa"
18 | )
19 | div(
20 | class="spa-view"
21 | style="z-index: 1;"
22 | )
23 | button(
24 | type="button"
25 | class="btn btn-success"
26 | id="greenButton"
27 | ) Button
28 | div
29 | br
30 |
31 | script.
32 | function ClickEventHandler(event)
33 | {
34 | if (event.target.id == "greenButton")
35 | {
36 | console.log("Green button pressed");
37 | if ($("#blueButton").length)
38 | {
39 | $("#blueButton").parent().append("
User can not click green button in the current application state!
");
40 | }
41 | $("#spa").append('');
42 | }
43 | else if (event.target.id == "blueButton")
44 | {
45 | console.log("Blue button pressed");
46 | }
47 | }
48 | document.body.addEventListener('click', ClickEventHandler, true);
49 |
50 | include footer.html
51 |
52 |
--------------------------------------------------------------------------------
/views/Alerts.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p Dealing with standard alerts, prompts and confirmations is an important skill in test automation.
11 | h4 Scenario
12 | ul
13 | li Record clicks on `Alert`, `Confirm` and `Prompt` buttons. Click `OK` to confirm, answer with non-default value to the prompt.
14 | li Then execute your test to make sure that it passes completely without manual steps.
15 | h4 Playground
16 | button(
17 | id="alertButton"
18 | type="button"
19 | class="btn btn-primary"
20 | ) Alert
21 | span
22 | button(
23 | id="confirmButton"
24 | type="button"
25 | class="btn btn-primary"
26 | ) Confirm
27 | span
28 | button(
29 | id="promptButton"
30 | type="button"
31 | class="btn btn-primary"
32 | ) Prompt
33 |
34 | script.
35 | function ClickEventHandler(event)
36 | {
37 | if (event.target.id == "alertButton")
38 | {
39 | alert("Today is a working day.\nOr less likely a holiday.");
40 | console.log("Alert closed");
41 | }
42 | else if (event.target.id == "confirmButton")
43 | {
44 | if (confirm("Today is Friday.\nDo you agree?"))
45 | {
46 | setTimeout(function () { alert("Yes") }, 1000);
47 | }
48 | else
49 | {
50 | setTimeout(function () { alert("No") }, 1000);
51 | }
52 | }
53 | else if (event.target.id == "promptButton")
54 | {
55 | var res = prompt("Choose \"cats\" or 'dogs'.\nEnter your value:", "cats");
56 | if (res == null)
57 | {
58 | res = "no answer";
59 | }
60 | console.log("Prompt answer: " + res);
61 | setTimeout(function () { alert("User value: " + res) }, 1000);
62 | }
63 | }
64 | document.body.addEventListener('click', ClickEventHandler, true);
65 |
66 |
67 | include footer.html
68 |
--------------------------------------------------------------------------------
/views/TextInput.pug:
--------------------------------------------------------------------------------
1 | doctype html
2 | html(lang="en")
3 | include head.pug
4 | body
5 | include navbar.pug
6 |
7 | section
8 | div(class="container")
9 | h3=title
10 | p Entering text with physical keyboard can be different from sending DOM events to an element. This page is specifically desined to illustrate this problem. There are cases when attempts to set a text via DOM events lead to nowhere and the only way to proceed is to emulate real keyboard input at OS level.
11 | h4 Scenario
12 | ul
13 | li Record setting text into the input field and pressing the button.
14 | li Then execute your test to make sure that the button name is changing.
15 | h4 Playground
16 |