@nuxt/test-utils 3.22.0 → 4.0.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/dist/module.mjs CHANGED
@@ -1,16 +1,20 @@
1
- import { resolveIgnorePatterns, useNuxt, addDevServerHandler, defineNuxtModule, createResolver, resolvePath, logger } from '@nuxt/kit';
2
- import { extname, join, dirname, resolve, relative } from 'pathe';
3
- import { provider, isCI } from 'std-env';
1
+ import { resolveIgnorePatterns, logger, addDevServerHandler, useNuxt, defineNuxtModule, createResolver, resolvePath } from '@nuxt/kit';
2
+ import { refreshCustomTabs, addCustomTab, onDevToolsInitialized } from '@nuxt/devtools-kit';
3
+ import { extname, join, dirname, relative, resolve } from 'pathe';
4
+ import { isCI, hasTTY, provider } from 'std-env';
4
5
  import { walk } from 'estree-walker';
5
6
  import MagicString from 'magic-string';
6
7
  import { createUnplugin } from 'unplugin';
7
8
  import { l as loadKit } from './shared/test-utils.BIY9XRkB.mjs';
8
- import { readFileSync } from 'node:fs';
9
+ import { readFileSync, existsSync, promises } from 'node:fs';
10
+ import process$1 from 'node:process';
11
+ import { intro, multiselect, isCancel, cancel, select, confirm, outro } from '@clack/prompts';
12
+ import { colors } from 'consola/utils';
13
+ import { detectPackageManager, addDependency } from 'nypm';
9
14
  import { h } from 'vue';
10
- import { defineEventHandler } from 'h3';
11
15
  import { debounce } from 'perfect-debounce';
12
16
  import { fork } from 'node:child_process';
13
- import { c as createVitestTestSummary, l as listenCliMessages, s as sendMessageToCli } from './shared/test-utils.DDUpsMYL.mjs';
17
+ import { l as listenCliMessages, s as sendMessageToCli, c as createVitestTestSummary } from './shared/test-utils.DDUpsMYL.mjs';
14
18
  import { distDir } from '#dirs';
15
19
  import 'destr';
16
20
  import 'scule';
@@ -21,6 +25,7 @@ const PLUGIN_NAME$1 = "nuxt:vitest:mock-transform";
21
25
  const HELPER_MOCK_IMPORT = "mockNuxtImport";
22
26
  const HELPER_MOCK_COMPONENT = "mockComponent";
23
27
  const HELPER_MOCK_HOIST = "__NUXT_VITEST_MOCKS";
28
+ const HELPER_MOCK_HOIST_ORIGINAL = "__NUXT_VITEST_MOCKS_ORIGINAL";
24
29
  const HELPERS_NAME = [HELPER_MOCK_IMPORT, HELPER_MOCK_COMPONENT];
25
30
  const createMockPlugin = (ctx) => createUnplugin(() => {
26
31
  function transform(code, id) {
@@ -79,7 +84,6 @@ const createMockPlugin = (ctx) => createUnplugin(() => {
79
84
  }
80
85
  const importItem = ctx.imports.find((_) => name === (_.as || _.name));
81
86
  if (!importItem) {
82
- console.log({ imports: ctx.imports });
83
87
  return this.error(`Cannot find import "${name}" to mock`);
84
88
  }
85
89
  s.overwrite(
@@ -148,25 +152,23 @@ const createMockPlugin = (ctx) => createUnplugin(() => {
148
152
  ...Array.from(mockImportMap.entries()).flatMap(
149
153
  ([from, mocks]) => {
150
154
  importPathsList.add(from);
155
+ const quotedFrom = JSON.stringify(from);
156
+ const mockModuleEntry = `globalThis.${HELPER_MOCK_HOIST}[${quotedFrom}]`;
151
157
  const lines = [
152
- `vi.mock(${JSON.stringify(from)}, async (importOriginal) => {`,
153
- ` const mocks = globalThis.${HELPER_MOCK_HOIST}`,
154
- ` if (!mocks[${JSON.stringify(from)}]) {`,
155
- ` mocks[${JSON.stringify(from)}] = { ...await importOriginal(${JSON.stringify(from)}) }`,
158
+ `vi.mock(${quotedFrom}, async (importOriginal) => {`,
159
+ ` if (!${mockModuleEntry}) {`,
160
+ ` const original = await importOriginal(${quotedFrom})`,
161
+ ` ${mockModuleEntry} = { ...original }`,
162
+ ` ${mockModuleEntry}.${HELPER_MOCK_HOIST_ORIGINAL} = { ...original }`,
156
163
  ` }`
157
164
  ];
158
165
  for (const mock of mocks) {
159
- if (mock.import.name === "default") {
160
- lines.push(
161
- ` mocks[${JSON.stringify(from)}]["default"] = await (${mock.factory})();`
162
- );
163
- } else {
164
- lines.push(
165
- ` mocks[${JSON.stringify(from)}][${JSON.stringify(mock.name)}] = await (${mock.factory})();`
166
- );
167
- }
166
+ const quotedName = JSON.stringify(mock.import.name === "default" ? "default" : mock.name);
167
+ lines.push(
168
+ ` ${mockModuleEntry}[${quotedName}] = await (${mock.factory})(${mockModuleEntry}.${HELPER_MOCK_HOIST_ORIGINAL}[${quotedName}]);`
169
+ );
168
170
  }
169
- lines.push(` return mocks[${JSON.stringify(from)}] `);
171
+ lines.push(` return ${mockModuleEntry} `);
170
172
  lines.push(`});`);
171
173
  return lines;
172
174
  }
@@ -323,25 +325,455 @@ const NuxtRootStubPlugin = (options) => {
323
325
  };
324
326
  };
325
327
 
328
+ function generateVitestConfig(answers) {
329
+ let config = `import { fileURLToPath } from 'node:url'
330
+ import { defineConfig } from 'vitest/config'
331
+ import { defineVitestProject } from '@nuxt/test-utils/config'`;
332
+ if (answers.browserMode) {
333
+ config += `
334
+ import { playwright } from '@vitest/browser-playwright'`;
335
+ }
336
+ config += `
337
+
338
+ export default defineConfig({
339
+ `;
340
+ config += ` test: {
341
+ projects: [
342
+ `;
343
+ if (answers.testingScope.includes("unit")) {
344
+ config += ` {
345
+ test: {
346
+ name: 'unit',
347
+ include: ['test/unit/*.{test,spec}.ts'],
348
+ environment: 'node',
349
+ },
350
+ },
351
+ `;
352
+ }
353
+ config += ` await defineVitestProject({
354
+ test: {
355
+ name: 'nuxt',
356
+ include: ['test/nuxt/*.{test,spec}.ts'],
357
+ environment: 'nuxt',
358
+ environmentOptions: {
359
+ nuxt: {
360
+ rootDir: fileURLToPath(new URL('.', import.meta.url)),${answers.browserMode ? "" : `
361
+ domEnvironment: '${answers.domEnvironment || "happy-dom"}',`}
362
+ },
363
+ },${answers.browserMode ? `
364
+ browser: {
365
+ enabled: true,
366
+ provider: playwright(),
367
+ instances: [
368
+ { browser: 'chromium' },
369
+ ],
370
+ },` : ""}
371
+ },
372
+ }),
373
+ `;
374
+ if (answers.testingScope.includes("e2e") && answers.e2eRunner === "vitest") {
375
+ config += ` {
376
+ test: {
377
+ name: 'e2e',
378
+ include: ['test/e2e/*.{test,spec}.ts'],
379
+ environment: 'node',
380
+ },
381
+ },
382
+ `;
383
+ }
384
+ config += ` ],
385
+ `;
386
+ if (answers.coverage) {
387
+ config += ` coverage: {
388
+ enabled: true,
389
+ provider: 'v8',
390
+ },
391
+ `;
392
+ }
393
+ config += ` },
394
+ `;
395
+ config += `})
396
+ `;
397
+ return config;
398
+ }
399
+ function generatePlaywrightConfig() {
400
+ return `import { fileURLToPath } from 'node:url'
401
+ import { defineConfig, devices } from '@playwright/test'
402
+ import type { ConfigOptions } from '@nuxt/test-utils/playwright'
403
+
404
+ export default defineConfig<ConfigOptions>({
405
+ testDir: './tests',
406
+ fullyParallel: true,
407
+ forbidOnly: !!process.env.CI,
408
+ retries: process.env.CI ? 2 : 0,
409
+ workers: process.env.CI ? 1 : undefined,
410
+ reporter: 'html',
411
+ use: {
412
+ trace: 'on-first-retry',
413
+ nuxt: {
414
+ rootDir: fileURLToPath(new URL('.', import.meta.url)),
415
+ },
416
+ },
417
+ projects: [
418
+ {
419
+ name: 'chromium',
420
+ use: { ...devices['Desktop Chrome'] },
421
+ },
422
+ ],
423
+ })
424
+ `;
425
+ }
426
+ function getDependencies(answers) {
427
+ const dependencies = [];
428
+ if (answers.testingScope.includes("unit") || answers.testingScope.includes("runtime")) {
429
+ dependencies.push("vitest", "@vue/test-utils");
430
+ if (answers.domEnvironment) {
431
+ dependencies.push(answers.domEnvironment);
432
+ }
433
+ if (answers.browserMode) {
434
+ dependencies.push("@vitest/browser-playwright");
435
+ }
436
+ }
437
+ if (answers.e2eRunner === "playwright") {
438
+ dependencies.push("@playwright/test", "playwright-core");
439
+ } else if (answers.e2eRunner === "cucumber") {
440
+ dependencies.push("@cucumber/cucumber");
441
+ } else if (answers.e2eRunner === "jest") {
442
+ dependencies.push("@jest/globals");
443
+ }
444
+ if (answers.coverage) {
445
+ dependencies.push("@vitest/coverage-v8");
446
+ }
447
+ return dependencies;
448
+ }
449
+ function getPackageScripts(answers) {
450
+ const scripts = {};
451
+ if (answers.testingScope.includes("unit") || answers.testingScope.includes("runtime")) {
452
+ scripts.test = "vitest";
453
+ scripts["test:watch"] = "vitest --watch";
454
+ if (answers.coverage) {
455
+ scripts["test:coverage"] = "vitest --coverage";
456
+ }
457
+ if (answers.testingScope.includes("unit")) {
458
+ scripts["test:unit"] = "vitest --project unit";
459
+ }
460
+ scripts["test:nuxt"] = "vitest --project nuxt";
461
+ if (answers.testingScope.includes("e2e") && answers.e2eRunner === "vitest") {
462
+ scripts["test:e2e"] = "vitest --project e2e";
463
+ }
464
+ }
465
+ if (answers.e2eRunner === "playwright") {
466
+ scripts["test:e2e"] = "playwright test";
467
+ scripts["test:e2e:ui"] = "playwright test --ui";
468
+ }
469
+ return scripts;
470
+ }
471
+ async function runInstallWizard(nuxt) {
472
+ if (isCI || !hasTTY || nuxt.options.test) {
473
+ return;
474
+ }
475
+ if (nuxt.options.workspaceDir && nuxt.options.workspaceDir !== nuxt.options.rootDir) {
476
+ logger.info("Monorepo detected. Skipping setup wizard.");
477
+ return;
478
+ }
479
+ const rootDir = nuxt.options.rootDir;
480
+ const hasVitestConfig = existsSync(join(rootDir, "vitest.config.ts")) || existsSync(join(rootDir, "vitest.config.js")) || existsSync(join(rootDir, "vitest.config.mts")) || existsSync(join(rootDir, "vitest.config.mjs"));
481
+ const hasPlaywrightConfig = existsSync(join(rootDir, "playwright.config.ts")) || existsSync(join(rootDir, "playwright.config.js"));
482
+ if (hasVitestConfig || hasPlaywrightConfig) {
483
+ logger.info("Test configuration already exists. Skipping setup wizard.");
484
+ return;
485
+ }
486
+ intro(colors.bold(colors.cyan("\u{1F9EA} Nuxt Test Utils Setup")));
487
+ const answers = {};
488
+ const testingScope = await multiselect({
489
+ message: "What kind of tests will you need?",
490
+ options: [
491
+ {
492
+ value: "runtime",
493
+ label: "Runtime",
494
+ hint: "components or composables running in a Nuxt runtime environment"
495
+ },
496
+ {
497
+ value: "unit",
498
+ label: "Unit tests",
499
+ hint: "pure functions or build-time/Node tests"
500
+ },
501
+ {
502
+ value: "e2e",
503
+ label: "End-to-end",
504
+ hint: "full application flows in browser"
505
+ }
506
+ ],
507
+ required: true
508
+ });
509
+ if (isCancel(testingScope)) {
510
+ cancel("Setup cancelled.");
511
+ process$1.exit(0);
512
+ }
513
+ answers.testingScope = testingScope;
514
+ const needsVitest = answers.testingScope.includes("unit") || answers.testingScope.includes("runtime");
515
+ const needsE2E = answers.testingScope.includes("e2e");
516
+ if (answers.testingScope.includes("runtime")) {
517
+ const domEnvironment = await select({
518
+ message: "Which Vitest environment would you like to use for runtime tests?",
519
+ options: [
520
+ {
521
+ value: "happy-dom",
522
+ label: "happy-dom",
523
+ hint: "recommended - faster, lighter"
524
+ },
525
+ {
526
+ value: "jsdom",
527
+ label: "jsdom",
528
+ hint: "more complete browser simulation"
529
+ },
530
+ {
531
+ value: "browser",
532
+ label: "browser mode",
533
+ hint: "real browser with Playwright"
534
+ }
535
+ ],
536
+ initialValue: "happy-dom"
537
+ });
538
+ if (isCancel(domEnvironment)) {
539
+ cancel("Setup cancelled.");
540
+ process$1.exit(0);
541
+ }
542
+ if (domEnvironment === "browser") {
543
+ answers.browserMode = true;
544
+ } else {
545
+ answers.domEnvironment = domEnvironment;
546
+ }
547
+ }
548
+ if (needsE2E) {
549
+ const e2eRunner = await select({
550
+ message: "Which end-to-end test runner would you like to use?",
551
+ options: [
552
+ {
553
+ value: "playwright",
554
+ label: "Playwright",
555
+ hint: "recommended - modern, multi-browser"
556
+ },
557
+ {
558
+ value: "vitest",
559
+ label: "Vitest",
560
+ hint: "same runner as unit tests"
561
+ },
562
+ {
563
+ value: "cucumber",
564
+ label: "Cucumber",
565
+ hint: "behavior-driven development"
566
+ },
567
+ {
568
+ value: "jest",
569
+ label: "Jest",
570
+ hint: "legacy test runner"
571
+ }
572
+ ],
573
+ initialValue: "playwright"
574
+ });
575
+ if (isCancel(e2eRunner)) {
576
+ cancel("Setup cancelled.");
577
+ process$1.exit(0);
578
+ }
579
+ answers.e2eRunner = e2eRunner;
580
+ }
581
+ if (needsVitest) {
582
+ const coverage = await confirm({
583
+ message: "Would you like to set up test coverage?",
584
+ initialValue: false
585
+ });
586
+ if (isCancel(coverage)) {
587
+ cancel("Setup cancelled.");
588
+ process$1.exit(0);
589
+ }
590
+ answers.coverage = coverage;
591
+ }
592
+ const exampleTests = await confirm({
593
+ message: "Create example test files?",
594
+ initialValue: true
595
+ });
596
+ if (isCancel(exampleTests)) {
597
+ cancel("Setup cancelled.");
598
+ process$1.exit(0);
599
+ }
600
+ answers.exampleTests = exampleTests;
601
+ await performSetup(nuxt, answers);
602
+ outro(colors.green("\u2728 Test setup complete!"));
603
+ }
604
+ async function performSetup(nuxt, answers) {
605
+ const rootDir = nuxt.options.rootDir;
606
+ const packageManager = await detectPackageManager(rootDir);
607
+ logger.info("Installing dependencies...");
608
+ const dependencies = getDependencies(answers);
609
+ if (dependencies.length > 0) {
610
+ try {
611
+ await addDependency(dependencies, {
612
+ cwd: rootDir,
613
+ dev: true,
614
+ packageManager
615
+ });
616
+ } catch (error) {
617
+ logger.error("Failed to install dependencies:", error);
618
+ return;
619
+ }
620
+ }
621
+ if (answers.testingScope.includes("unit") || answers.testingScope.includes("runtime")) {
622
+ await createVitestConfig(nuxt, answers);
623
+ }
624
+ if (answers.e2eRunner === "playwright") {
625
+ await createPlaywrightConfig(nuxt);
626
+ }
627
+ await createTestDirectories(nuxt, answers);
628
+ if (answers.exampleTests) {
629
+ await createExampleTests(nuxt, answers);
630
+ }
631
+ await updatePackageScripts(nuxt, answers);
632
+ await updateGitignore(nuxt, answers);
633
+ }
634
+ async function createVitestConfig(nuxt, answers) {
635
+ const rootDir = nuxt.options.rootDir;
636
+ const configPath = join(rootDir, "vitest.config.ts");
637
+ const config = generateVitestConfig(answers);
638
+ await promises.writeFile(configPath, config, "utf-8");
639
+ logger.success(`Created ${colors.cyan(relative(process$1.cwd(), configPath))}`);
640
+ }
641
+ async function createPlaywrightConfig(nuxt) {
642
+ const rootDir = nuxt.options.rootDir;
643
+ const configPath = join(rootDir, "playwright.config.ts");
644
+ const config = generatePlaywrightConfig();
645
+ await promises.writeFile(configPath, config, "utf-8");
646
+ logger.success(`Created ${colors.cyan(relative(process$1.cwd(), configPath))}`);
647
+ }
648
+ async function createTestDirectories(nuxt, answers) {
649
+ const rootDir = nuxt.options.rootDir;
650
+ if (answers.testingScope.includes("unit")) {
651
+ const unitDir = join(rootDir, "test/unit");
652
+ await promises.mkdir(unitDir, { recursive: true });
653
+ logger.success(`Created ${colors.cyan(relative(process$1.cwd(), unitDir))}`);
654
+ }
655
+ if (answers.testingScope.includes("runtime")) {
656
+ const nuxtDir = join(rootDir, "test/nuxt");
657
+ await promises.mkdir(nuxtDir, { recursive: true });
658
+ logger.success(`Created ${colors.cyan(relative(process$1.cwd(), nuxtDir))}`);
659
+ }
660
+ if (answers.testingScope.includes("e2e")) {
661
+ const e2eDir = answers.e2eRunner === "playwright" ? join(rootDir, "tests") : join(rootDir, "test/e2e");
662
+ await promises.mkdir(e2eDir, { recursive: true });
663
+ logger.success(`Created ${colors.cyan(relative(process$1.cwd(), e2eDir))}`);
664
+ }
665
+ }
666
+ async function createExampleTests(nuxt, answers) {
667
+ const rootDir = nuxt.options.rootDir;
668
+ if (answers.testingScope.includes("unit")) {
669
+ const unitTestPath = join(rootDir, "test/unit/example.test.ts");
670
+ const unitTest = `import { describe, expect, it } from 'vitest'
671
+
672
+ describe('example unit test', () => {
673
+ it('should pass', () => {
674
+ expect(1 + 1).toBe(2)
675
+ })
676
+ })
677
+ `;
678
+ await promises.writeFile(unitTestPath, unitTest, "utf-8");
679
+ logger.success(`Created ${colors.cyan(relative(process$1.cwd(), unitTestPath))}`);
680
+ }
681
+ if (answers.testingScope.includes("runtime")) {
682
+ const componentTestPath = join(rootDir, "test/nuxt/component.test.ts");
683
+ const componentTest = `import { describe, expect, it } from 'vitest'
684
+ import { mountSuspended } from '@nuxt/test-utils/runtime'
685
+ import { defineComponent, h } from 'vue'
686
+
687
+ describe('component test example', () => {
688
+ it('can mount components', async () => {
689
+ const TestComponent = defineComponent({
690
+ setup() {
691
+ return () => h('div', 'Hello Nuxt!')
692
+ },
693
+ })
694
+
695
+ const component = await mountSuspended(TestComponent)
696
+
697
+ expect(component.text()).toBe('Hello Nuxt!')
698
+ })
699
+ })
700
+ `;
701
+ await promises.writeFile(componentTestPath, componentTest, "utf-8");
702
+ logger.success(`Created ${colors.cyan(relative(process$1.cwd(), componentTestPath))}`);
703
+ }
704
+ if (answers.testingScope.includes("e2e")) {
705
+ if (answers.e2eRunner === "playwright") {
706
+ const e2eTestPath = join(rootDir, "tests/example.spec.ts");
707
+ const e2eTest = `import { expect, test } from '@nuxt/test-utils/playwright'
708
+
709
+ test('example e2e test', async ({ page, goto }) => {
710
+ await goto('/', { waitUntil: 'hydration' })
711
+ await expect(page).toHaveTitle(/Nuxt/)
712
+ })
713
+ `;
714
+ await promises.writeFile(e2eTestPath, e2eTest, "utf-8");
715
+ logger.success(`Created ${colors.cyan(relative(process$1.cwd(), e2eTestPath))}`);
716
+ } else {
717
+ const e2eTestPath = join(rootDir, "test/e2e/example.test.ts");
718
+ const e2eTest = `import { describe, expect, it } from 'vitest'
719
+ import { $fetch, setup } from '@nuxt/test-utils/e2e'
720
+
721
+ describe('example e2e test', async () => {
722
+ await setup()
723
+
724
+ it('renders the index page', async () => {
725
+ const html = await $fetch('/')
726
+ expect(html).toContain('Nuxt')
727
+ })
728
+ })
729
+ `;
730
+ await promises.writeFile(e2eTestPath, e2eTest, "utf-8");
731
+ logger.success(`Created ${colors.cyan(relative(process$1.cwd(), e2eTestPath))}`);
732
+ }
733
+ }
734
+ }
735
+ async function updatePackageScripts(nuxt, answers) {
736
+ const rootDir = nuxt.options.rootDir;
737
+ const packageJsonPath = join(rootDir, "package.json");
738
+ const packageJson = JSON.parse(await promises.readFile(packageJsonPath, "utf-8"));
739
+ packageJson.scripts = packageJson.scripts || {};
740
+ const newScripts = getPackageScripts(answers);
741
+ Object.assign(packageJson.scripts, newScripts);
742
+ await promises.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n", "utf-8");
743
+ logger.success("Updated package.json scripts");
744
+ }
745
+ async function updateGitignore(nuxt, answers) {
746
+ const rootDir = nuxt.options.rootDir;
747
+ const gitignorePath = join(rootDir, ".gitignore");
748
+ let gitignore = "";
749
+ if (existsSync(gitignorePath)) {
750
+ gitignore = await promises.readFile(gitignorePath, "utf-8");
751
+ }
752
+ const lines = [];
753
+ if (answers.coverage && !gitignore.includes("coverage")) {
754
+ lines.push("# Test coverage", "coverage/", "");
755
+ }
756
+ if (answers.e2eRunner === "playwright") {
757
+ if (!gitignore.includes("playwright-report")) {
758
+ lines.push("# Playwright", "playwright-report/", "test-results/", "");
759
+ }
760
+ }
761
+ if (lines.length > 0) {
762
+ gitignore += "\n" + lines.join("\n");
763
+ await promises.writeFile(gitignorePath, gitignore, "utf-8");
764
+ logger.success("Updated .gitignore");
765
+ }
766
+ }
767
+
326
768
  async function setupDevTools(vitestWrapper, nuxt = useNuxt()) {
327
769
  const iframeSrc = "/__test_utils_vitest__/";
328
770
  const updateTabs = debounce(() => {
329
- nuxt.callHook("devtools:customTabs:refresh");
771
+ refreshCustomTabs(nuxt);
330
772
  }, 100);
331
- nuxt.hook("devtools:customTabs", (tabs) => {
332
- const tab = createVitestCustomTab(vitestWrapper, { iframeSrc });
333
- const index = tabs.findIndex(({ name }) => tab.name === name);
334
- if (index === -1) {
335
- tabs.push(tab);
336
- } else {
337
- tabs.splice(index, 1, tab);
338
- }
339
- });
773
+ addCustomTab(() => createVitestCustomTab(vitestWrapper, { iframeSrc }), nuxt);
340
774
  addDevServerHandler({
341
775
  route: iframeSrc,
342
- handler: defineEventHandler(
343
- () => iframeContentHtml(vitestWrapper.uiUrl)
344
- )
776
+ handler: Object.assign(() => iframeContentHtml(vitestWrapper.uiUrl), { __is_handler__: true })
345
777
  });
346
778
  vitestWrapper.ons({
347
779
  started() {
@@ -521,15 +953,23 @@ function vitestWrapper(options) {
521
953
  };
522
954
  }
523
955
 
956
+ const version = "4.0.0";
957
+ const pkg = {
958
+ version: version};
959
+
524
960
  const module$1 = defineNuxtModule({
525
961
  meta: {
526
962
  name: "@nuxt/test-utils",
527
- configKey: "testUtils"
963
+ configKey: "testUtils",
964
+ version: pkg.version
528
965
  },
529
966
  defaults: {
530
967
  startOnBoot: false,
531
968
  logToConsole: false
532
969
  },
970
+ async onInstall(nuxt) {
971
+ await runInstallWizard(nuxt);
972
+ },
533
973
  async setup(options, nuxt) {
534
974
  if (nuxt.options.test || nuxt.options.dev) {
535
975
  await setupImportMocking(nuxt);
@@ -559,9 +999,9 @@ const module$1 = defineNuxtModule({
559
999
  if (!nuxt.options.dev) return;
560
1000
  if (process.env.TEST || process.env.VITE_TEST) return;
561
1001
  const vitestWrapper2 = createVitestWrapper(options, nuxt);
562
- nuxt.hook("devtools:before", async () => {
1002
+ onDevToolsInitialized(async () => {
563
1003
  await setupDevTools(vitestWrapper2, nuxt);
564
- });
1004
+ }, nuxt);
565
1005
  if (options.startOnBoot) {
566
1006
  vitestWrapper2.start();
567
1007
  }
@@ -1,9 +1,10 @@
1
1
  import * as _playwright_test from '@playwright/test';
2
2
  export { expect } from '@playwright/test';
3
3
  import { Response } from 'playwright-core';
4
- import { T as TestOptions$1, G as GotoOptions, a as TestHooks } from './shared/test-utils.ZByFDqps.mjs';
4
+ import { T as TestOptions$1, G as GotoOptions, a as TestHooks } from './shared/test-utils.BLyxqr96.mjs';
5
5
  import '@nuxt/schema';
6
6
  import 'tinyexec';
7
+ import 'ofetch';
7
8
 
8
9
  type ConfigOptions = {
9
10
  nuxt: Partial<TestOptions$1> | undefined;
@@ -1,17 +1,17 @@
1
1
  import defu from 'defu';
2
2
  import { test as test$1 } from '@playwright/test';
3
3
  export { expect } from '@playwright/test';
4
- import { w as waitForHydration, d as createTest } from './shared/test-utils.D2ZzXztg.mjs';
4
+ import { isWindows } from 'std-env';
5
+ import { w as waitForHydration, d as createTest } from './shared/test-utils.E_cAGA8l.mjs';
5
6
  import 'node:path';
6
7
  import 'ufo';
7
- import 'std-env';
8
8
  import 'consola';
9
9
  import 'node:fs';
10
10
  import 'destr';
11
11
  import 'scule';
12
12
  import 'node:url';
13
13
  import 'exsolve';
14
- import { d as url } from './shared/test-utils.C_clWQBc.mjs';
14
+ import { d as url } from './shared/test-utils.BsmyE2FA.mjs';
15
15
  import 'pathe';
16
16
  import '#dirs';
17
17
  import './shared/test-utils.BIY9XRkB.mjs';
@@ -19,6 +19,7 @@ import 'tinyexec';
19
19
  import 'get-port-please';
20
20
  import 'ofetch';
21
21
 
22
+ const FIXTURE_TIMEOUT = isWindows ? 12e4 : 6e4;
22
23
  const test = test$1.extend({
23
24
  nuxt: [void 0, { option: true, scope: "worker" }],
24
25
  defaults: [{ nuxt: void 0 }, { option: true, scope: "worker" }],
@@ -29,7 +30,7 @@ const test = test$1.extend({
29
30
  await use(hooks);
30
31
  await hooks.afterAll();
31
32
  },
32
- { scope: "worker" }
33
+ { scope: "worker", timeout: FIXTURE_TIMEOUT }
33
34
  ],
34
35
  baseURL: async ({ _nuxtHooks }, use) => {
35
36
  _nuxtHooks.beforeEach();
@@ -1,8 +1,5 @@
1
1
  import environmentOptions from "nuxt-vitest-environment-options";
2
2
  import { setupNuxt } from "./shared/nuxt.mjs";
3
3
  import { setupWindow } from "./shared/environment.mjs";
4
- const el = document.querySelector(environmentOptions.nuxt.rootId || "nuxt-test");
5
- if (!el) {
6
- await setupWindow(window, environmentOptions);
7
- await setupNuxt();
8
- }
4
+ await setupWindow(window, environmentOptions);
5
+ await setupNuxt();
@@ -1,7 +1,8 @@
1
- import { vi } from "vitest";
1
+ import { beforeAll } from "vitest";
2
2
  import { setupNuxt } from "./shared/nuxt.mjs";
3
3
  if (typeof window !== "undefined" && window.__NUXT_VITEST_ENVIRONMENT__) {
4
- await setupNuxt();
5
- vi.resetModules();
4
+ beforeAll(async () => {
5
+ await setupNuxt();
6
+ });
6
7
  }
7
8
  export {};