@quickpickle/vitest-browser 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/README.md +70 -0
- package/dist/VitestBrowserWorld.cjs +36 -17
- package/dist/VitestBrowserWorld.cjs.map +1 -1
- package/dist/VitestBrowserWorld.d.ts +36 -10
- package/dist/VitestBrowserWorld.mjs +36 -17
- package/dist/VitestBrowserWorld.mjs.map +1 -1
- package/dist/actions.steps.cjs +24 -0
- package/dist/actions.steps.cjs.map +1 -1
- package/dist/actions.steps.mjs +25 -1
- package/dist/actions.steps.mjs.map +1 -1
- package/dist/frameworks/ReactBrowserWorld.cjs +17 -6
- package/dist/frameworks/ReactBrowserWorld.cjs.map +1 -1
- package/dist/frameworks/ReactBrowserWorld.d.ts +9 -0
- package/dist/frameworks/ReactBrowserWorld.mjs +17 -7
- package/dist/frameworks/ReactBrowserWorld.mjs.map +1 -1
- package/dist/frameworks/SvelteBrowserWorld.cjs +11 -2
- package/dist/frameworks/SvelteBrowserWorld.cjs.map +1 -1
- package/dist/frameworks/SvelteBrowserWorld.d.ts +2 -3
- package/dist/frameworks/SvelteBrowserWorld.mjs +11 -2
- package/dist/frameworks/SvelteBrowserWorld.mjs.map +1 -1
- package/dist/frameworks/VueBrowserWorld.cjs +6 -4
- package/dist/frameworks/VueBrowserWorld.cjs.map +1 -1
- package/dist/frameworks/VueBrowserWorld.d.ts +1 -3
- package/dist/frameworks/VueBrowserWorld.mjs +6 -4
- package/dist/frameworks/VueBrowserWorld.mjs.map +1 -1
- package/dist/outcomes.steps.cjs +74 -0
- package/dist/outcomes.steps.cjs.map +1 -1
- package/dist/outcomes.steps.mjs +74 -0
- package/dist/outcomes.steps.mjs.map +1 -1
- package/package.json +2 -2
- package/src/VitestBrowserWorld.ts +60 -26
- package/src/actions.steps.ts +26 -0
- package/src/frameworks/ReactBrowserWorld.ts +22 -9
- package/src/frameworks/SvelteBrowserWorld.ts +11 -3
- package/src/frameworks/VueBrowserWorld.ts +6 -5
- package/src/outcomes.steps.ts +75 -0
- package/tests/generic/browser-actions.feature +193 -0
- package/tests/generic/browser-generic.feature +79 -0
- package/tests/generic/browser-outcomes.feature +138 -0
- package/tests/generic/generic.steps.ts +23 -0
- package/tests/svelte/Example.svelte +153 -0
- package/vite.config.ts +8 -0
- package/vitest.workspace.ts +5 -9
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
Feature: Outcome step definitions on a static page
|
|
2
|
+
|
|
3
|
+
As a developer or tester
|
|
4
|
+
I need to be sure that the step definitions work as promised
|
|
5
|
+
|
|
6
|
+
Background: Load the example HTML page
|
|
7
|
+
Given I render the "Example" component
|
|
8
|
+
|
|
9
|
+
Scenario: test if text is visible when a single element matches
|
|
10
|
+
Then I should see "Item 1"
|
|
11
|
+
And the text "Item 1" should be visible
|
|
12
|
+
|
|
13
|
+
Scenario: test if text is visible when multiple elements match
|
|
14
|
+
Then I should see "Image"
|
|
15
|
+
And the text "Image" should be visible
|
|
16
|
+
|
|
17
|
+
Scenario: test that text is not visible
|
|
18
|
+
Then I should not see "FWAH!!!"
|
|
19
|
+
And the text "FWAH!!!" should not be visible
|
|
20
|
+
|
|
21
|
+
Scenario: test that elements are visible with name and role
|
|
22
|
+
Then I should see an "Email:" textbox
|
|
23
|
+
And I should see a "Form" heading
|
|
24
|
+
|
|
25
|
+
Scenario: test that elements are visible with inexact name and role
|
|
26
|
+
Then I should see an "orm" heading
|
|
27
|
+
|
|
28
|
+
Scenario: test that elements are not visible
|
|
29
|
+
Then I should not see a "FWAH!!!" textbox
|
|
30
|
+
And I should not see a "Form" notheading
|
|
31
|
+
|
|
32
|
+
Scenario: test that an element hidden with display:none is not visible
|
|
33
|
+
Then I should not see "Hidden item"
|
|
34
|
+
|
|
35
|
+
Scenario: test that an element hidden with visibility:hidden is not visible
|
|
36
|
+
Then I should not see "Invisible item"
|
|
37
|
+
|
|
38
|
+
@todo
|
|
39
|
+
Scenario: test that elements matching text are visible
|
|
40
|
+
Then I should see an "h1" element with the text "HTML Test Page"
|
|
41
|
+
And I should see an "li" with the text "First item"
|
|
42
|
+
|
|
43
|
+
@todo
|
|
44
|
+
Scenario: test that elements matching text are not visible
|
|
45
|
+
Then I should NOT see an "h1" element with the text "FWAH!!!"
|
|
46
|
+
And I should NOT see a "fwah" element with the text "FWEEE!!!"
|
|
47
|
+
|
|
48
|
+
Rule: All of the ways of addressing an element should be tested
|
|
49
|
+
|
|
50
|
+
@todo
|
|
51
|
+
Example: it works to address an element with css selector
|
|
52
|
+
Then a "textarea#message" element should be visible
|
|
53
|
+
And an 'input[type="submit"]' element should be visible
|
|
54
|
+
And a "ul>li" element should be visible
|
|
55
|
+
And a "li.hidden" element should be hidden
|
|
56
|
+
|
|
57
|
+
@should-fail @todo
|
|
58
|
+
Example: it FAILS to address an element with a css selector AND a role other than "element"
|
|
59
|
+
Then a "ul>li" listitem should be visible
|
|
60
|
+
|
|
61
|
+
@todo
|
|
62
|
+
Example: it works to address an element with name and role
|
|
63
|
+
Then an "XKCD Comic" img should be visible
|
|
64
|
+
And a "message" textbox should be visible
|
|
65
|
+
And a "lists" link should be visible
|
|
66
|
+
|
|
67
|
+
@should-fail @todo
|
|
68
|
+
Example: it FAILS to address an element with name and role IF the element is hidden
|
|
69
|
+
And a "Hidden item" listitem should be hidden
|
|
70
|
+
|
|
71
|
+
@todo
|
|
72
|
+
Example: it works to address an element with css selector and text
|
|
73
|
+
Then the 'a[href="https://xkcd.com/2928"]' element with the text "2928" should be visible
|
|
74
|
+
And the "li.hidden" element with the text "Hidden item" should be hidden
|
|
75
|
+
|
|
76
|
+
Rule: Testing for invisible elements should be possible
|
|
77
|
+
|
|
78
|
+
@todo
|
|
79
|
+
Scenario: "I should not see" does not ensure presence of invisible elements
|
|
80
|
+
Then I should not see an "li.absent" with the text "nothing"
|
|
81
|
+
|
|
82
|
+
@todo
|
|
83
|
+
Scenario: "the {string} should be hidden" passes when elements are present and invisible
|
|
84
|
+
Then the "li.hidden" element should be invisible
|
|
85
|
+
|
|
86
|
+
@should-fail @todo
|
|
87
|
+
Scenario: "the {string} should be hidden" FAILS when elements are not present
|
|
88
|
+
Then the "li.imaginary" element should be invisible
|
|
89
|
+
|
|
90
|
+
Rule: Testing for disabled / enabled state should be possible
|
|
91
|
+
|
|
92
|
+
Scenario: test that elements are disabled
|
|
93
|
+
Then the "From" textbox should be disabled
|
|
94
|
+
|
|
95
|
+
Scenario: test that elements are enabled
|
|
96
|
+
Then the "Email" textbox should be enabled
|
|
97
|
+
|
|
98
|
+
Rule: Testing for checked / unchecked state should be possible
|
|
99
|
+
|
|
100
|
+
Scenario: Checking a checkbox
|
|
101
|
+
Then the "I agree" checkbox should be unchecked
|
|
102
|
+
When I click the "I agree" checkbox
|
|
103
|
+
Then the "I agree" checkbox should be checked
|
|
104
|
+
|
|
105
|
+
Scenario: Checking a radio button
|
|
106
|
+
Then the "now" radio should be checked
|
|
107
|
+
When I click the "later" radio
|
|
108
|
+
Then the "now" radio should be unchecked
|
|
109
|
+
And the "later" radio should be checked
|
|
110
|
+
|
|
111
|
+
Rule: Testing for focused / unfocused state should be possible
|
|
112
|
+
|
|
113
|
+
Scenario: navigating through the form
|
|
114
|
+
When I click the "Name" textbox
|
|
115
|
+
Then the "Name" textbox should be focused
|
|
116
|
+
When I activate the "Email" textbox
|
|
117
|
+
Then the "Name" textbox should be blurred
|
|
118
|
+
And the "Email" textbox should be focused
|
|
119
|
+
When I type the following keys: Tab
|
|
120
|
+
Then the "Email" textbox should be blurred
|
|
121
|
+
And the "Message" textbox should be focused
|
|
122
|
+
|
|
123
|
+
Rule: Testing for form input values should be possible
|
|
124
|
+
|
|
125
|
+
Scenario: default values should be available
|
|
126
|
+
Then the value of the "From" textbox should be "example@example.com"
|
|
127
|
+
And the value of the "From" textbox should contain "example"
|
|
128
|
+
And the value of the "From" textbox should not include "FWAH!"
|
|
129
|
+
And the value of the "From" textbox should NOT be "example"
|
|
130
|
+
And the value of "From" should contain "example"
|
|
131
|
+
And the value of "From" should NOT be "example"
|
|
132
|
+
|
|
133
|
+
Scenario: date values
|
|
134
|
+
Then the value of the "Date" textbox should be "2024-10-19"
|
|
135
|
+
When I focus on the "Date" textbox
|
|
136
|
+
And I type the following keys: ArrowLeft ArrowLeft ArrowLeft ArrowUp
|
|
137
|
+
Then the value of the "Date" textbox should be "2024-11-19"
|
|
138
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Before, Then } from 'quickpickle'
|
|
2
|
+
import type { VitestBrowserWorld } from '../../src/VitestBrowserWorld'
|
|
3
|
+
import { expect } from 'vitest'
|
|
4
|
+
import { commands } from '@vitest/browser/context'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
// Screenshots
|
|
9
|
+
Then('the screenshot {string} should exist(--delete it)', async function (world:VitestBrowserWorld, filepath:string) {
|
|
10
|
+
let fullpath = world.fullPath(`${world.screenshotDir}/${filepath}`)
|
|
11
|
+
await expect(commands.readFile(fullpath)).toBeTruthy();
|
|
12
|
+
if (world.info.step?.match(/--delete it$/)) await commands.removeFile(fullpath)
|
|
13
|
+
})
|
|
14
|
+
Then('the screenshot {string} should not exist', async function (world:VitestBrowserWorld, filepath:string) {
|
|
15
|
+
let fullpath = world.fullPath(`${world.screenshotDir}/${filepath}`)
|
|
16
|
+
try {
|
|
17
|
+
await expect(commands.readFile(fullpath)).toBeTruthy();
|
|
18
|
+
throw new Error(`Screenshot ${filepath} should not exist`)
|
|
19
|
+
}
|
|
20
|
+
catch(e) {
|
|
21
|
+
if (e.message === `Screenshot ${filepath} should not exist`) throw e
|
|
22
|
+
}
|
|
23
|
+
})
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
.hidden { display:none; }
|
|
3
|
+
.invisible { visibility:hidden; }
|
|
4
|
+
|
|
5
|
+
.faq-item:has(input:checked) .faq-answer {
|
|
6
|
+
display: block;
|
|
7
|
+
max-height: 200px; /* Adjust this value based on your content */
|
|
8
|
+
transition: max-height 0.5s ease-in;
|
|
9
|
+
}
|
|
10
|
+
.faq-toggle { cursor: pointer;}
|
|
11
|
+
.faq-answer {
|
|
12
|
+
max-height: 0;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
transition: max-height 0.3s ease-out;
|
|
15
|
+
}
|
|
16
|
+
.faq-item {
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
}
|
|
19
|
+
.faq-item input[type="checkbox"] {
|
|
20
|
+
display: none;
|
|
21
|
+
}
|
|
22
|
+
</style>
|
|
23
|
+
|
|
24
|
+
<header>
|
|
25
|
+
<h1>HTML Test Page</h1>
|
|
26
|
+
<nav>
|
|
27
|
+
<ul>
|
|
28
|
+
<li><a href="#text">Text</a></li>
|
|
29
|
+
<li><a href="#lists">Lists</a></li>
|
|
30
|
+
<li><a href="#table">Table</a></li>
|
|
31
|
+
<li><a href="#form">Form</a></li>
|
|
32
|
+
<li><a href="#faq">FAQ</a></li>
|
|
33
|
+
<li><a href="#image">Image</a></li>
|
|
34
|
+
</ul>
|
|
35
|
+
</nav>
|
|
36
|
+
</header>
|
|
37
|
+
|
|
38
|
+
<main>
|
|
39
|
+
<section id="text">
|
|
40
|
+
<h2>Text Elements</h2>
|
|
41
|
+
<p>This is a paragraph with <strong>bold</strong> and <em>italic</em> text.</p>
|
|
42
|
+
<p>Here's a <a href="https://www.example.com">link</a> to an example website.</p>
|
|
43
|
+
<blockquote>This is a blockquote.</blockquote>
|
|
44
|
+
</section>
|
|
45
|
+
|
|
46
|
+
<section id="lists">
|
|
47
|
+
<h2>Lists</h2>
|
|
48
|
+
<h3>Unordered List</h3>
|
|
49
|
+
<ul>
|
|
50
|
+
<li>Item 1</li>
|
|
51
|
+
<li>Item 2</li>
|
|
52
|
+
<li>Item 3</li>
|
|
53
|
+
</ul>
|
|
54
|
+
<h3>Ordered List</h3>
|
|
55
|
+
<ol>
|
|
56
|
+
<li>First item</li>
|
|
57
|
+
<li>Second item</li>
|
|
58
|
+
<li>Third item</li>
|
|
59
|
+
<li class="hidden">Hidden item</li>
|
|
60
|
+
<li class="invisible">Invisible item</li>
|
|
61
|
+
</ol>
|
|
62
|
+
</section>
|
|
63
|
+
|
|
64
|
+
<section id="table">
|
|
65
|
+
<h2>Table</h2>
|
|
66
|
+
<table border="1">
|
|
67
|
+
<thead>
|
|
68
|
+
<tr>
|
|
69
|
+
<th>Header 1</th>
|
|
70
|
+
<th>Header 2</th>
|
|
71
|
+
</tr>
|
|
72
|
+
</thead>
|
|
73
|
+
<tbody>
|
|
74
|
+
<tr>
|
|
75
|
+
<td>Row 1, Cell 1</td>
|
|
76
|
+
<td>Row 1, Cell 2</td>
|
|
77
|
+
</tr>
|
|
78
|
+
<tr>
|
|
79
|
+
<td>Row 2, Cell 1</td>
|
|
80
|
+
<td>Row 2, Cell 2</td>
|
|
81
|
+
</tr>
|
|
82
|
+
</tbody>
|
|
83
|
+
</table>
|
|
84
|
+
</section>
|
|
85
|
+
|
|
86
|
+
<section id="form">
|
|
87
|
+
<h2>Form</h2>
|
|
88
|
+
<form action="#" method="post">
|
|
89
|
+
<label for="name">Name:</label>
|
|
90
|
+
<input type="text" id="name" name="name" required><br><br>
|
|
91
|
+
|
|
92
|
+
<label for="email">Email:</label>
|
|
93
|
+
<input type="email" id="email" name="email" required><br><br>
|
|
94
|
+
|
|
95
|
+
<label for="message">Message:</label><br>
|
|
96
|
+
<textarea id="message" name="message" rows="4" cols="50"></textarea><br><br>
|
|
97
|
+
|
|
98
|
+
<label for="from">From:</label>
|
|
99
|
+
<input type="text" id="from" name="from" disabled value="example@example.com"><br><br>
|
|
100
|
+
|
|
101
|
+
<label for="date">Date:</label>
|
|
102
|
+
<input type="date" id="date" name="date" value="2024-10-19"><br><br>
|
|
103
|
+
|
|
104
|
+
<label for="number">Number:</label>
|
|
105
|
+
<input type="number" id="number" name="number"><br><br>
|
|
106
|
+
|
|
107
|
+
<label for="color">Color:</label>
|
|
108
|
+
<select id="color" name="color">
|
|
109
|
+
<option value="">- none -</option>
|
|
110
|
+
<option value="red">Red</option>
|
|
111
|
+
<option value="green">Green</option>
|
|
112
|
+
<option value="blue">Blue</option>
|
|
113
|
+
</select><br><br>
|
|
114
|
+
|
|
115
|
+
<div>Send this message:</div>
|
|
116
|
+
<input type="radio" name="sendtime" id="sendtime-now" value="now" checked>
|
|
117
|
+
<label for="sendtime-now">Now</label>
|
|
118
|
+
<input type="radio" name="sendtime" id="sendtime-later" value="later">
|
|
119
|
+
<label for="sendtime-later">Later</label><br><br>
|
|
120
|
+
|
|
121
|
+
<input type="checkbox" name="tnc" id="tnc">
|
|
122
|
+
<label for="tnc">I agree to the terms and conditions</label><br><br>
|
|
123
|
+
|
|
124
|
+
<input type="submit" value="Submit">
|
|
125
|
+
</form>
|
|
126
|
+
</section>
|
|
127
|
+
|
|
128
|
+
<section id="faq">
|
|
129
|
+
<h2>FAQ</h2>
|
|
130
|
+
<div class="faq-item" id="faq-item-1">
|
|
131
|
+
<label for="faq-1" class="faq-toggle">
|
|
132
|
+
<input type="checkbox" id="faq-1" class="faq-toggle">
|
|
133
|
+
<h3>Do CSS transitions affect Playwright awaits?</h3>
|
|
134
|
+
</label>
|
|
135
|
+
<p class="faq-answer">
|
|
136
|
+
AI says: "CSS transitions can affect Playwright awaits if not handled properly.
|
|
137
|
+
Playwright's default waiting mechanism might not account for CSS transitions,
|
|
138
|
+
potentially leading to flaky tests. It's important to use appropriate waiting
|
|
139
|
+
strategies or disable transitions in test environments to ensure consistency."
|
|
140
|
+
</p>
|
|
141
|
+
</div>
|
|
142
|
+
</section>
|
|
143
|
+
|
|
144
|
+
<section id="image">
|
|
145
|
+
<h2>Image</h2>
|
|
146
|
+
<img src="https://imgs.xkcd.com/comics/software_testing_day.png" alt="XKCD Comic 2928: Software Testing Day" width="320">
|
|
147
|
+
<p>Image source: <a href="https://xkcd.com/2928">xkcd.com/2928</a></p>
|
|
148
|
+
</section>
|
|
149
|
+
</main>
|
|
150
|
+
|
|
151
|
+
<footer>
|
|
152
|
+
<p>© 2023 HTML Test Page. All rights reserved.</p>
|
|
153
|
+
</footer>
|
package/vite.config.ts
CHANGED
package/vitest.workspace.ts
CHANGED
|
@@ -10,17 +10,10 @@ export default [
|
|
|
10
10
|
name: 'svelte',
|
|
11
11
|
extends: `vite.config.ts`,
|
|
12
12
|
plugins: [svelte()],
|
|
13
|
-
optimizeDeps: {
|
|
14
|
-
include: [
|
|
15
|
-
'vue',
|
|
16
|
-
'react',
|
|
17
|
-
'svelte',
|
|
18
|
-
],
|
|
19
|
-
},
|
|
20
13
|
test: {
|
|
21
14
|
name: 'svelte',
|
|
22
|
-
include: [ `tests/svelte/*.feature` ],
|
|
23
|
-
setupFiles: [ `src/frameworks/svelte.ts`, 'src/actions.steps.ts', 'src/outcomes.steps.ts' ],
|
|
15
|
+
include: [ `tests/svelte/*.feature`, `tests/generic/*.feature` ],
|
|
16
|
+
setupFiles: [ `src/frameworks/svelte.ts`, 'src/actions.steps.ts', 'src/outcomes.steps.ts', 'tests/generic/generic.steps.ts' ],
|
|
24
17
|
quickpickle: {
|
|
25
18
|
worldConfig: {
|
|
26
19
|
componentDir: 'tests/svelte',
|
|
@@ -29,6 +22,7 @@ export default [
|
|
|
29
22
|
environment: 'browser',
|
|
30
23
|
browser: {
|
|
31
24
|
enabled: true,
|
|
25
|
+
screenshotFailures: false,
|
|
32
26
|
name: 'chromium',
|
|
33
27
|
provider: 'playwright',
|
|
34
28
|
ui: showBrowser,
|
|
@@ -55,6 +49,7 @@ export default [
|
|
|
55
49
|
environment: 'browser',
|
|
56
50
|
browser: {
|
|
57
51
|
enabled: true,
|
|
52
|
+
screenshotFailures: false,
|
|
58
53
|
name: 'chromium',
|
|
59
54
|
provider: 'playwright',
|
|
60
55
|
ui: showBrowser,
|
|
@@ -81,6 +76,7 @@ export default [
|
|
|
81
76
|
environment: 'browser',
|
|
82
77
|
browser: {
|
|
83
78
|
enabled: true,
|
|
79
|
+
screenshotFailures: false,
|
|
84
80
|
name: 'chromium',
|
|
85
81
|
provider: 'playwright',
|
|
86
82
|
ui: showBrowser,
|