@nuxt/test-utils 3.22.0 → 3.23.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/config.d.mts CHANGED
@@ -46,6 +46,7 @@ interface NuxtEnvironmentOptions {
46
46
  * @default 'happy-dom'
47
47
  */
48
48
  domEnvironment?: 'happy-dom' | 'jsdom';
49
+ h3Version?: 1 | 2;
49
50
  mock?: {
50
51
  intersectionObserver?: boolean;
51
52
  indexedDb?: boolean;
package/dist/config.mjs CHANGED
@@ -3,11 +3,12 @@ import { defineConfig } from 'vite';
3
3
  import { setupDotenv } from 'c12';
4
4
  import { defu } from 'defu';
5
5
  import { createResolver, findPath } from '@nuxt/kit';
6
+ import { resolveModulePath } from 'exsolve';
7
+ import { getPackageInfoSync } from 'local-pkg';
6
8
  import { a as applyEnv, l as loadKit } from './shared/test-utils.BIY9XRkB.mjs';
7
9
  import 'destr';
8
10
  import 'scule';
9
11
  import 'node:url';
10
- import 'exsolve';
11
12
 
12
13
  const PLUGIN_NAME = "nuxt:vitest:nuxt-environment-options";
13
14
  const STUB_ID = "nuxt-vitest-environment-options";
@@ -94,6 +95,21 @@ async function getVitestConfigFromNuxt(options, loadNuxtOptions = {}) {
94
95
  }
95
96
  delete options.viteConfig.root;
96
97
  options.viteConfig.plugins = (options.viteConfig.plugins || []).filter((p) => !p || !("name" in p) || !excludedPlugins.includes(p.name));
98
+ const nuxtServerIntegration = getPackageInfoSync("@nuxt/nitro-server", {
99
+ paths: [options.nuxt.options.appDir]
100
+ });
101
+ let nitroPath;
102
+ for (const nitroCandidate of [
103
+ ...nuxtServerIntegration?.packageJson.dependencies?.nitro ? ["nitro", "nitro-nightly"] : ["nitropack", "nitropack-nightly"]
104
+ ]) {
105
+ nitroPath = resolveModulePath(nitroCandidate, { from: nuxtServerIntegration?.rootPath || options.nuxt.options.appDir, try: true });
106
+ if (nitroPath) {
107
+ break;
108
+ }
109
+ }
110
+ const h3Info = getPackageInfoSync("h3", {
111
+ paths: nitroPath ? [nitroPath] : options.nuxt.options.modulesDir
112
+ });
97
113
  const resolver = createResolver(import.meta.url);
98
114
  const resolvedConfig = defu(
99
115
  // overrides
@@ -188,6 +204,7 @@ async function getVitestConfigFromNuxt(options, loadNuxtOptions = {}) {
188
204
  environmentOptions: {
189
205
  nuxt: {
190
206
  rootId: options.nuxt.options.app.rootId || void 0,
207
+ h3Version: h3Info?.version?.startsWith("2.") ? 2 : 1,
191
208
  mock: {
192
209
  intersectionObserver: true,
193
210
  indexedDb: false
package/dist/e2e.d.mts CHANGED
@@ -1,9 +1,10 @@
1
- import { T as TestOptions, b as TestContext, a as TestHooks } from './shared/test-utils.ZByFDqps.mjs';
2
- export { $ as $fetch, G as GotoOptions, N as NuxtPage, S as StartServerOptions, h as TestRunner, c as createBrowser, d as createPage, f as fetch, g as getBrowser, s as startServer, e as stopServer, u as url, w as waitForHydration } from './shared/test-utils.ZByFDqps.mjs';
1
+ import { T as TestOptions, b as TestContext, a as TestHooks } from './shared/test-utils.C9GKP_T5.mjs';
2
+ export { $ as $fetch, G as GotoOptions, N as NuxtPage, S as StartServerOptions, h as TestRunner, c as createBrowser, d as createPage, f as fetch, g as getBrowser, s as startServer, e as stopServer, u as url, w as waitForHydration } from './shared/test-utils.C9GKP_T5.mjs';
3
3
  import { LogType } from 'consola';
4
4
  import 'playwright-core';
5
5
  import '@nuxt/schema';
6
6
  import 'tinyexec';
7
+ import 'ofetch';
7
8
 
8
9
  declare function createTestContext(options: Partial<TestOptions>): TestContext;
9
10
  declare function useTestContext(): TestContext;
package/dist/e2e.mjs CHANGED
@@ -1,6 +1,6 @@
1
- export { b as buildFixture, c as createBrowser, a as createPage, d as createTest, g as getBrowser, l as loadFixture, e as setup, s as setupMaps, w as waitForHydration } from './shared/test-utils.D2ZzXztg.mjs';
2
- import { u as useTestContext } from './shared/test-utils.C_clWQBc.mjs';
3
- 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.C_clWQBc.mjs';
1
+ export { b as buildFixture, c as createBrowser, a as createPage, d as createTest, g as getBrowser, l as loadFixture, e as setup, s as setupMaps, w as waitForHydration } from './shared/test-utils.5cnw0YZR.mjs';
2
+ import { u as useTestContext } from './shared/test-utils.BsmyE2FA.mjs';
3
+ 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.BsmyE2FA.mjs';
4
4
  import { consola } from 'consola';
5
5
  import { resolve } from 'pathe';
6
6
  import { distDir } from '#dirs';
@@ -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.C_clWQBc.mjs';
3
+ import { $ as $fetch, u as useTestContext } from './shared/test-utils.BsmyE2FA.mjs';
4
4
  import 'tinyexec';
5
5
  import 'get-port-please';
6
6
  import 'ofetch';
package/dist/module.mjs CHANGED
@@ -1,13 +1,16 @@
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, useNuxt, addDevServerHandler, defineNuxtModule, createResolver, resolvePath } from '@nuxt/kit';
2
+ import { extname, join, dirname, relative, resolve } from 'pathe';
3
+ import { isCI, hasTTY, provider } from 'std-env';
4
4
  import { walk } from 'estree-walker';
5
5
  import MagicString from 'magic-string';
6
6
  import { createUnplugin } from 'unplugin';
7
7
  import { l as loadKit } from './shared/test-utils.BIY9XRkB.mjs';
8
- import { readFileSync } from 'node:fs';
8
+ import { readFileSync, existsSync, promises } from 'node:fs';
9
+ import process$1 from 'node:process';
10
+ import { intro, multiselect, isCancel, cancel, select, confirm, outro } from '@clack/prompts';
11
+ import { colors } from 'consola/utils';
12
+ import { detectPackageManager, addDependency } from 'nypm';
9
13
  import { h } from 'vue';
10
- import { defineEventHandler } from 'h3';
11
14
  import { debounce } from 'perfect-debounce';
12
15
  import { fork } from 'node:child_process';
13
16
  import { c as createVitestTestSummary, l as listenCliMessages, s as sendMessageToCli } from './shared/test-utils.DDUpsMYL.mjs';
@@ -79,7 +82,6 @@ const createMockPlugin = (ctx) => createUnplugin(() => {
79
82
  }
80
83
  const importItem = ctx.imports.find((_) => name === (_.as || _.name));
81
84
  if (!importItem) {
82
- console.log({ imports: ctx.imports });
83
85
  return this.error(`Cannot find import "${name}" to mock`);
84
86
  }
85
87
  s.overwrite(
@@ -323,6 +325,446 @@ 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(() => {
@@ -339,9 +781,7 @@ async function setupDevTools(vitestWrapper, nuxt = useNuxt()) {
339
781
  });
340
782
  addDevServerHandler({
341
783
  route: iframeSrc,
342
- handler: defineEventHandler(
343
- () => iframeContentHtml(vitestWrapper.uiUrl)
344
- )
784
+ handler: Object.assign(() => iframeContentHtml(vitestWrapper.uiUrl), { __is_handler__: true })
345
785
  });
346
786
  vitestWrapper.ons({
347
787
  started() {
@@ -521,15 +961,23 @@ function vitestWrapper(options) {
521
961
  };
522
962
  }
523
963
 
964
+ const version = "3.23.0";
965
+ const pkg = {
966
+ version: version};
967
+
524
968
  const module$1 = defineNuxtModule({
525
969
  meta: {
526
970
  name: "@nuxt/test-utils",
527
- configKey: "testUtils"
971
+ configKey: "testUtils",
972
+ version: pkg.version
528
973
  },
529
974
  defaults: {
530
975
  startOnBoot: false,
531
976
  logToConsole: false
532
977
  },
978
+ async onInstall(nuxt) {
979
+ await runInstallWizard(nuxt);
980
+ },
533
981
  async setup(options, nuxt) {
534
982
  if (nuxt.options.test || nuxt.options.dev) {
535
983
  await setupImportMocking(nuxt);
@@ -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.C9GKP_T5.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,7 +1,7 @@
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 { w as waitForHydration, d as createTest } from './shared/test-utils.5cnw0YZR.mjs';
5
5
  import 'node:path';
6
6
  import 'ufo';
7
7
  import 'std-env';
@@ -11,7 +11,7 @@ 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';