@nuxt/test-utils 3.11.0 → 3.12.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.
package/dist/config.mjs CHANGED
@@ -176,6 +176,7 @@ async function getVitestConfigFromNuxt(options, loadNuxtOptions = {}) {
176
176
  }
177
177
  );
178
178
  delete resolvedConfig.define["process.browser"];
179
+ delete resolvedConfig.customLogger;
179
180
  if (!Array.isArray(resolvedConfig.test.setupFiles)) {
180
181
  resolvedConfig.test.setupFiles = [resolvedConfig.test.setupFiles].filter(Boolean);
181
182
  }
package/dist/e2e.d.mts CHANGED
@@ -1,55 +1,9 @@
1
- import * as playwright_core from 'playwright-core';
2
- import { Browser, BrowserContextOptions, LaunchOptions } from 'playwright-core';
3
- import { NuxtConfig, Nuxt } from '@nuxt/schema';
4
- import { ExecaChildProcess } from 'execa';
1
+ import { T as TestOptions, a as TestContext, b as TestHooks } from './shared/test-utils.9059LSjm.mjs';
2
+ export { G as GotoOptions, e as TestRunner, c as createBrowser, d as createPage, g as getBrowser, w as waitForHydration } from './shared/test-utils.9059LSjm.mjs';
5
3
  import { FetchOptions } from 'ofetch';
6
-
7
- declare function createBrowser(): Promise<void>;
8
- declare function getBrowser(): Promise<Browser>;
9
- declare function createPage(path?: string, options?: BrowserContextOptions): Promise<playwright_core.Page>;
10
-
11
- type TestRunner = 'vitest' | 'jest' | 'cucumber';
12
- interface TestOptions {
13
- testDir: string;
14
- fixture: string;
15
- configFile: string;
16
- rootDir: string;
17
- buildDir: string;
18
- nuxtConfig: NuxtConfig;
19
- build: boolean;
20
- dev: boolean;
21
- setupTimeout: number;
22
- waitFor: number;
23
- browser: boolean;
24
- runner: TestRunner;
25
- logLevel: number;
26
- browserOptions: {
27
- type: 'chromium' | 'firefox' | 'webkit';
28
- launch?: LaunchOptions;
29
- };
30
- server: boolean;
31
- port?: number;
32
- }
33
- interface TestContext {
34
- options: TestOptions;
35
- nuxt?: Nuxt;
36
- browser?: Browser;
37
- url?: string;
38
- serverProcess?: ExecaChildProcess;
39
- mockFn?: Function;
40
- /**
41
- * Functions to run on the vitest `afterAll` hook.
42
- * Useful for removing anything created during the test.
43
- */
44
- teardown?: (() => void)[];
45
- }
46
- interface TestHooks {
47
- beforeEach: () => void;
48
- afterEach: () => void;
49
- afterAll: () => Promise<void>;
50
- setup: () => Promise<void>;
51
- ctx: TestContext;
52
- }
4
+ import 'playwright-core';
5
+ import '@nuxt/schema';
6
+ import 'execa';
53
7
 
54
8
  declare function createTestContext(options: Partial<TestOptions>): TestContext;
55
9
  declare function useTestContext(): TestContext;
@@ -97,4 +51,4 @@ interface RunTestOptions {
97
51
  }
98
52
  declare function runTests(opts: RunTestOptions): Promise<void>;
99
53
 
100
- export { $fetch, type RunTestOptions, type StartServerOptions, type TestContext, type TestHooks, type TestOptions, type TestRunner, buildFixture, createBrowser, createPage, createTest, createTestContext, exposeContextToEnv, fetch, getBrowser, isDev, loadFixture, mockFn, mockLogger, recoverContextFromEnv, runTests, setTestContext, setup, setupMaps, startServer, stopServer, url, useTestContext };
54
+ export { $fetch, type RunTestOptions, type StartServerOptions, TestContext, TestHooks, TestOptions, buildFixture, createTest, createTestContext, exposeContextToEnv, fetch, isDev, loadFixture, mockFn, mockLogger, recoverContextFromEnv, runTests, setTestContext, setup, setupMaps, startServer, stopServer, url, useTestContext };
package/dist/e2e.d.ts CHANGED
@@ -1,55 +1,9 @@
1
- import * as playwright_core from 'playwright-core';
2
- import { Browser, BrowserContextOptions, LaunchOptions } from 'playwright-core';
3
- import { NuxtConfig, Nuxt } from '@nuxt/schema';
4
- import { ExecaChildProcess } from 'execa';
1
+ import { T as TestOptions, a as TestContext, b as TestHooks } from './shared/test-utils.9059LSjm.js';
2
+ export { G as GotoOptions, e as TestRunner, c as createBrowser, d as createPage, g as getBrowser, w as waitForHydration } from './shared/test-utils.9059LSjm.js';
5
3
  import { FetchOptions } from 'ofetch';
6
-
7
- declare function createBrowser(): Promise<void>;
8
- declare function getBrowser(): Promise<Browser>;
9
- declare function createPage(path?: string, options?: BrowserContextOptions): Promise<playwright_core.Page>;
10
-
11
- type TestRunner = 'vitest' | 'jest' | 'cucumber';
12
- interface TestOptions {
13
- testDir: string;
14
- fixture: string;
15
- configFile: string;
16
- rootDir: string;
17
- buildDir: string;
18
- nuxtConfig: NuxtConfig;
19
- build: boolean;
20
- dev: boolean;
21
- setupTimeout: number;
22
- waitFor: number;
23
- browser: boolean;
24
- runner: TestRunner;
25
- logLevel: number;
26
- browserOptions: {
27
- type: 'chromium' | 'firefox' | 'webkit';
28
- launch?: LaunchOptions;
29
- };
30
- server: boolean;
31
- port?: number;
32
- }
33
- interface TestContext {
34
- options: TestOptions;
35
- nuxt?: Nuxt;
36
- browser?: Browser;
37
- url?: string;
38
- serverProcess?: ExecaChildProcess;
39
- mockFn?: Function;
40
- /**
41
- * Functions to run on the vitest `afterAll` hook.
42
- * Useful for removing anything created during the test.
43
- */
44
- teardown?: (() => void)[];
45
- }
46
- interface TestHooks {
47
- beforeEach: () => void;
48
- afterEach: () => void;
49
- afterAll: () => Promise<void>;
50
- setup: () => Promise<void>;
51
- ctx: TestContext;
52
- }
4
+ import 'playwright-core';
5
+ import '@nuxt/schema';
6
+ import 'execa';
53
7
 
54
8
  declare function createTestContext(options: Partial<TestOptions>): TestContext;
55
9
  declare function useTestContext(): TestContext;
@@ -97,4 +51,4 @@ interface RunTestOptions {
97
51
  }
98
52
  declare function runTests(opts: RunTestOptions): Promise<void>;
99
53
 
100
- export { $fetch, type RunTestOptions, type StartServerOptions, type TestContext, type TestHooks, type TestOptions, type TestRunner, buildFixture, createBrowser, createPage, createTest, createTestContext, exposeContextToEnv, fetch, getBrowser, isDev, loadFixture, mockFn, mockLogger, recoverContextFromEnv, runTests, setTestContext, setup, setupMaps, startServer, stopServer, url, useTestContext };
54
+ export { $fetch, type RunTestOptions, type StartServerOptions, TestContext, TestHooks, TestOptions, buildFixture, createTest, createTestContext, exposeContextToEnv, fetch, isDev, loadFixture, mockFn, mockLogger, recoverContextFromEnv, runTests, setTestContext, setup, setupMaps, startServer, stopServer, url, useTestContext };
package/dist/e2e.mjs CHANGED
@@ -1,52 +1,18 @@
1
- import { u as useTestContext, a as url, c as createTestContext, s as setTestContext, b as stopServer, d as startServer } from './shared/test-utils.JYxxBhQl.mjs';
2
- export { $ as $fetch, e as exposeContextToEnv, f as fetch, i as isDev, r as recoverContextFromEnv } from './shared/test-utils.JYxxBhQl.mjs';
1
+ import { d as distDir } from './shared/test-utils.B57u8E0c.mjs';
2
+ export { b as buildFixture, c as createBrowser, a as createPage, e as createTest, g as getBrowser, l as loadFixture, f as setup, s as setupMaps, w as waitForHydration } from './shared/test-utils.B57u8E0c.mjs';
3
+ import { u as useTestContext } from './shared/test-utils.BegIhSnH.mjs';
4
+ export { $ as $fetch, c as createTestContext, e as exposeContextToEnv, f as fetch, i as isDev, r as recoverContextFromEnv, s as setTestContext, a as startServer, b as stopServer, d as url } from './shared/test-utils.BegIhSnH.mjs';
3
5
  import { consola } from 'consola';
4
- import { existsSync, promises } from 'node:fs';
5
- import { resolve } from 'node:path';
6
- import { defu } from 'defu';
7
- import * as _kit from '@nuxt/kit';
8
- import { dirname, resolve as resolve$1 } from 'pathe';
9
- import { fileURLToPath } from 'node:url';
6
+ import { resolve } from 'pathe';
7
+ import 'node:fs';
8
+ import 'node:path';
9
+ import 'defu';
10
+ import '@nuxt/kit';
11
+ import 'node:url';
10
12
  import 'execa';
11
13
  import 'get-port-please';
12
14
  import 'ofetch';
13
15
 
14
- async function createBrowser() {
15
- const ctx = useTestContext();
16
- let playwright;
17
- try {
18
- playwright = await import(
19
- /* vite-ignore */
20
- 'playwright-core'
21
- );
22
- } catch {
23
- throw new Error(`
24
- The dependency 'playwright-core' not found.
25
- Please run 'yarn add --dev playwright-core' or 'npm install --save-dev playwright-core'
26
- `);
27
- }
28
- const { type, launch } = ctx.options.browserOptions;
29
- if (!playwright[type]) {
30
- throw new Error(`Invalid browser '${type}'`);
31
- }
32
- ctx.browser = await playwright[type].launch(launch);
33
- }
34
- async function getBrowser() {
35
- const ctx = useTestContext();
36
- if (!ctx.browser) {
37
- await createBrowser();
38
- }
39
- return ctx.browser;
40
- }
41
- async function createPage(path, options) {
42
- const browser = await getBrowser();
43
- const page = await browser.newPage(options);
44
- if (path) {
45
- await page.goto(url(path));
46
- }
47
- return page;
48
- }
49
-
50
16
  function mockFn() {
51
17
  const ctx = useTestContext();
52
18
  return ctx.mockFn;
@@ -60,146 +26,6 @@ function mockLogger() {
60
26
  return mocks;
61
27
  }
62
28
 
63
- const kit = _kit.default || _kit;
64
- const isNuxtApp = (dir) => {
65
- return existsSync(dir) && (existsSync(resolve(dir, "pages")) || existsSync(resolve(dir, "nuxt.config.js")) || existsSync(resolve(dir, "nuxt.config.mjs")) || existsSync(resolve(dir, "nuxt.config.cjs")) || existsSync(resolve(dir, "nuxt.config.ts")));
66
- };
67
- const resolveRootDir = () => {
68
- const { options } = useTestContext();
69
- const dirs = [
70
- options.rootDir,
71
- resolve(options.testDir, options.fixture),
72
- process.cwd()
73
- ];
74
- for (const dir of dirs) {
75
- if (dir && isNuxtApp(dir)) {
76
- return dir;
77
- }
78
- }
79
- throw new Error("Invalid nuxt app. (Please explicitly set `options.rootDir` pointing to a valid nuxt app)");
80
- };
81
- async function loadFixture() {
82
- const ctx = useTestContext();
83
- ctx.options.rootDir = resolveRootDir();
84
- if (!ctx.options.dev) {
85
- const randomId = Math.random().toString(36).slice(2, 8);
86
- const buildDir2 = ctx.options.buildDir || resolve(ctx.options.rootDir, ".nuxt", "test", randomId);
87
- ctx.options.nuxtConfig = defu(ctx.options.nuxtConfig, {
88
- buildDir: buildDir2,
89
- nitro: {
90
- output: {
91
- dir: resolve(buildDir2, "output")
92
- }
93
- }
94
- });
95
- }
96
- ctx.nuxt = await kit.loadNuxt({
97
- cwd: ctx.options.rootDir,
98
- dev: ctx.options.dev,
99
- overrides: ctx.options.nuxtConfig,
100
- configFile: ctx.options.configFile
101
- });
102
- const buildDir = ctx.nuxt.options.buildDir;
103
- if (!existsSync(buildDir)) {
104
- await promises.mkdir(buildDir, { recursive: true });
105
- ctx.teardown = ctx.teardown || [];
106
- ctx.teardown.push(() => promises.rm(buildDir, { recursive: true, force: true }));
107
- }
108
- }
109
- async function buildFixture() {
110
- const ctx = useTestContext();
111
- const prevLevel = kit.logger.level;
112
- kit.logger.level = ctx.options.logLevel;
113
- await kit.buildNuxt(ctx.nuxt);
114
- kit.logger.level = prevLevel;
115
- }
116
-
117
- async function setupCucumber(hooks) {
118
- const { After, AfterAll, Before, BeforeAll } = await import('@cucumber/cucumber');
119
- BeforeAll({ timeout: hooks.ctx.options.setupTimeout }, hooks.setup);
120
- Before(hooks.beforeEach);
121
- After(hooks.afterEach);
122
- AfterAll(hooks.afterAll);
123
- }
124
-
125
- async function setupJest(hooks) {
126
- const { jest, test, beforeEach, afterAll, afterEach } = await import('@jest/globals');
127
- hooks.ctx.mockFn = jest.fn;
128
- test("setup", hooks.setup, hooks.ctx.options.setupTimeout);
129
- beforeEach(hooks.beforeEach);
130
- afterEach(hooks.afterEach);
131
- afterAll(hooks.afterAll);
132
- }
133
-
134
- async function setupVitest(hooks) {
135
- const vitest = await import('vitest');
136
- hooks.ctx.mockFn = vitest.vi.fn;
137
- vitest.beforeAll(hooks.setup, hooks.ctx.options.setupTimeout);
138
- vitest.beforeEach(hooks.beforeEach);
139
- vitest.afterEach(hooks.afterEach);
140
- vitest.afterAll(hooks.afterAll);
141
- }
142
-
143
- const setupMaps = {
144
- cucumber: setupCucumber,
145
- jest: setupJest,
146
- vitest: setupVitest
147
- };
148
- function createTest(options) {
149
- const ctx = createTestContext(options);
150
- const beforeEach = () => {
151
- setTestContext(ctx);
152
- };
153
- const afterEach = () => {
154
- setTestContext(void 0);
155
- };
156
- const afterAll = async () => {
157
- if (ctx.serverProcess) {
158
- setTestContext(ctx);
159
- await stopServer();
160
- setTestContext(void 0);
161
- }
162
- if (ctx.nuxt && ctx.nuxt.options.dev) {
163
- await ctx.nuxt.close();
164
- }
165
- if (ctx.browser) {
166
- await ctx.browser.close();
167
- }
168
- await Promise.all((ctx.teardown || []).map((fn) => fn()));
169
- };
170
- const setup2 = async () => {
171
- if (ctx.options.fixture) {
172
- await loadFixture();
173
- }
174
- if (ctx.options.build) {
175
- await buildFixture();
176
- }
177
- if (ctx.options.server) {
178
- await startServer();
179
- }
180
- if (ctx.options.waitFor) {
181
- await new Promise((resolve) => setTimeout(resolve, ctx.options.waitFor));
182
- }
183
- if (ctx.options.browser) {
184
- await createBrowser();
185
- }
186
- };
187
- return {
188
- beforeEach,
189
- afterEach,
190
- afterAll,
191
- setup: setup2,
192
- ctx
193
- };
194
- }
195
- async function setup(options = {}) {
196
- const hooks = createTest(options);
197
- const setupFn = setupMaps[hooks.ctx.options.runner];
198
- await setupFn(hooks);
199
- }
200
-
201
- const distDir = dirname(fileURLToPath(import.meta.url));
202
-
203
29
  const RunTestDefaults = {
204
30
  runner: "vitest",
205
31
  globalSetup: true
@@ -242,7 +68,7 @@ async function runTests(opts) {
242
68
  },
243
69
  globals: true,
244
70
  globalSetup: [
245
- ...opts.globalSetup ? [resolve$1(distDir, "./runtime/global-setup")] : []
71
+ ...opts.globalSetup ? [resolve(distDir, "./runtime/global-setup")] : []
246
72
  ]
247
73
  }
248
74
  }
@@ -252,4 +78,4 @@ async function runTests(opts) {
252
78
  }
253
79
  }
254
80
 
255
- export { buildFixture, createBrowser, createPage, createTest, createTestContext, getBrowser, loadFixture, mockFn, mockLogger, runTests, setTestContext, setup, setupMaps, startServer, stopServer, url, useTestContext };
81
+ export { mockFn, mockLogger, runTests, useTestContext };
@@ -1,6 +1,6 @@
1
1
  import { resolve } from 'pathe';
2
2
  import { stringifyQuery } from 'ufo';
3
- import { $ as $fetch, u as useTestContext } from './shared/test-utils.JYxxBhQl.mjs';
3
+ import { $ as $fetch, u as useTestContext } from './shared/test-utils.BegIhSnH.mjs';
4
4
  import 'execa';
5
5
  import 'get-port-please';
6
6
  import 'ofetch';
@@ -0,0 +1,33 @@
1
+ import * as _playwright_test from '@playwright/test';
2
+ export { expect } from '@playwright/test';
3
+ import { Response } from 'playwright-core';
4
+ import { T as TestOptions$1, b as TestHooks, G as GotoOptions } from './shared/test-utils.9059LSjm.mjs';
5
+ import '@nuxt/schema';
6
+ import 'execa';
7
+
8
+ type ConfigOptions = {
9
+ nuxt: Partial<TestOptions$1> | undefined;
10
+ };
11
+ type WorkerOptions = {
12
+ _nuxtHooks: TestHooks;
13
+ };
14
+ type TestOptions = {
15
+ goto: (url: string, options?: GotoOptions) => Promise<Response | null>;
16
+ };
17
+ /**
18
+ * Use a preconfigured Nuxt fixture.
19
+ *
20
+ * You can pass a `nuxt: {}` object in your device configuration, in the `use` key of your config file,
21
+ * or use the following syntax within your test file to configure your Nuxt fixture:
22
+ *
23
+ ```ts
24
+ test.use({
25
+ nuxt: {
26
+ rootDir: fileURLToPath(new URL('.', import.meta.url)),
27
+ }
28
+ })
29
+ ```
30
+ */
31
+ declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & TestOptions, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerOptions & ConfigOptions>;
32
+
33
+ export { type ConfigOptions, test };
@@ -0,0 +1,33 @@
1
+ import * as _playwright_test from '@playwright/test';
2
+ export { expect } from '@playwright/test';
3
+ import { Response } from 'playwright-core';
4
+ import { T as TestOptions$1, b as TestHooks, G as GotoOptions } from './shared/test-utils.9059LSjm.js';
5
+ import '@nuxt/schema';
6
+ import 'execa';
7
+
8
+ type ConfigOptions = {
9
+ nuxt: Partial<TestOptions$1> | undefined;
10
+ };
11
+ type WorkerOptions = {
12
+ _nuxtHooks: TestHooks;
13
+ };
14
+ type TestOptions = {
15
+ goto: (url: string, options?: GotoOptions) => Promise<Response | null>;
16
+ };
17
+ /**
18
+ * Use a preconfigured Nuxt fixture.
19
+ *
20
+ * You can pass a `nuxt: {}` object in your device configuration, in the `use` key of your config file,
21
+ * or use the following syntax within your test file to configure your Nuxt fixture:
22
+ *
23
+ ```ts
24
+ test.use({
25
+ nuxt: {
26
+ rootDir: fileURLToPath(new URL('.', import.meta.url)),
27
+ }
28
+ })
29
+ ```
30
+ */
31
+ declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArgs & _playwright_test.PlaywrightTestOptions & TestOptions, _playwright_test.PlaywrightWorkerArgs & _playwright_test.PlaywrightWorkerOptions & WorkerOptions & ConfigOptions>;
32
+
33
+ export { type ConfigOptions, test };
@@ -0,0 +1,66 @@
1
+ import { test as test$1 } from '@playwright/test';
2
+ export { expect } from '@playwright/test';
3
+ import { e as createTest, w as waitForHydration } from './shared/test-utils.B57u8E0c.mjs';
4
+ import 'node:path';
5
+ import 'defu';
6
+ import 'consola';
7
+ import 'node:fs';
8
+ import '@nuxt/kit';
9
+ import { d as url } from './shared/test-utils.BegIhSnH.mjs';
10
+ import 'pathe';
11
+ import 'node:url';
12
+ import 'execa';
13
+ import 'get-port-please';
14
+ import 'ofetch';
15
+
16
+ {
17
+ if (process.env.TEST_WORKER_INDEX) {
18
+ for (const stream of [process.stdout, process.stderr]) {
19
+ if (!stream.clearLine) {
20
+ stream.clearLine = (dir, callback) => {
21
+ callback?.();
22
+ return true;
23
+ };
24
+ }
25
+ if (!stream.cursorTo) {
26
+ stream.cursorTo = (x, y, callback) => {
27
+ if (callback)
28
+ callback();
29
+ else if (y instanceof Function)
30
+ y();
31
+ return true;
32
+ };
33
+ }
34
+ }
35
+ }
36
+ }
37
+ const test = test$1.extend({
38
+ nuxt: [void 0, { option: true, scope: "worker" }],
39
+ _nuxtHooks: [
40
+ async ({ nuxt }, use) => {
41
+ const hooks = createTest(nuxt || {});
42
+ await hooks.setup();
43
+ await use(hooks);
44
+ await hooks.afterAll();
45
+ },
46
+ { scope: "worker" }
47
+ ],
48
+ baseURL: async ({ _nuxtHooks }, use) => {
49
+ _nuxtHooks.beforeEach();
50
+ await use(url("/"));
51
+ _nuxtHooks.afterEach();
52
+ },
53
+ goto: async ({ page }, use) => {
54
+ await use(async (url2, options) => {
55
+ const waitUntil = options?.waitUntil;
56
+ if (waitUntil && ["hydration", "route"].includes(waitUntil)) {
57
+ delete options.waitUntil;
58
+ }
59
+ const response = await page.goto(url2, options);
60
+ await waitForHydration(page, url2, waitUntil);
61
+ return response;
62
+ });
63
+ }
64
+ });
65
+
66
+ export { test };
@@ -0,0 +1,60 @@
1
+ import { Browser, BrowserContextOptions, Page, Response, LaunchOptions } from 'playwright-core';
2
+ import { NuxtConfig, Nuxt } from '@nuxt/schema';
3
+ import { ExecaChildProcess } from 'execa';
4
+
5
+ declare function createBrowser(): Promise<void>;
6
+ declare function getBrowser(): Promise<Browser>;
7
+ type _GotoOptions = NonNullable<Parameters<Page['goto']>[1]>;
8
+ interface GotoOptions extends Omit<_GotoOptions, 'waitUntil'> {
9
+ waitUntil?: 'hydration' | 'route' | _GotoOptions['waitUntil'];
10
+ }
11
+ interface NuxtPage extends Omit<Page, 'goto'> {
12
+ goto: (url: string, options?: GotoOptions) => Promise<Response | null>;
13
+ }
14
+ declare function createPage(path?: string, options?: BrowserContextOptions): Promise<NuxtPage>;
15
+ declare function waitForHydration(page: Page, url: string, waitUntil?: GotoOptions['waitUntil']): Promise<void>;
16
+
17
+ type TestRunner = 'vitest' | 'jest' | 'cucumber';
18
+ interface TestOptions {
19
+ testDir: string;
20
+ fixture: string;
21
+ configFile: string;
22
+ rootDir: string;
23
+ buildDir: string;
24
+ nuxtConfig: NuxtConfig;
25
+ build: boolean;
26
+ dev: boolean;
27
+ setupTimeout: number;
28
+ waitFor: number;
29
+ browser: boolean;
30
+ runner: TestRunner;
31
+ logLevel: number;
32
+ browserOptions: {
33
+ type: 'chromium' | 'firefox' | 'webkit';
34
+ launch?: LaunchOptions;
35
+ };
36
+ server: boolean;
37
+ port?: number;
38
+ }
39
+ interface TestContext {
40
+ options: TestOptions;
41
+ nuxt?: Nuxt;
42
+ browser?: Browser;
43
+ url?: string;
44
+ serverProcess?: ExecaChildProcess;
45
+ mockFn?: Function;
46
+ /**
47
+ * Functions to run on the vitest `afterAll` hook.
48
+ * Useful for removing anything created during the test.
49
+ */
50
+ teardown?: (() => void)[];
51
+ }
52
+ interface TestHooks {
53
+ beforeEach: () => void;
54
+ afterEach: () => void;
55
+ afterAll: () => Promise<void>;
56
+ setup: () => Promise<void>;
57
+ ctx: TestContext;
58
+ }
59
+
60
+ export { type GotoOptions as G, type TestOptions as T, type TestContext as a, type TestHooks as b, createBrowser as c, createPage as d, type TestRunner as e, getBrowser as g, waitForHydration as w };
@@ -0,0 +1,60 @@
1
+ import { Browser, BrowserContextOptions, Page, Response, LaunchOptions } from 'playwright-core';
2
+ import { NuxtConfig, Nuxt } from '@nuxt/schema';
3
+ import { ExecaChildProcess } from 'execa';
4
+
5
+ declare function createBrowser(): Promise<void>;
6
+ declare function getBrowser(): Promise<Browser>;
7
+ type _GotoOptions = NonNullable<Parameters<Page['goto']>[1]>;
8
+ interface GotoOptions extends Omit<_GotoOptions, 'waitUntil'> {
9
+ waitUntil?: 'hydration' | 'route' | _GotoOptions['waitUntil'];
10
+ }
11
+ interface NuxtPage extends Omit<Page, 'goto'> {
12
+ goto: (url: string, options?: GotoOptions) => Promise<Response | null>;
13
+ }
14
+ declare function createPage(path?: string, options?: BrowserContextOptions): Promise<NuxtPage>;
15
+ declare function waitForHydration(page: Page, url: string, waitUntil?: GotoOptions['waitUntil']): Promise<void>;
16
+
17
+ type TestRunner = 'vitest' | 'jest' | 'cucumber';
18
+ interface TestOptions {
19
+ testDir: string;
20
+ fixture: string;
21
+ configFile: string;
22
+ rootDir: string;
23
+ buildDir: string;
24
+ nuxtConfig: NuxtConfig;
25
+ build: boolean;
26
+ dev: boolean;
27
+ setupTimeout: number;
28
+ waitFor: number;
29
+ browser: boolean;
30
+ runner: TestRunner;
31
+ logLevel: number;
32
+ browserOptions: {
33
+ type: 'chromium' | 'firefox' | 'webkit';
34
+ launch?: LaunchOptions;
35
+ };
36
+ server: boolean;
37
+ port?: number;
38
+ }
39
+ interface TestContext {
40
+ options: TestOptions;
41
+ nuxt?: Nuxt;
42
+ browser?: Browser;
43
+ url?: string;
44
+ serverProcess?: ExecaChildProcess;
45
+ mockFn?: Function;
46
+ /**
47
+ * Functions to run on the vitest `afterAll` hook.
48
+ * Useful for removing anything created during the test.
49
+ */
50
+ teardown?: (() => void)[];
51
+ }
52
+ interface TestHooks {
53
+ beforeEach: () => void;
54
+ afterEach: () => void;
55
+ afterAll: () => Promise<void>;
56
+ setup: () => Promise<void>;
57
+ ctx: TestContext;
58
+ }
59
+
60
+ export { type GotoOptions as G, type TestOptions as T, type TestContext as a, type TestHooks as b, createBrowser as c, createPage as d, type TestRunner as e, getBrowser as g, waitForHydration as w };
@@ -0,0 +1,202 @@
1
+ import { u as useTestContext, d as url, c as createTestContext, s as setTestContext, b as stopServer, a as startServer } from './test-utils.BegIhSnH.mjs';
2
+ import { existsSync, promises } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+ import { defu } from 'defu';
5
+ import * as _kit from '@nuxt/kit';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { dirname } from 'pathe';
8
+
9
+ async function createBrowser() {
10
+ const ctx = useTestContext();
11
+ let playwright;
12
+ try {
13
+ playwright = await import(
14
+ /* vite-ignore */
15
+ 'playwright-core'
16
+ );
17
+ } catch {
18
+ throw new Error(`
19
+ The dependency 'playwright-core' not found.
20
+ Please run 'yarn add --dev playwright-core' or 'npm install --save-dev playwright-core'
21
+ `);
22
+ }
23
+ const { type, launch } = ctx.options.browserOptions;
24
+ if (!playwright[type]) {
25
+ throw new Error(`Invalid browser '${type}'`);
26
+ }
27
+ ctx.browser = await playwright[type].launch(launch);
28
+ }
29
+ async function getBrowser() {
30
+ const ctx = useTestContext();
31
+ if (!ctx.browser) {
32
+ await createBrowser();
33
+ }
34
+ return ctx.browser;
35
+ }
36
+ async function createPage(path, options) {
37
+ const browser = await getBrowser();
38
+ const page = await browser.newPage(options);
39
+ const _goto = page.goto.bind(page);
40
+ page.goto = async (url2, options2) => {
41
+ const waitUntil = options2?.waitUntil;
42
+ if (waitUntil && ["hydration", "route"].includes(waitUntil)) {
43
+ delete options2.waitUntil;
44
+ }
45
+ const res = await _goto(url2, options2);
46
+ await waitForHydration(page, url2, waitUntil);
47
+ return res;
48
+ };
49
+ if (path) {
50
+ await page.goto(url(path), { waitUntil: "hydration" });
51
+ }
52
+ return page;
53
+ }
54
+ async function waitForHydration(page, url2, waitUntil) {
55
+ if (waitUntil === "hydration") {
56
+ await page.waitForFunction(() => window.useNuxtApp?.().isHydrating === false);
57
+ } else if (waitUntil === "route") {
58
+ await page.waitForFunction((route) => window.useNuxtApp?.()._route.fullPath === route, url2);
59
+ }
60
+ }
61
+
62
+ const kit = _kit.default || _kit;
63
+ const isNuxtApp = (dir) => {
64
+ return existsSync(dir) && (existsSync(resolve(dir, "pages")) || existsSync(resolve(dir, "nuxt.config.js")) || existsSync(resolve(dir, "nuxt.config.mjs")) || existsSync(resolve(dir, "nuxt.config.cjs")) || existsSync(resolve(dir, "nuxt.config.ts")));
65
+ };
66
+ const resolveRootDir = () => {
67
+ const { options } = useTestContext();
68
+ const dirs = [
69
+ options.rootDir,
70
+ resolve(options.testDir, options.fixture),
71
+ process.cwd()
72
+ ];
73
+ for (const dir of dirs) {
74
+ if (dir && isNuxtApp(dir)) {
75
+ return dir;
76
+ }
77
+ }
78
+ throw new Error("Invalid nuxt app. (Please explicitly set `options.rootDir` pointing to a valid nuxt app)");
79
+ };
80
+ async function loadFixture() {
81
+ const ctx = useTestContext();
82
+ ctx.options.rootDir = resolveRootDir();
83
+ if (!ctx.options.dev) {
84
+ const randomId = Math.random().toString(36).slice(2, 8);
85
+ const buildDir2 = ctx.options.buildDir || resolve(ctx.options.rootDir, ".nuxt", "test", randomId);
86
+ ctx.options.nuxtConfig = defu(ctx.options.nuxtConfig, {
87
+ buildDir: buildDir2,
88
+ nitro: {
89
+ output: {
90
+ dir: resolve(buildDir2, "output")
91
+ }
92
+ }
93
+ });
94
+ }
95
+ ctx.nuxt = await kit.loadNuxt({
96
+ cwd: ctx.options.rootDir,
97
+ dev: ctx.options.dev,
98
+ overrides: ctx.options.nuxtConfig,
99
+ configFile: ctx.options.configFile
100
+ });
101
+ const buildDir = ctx.nuxt.options.buildDir;
102
+ if (!existsSync(buildDir)) {
103
+ await promises.mkdir(buildDir, { recursive: true });
104
+ ctx.teardown = ctx.teardown || [];
105
+ ctx.teardown.push(() => promises.rm(buildDir, { recursive: true, force: true }));
106
+ }
107
+ }
108
+ async function buildFixture() {
109
+ const ctx = useTestContext();
110
+ const prevLevel = kit.logger.level;
111
+ kit.logger.level = ctx.options.logLevel;
112
+ await kit.buildNuxt(ctx.nuxt);
113
+ kit.logger.level = prevLevel;
114
+ }
115
+
116
+ async function setupCucumber(hooks) {
117
+ const { After, AfterAll, Before, BeforeAll } = await import('@cucumber/cucumber');
118
+ BeforeAll({ timeout: hooks.ctx.options.setupTimeout }, hooks.setup);
119
+ Before(hooks.beforeEach);
120
+ After(hooks.afterEach);
121
+ AfterAll(hooks.afterAll);
122
+ }
123
+
124
+ async function setupJest(hooks) {
125
+ const { jest, test, beforeEach, afterAll, afterEach } = await import('@jest/globals');
126
+ hooks.ctx.mockFn = jest.fn;
127
+ test("setup", hooks.setup, hooks.ctx.options.setupTimeout);
128
+ beforeEach(hooks.beforeEach);
129
+ afterEach(hooks.afterEach);
130
+ afterAll(hooks.afterAll);
131
+ }
132
+
133
+ async function setupVitest(hooks) {
134
+ const vitest = await import('vitest');
135
+ hooks.ctx.mockFn = vitest.vi.fn;
136
+ vitest.beforeAll(hooks.setup, hooks.ctx.options.setupTimeout);
137
+ vitest.beforeEach(hooks.beforeEach);
138
+ vitest.afterEach(hooks.afterEach);
139
+ vitest.afterAll(hooks.afterAll);
140
+ }
141
+
142
+ const setupMaps = {
143
+ cucumber: setupCucumber,
144
+ jest: setupJest,
145
+ vitest: setupVitest
146
+ };
147
+ function createTest(options) {
148
+ const ctx = createTestContext(options);
149
+ const beforeEach = () => {
150
+ setTestContext(ctx);
151
+ };
152
+ const afterEach = () => {
153
+ setTestContext(void 0);
154
+ };
155
+ const afterAll = async () => {
156
+ if (ctx.serverProcess) {
157
+ setTestContext(ctx);
158
+ await stopServer();
159
+ setTestContext(void 0);
160
+ }
161
+ if (ctx.nuxt && ctx.nuxt.options.dev) {
162
+ await ctx.nuxt.close();
163
+ }
164
+ if (ctx.browser) {
165
+ await ctx.browser.close();
166
+ }
167
+ await Promise.all((ctx.teardown || []).map((fn) => fn()));
168
+ };
169
+ const setup2 = async () => {
170
+ if (ctx.options.fixture) {
171
+ await loadFixture();
172
+ }
173
+ if (ctx.options.build) {
174
+ await buildFixture();
175
+ }
176
+ if (ctx.options.server) {
177
+ await startServer();
178
+ }
179
+ if (ctx.options.waitFor) {
180
+ await new Promise((resolve) => setTimeout(resolve, ctx.options.waitFor));
181
+ }
182
+ if (ctx.options.browser) {
183
+ await createBrowser();
184
+ }
185
+ };
186
+ return {
187
+ beforeEach,
188
+ afterEach,
189
+ afterAll,
190
+ setup: setup2,
191
+ ctx
192
+ };
193
+ }
194
+ async function setup(options = {}) {
195
+ const hooks = createTest(options);
196
+ const setupFn = setupMaps[hooks.ctx.options.runner];
197
+ await setupFn(hooks);
198
+ }
199
+
200
+ const distDir = dirname(fileURLToPath(import.meta.url));
201
+
202
+ export { createPage as a, buildFixture as b, createBrowser as c, distDir as d, createTest as e, setup as f, getBrowser as g, loadFixture as l, setupMaps as s, waitForHydration as w };
@@ -18,11 +18,15 @@ function createTestContext(options) {
18
18
  server: true,
19
19
  build: options.browser !== false || options.server !== false,
20
20
  nuxtConfig: {},
21
- runner: process.env.VITEST === "true" ? "vitest" : "jest",
22
21
  browserOptions: {
23
22
  type: "chromium"
24
23
  }
25
24
  });
25
+ if (process.env.VITEST === "true") {
26
+ _options.runner || (_options.runner = "vitest");
27
+ } else if (process.env.JEST_WORKER_ID) {
28
+ _options.runner || (_options.runner = "jest");
29
+ }
26
30
  return setTestContext({
27
31
  options: _options
28
32
  });
@@ -129,4 +133,4 @@ function url(path) {
129
133
  return ctx.url + path;
130
134
  }
131
135
 
132
- export { $fetch as $, url as a, stopServer as b, createTestContext as c, startServer as d, exposeContextToEnv as e, fetch as f, isDev as i, recoverContextFromEnv as r, setTestContext as s, useTestContext as u };
136
+ export { $fetch as $, startServer as a, stopServer as b, createTestContext as c, url as d, exposeContextToEnv as e, fetch as f, isDev as i, recoverContextFromEnv as r, setTestContext as s, useTestContext as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/test-utils",
3
- "version": "3.11.0",
3
+ "version": "3.12.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/nuxt/test-utils.git"
@@ -13,6 +13,7 @@
13
13
  ".": "./dist/e2e.mjs",
14
14
  "./config": "./dist/config.mjs",
15
15
  "./e2e": "./dist/e2e.mjs",
16
+ "./playwright": "./dist/playwright.mjs",
16
17
  "./experimental": "./dist/experimental.mjs",
17
18
  "./module": "./dist/module.mjs",
18
19
  "./runtime": "./dist/runtime-utils/index.mjs",
@@ -24,32 +25,43 @@
24
25
  "e2e.d.ts",
25
26
  "experimental.d.ts",
26
27
  "module.d.ts",
28
+ "playwright.d.ts",
27
29
  "runtime.d.ts",
28
30
  "vitest-environment.d.ts"
29
31
  ],
32
+ "scripts": {
33
+ "lint": "eslint --ext .vue,.ts,.js,.mjs .",
34
+ "lint:fix": "eslint --ext .vue,.ts,.js,.mjs . --fix",
35
+ "test:examples": "pnpm -r test --filter !nuxt-app-cucumber && pnpm -r test --filter nuxt-app-cucumber",
36
+ "test:types": "vue-tsc --noEmit",
37
+ "test:unit": "vitest test/unit --run",
38
+ "prepack": "unbuild",
39
+ "dev:prepare": "nuxi prepare && unbuild --stub && pnpm -r dev:prepare",
40
+ "release": "pnpm prepack && pnpm test:examples && changelogen --release --push"
41
+ },
30
42
  "dependencies": {
31
- "@nuxt/kit": "^3.9.3",
32
- "@nuxt/schema": "^3.9.3",
33
- "c12": "^1.6.1",
43
+ "@nuxt/kit": "^3.11.1",
44
+ "@nuxt/schema": "^3.11.1",
45
+ "c12": "^1.10.0",
34
46
  "consola": "^3.2.3",
35
47
  "defu": "^6.1.4",
36
- "destr": "^2.0.2",
48
+ "destr": "^2.0.3",
37
49
  "estree-walker": "^3.0.3",
38
50
  "execa": "^8.0.1",
39
51
  "fake-indexeddb": "^5.0.2",
40
52
  "get-port-please": "^3.1.2",
41
53
  "local-pkg": "^0.5.0",
42
- "magic-string": "^0.30.5",
43
- "node-fetch-native": "^1.6.1",
54
+ "magic-string": "^0.30.8",
55
+ "node-fetch-native": "^1.6.2",
44
56
  "ofetch": "^1.3.3",
45
57
  "pathe": "^1.1.2",
46
58
  "perfect-debounce": "^1.0.0",
47
- "radix3": "^1.1.0",
48
- "scule": "^1.2.0",
59
+ "radix3": "^1.1.1",
60
+ "scule": "^1.3.0",
49
61
  "std-env": "^3.7.0",
50
- "ufo": "^1.3.2",
62
+ "ufo": "^1.5.2",
51
63
  "unenv": "^1.9.0",
52
- "unplugin": "^1.6.0",
64
+ "unplugin": "^1.10.0",
53
65
  "vitest-environment-nuxt": "^1.0.0"
54
66
  },
55
67
  "devDependencies": {
@@ -58,39 +70,41 @@
58
70
  "@nuxt/devtools": "1.0.8",
59
71
  "@nuxt/eslint-config": "0.2.0",
60
72
  "@nuxt/module-builder": "0.5.5",
61
- "@testing-library/vue": "8.0.1",
73
+ "@playwright/test": "1.42.1",
74
+ "@testing-library/vue": "8.0.3",
62
75
  "@types/estree": "1.0.5",
63
76
  "@types/jsdom": "21.1.6",
64
- "@types/semver": "7.5.6",
65
- "@vitest/ui": "1.2.2",
66
- "@vue/test-utils": "2.4.4",
77
+ "@types/semver": "7.5.8",
78
+ "@vitest/ui": "1.4.0",
79
+ "@vue/test-utils": "2.4.5",
67
80
  "changelogen": "0.5.5",
68
- "eslint": "8.56.0",
81
+ "eslint": "8.57.0",
69
82
  "eslint-plugin-import": "2.29.1",
70
- "eslint-plugin-jsdoc": "48.0.4",
83
+ "eslint-plugin-jsdoc": "48.2.1",
71
84
  "eslint-plugin-no-only-tests": "3.1.0",
72
- "eslint-plugin-unicorn": "50.0.1",
73
- "h3": "1.10.1",
85
+ "eslint-plugin-unicorn": "51.0.1",
86
+ "h3": "1.11.1",
74
87
  "jiti": "1.21.0",
75
- "nuxt": "3.9.3",
76
- "playwright-core": "1.41.1",
77
- "rollup": "4.9.6",
78
- "semver": "7.5.4",
88
+ "nuxt": "3.11.1",
89
+ "playwright-core": "1.42.1",
90
+ "rollup": "4.13.0",
91
+ "semver": "7.6.0",
79
92
  "unbuild": "latest",
80
93
  "unimport": "3.7.1",
81
- "vite": "5.0.12",
82
- "vitest": "1.2.2",
83
- "vue-router": "4.2.5",
84
- "vue-tsc": "1.8.27"
94
+ "vite": "5.1.6",
95
+ "vitest": "1.4.0",
96
+ "vue-router": "4.3.0",
97
+ "vue-tsc": "2.0.6"
85
98
  },
86
99
  "peerDependencies": {
87
100
  "@cucumber/cucumber": "^10.3.1",
88
101
  "@jest/globals": "^29.5.0",
102
+ "@playwright/test": "^1.42.1",
89
103
  "@testing-library/vue": "^7.0.0 || ^8.0.1",
90
104
  "@vitest/ui": "^0.34.6 || ^1.0.0",
91
105
  "@vue/test-utils": "^2.4.2",
92
106
  "h3": "*",
93
- "happy-dom": "^9.10.9 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0",
107
+ "happy-dom": "^9.10.9 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0",
94
108
  "jsdom": "^22.0.0 || ^23.0.0 || ^24.0.0",
95
109
  "playwright-core": "^1.34.3",
96
110
  "vite": "*",
@@ -102,6 +116,9 @@
102
116
  "@cucumber/cucumber": {
103
117
  "optional": true
104
118
  },
119
+ "@playwright/test": {
120
+ "optional": true
121
+ },
105
122
  "@testing-library/vue": {
106
123
  "optional": true
107
124
  },
@@ -128,24 +145,15 @@
128
145
  }
129
146
  },
130
147
  "resolutions": {
131
- "@nuxt/kit": "^3.9.3",
132
- "@nuxt/schema": "^3.9.3",
148
+ "@nuxt/kit": "^3.11.1",
149
+ "@nuxt/schema": "^3.11.1",
133
150
  "@nuxt/test-utils": "workspace:*",
134
- "rollup": "4.9.6",
135
- "vite": "5.0.12",
136
- "vue": "^3.4.15"
151
+ "rollup": "4.13.0",
152
+ "vite": "5.1.6",
153
+ "vue": "^3.4.21"
137
154
  },
138
155
  "engines": {
139
156
  "node": "^14.18.0 || >=16.10.0"
140
157
  },
141
- "packageManager": "pnpm@8.15.0",
142
- "scripts": {
143
- "lint": "eslint --ext .vue,.ts,.js,.mjs .",
144
- "lint:fix": "eslint --ext .vue,.ts,.js,.mjs . --fix",
145
- "test:examples": "pnpm -r test --filter !nuxt-app-cucumber && pnpm -r test --filter nuxt-app-cucumber",
146
- "test:types": "vue-tsc --noEmit",
147
- "test:unit": "vitest test/unit --run",
148
- "dev:prepare": "nuxi prepare && unbuild --stub && pnpm -r dev:prepare",
149
- "release": "pnpm test:examples && pnpm prepack && changelogen --release --push && pnpm publish"
150
- }
158
+ "packageManager": "pnpm@8.15.5"
151
159
  }
@@ -0,0 +1 @@
1
+ export * from './dist/playwright'