@quickpickle/vitest-browser 0.1.0 → 0.2.1

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +3 -2
  3. package/dist/VitestBrowserWorld.cjs +66 -16
  4. package/dist/VitestBrowserWorld.cjs.map +1 -1
  5. package/dist/VitestBrowserWorld.d.ts +16 -18
  6. package/dist/VitestBrowserWorld.mjs +67 -17
  7. package/dist/VitestBrowserWorld.mjs.map +1 -1
  8. package/dist/actions.steps.cjs +2 -2
  9. package/dist/actions.steps.cjs.map +1 -1
  10. package/dist/actions.steps.mjs +2 -2
  11. package/dist/actions.steps.mjs.map +1 -1
  12. package/dist/frameworks/ReactBrowserWorld.cjs +2 -0
  13. package/dist/frameworks/ReactBrowserWorld.cjs.map +1 -1
  14. package/dist/frameworks/ReactBrowserWorld.mjs +2 -0
  15. package/dist/frameworks/ReactBrowserWorld.mjs.map +1 -1
  16. package/dist/frameworks/SvelteBrowserWorld.cjs +2 -0
  17. package/dist/frameworks/SvelteBrowserWorld.cjs.map +1 -1
  18. package/dist/frameworks/SvelteBrowserWorld.mjs +2 -0
  19. package/dist/frameworks/SvelteBrowserWorld.mjs.map +1 -1
  20. package/dist/frameworks/VueBrowserWorld.cjs +2 -0
  21. package/dist/frameworks/VueBrowserWorld.cjs.map +1 -1
  22. package/dist/frameworks/VueBrowserWorld.mjs +2 -0
  23. package/dist/frameworks/VueBrowserWorld.mjs.map +1 -1
  24. package/dist/frameworks/react.cjs +2 -0
  25. package/dist/frameworks/react.cjs.map +1 -1
  26. package/dist/frameworks/react.mjs +2 -0
  27. package/dist/frameworks/react.mjs.map +1 -1
  28. package/dist/frameworks/svelte.cjs +2 -0
  29. package/dist/frameworks/svelte.cjs.map +1 -1
  30. package/dist/frameworks/svelte.mjs +2 -0
  31. package/dist/frameworks/svelte.mjs.map +1 -1
  32. package/dist/frameworks/vue.cjs +2 -0
  33. package/dist/frameworks/vue.cjs.map +1 -1
  34. package/dist/frameworks/vue.mjs +2 -0
  35. package/dist/frameworks/vue.mjs.map +1 -1
  36. package/dist/outcomes.steps.cjs +4 -22
  37. package/dist/outcomes.steps.cjs.map +1 -1
  38. package/dist/outcomes.steps.mjs +4 -22
  39. package/dist/outcomes.steps.mjs.map +1 -1
  40. package/package.json +5 -4
  41. package/rollup.config.js +1 -1
  42. package/src/VitestBrowserWorld.ts +85 -26
  43. package/src/actions.steps.ts +2 -2
  44. package/src/outcomes.steps.ts +4 -22
  45. package/tests/generic/browser-actions.feature +5 -5
  46. package/tests/generic/browser-generic.feature +26 -64
  47. package/tests/generic/generic.steps.ts +27 -6
  48. package/vitest.workspace.ts +30 -27
@@ -148,10 +148,10 @@ When('I uncheck (the ){string}( checkbox)( box)', async function (world:VitestBr
148
148
  // })
149
149
 
150
150
  When('I wait (for ){int}ms', async function (world:VitestBrowserWorld, num) {
151
- await world.waitForTimeout(num)
151
+ await world.wait(num)
152
152
  })
153
153
  When('I wait (for ){float} second(s)', async function (world:VitestBrowserWorld, num) {
154
- await world.waitForTimeout(num * 1000)
154
+ await world.wait(num * 1000)
155
155
  })
156
156
 
157
157
  // ================
@@ -232,34 +232,16 @@ Then('a/an/the (value of )(the ){string} {word} should not/NOT be/equal {int}',
232
232
 
233
233
  // Visual regression testing
234
234
  Then('(the )screenshot/snapshot should match', async function (world:VitestBrowserWorld) {
235
- await expect(world.page).toMatchImageSnapshot({
236
- ...world.worldConfig.screenshotOptions,
237
- customSnapshotsDir: world.screenshotDir,
238
- customSnapshotIdentifier: world.screenshotFilename,
239
- })
235
+ await world.expectScreenshotMatch(world.page)
240
236
  })
241
237
  Then('(the )screenshot/snapshot {string} should match', async function (world:VitestBrowserWorld, name:string) {
242
- let explodedTags = world.info.explodedIdx ? `_(${world.info.tags.join(',')})` : ''
243
- await expect(world.page).toMatchImageSnapshot({
244
- ...world.worldConfig.screenshotOptions,
245
- customSnapshotsDir: world.screenshotDir,
246
- customSnapshotIdentifier: `${name}${explodedTags}`,
247
- })
238
+ await world.expectScreenshotMatch(world.page, name)
248
239
  })
249
240
  Then('(the )screenshot/snapshot of the {string} {word} should match', async function (world:VitestBrowserWorld, identifier, role) {
250
241
  let locator = await world.getLocator(world.page, identifier, role)
251
- await expect(locator).toMatchImageSnapshot({
252
- ...world.worldConfig.screenshotOptions,
253
- customSnapshotsDir: world.screenshotDir,
254
- customSnapshotIdentifier: world.screenshotFilename,
255
- })
242
+ await world.expectScreenshotMatch(locator)
256
243
  })
257
244
  Then('(the )screenshot/snapshot {string} of the {string} {word} should match', async function (world:VitestBrowserWorld, name, identifier, role) {
258
245
  let locator = await world.getLocator(world.page, identifier, role)
259
- let explodedTags = world.info.explodedIdx ? `_(${world.info.tags.join(',')})` : ''
260
- await expect(locator).toMatchImageSnapshot({
261
- ...world.worldConfig.screenshotOptions,
262
- customSnapshotsDir: world.screenshotDir,
263
- customSnapshotIdentifier: `${name}${explodedTags}`,
264
- })
246
+ await world.expectScreenshotMatch(locator, name)
265
247
  })
@@ -168,7 +168,7 @@ Feature: Actions step definitions in Vitest Browser
168
168
 
169
169
  Scenario: Taking a default screenshot
170
170
  When I take a screenshot
171
- Then the screenshot "Actions step definitions in Vitest Browser_Taking a default screenshot_01.png" should exist--delete it
171
+ Then the screenshot "Feature Actions step definitions in Vitest Browser_Taking a default screenshot_01.png" should exist--delete it
172
172
 
173
173
  Scenario: Taking a named screenshot
174
174
  When I take a screenshot named "pickles"
@@ -184,10 +184,10 @@ Feature: Actions step definitions in Vitest Browser
184
184
 
185
185
  @sequential
186
186
  Scenario: Cleaning up the screenshots with exploded tags
187
- Then the screenshot "Actions step definitions in Vitest Browser_Taking a default screenshot with exploded tags (sequential,tag1)_01.png" should exist--delete it
188
- And the screenshot "Actions step definitions in Vitest Browser_Taking a default screenshot with exploded tags (sequential,tag2)_01.png" should exist--delete it
187
+ Then the screenshot "Feature Actions step definitions in Vitest Browser_Taking a default screenshot with exploded tags (sequential,tag1)_01.png" should exist--delete it
188
+ And the screenshot "Feature Actions step definitions in Vitest Browser_Taking a default screenshot with exploded tags (sequential,tag2)_01.png" should exist--delete it
189
189
 
190
190
  @sequential @skip-ci
191
191
  Scenario: Cleaning up the screenshots with exploded tags
192
- And the screenshot "temp (sequential,tag1).png" should exist--delete it
193
- And the screenshot "temp (sequential,tag2).png" should exist--delete it
192
+ And the screenshot "temp_(sequential,tag1).png" should exist--delete it
193
+ And the screenshot "temp_(sequential,tag2).png" should exist--delete it
@@ -1,79 +1,41 @@
1
- @todo
2
1
  Feature: Basic tests of Vitest Browser Mode and steps
3
2
 
4
- @skip-ci
3
+ Background:
4
+ Given I render the "Example" component
5
+
5
6
  Rule: Visual regression testing must be supported
6
7
 
8
+ @soft
9
+ Example: New visual regression test
10
+ Given the screenshot "example" does not exist
11
+ When the screenshot "example" should match
12
+ Then the screenshot "example" should exist--delete it
13
+ And there should have been 1 error
14
+
7
15
  Example: Passing visual regression test
8
- When I render the "Example" component
9
- Then the screenshot should match
16
+ Given the screenshot should match
10
17
 
11
18
  Example: Passing named visual regression test
12
- When I render the "Example" component
13
19
  Then the screenshot "visual-regression-example-page" should match
14
20
 
15
21
  Example: Passing visual regression test of an element
16
- When I render the "Example" component
17
22
  Then the screenshot of the "XKCD Comic" img should match
18
23
 
24
+ @todo
19
25
  Example: Passing named visual regression test of an element
20
- When I render the "Example" component
21
26
  Then the screenshot "visual-regression-faq-section" of the "#faq" element should match
22
27
 
23
- @fails
24
- Example: Failing visual regression test
25
- When I render the "Example" component
26
- Then the screenshot "visual-regression-simple-page.png.diff.png" should not exist
27
- And the screenshot "visual-regression-simple-page.png.actual.png" should not exist
28
- And the screenshot "visual-regression-simple-page" should match
29
-
30
- Scenario: Delete the visual regression failure file
31
- Then the screenshot "visual-regression-simple-page.png.diff.png" should not exist
32
- And the screenshot "visual-regression-simple-page.png.actual.png" should exist--delete it
33
-
34
- @todo
35
- Rule: Setting screenshot options must be supported
36
-
37
- Scenario: Setting a screenshot mask
38
- Given I render the "Example" component
39
- And the following world config:
40
- ```yaml
41
- screenshotOptions:
42
- mask:
43
- - form
44
- ```
45
- Then the screenshot should match
46
-
47
- Scenario: Setting a clip area
48
- Given I render the "Example" component
49
- And the following world config:
50
- ```yaml
51
- screenshotOptions:
52
- clip:
53
- x: 0
54
- y: 60
55
- width: 300
56
- height: 180
57
- ```
58
- Then the screenshot should match
59
-
60
- Rule: Screenshots should be placed in the proper directory
61
-
62
- Scenario: Taking a screenshot
63
- When I take a screenshot
64
- Then the screenshot "Feature Basic tests of Vitest Browser Mode and steps_Taking a screenshot_01.png" should exist--delete it
65
-
66
- Scenario: Taking a named screenshot
67
- When I take a screenshot named "test"
68
- Then the screenshot "test.png" should exist--delete it
69
-
70
- Scenario: Taking a screenshot of an element
71
- Given I load the file "tests/examples/example.html"
72
- When I take a screenshot of the "Image" link
73
- Then the screenshot "Feature Basic tests of Vitest Browser Mode and steps_Taking a screenshot of an element_02.png" should exist--delete it
74
-
75
- Scenario: Taking a named screenshot of an element
76
- Given I load the file "tests/examples/example.html"
77
- When I take a screenshot of the "XKCD Comic" img named "test2"
78
- Then the screenshot "test2.png" should exist--delete it
79
-
28
+ @soft
29
+ Example: Failing visual regression test (different image content)
30
+ Given the screenshot "visual-regression-example-page" should exist
31
+ When headings have a green background
32
+ And the screenshot "visual-regression-example-page" should match
33
+ Then error 1 should contain "images were too different"
34
+ And there should have been 1 error
35
+
36
+ @soft
37
+ Example: Failing visual regression test (different image size)
38
+ Given the screenshot "visual-regression-example-page" should exist
39
+ When the screenshot "visual-regression-example-page" of the "Image" header should match
40
+ Then error 1 should contain "sizes do not match"
41
+ And there should have been 1 error
@@ -1,4 +1,4 @@
1
- import { Before, Then } from 'quickpickle'
1
+ import { Before, Then, When } from 'quickpickle'
2
2
  import type { VitestBrowserWorld } from '../../src/VitestBrowserWorld'
3
3
  import { expect } from 'vitest'
4
4
  import { commands } from '@vitest/browser/context'
@@ -7,17 +7,38 @@ import { commands } from '@vitest/browser/context'
7
7
 
8
8
  // Screenshots
9
9
  Then('the screenshot {string} should exist(--delete it)', async function (world:VitestBrowserWorld, filepath:string) {
10
- let fullpath = world.fullPath(`${world.screenshotDir}/${filepath}`)
10
+ let fullpath = world.fullPath(`${world.screenshotDir}/${filepath}.png`)
11
11
  await expect(commands.readFile(fullpath)).toBeTruthy();
12
12
  if (world.info.step?.match(/--delete it$/)) await commands.removeFile(fullpath)
13
13
  })
14
- Then('the screenshot {string} should not exist', async function (world:VitestBrowserWorld, filepath:string) {
15
- let fullpath = world.fullPath(`${world.screenshotDir}/${filepath}`)
14
+ Then('the screenshot {string} should/does not exist', async function (world:VitestBrowserWorld, filepath:string) {
15
+ let fullpath = world.fullPath(`${world.screenshotDir}/${filepath}.png`)
16
16
  try {
17
- await expect(commands.readFile(fullpath)).toBeTruthy();
17
+ await commands.readFile(fullpath);
18
18
  throw new Error(`Screenshot ${filepath} should not exist`)
19
19
  }
20
20
  catch(e) {
21
- if (e.message === `Screenshot ${filepath} should not exist`) throw e
21
+ if (!e.message.match(/ENOENT/i)) throw e
22
22
  }
23
23
  })
24
+ Then('(the )error {int} should contain {string}', async (world, idx, expected) => {
25
+ let error = world.info.errors[idx-1]
26
+ await expect(error.message).toContain(expected)
27
+ })
28
+ Then('(the )error {int} should contain the following text:', async (world, idx, expected) => {
29
+ let error = world.info.errors[idx-1]
30
+ await expect(error.message).toContain(expected.toString())
31
+ })
32
+ Then('the stack for error {int} should contain {string}', async (world, idx, expected) => {
33
+ let stack = world.info.errors[idx-1].stack.split('\n')[0]
34
+ await expect(stack).toContain(expected)
35
+ })
36
+ Then('there should have been {int} error(s)', async (world:VitestBrowserWorld, int:number) => {
37
+ expect(world.info.errors.length).toBe(int)
38
+ world.info.errors = []
39
+ })
40
+ When('headings have a {word} background', async (world:VitestBrowserWorld, color:string) => {
41
+ await world.page.getByRole('heading').all().map(el => {
42
+ el.element().setAttribute('style', `background-color: ${color};`)
43
+ })
44
+ })
@@ -17,6 +17,7 @@ export default [
17
17
  quickpickle: {
18
18
  worldConfig: {
19
19
  componentDir: 'tests/svelte',
20
+ screenshotDir: 'tests/svelte/screenshots',
20
21
  }
21
22
  },
22
23
  environment: 'browser',
@@ -33,33 +34,34 @@ export default [
33
34
  }
34
35
  }
35
36
  },
36
- {
37
- name: 'react',
38
- extends: 'vite.config.ts',
39
- plugins: [react()],
40
- test: {
41
- name: 'react',
42
- include: [ 'tests/react/*.feature' ],
43
- setupFiles: [ 'src/frameworks/react.ts', 'src/actions.steps.ts', 'src/outcomes.steps.ts' ],
44
- quickpickle: {
45
- worldConfig: {
46
- componentDir: 'tests/react',
47
- }
48
- },
49
- environment: 'browser',
50
- browser: {
51
- enabled: true,
52
- screenshotFailures: false,
53
- name: 'chromium',
54
- provider: 'playwright',
55
- ui: showBrowser,
56
- headless: !showBrowser,
57
- instances: [
58
- { browser:'chromium' },
59
- ]
60
- }
61
- }
62
- },
37
+ // {
38
+ // name: 'react',
39
+ // extends: 'vite.config.ts',
40
+ // plugins: [react()],
41
+ // test: {
42
+ // name: 'react',
43
+ // include: [ 'tests/react/*.feature' ],
44
+ // setupFiles: [ 'src/frameworks/react.ts', 'src/actions.steps.ts', 'src/outcomes.steps.ts' ],
45
+ // quickpickle: {
46
+ // worldConfig: {
47
+ // componentDir: 'tests/react',
48
+ // screenshotDir: 'tests/react/screenshots',
49
+ // }
50
+ // },
51
+ // environment: 'browser',
52
+ // browser: {
53
+ // enabled: true,
54
+ // screenshotFailures: false,
55
+ // name: 'chromium',
56
+ // provider: 'playwright',
57
+ // ui: showBrowser,
58
+ // headless: !showBrowser,
59
+ // instances: [
60
+ // { browser:'chromium' },
61
+ // ]
62
+ // }
63
+ // }
64
+ // },
63
65
  {
64
66
  name: 'vue',
65
67
  extends: 'vite.config.ts',
@@ -71,6 +73,7 @@ export default [
71
73
  quickpickle: {
72
74
  worldConfig: {
73
75
  componentDir: 'tests/vue',
76
+ screenshotDir: 'tests/vue/screenshots',
74
77
  }
75
78
  },
76
79
  environment: 'browser',