@dargmuesli/nuxt-vio-testing 23.1.1 → 23.1.3

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.
@@ -410,11 +410,15 @@ const testMetadata = async ({ page, path, title }) => {
410
410
  };
411
411
  const testOgImage = (paths) => vioTest.describe("visual regression", () => {
412
412
  vioTest("generates the open graph image", async ({ page }) => {
413
+ const base = new URL(SITE_URL);
413
414
  for (const path of [paths.en, paths.de]) {
414
415
  await page.goto(path);
415
416
  const ogImageUrl = await page.locator("meta[property=\"og:image\"]").getAttribute("content");
416
417
  if (!ogImageUrl) throw new Error("The og:image url is not given.");
417
- await page.goto(ogImageUrl);
418
+ const ogImage = new URL(ogImageUrl);
419
+ ogImage.protocol = base.protocol;
420
+ ogImage.host = base.host;
421
+ await page.goto(ogImage.toString());
418
422
  await expect(page).toHaveScreenshot();
419
423
  }
420
424
  });
@@ -1,7 +1,9 @@
1
1
  import { SITE_URL, TIMEOUT } from "./e2e/utils/constants.mjs";
2
2
  import { defineConfig, devices } from "@playwright/test";
3
+ import { fileURLToPath } from "node:url";
3
4
  //#region playwright.config.ts
4
5
  const VIO_SERVER = process.env.VIO_SERVER || "dev";
6
+ const WARM_DEV_SERVER_SCRIPT = fileURLToPath(new URL("./scripts/warm-dev-server.mjs", import.meta.url));
5
7
  /**
6
8
  * Read environment variables from file.
7
9
  * https://github.com/motdotla/dotenv
@@ -37,7 +39,7 @@ var playwright_config_default = defineConfig({
37
39
  trace: "on-first-retry"
38
40
  },
39
41
  webServer: {
40
- command: VIO_SERVER === "dev" ? "pnpm run --dir ../src certificates && node ./scripts/warm-dev-server.mjs" : `pnpm run --dir ../src certificates && pnpm run --dir ../src start:${VIO_SERVER}`,
42
+ command: VIO_SERVER === "dev" ? `pnpm run --dir ../src certificates && node ${WARM_DEV_SERVER_SCRIPT}` : `pnpm run --dir ../src certificates && pnpm run --dir ../src start:${VIO_SERVER}`,
41
43
  env: {
42
44
  NUXT_APP_SECRET: "vio-testing-app-secret-0123456789",
43
45
  NUXT_PUBLIC_VIO_IS_TESTING: "true"
@@ -0,0 +1,115 @@
1
+ // Runs the dev server on an internal port, warms it up, then proxies the
2
+ // public port to it transparently.
3
+ //
4
+ // nuxt dev answers 503 "Starting Nuxt..." while it starts up, and a request
5
+ // that reaches it during the switch to the real app can hang without ever
6
+ // being answered. Playwright's webServer availability check has no
7
+ // per-request timeout and does not retry while one is in flight, so a single
8
+ // check landing in that window would exhaust the whole timeout even though
9
+ // the site is up. Keeping the server on an internal port until it has
10
+ // answered real page loads twice in a row means the checks and the browsers
11
+ // only ever talk to a warm server; until the proxy opens they get connection
12
+ // refused, which they retry without hanging. The warmup polls use a fresh
13
+ // connection and a hard timeout per attempt, so a single orphaned request
14
+ // cannot stall them.
15
+ //
16
+ // Usage: node warm-dev-server.mjs
17
+ // The public port comes from PORT (as set by the e2e script); the dev server
18
+ // runs on PORT + 1000.
19
+
20
+ import { spawn } from 'node:child_process'
21
+ import https from 'node:https'
22
+ import net from 'node:net'
23
+
24
+ const host = process.env.HOST || 'app.localhost'
25
+ const publicPort = Number(process.env.PORT || 3000)
26
+ const internalPort = publicPort + 1000
27
+ const warmupBudgetMs = 120_000
28
+
29
+ const server = spawn('pnpm run --dir ../src start:dev', {
30
+ env: { ...process.env, PORT: String(internalPort) },
31
+ shell: true,
32
+ stdio: 'inherit',
33
+ })
34
+
35
+ function stop(code) {
36
+ server.kill('SIGTERM')
37
+ process.exit(code)
38
+ }
39
+
40
+ process.on('SIGTERM', () => stop(0))
41
+ process.on('SIGINT', () => stop(0))
42
+ server.on('exit', (code) => stop(code ?? 1))
43
+
44
+ // matches playwright's own availability check: 200 to 403
45
+ function probe() {
46
+ return new Promise((resolve) => {
47
+ const request = https.get(
48
+ {
49
+ host,
50
+ path: '/',
51
+ port: internalPort,
52
+ // talks only to the local dev server we just spawned on an internal, un-exposed
53
+ // loopback port, with our own mkcert dev cert, so there is no untrusted peer to
54
+ // authenticate; mirrors the e2e's ignoreHTTPSErrors. We only care that it is up.
55
+ rejectUnauthorized: false,
56
+ timeout: 2500,
57
+ },
58
+ (response) => {
59
+ const available =
60
+ response.statusCode >= 200 && response.statusCode < 404
61
+ response.resume()
62
+ response.on('end', () => resolve(available))
63
+ },
64
+ )
65
+ request.on('error', () => resolve(false))
66
+ request.on('timeout', () => {
67
+ request.destroy()
68
+ resolve(false)
69
+ })
70
+ })
71
+ }
72
+
73
+ async function waitForWarmup() {
74
+ const start = Date.now()
75
+ let consecutive = 0
76
+ while (Date.now() - start < warmupBudgetMs) {
77
+ if (await probe()) consecutive += 1
78
+ else consecutive = 0
79
+ if (consecutive >= 2) return true
80
+ await new Promise((resolve) => setTimeout(resolve, 1000))
81
+ }
82
+ return false
83
+ }
84
+
85
+ async function openProxy() {
86
+ const proxy = net.createServer((socket) => {
87
+ const upstream = net.connect({ host: '127.0.0.1', port: internalPort })
88
+ socket.pipe(upstream)
89
+ upstream.pipe(socket)
90
+ socket.on('error', () => upstream.destroy())
91
+ upstream.on('error', () => socket.destroy())
92
+ })
93
+ await new Promise((resolve, reject) => {
94
+ proxy.once('error', reject)
95
+ proxy.listen(publicPort, resolve)
96
+ })
97
+ return proxy
98
+ }
99
+
100
+ if (!(await waitForWarmup())) {
101
+ process.stderr.write('dev server did not warm up in time\n')
102
+ stop(1)
103
+ }
104
+
105
+ let proxy
106
+ try {
107
+ proxy = await openProxy()
108
+ } catch (error) {
109
+ process.stderr.write(
110
+ `could not open the proxy on port ${publicPort}: ${error.message}\n`,
111
+ )
112
+ stop(1)
113
+ }
114
+
115
+ proxy.on('close', () => stop(0))
package/package.json CHANGED
@@ -56,9 +56,10 @@
56
56
  "url": "git+https://github.com/dargmuesli/vio.git"
57
57
  },
58
58
  "type": "module",
59
- "version": "23.1.1",
59
+ "version": "23.1.3",
60
60
  "scripts": {
61
61
  "build": "tsdown",
62
+ "postbuild": "node -e \"import('node:fs').then(fs=>{fs.mkdirSync('dist/scripts',{recursive:true});fs.copyFileSync('scripts/warm-dev-server.mjs','dist/scripts/warm-dev-server.mjs')})\"",
62
63
  "build:watch": "tsdown --watch",
63
64
  "lint": "pnpm run lint:js && pnpm run lint:ts",
64
65
  "lint:fix": "pnpm run lint:js --fix",