@dargmuesli/nuxt-vio-testing 20.6.7 → 20.7.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.
@@ -0,0 +1,17 @@
1
+ import * as _playwright_test0 from "@playwright/test";
2
+ import { Page } from "@playwright/test";
3
+
4
+ //#region e2e/fixtures/vioTest.d.ts
5
+ declare const createDefaultPage: (page: Page) => {
6
+ page: Page;
7
+ goto: (url: string, options?: {
8
+ cookieControl?: boolean;
9
+ isLoading?: boolean;
10
+ }) => Promise<void>;
11
+ };
12
+ declare const vioTest: _playwright_test0.TestType<_playwright_test0.PlaywrightTestArgs & _playwright_test0.PlaywrightTestOptions & {
13
+ defaultPage: ReturnType<typeof createDefaultPage>;
14
+ _autoSnapshotSuffix: unknown;
15
+ }, _playwright_test0.PlaywrightWorkerArgs & _playwright_test0.PlaywrightWorkerOptions>;
16
+ //#endregion
17
+ export { vioTest };
@@ -0,0 +1,38 @@
1
+ import { expect, test } from "@playwright/test";
2
+
3
+ //#region e2e/fixtures/vioTest.ts
4
+ const createDefaultPage = (page) => {
5
+ return {
6
+ page,
7
+ goto: async (url, options) => {
8
+ await page.goto(url);
9
+ if (!options || options.isLoading !== false) await expect(page.getByTestId("is-loading")).toHaveAttribute("data-is-loading", "false");
10
+ }
11
+ };
12
+ };
13
+ const vioTest = test.extend({ defaultPage: async ({ page, context }, use) => {
14
+ await context.addCookies([
15
+ {
16
+ domain: "localhost",
17
+ name: "vio_is-testing",
18
+ path: "/",
19
+ value: "true"
20
+ },
21
+ {
22
+ domain: "localhost",
23
+ name: "vio_tz",
24
+ path: "/",
25
+ value: "Europe/Berlin"
26
+ },
27
+ {
28
+ domain: "localhost",
29
+ name: "ncc_c",
30
+ path: "/",
31
+ value: "ctga"
32
+ }
33
+ ]);
34
+ await use(createDefaultPage(page));
35
+ } });
36
+
37
+ //#endregion
38
+ export { vioTest };
@@ -0,0 +1,18 @@
1
+ import { Page } from "playwright-core";
2
+
3
+ //#region e2e/utils/constants.d.ts
4
+ declare const TIMEOUT = 60000;
5
+ declare const PAGE_READY: ({
6
+ page,
7
+ options
8
+ }: {
9
+ page: Page;
10
+ options?: {
11
+ cookieControl?: boolean;
12
+ devTools?: boolean;
13
+ isLoading?: boolean;
14
+ };
15
+ }) => Promise<void>;
16
+ declare const SITE_URL: string;
17
+ //#endregion
18
+ export { PAGE_READY, SITE_URL, TIMEOUT };
@@ -0,0 +1,12 @@
1
+ import { expect } from "@playwright/test";
2
+
3
+ //#region e2e/utils/constants.ts
4
+ const TIMEOUT = 6e4;
5
+ const PAGE_READY = async ({ page, options }) => {
6
+ if (!options || options.cookieControl !== false) await expect(page.getByRole("button", { name: "Cookie control" })).toBeVisible();
7
+ if (!options || options.isLoading !== false) await expect(page.getByTestId("is-loading")).toHaveAttribute("data-is-loading", "false");
8
+ };
9
+ const SITE_URL = process.env.NUXT_PUBLIC_SITE_URL || `https://${process.env.HOST || "localhost"}:${process.env.PORT || "3000"}`;
10
+
11
+ //#endregion
12
+ export { PAGE_READY, SITE_URL, TIMEOUT };
@@ -0,0 +1,18 @@
1
+ import { Page } from "@playwright/test";
2
+
3
+ //#region e2e/utils/tests.d.ts
4
+ declare const testA11y: (url: string) => void;
5
+ declare const testMetadata: ({
6
+ page,
7
+ path,
8
+ title
9
+ }: {
10
+ page: Page;
11
+ path: string;
12
+ title: string;
13
+ }) => Promise<void>;
14
+ declare const testOgImage: (url: string) => void;
15
+ declare const testPageLoad: (url: string, status?: number) => void;
16
+ declare const testVisualRegression: (url: string, plain?: boolean) => void;
17
+ //#endregion
18
+ export { testA11y, testMetadata, testOgImage, testPageLoad, testVisualRegression };
@@ -0,0 +1,464 @@
1
+ import { SITE_URL, TIMEOUT } from "./constants.mjs";
2
+ import { vioTest } from "../fixtures/vioTest.mjs";
3
+ import { expect } from "@playwright/test";
4
+ import AxeBuilder from "@axe-core/playwright";
5
+ import { joinURL, withoutTrailingSlash } from "ufo";
6
+
7
+ //#region e2e/utils/tests.ts
8
+ const testA11y = (url) => vioTest.describe("a11y", () => {
9
+ vioTest("should not have any automatically detectable accessibility issues", async ({ defaultPage }) => {
10
+ await defaultPage.goto(url);
11
+ expect((await new AxeBuilder({ page: defaultPage.page }).analyze()).violations.map((x) => `${x.id}\n${x.nodes.map((y) => `${y.failureSummary}\n(${y.html}\n(${y.target})`)}`).join("\n")).toEqual("");
12
+ });
13
+ });
14
+ const testMetadata = async ({ page, path, title }) => {
15
+ await page.goto(path);
16
+ expect(await page.title()).toStrictEqual(title);
17
+ const meta = [
18
+ {
19
+ tag: "html",
20
+ attributes: [{
21
+ key: "dir",
22
+ value: "ltr"
23
+ }, {
24
+ key: "lang",
25
+ value: "en"
26
+ }]
27
+ },
28
+ {
29
+ tag: "link",
30
+ attributes: [
31
+ {
32
+ key: "data-testid",
33
+ value: "polyfill-preload"
34
+ },
35
+ {
36
+ key: "rel",
37
+ value: "preload"
38
+ },
39
+ {
40
+ key: "href",
41
+ value: "https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=Promise&flags=gated"
42
+ },
43
+ {
44
+ key: "crossorigin",
45
+ value: "anonymous"
46
+ },
47
+ {
48
+ key: "as",
49
+ value: "script"
50
+ }
51
+ ]
52
+ },
53
+ {
54
+ tag: "meta",
55
+ attributes: [{
56
+ key: "charset",
57
+ value: "utf-8"
58
+ }]
59
+ },
60
+ {
61
+ tag: "meta",
62
+ attributes: [{
63
+ key: "name",
64
+ value: "viewport"
65
+ }, {
66
+ key: "content",
67
+ value: "width=device-width, initial-scale=1"
68
+ }]
69
+ },
70
+ {
71
+ tag: "meta",
72
+ attributes: [{
73
+ key: "property",
74
+ value: "og:image"
75
+ }, {
76
+ key: "content",
77
+ value: joinURL(SITE_URL, `/__og-image__/${process.env.VIO_SERVER === "static" ? "static" : "image"}`, path, "/og.png")
78
+ }]
79
+ },
80
+ {
81
+ tag: "meta",
82
+ attributes: [{
83
+ key: "property",
84
+ value: "og:image:type"
85
+ }, {
86
+ key: "content",
87
+ value: "image/png"
88
+ }]
89
+ },
90
+ {
91
+ tag: "meta",
92
+ attributes: [{
93
+ key: "name",
94
+ value: "twitter:card"
95
+ }, {
96
+ key: "content",
97
+ value: "summary_large_image"
98
+ }]
99
+ },
100
+ {
101
+ tag: "meta",
102
+ attributes: [{
103
+ key: "name",
104
+ value: "twitter:image"
105
+ }, {
106
+ key: "content",
107
+ value: joinURL(SITE_URL, `/__og-image__/${process.env.VIO_SERVER === "static" ? "static" : "image"}`, path, "/og.png")
108
+ }]
109
+ },
110
+ {
111
+ tag: "meta",
112
+ attributes: [{
113
+ key: "name",
114
+ value: "twitter:image:src"
115
+ }, {
116
+ key: "content",
117
+ value: joinURL(SITE_URL, `/__og-image__/${process.env.VIO_SERVER === "static" ? "static" : "image"}`, path, "/og.png")
118
+ }]
119
+ },
120
+ {
121
+ tag: "meta",
122
+ attributes: [{
123
+ key: "property",
124
+ value: "og:image:width"
125
+ }, {
126
+ key: "content",
127
+ value: "1200"
128
+ }]
129
+ },
130
+ {
131
+ tag: "meta",
132
+ attributes: [{
133
+ key: "name",
134
+ value: "twitter:image:width"
135
+ }, {
136
+ key: "content",
137
+ value: "1200"
138
+ }]
139
+ },
140
+ {
141
+ tag: "meta",
142
+ attributes: [{
143
+ key: "property",
144
+ value: "og:image:height"
145
+ }, {
146
+ key: "content",
147
+ value: "600"
148
+ }]
149
+ },
150
+ {
151
+ tag: "meta",
152
+ attributes: [{
153
+ key: "name",
154
+ value: "twitter:image:height"
155
+ }, {
156
+ key: "content",
157
+ value: "600"
158
+ }]
159
+ },
160
+ {
161
+ tag: "meta",
162
+ attributes: [{
163
+ key: "property",
164
+ value: "og:image:alt"
165
+ }, {
166
+ key: "content",
167
+ value: "Social Preview Image for a Vio webpage."
168
+ }]
169
+ },
170
+ {
171
+ tag: "meta",
172
+ attributes: [{
173
+ key: "name",
174
+ value: "twitter:image:alt"
175
+ }, {
176
+ key: "content",
177
+ value: "Social Preview Image for a Vio webpage."
178
+ }]
179
+ },
180
+ {
181
+ tag: "link",
182
+ attributes: [
183
+ {
184
+ key: "rel",
185
+ value: "icon"
186
+ },
187
+ {
188
+ key: "href",
189
+ value: "/favicon.ico?v=zeMtipb6C9"
190
+ },
191
+ {
192
+ key: "sizes",
193
+ value: "48x48"
194
+ }
195
+ ]
196
+ },
197
+ {
198
+ tag: "link",
199
+ attributes: [
200
+ {
201
+ key: "rel",
202
+ value: "icon"
203
+ },
204
+ {
205
+ key: "href",
206
+ value: "/assets/static/favicon/favicon.svg?v=zeMtipb6C9"
207
+ },
208
+ {
209
+ key: "sizes",
210
+ value: "any"
211
+ },
212
+ {
213
+ key: "type",
214
+ value: "image/svg+xml"
215
+ }
216
+ ]
217
+ },
218
+ {
219
+ tag: "link",
220
+ attributes: [{
221
+ key: "rel",
222
+ value: "apple-touch-icon"
223
+ }, {
224
+ key: "href",
225
+ value: "/assets/static/favicon/apple-touch-icon-180x180.png?v=zeMtipb6C9"
226
+ }]
227
+ },
228
+ {
229
+ tag: "meta",
230
+ attributes: [{
231
+ key: "property",
232
+ value: "og:type"
233
+ }, {
234
+ key: "content",
235
+ value: "website"
236
+ }]
237
+ },
238
+ {
239
+ tag: "link",
240
+ attributes: [{
241
+ key: "rel",
242
+ value: "canonical"
243
+ }, {
244
+ key: "href",
245
+ value: `${SITE_URL}${path}`
246
+ }]
247
+ },
248
+ {
249
+ tag: "meta",
250
+ attributes: [{
251
+ key: "name",
252
+ value: "robots"
253
+ }, {
254
+ key: "content",
255
+ value: process.env.NODE_ENV === "production" ? "index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1" : "noindex, nofollow"
256
+ }]
257
+ },
258
+ {
259
+ tag: "link",
260
+ attributes: [
261
+ {
262
+ key: "href",
263
+ value: withoutTrailingSlash(`${SITE_URL}${path}`)
264
+ },
265
+ {
266
+ key: "hreflang",
267
+ value: "en"
268
+ },
269
+ {
270
+ key: "rel",
271
+ value: "alternate"
272
+ }
273
+ ]
274
+ },
275
+ {
276
+ tag: "link",
277
+ attributes: [
278
+ {
279
+ key: "href",
280
+ value: withoutTrailingSlash(`${SITE_URL}/de${path}`)
281
+ },
282
+ {
283
+ key: "hreflang",
284
+ value: "de"
285
+ },
286
+ {
287
+ key: "rel",
288
+ value: "alternate"
289
+ }
290
+ ]
291
+ },
292
+ {
293
+ tag: "link",
294
+ attributes: [
295
+ {
296
+ key: "href",
297
+ value: withoutTrailingSlash(`${SITE_URL}${path}`)
298
+ },
299
+ {
300
+ key: "hreflang",
301
+ value: "x-default"
302
+ },
303
+ {
304
+ key: "rel",
305
+ value: "alternate"
306
+ }
307
+ ]
308
+ },
309
+ {
310
+ tag: "meta",
311
+ attributes: [{
312
+ key: "property",
313
+ value: "og:url"
314
+ }, {
315
+ key: "content",
316
+ value: `${SITE_URL}${path}`
317
+ }]
318
+ },
319
+ {
320
+ tag: "meta",
321
+ attributes: [{
322
+ key: "property",
323
+ value: "og:locale"
324
+ }, {
325
+ key: "content",
326
+ value: "en"
327
+ }]
328
+ },
329
+ {
330
+ tag: "meta",
331
+ attributes: [{
332
+ key: "property",
333
+ value: "og:locale:alternate"
334
+ }, {
335
+ key: "content",
336
+ value: "de"
337
+ }]
338
+ },
339
+ {
340
+ tag: "meta",
341
+ attributes: [{
342
+ key: "name",
343
+ value: "theme-color"
344
+ }, {
345
+ key: "content",
346
+ value: "#202020"
347
+ }]
348
+ },
349
+ {
350
+ tag: "link",
351
+ attributes: [{
352
+ key: "href",
353
+ value: "/site.webmanifest?v=zeMtipb6C9"
354
+ }, {
355
+ key: "rel",
356
+ value: "manifest"
357
+ }]
358
+ },
359
+ {
360
+ tag: "meta",
361
+ attributes: [{
362
+ key: "name",
363
+ value: "description"
364
+ }, {
365
+ key: "content",
366
+ value: "Vio is @dargmuesli's Nuxt layer."
367
+ }]
368
+ },
369
+ {
370
+ tag: "meta",
371
+ attributes: [{
372
+ key: "property",
373
+ value: "og:description"
374
+ }, {
375
+ key: "content",
376
+ value: "Vio is @dargmuesli's Nuxt layer."
377
+ }]
378
+ },
379
+ {
380
+ tag: "meta",
381
+ attributes: [{
382
+ key: "name",
383
+ value: "twitter:description"
384
+ }, {
385
+ key: "content",
386
+ value: "Vio is @dargmuesli's Nuxt layer."
387
+ }]
388
+ },
389
+ {
390
+ tag: "meta",
391
+ attributes: [{
392
+ key: "property",
393
+ value: "og:title"
394
+ }, {
395
+ key: "content",
396
+ value: title
397
+ }]
398
+ },
399
+ {
400
+ tag: "meta",
401
+ attributes: [{
402
+ key: "name",
403
+ value: "twitter:title"
404
+ }, {
405
+ key: "content",
406
+ value: title
407
+ }]
408
+ },
409
+ {
410
+ tag: "meta",
411
+ attributes: [{
412
+ key: "property",
413
+ value: "og:site_name"
414
+ }, {
415
+ key: "content",
416
+ value: "Vio Playground"
417
+ }]
418
+ },
419
+ {
420
+ tag: "meta",
421
+ attributes: [{
422
+ key: "name",
423
+ value: "twitter:site"
424
+ }, {
425
+ key: "content",
426
+ value: "@dargmuesli"
427
+ }]
428
+ },
429
+ {
430
+ tag: "script",
431
+ attributes: [{
432
+ key: "data-hid",
433
+ value: "schema-org-graph"
434
+ }, {
435
+ key: "type",
436
+ value: "application/ld+json"
437
+ }]
438
+ }
439
+ ];
440
+ for (const object of meta) await expect(page.locator(object.tag + object.attributes?.map((attribute) => `[${attribute.key}="${attribute.value}"]`).join(""))).toBeAttached();
441
+ expect(await page.locator("script[data-hid=\"schema-org-graph\"]").innerText()).toMatchSnapshot(`schema-org-graph-${process.env.VIO_SERVER || "dev"}.json`);
442
+ };
443
+ const testOgImage = (url) => vioTest.describe("visual regression", () => {
444
+ vioTest("generates the open graph image", async ({ page }) => {
445
+ await page.goto(joinURL(`/__og-image__/${process.env.VIO_SERVER === "static" ? "static" : "image"}${url}/og.png`));
446
+ await expect(page).toHaveScreenshot();
447
+ await page.goto(joinURL(`/__og-image__/${process.env.VIO_SERVER === "static" ? "static" : "image"}/de${url}/og.png`));
448
+ await expect(page).toHaveScreenshot();
449
+ });
450
+ });
451
+ const testPageLoad = (url, status = 200) => vioTest.describe("page load", () => {
452
+ vioTest("loads the page successfully", async ({ request }) => {
453
+ expect((await request.get(url, { headers: { Cookie: "vio_is-testing=true" } })).status()).toBe(status);
454
+ });
455
+ });
456
+ const testVisualRegression = (url, plain) => vioTest.describe("visual regression", () => {
457
+ vioTest("looks as before", async ({ defaultPage, page }) => {
458
+ await (plain ? page : defaultPage).goto(url);
459
+ await expect(plain ? page : defaultPage.page).toHaveScreenshot({ timeout: TIMEOUT });
460
+ });
461
+ });
462
+
463
+ //#endregion
464
+ export { testA11y, testMetadata, testOgImage, testPageLoad, testVisualRegression };
@@ -0,0 +1,13 @@
1
+ import * as _playwright_test0 from "@playwright/test";
2
+
3
+ //#region playwright.config.d.ts
4
+ /**
5
+ * Read environment variables from file.
6
+ * https://github.com/motdotla/dotenv
7
+ */
8
+ /**
9
+ * See https://playwright.dev/docs/test-configuration.
10
+ */
11
+ declare const _default: _playwright_test0.PlaywrightTestConfig<{}, {}>;
12
+ //#endregion
13
+ export { _default as default };
@@ -0,0 +1,51 @@
1
+ import { SITE_URL, TIMEOUT } from "./e2e/utils/constants.mjs";
2
+ import { defineConfig, devices } from "@playwright/test";
3
+
4
+ //#region playwright.config.ts
5
+ /**
6
+ * Read environment variables from file.
7
+ * https://github.com/motdotla/dotenv
8
+ */
9
+ /**
10
+ * See https://playwright.dev/docs/test-configuration.
11
+ */
12
+ var playwright_config_default = defineConfig({
13
+ expect: { toHaveScreenshot: { maxDiffPixelRatio: .01 } },
14
+ forbidOnly: !!process.env.CI,
15
+ fullyParallel: true,
16
+ outputDir: "e2e/results",
17
+ projects: [
18
+ {
19
+ name: "chromium",
20
+ use: { ...devices["Desktop Chrome"] }
21
+ },
22
+ {
23
+ name: "firefox",
24
+ use: { ...devices["Desktop Firefox"] }
25
+ },
26
+ {
27
+ name: "webkit",
28
+ use: { ...devices["Desktop Safari"] }
29
+ }
30
+ ],
31
+ reporter: [["html", { outputFolder: "e2e/report" }]],
32
+ retries: process.env.CI ? 1 : 0,
33
+ testDir: "./e2e/specs",
34
+ use: {
35
+ baseURL: SITE_URL,
36
+ ignoreHTTPSErrors: true,
37
+ trace: "on-first-retry"
38
+ },
39
+ webServer: {
40
+ command: `pnpm run --dir ../src certificates && pnpm run --dir ../src start:${process.env.VIO_SERVER || "dev"}`,
41
+ env: { NUXT_PUBLIC_VIO_IS_TESTING: "true" },
42
+ ignoreHTTPSErrors: true,
43
+ timeout: TIMEOUT,
44
+ url: SITE_URL,
45
+ reuseExistingServer: !process.env.CI
46
+ },
47
+ workers: void 0
48
+ });
49
+
50
+ //#endregion
51
+ export { playwright_config_default as default };
package/package.json CHANGED
@@ -9,6 +9,8 @@
9
9
  "eslint-config-prettier": "10.1.8",
10
10
  "eslint-plugin-prettier": "5.5.5",
11
11
  "lodash-es": "4.17.23",
12
+ "playwright-core": "1.58.2",
13
+ "tsdown": "0.20.3",
12
14
  "typescript": "5.9.3",
13
15
  "typescript-eslint": "8.54.0",
14
16
  "ufo": "1.6.3"
@@ -16,16 +18,34 @@
16
18
  "engines": {
17
19
  "node": "24"
18
20
  },
21
+ "exports": {
22
+ "./e2e/fixtures/vioTest": {
23
+ "default": "./dist/e2e/fixtures/vioTest.mjs",
24
+ "types": "./dist/e2e/fixtures/vioTest.d.mts"
25
+ },
26
+ "./e2e/utils/constants": {
27
+ "default": "./dist/e2e/utils/constants.mjs",
28
+ "types": "./dist/e2e/utils/constants.d.mts"
29
+ },
30
+ "./e2e/utils/tests": {
31
+ "default": "./dist/e2e/utils/tests.mjs",
32
+ "types": "./dist/e2e/utils/tests.d.mts"
33
+ },
34
+ "./playwright.config": {
35
+ "default": "./dist/playwright.config.mjs",
36
+ "types": "./dist/playwright.config.d.mts"
37
+ }
38
+ },
19
39
  "files": [
20
- "e2e/fixtures",
21
- "e2e/utils",
22
- "package.json",
23
- "playwright.config.ts",
24
- "tsconfig.json"
40
+ "dist"
25
41
  ],
26
42
  "name": "@dargmuesli/nuxt-vio-testing",
27
43
  "peerDependencies": {
28
- "playwright-core": "1.58.2"
44
+ "@axe-core/playwright": "^4.11.1",
45
+ "@playwright/test": "^1.58.2",
46
+ "lodash-es": "^4.17.23",
47
+ "playwright-core": "^1.58.2",
48
+ "ufo": "^1.6.3"
29
49
  },
30
50
  "publishConfig": {
31
51
  "access": "public"
@@ -35,10 +55,13 @@
35
55
  "url": "git+https://github.com/dargmuesli/vio.git"
36
56
  },
37
57
  "scripts": {
58
+ "build": "tsdown",
59
+ "build:watch": "tsdown --watch",
38
60
  "lint": "pnpm run lint:js && pnpm run lint:ts",
39
61
  "lint:fix": "pnpm run lint:js --fix",
40
62
  "lint:js": "eslint --cache",
41
63
  "lint:ts": "tsc --noEmit",
64
+ "prepublishOnly": "pnpm run build",
42
65
  "test:e2e": "playwright test",
43
66
  "test:e2e:docker:br": "pnpm run test:e2e:docker:build && pnpm run test:e2e:docker:run",
44
67
  "test:e2e:docker:build": "sudo docker build -t test-e2e_development --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g) --target test-e2e_development ..",
@@ -54,5 +77,5 @@
54
77
  "test:e2e:server:static": "cross-env NODE_ENV=production PORT=\"${PORT:-3002}\" NUXT_PUBLIC_SITE_URL=\"${NUXT_PUBLIC_SITE_URL:-https://localhost:3002}\" VIO_SERVER=static pnpm run test:e2e"
55
78
  },
56
79
  "type": "module",
57
- "version": "20.6.7"
80
+ "version": "20.7.0"
58
81
  }