nuxt-spec 0.0.4 → 0.1.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/CHANGELOG.md +21 -0
- package/README.md +52 -11
- package/app/app.vue +9 -0
- package/{components → app/components}/NuxtTestComponent.vue +1 -1
- package/app/utils/vitest-config.ts +31 -0
- package/bin/spec-setup.js +25 -0
- package/bin/utils/create-file.js +37 -0
- package/bin/utils/modify-scripts.js +46 -0
- package/bin/utils/prompt-user.js +15 -0
- package/eslint.config.mjs +0 -3
- package/nuxt.config.ts +1 -1
- package/package.json +37 -33
- package/test/{nuxt-e2e.test.ts → e2e/nuxt-e2e.test.ts} +3 -3
- package/test/{nuxt-unit.test.ts → nuxt/nuxt-unit.test.ts} +1 -3
- package/vitest.config.ts +8 -0
- package/app.vue +0 -9
- package/vitest.config.mts +0 -8
- /package/{utils → app/utils}/vitest-utils.ts +0 -0
- /package/test/{vitest.test.ts → unit/vitest.test.ts} +0 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Overview of the newest features in Nuxt Spec.
|
|
4
|
+
|
|
5
|
+
## 0.1.1
|
|
6
|
+
|
|
7
|
+
**2025-08-09**
|
|
8
|
+
|
|
9
|
+
- feat: CLI tool for scaffolding `vitest.config.ts` and test-related scripts in `package.json`
|
|
10
|
+
- docs: added `CHANGELOG.md` and fixed link to `playwright-core`
|
|
11
|
+
|
|
12
|
+
## 0.1.0
|
|
13
|
+
|
|
14
|
+
**2025-08-08**
|
|
15
|
+
|
|
16
|
+
- initial release [v0.1.0](https://github.com/AloisSeckar/nuxt-spec/releases/tag/v0.1.0)
|
|
17
|
+
- key features:
|
|
18
|
+
- Nuxt base layer for testing
|
|
19
|
+
- Nuxt v4 and Vitest v4 compatibility
|
|
20
|
+
- Integrated `vitest`, `@vitest/browser`, `happy-dom`, `playwright-core`, `@vue/test-utils`, `@nuxt/test-utils`
|
|
21
|
+
- Support for custom configuration via `loadVitestConfig` function in `vitest.config.ts`
|
package/README.md
CHANGED
|
@@ -8,14 +8,13 @@ While Nuxt itself does have a [dedicated module for testing](https://nuxt.com/do
|
|
|
8
8
|
|
|
9
9
|
The most important client of `nuxt-spec` is my [Nuxt Ignis](https://github.com/AloisSeckar/nuxt-ignis) template starter that adds up even more ready-to-use cool stuff for your future awesome Nuxt websites.
|
|
10
10
|
|
|
11
|
-
|
|
12
11
|
## How to use
|
|
13
12
|
|
|
14
13
|
Aside from being "forked" and used as you seem fit, `nuxt-spec` is also available as an [NPM package](https://www.npmjs.com/package/nuxt-spec) that can be referenced as a single-import with all the features incoming.
|
|
15
14
|
|
|
16
15
|
1) Add following dependency into your `package.json`:
|
|
17
16
|
```
|
|
18
|
-
"nuxt-spec": "0.
|
|
17
|
+
"nuxt-spec": "0.1.1"
|
|
19
18
|
```
|
|
20
19
|
|
|
21
20
|
2) Add following section into your `nuxt.config.ts`:
|
|
@@ -33,26 +32,68 @@ strict-peer-dependencies=false
|
|
|
33
32
|
|
|
34
33
|
4) If you're prompoted, run `npm exec playwright-core install` to download and locally install headless browser runtimes.
|
|
35
34
|
|
|
36
|
-
|
|
37
35
|
**DONE.** You are just `npm install` and `npm run dev` away from testing your Nuxt projects!
|
|
38
36
|
|
|
37
|
+
### Optional setup
|
|
38
|
+
|
|
39
|
+
The `nuxt-spec` package comes with a CLI tool that can help you:
|
|
40
|
+
- scaffold the default `vitest.config.ts` (see [configuration](#configuration) section)
|
|
41
|
+
- add a few test-related script shorthands into your `package.json` (see [running tests](#running-tests) section)
|
|
42
|
+
|
|
43
|
+
To use it, just run the following command in your terminal after you installed `nuxt-spec` package (files must be available in your `node_modules` folder):
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx nuxt-spec-cli
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
You will be prompted for each action which allows you to choose only one action to run and skip the other.
|
|
50
|
+
|
|
51
|
+
### Running tests
|
|
52
|
+
|
|
53
|
+
Once installed, Vitest automatically discovers all `*.test.ts` and `*.spec.ts` files in project and will run them.
|
|
54
|
+
|
|
55
|
+
It is recommended to have following three commands `package.json` file in `"scripts"` section in order to run tests easilly:
|
|
56
|
+
- `test: vitest run` - runs once and ends
|
|
57
|
+
- `test-u: vitest run -u` - runs once and updates snapshots
|
|
58
|
+
- `test-i: vitest` - runs and waits in HMR mode for test file changes
|
|
59
|
+
|
|
60
|
+
Then you can call in terminal in root of your project:
|
|
61
|
+
|
|
62
|
+
`npm run test` | `npm run test-u` | `npm run test-i`
|
|
39
63
|
|
|
40
64
|
## Overview
|
|
41
65
|
|
|
42
|
-
**Nuxt
|
|
43
|
-
- [vitest](https://www.npmjs.com/package/vitest) as the fundamental testing framework
|
|
66
|
+
**Nuxt Spec** currently contains:
|
|
67
|
+
- [vitest](https://www.npmjs.com/package/vitest) **v4** as the fundamental testing framework
|
|
68
|
+
- [@vitest/browser](https://www.npmjs.com/package/@vitest/browser) as the experimental browser runner
|
|
44
69
|
- [happy-dom](https://www.npmjs.com/package/happy-dom) as the headless browser runtime
|
|
45
|
-
- [playwright-core](https://www.npmjs.com/package/
|
|
70
|
+
- [playwright-core](https://www.npmjs.com/package/playwright-core) as the headless browser testing framework
|
|
46
71
|
- [@vue/test-utils](https://www.npmjs.com/package/@vue/test-utils) for testing Vue stuff
|
|
47
72
|
- [@nuxt/test-utils](https://www.npmjs.com/package/@nuxt/test-utils) for testing Nuxt stuff
|
|
48
73
|
|
|
49
|
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
74
|
+
Planned future development:
|
|
75
|
+
- reason about (not) using Vitest browser mode (or make it optional)
|
|
76
|
+
- solution for visual testing - either [backstopjs](https://www.npmjs.com/package/backstopjs) or Vitest's native (currently experimental)
|
|
77
|
+
|
|
78
|
+
See [CHANGELOG.md](https://github.com/AloisSeckar/nuxt-spec/blob/main/CHANGELOG.md) for the latest updates and features.
|
|
79
|
+
|
|
80
|
+
## Configuration
|
|
81
|
+
|
|
82
|
+
By default, `nuxt-spec` uses Vitest configuration defined in [`/utils/vitest-config.ts`](https://github.com/AloisSeckar/nuxt-spec/blob/main/utils/vitest-config.ts). The configuration is based on [Nuxt team recommendations](https://nuxt.com/docs/4.x/getting-started/testing) and our best judgement.
|
|
83
|
+
|
|
84
|
+
To add/override your custom config, you can create a file named `vitest.config.ts` in the root of your project with the following content:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { loadVitestConfig } from './app/utils/vitest-config'
|
|
88
|
+
|
|
89
|
+
export default loadVitestConfig({
|
|
90
|
+
// your custom config here
|
|
91
|
+
})
|
|
92
|
+
```
|
|
52
93
|
|
|
53
|
-
|
|
54
|
-
- [backstopjs](https://www.npmjs.com/package/backstopjs) as the solution for visual testing
|
|
94
|
+
And pass whatever you want as a parameter object. It will be defu-merged with the defaults (custom config takes precedence).
|
|
55
95
|
|
|
96
|
+
Alternatively, if you don't want to use any part of the `nuxt-spec` default configuration, you can override `vitest.config.ts` file completely and define your own [Vitest configuration](https://vitest.dev/config/) from scratch.
|
|
56
97
|
|
|
57
98
|
## Contact
|
|
58
99
|
|
package/app/app.vue
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// this is the default Vitest config object
|
|
2
|
+
// based on https://nuxt.com/docs/4.x/getting-started/testing#setup
|
|
3
|
+
|
|
4
|
+
import { defu } from 'defu'
|
|
5
|
+
import { defineConfig } from 'vitest/config'
|
|
6
|
+
import { defineVitestProject } from '@nuxt/test-utils/config'
|
|
7
|
+
|
|
8
|
+
// @ts-expect-error no-implicit-any
|
|
9
|
+
// TODO set proper type for the object
|
|
10
|
+
export async function loadVitestConfig(userVitestConfig) {
|
|
11
|
+
return defu(userVitestConfig, defineConfig({
|
|
12
|
+
test: {
|
|
13
|
+
projects: [
|
|
14
|
+
{
|
|
15
|
+
test: {
|
|
16
|
+
name: 'node',
|
|
17
|
+
include: ['test/{e2e,unit}/*.{test,spec}.ts'],
|
|
18
|
+
environment: 'node',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
await defineVitestProject({
|
|
22
|
+
test: {
|
|
23
|
+
name: 'nuxt',
|
|
24
|
+
include: ['test/nuxt/*.{test,spec}.ts'],
|
|
25
|
+
environment: 'nuxt',
|
|
26
|
+
},
|
|
27
|
+
}),
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
}))
|
|
31
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// CLI tool to scaffold default `vitest.config.ts` file
|
|
4
|
+
// and to add test-related commands in `package.json`
|
|
5
|
+
// usage: `npx spec-setup.js` in target folder
|
|
6
|
+
|
|
7
|
+
import { createFileFromTemplate } from './utils/create-file.js'
|
|
8
|
+
import { updatePackageJsonScripts } from './utils/modify-scripts.js'
|
|
9
|
+
|
|
10
|
+
async function main() {
|
|
11
|
+
// 1) create vitest.config.ts
|
|
12
|
+
await createFileFromTemplate('../vitest.config.ts', 'vitest.config.ts')
|
|
13
|
+
|
|
14
|
+
// 2) modify scripts in package.json
|
|
15
|
+
await updatePackageJsonScripts({
|
|
16
|
+
'test': 'vitest run',
|
|
17
|
+
'test-u': 'vitest run -u',
|
|
18
|
+
'test-i': 'vitest',
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
main().catch((err) => {
|
|
23
|
+
console.error('Error:', err)
|
|
24
|
+
process.exit(1)
|
|
25
|
+
})
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import { existsSync, copyFileSync } from 'fs'
|
|
3
|
+
import { fileURLToPath } from 'url'
|
|
4
|
+
import { promptUser } from './prompt-user.js'
|
|
5
|
+
|
|
6
|
+
export async function createFileFromTemplate(templateFile, targetFile) {
|
|
7
|
+
const shouldCreate = await promptUser(
|
|
8
|
+
`This will create default 'vitest.config.ts' file. Continue?`,
|
|
9
|
+
)
|
|
10
|
+
if (shouldCreate) {
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
12
|
+
const __dirname = path.dirname(__filename)
|
|
13
|
+
|
|
14
|
+
const templatePath = path.resolve(__dirname, `../${templateFile}`)
|
|
15
|
+
const targetPath = path.resolve(process.cwd(), `../${targetFile}`)
|
|
16
|
+
|
|
17
|
+
if (!existsSync(templatePath)) {
|
|
18
|
+
console.error(`Template file not found at ${templatePath}`)
|
|
19
|
+
process.exit(1)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (existsSync(targetPath)) {
|
|
23
|
+
const shouldOverwrite = await promptUser(
|
|
24
|
+
`File 'vitest.config.ts' already exists. Overwrite?`,
|
|
25
|
+
)
|
|
26
|
+
if (!shouldOverwrite) {
|
|
27
|
+
console.log('Aborted.')
|
|
28
|
+
process.exit(0)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
copyFileSync(templatePath, targetPath)
|
|
33
|
+
console.log(`Default 'vitest.config.ts' successfully created.`)
|
|
34
|
+
} else {
|
|
35
|
+
console.log(`Creation of 'vitest.config.ts' skipped.`)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { promptUser } from './prompt-user.js'
|
|
4
|
+
|
|
5
|
+
export async function updatePackageJsonScripts(scriptsToAdd) {
|
|
6
|
+
const shouldUpdate = await promptUser(
|
|
7
|
+
`This will update scripts section of 'package.json' file. Continue?`,
|
|
8
|
+
)
|
|
9
|
+
if (shouldUpdate) {
|
|
10
|
+
const packageJsonPath = path.resolve(process.cwd(), 'package.json')
|
|
11
|
+
|
|
12
|
+
if (!existsSync(packageJsonPath)) {
|
|
13
|
+
console.warn(`No 'package.json' found in project root — skipping script updates.`)
|
|
14
|
+
return
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const pkgRaw = readFileSync(packageJsonPath, 'utf8')
|
|
18
|
+
let pkg
|
|
19
|
+
try {
|
|
20
|
+
pkg = JSON.parse(pkgRaw)
|
|
21
|
+
} catch {
|
|
22
|
+
console.error(`Could not parse 'package.json' — skipping script updates.`)
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
pkg.scripts = pkg.scripts || {}
|
|
27
|
+
|
|
28
|
+
let modified = false
|
|
29
|
+
|
|
30
|
+
for (const [name, cmd] of Object.entries(scriptsToAdd)) {
|
|
31
|
+
if (pkg.scripts[name] !== cmd) {
|
|
32
|
+
pkg.scripts[name] = cmd
|
|
33
|
+
modified = true
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (modified) {
|
|
38
|
+
writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8')
|
|
39
|
+
console.log(`Scripts section of 'package.json' updated.`)
|
|
40
|
+
} else {
|
|
41
|
+
console.log(`Scripts section of 'package.json' already up to date.`)
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
console.log(`Adding scripts to 'package.json' skipped.`)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import readline from 'readline'
|
|
2
|
+
|
|
3
|
+
export async function promptUser(question) {
|
|
4
|
+
const rl = readline.createInterface({
|
|
5
|
+
input: process.stdin,
|
|
6
|
+
output: process.stdout,
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
return new Promise((resolve) => {
|
|
10
|
+
rl.question(question + ' (y/N): ', (answer) => {
|
|
11
|
+
rl.close()
|
|
12
|
+
resolve(/^y(es)?$/i.test(answer.trim()))
|
|
13
|
+
})
|
|
14
|
+
})
|
|
15
|
+
}
|
package/eslint.config.mjs
CHANGED
|
@@ -5,9 +5,6 @@ import withNuxt from './.nuxt/eslint.config.mjs'
|
|
|
5
5
|
|
|
6
6
|
export default withNuxt([
|
|
7
7
|
|
|
8
|
-
// files to be processed (JS/TS + Vue components)
|
|
9
|
-
{ files: ['**/*.js', '**/*.ts', '**/*.vue'] },
|
|
10
|
-
|
|
11
8
|
// `rules` section can follow, where you can change default eslint behaviour if needed
|
|
12
9
|
// you can adjust or even turn off some rules if you cannot or don't want to satisfy them
|
|
13
10
|
{
|
package/nuxt.config.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,33 +1,37 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "nuxt-spec",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Test-pack layer for Nuxt Applications",
|
|
5
|
-
"repository": "github:AloisSeckar/nuxt-spec",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"main": "./nuxt.config.ts",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
},
|
|
20
|
-
"
|
|
21
|
-
"@nuxt/
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "nuxt-spec",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Test-pack layer for Nuxt Applications",
|
|
5
|
+
"repository": "github:AloisSeckar/nuxt-spec",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./nuxt.config.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"spec-setup": "./bin/spec-setup.js"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@nuxt/test-utils": "3.19.2",
|
|
14
|
+
"@vue/test-utils": "2.4.6",
|
|
15
|
+
"happy-dom": "18.0.1",
|
|
16
|
+
"playwright-core": "1.54.2",
|
|
17
|
+
"vitest": "4.0.0-beta.7",
|
|
18
|
+
"@vitest/browser": "4.0.0-beta.7"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@nuxt/eslint": "1.8.0",
|
|
22
|
+
"nuxt": "4.0.3",
|
|
23
|
+
"typescript": "5.9.2"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"analyze": "nuxt analyze",
|
|
27
|
+
"eslint": "eslint .",
|
|
28
|
+
"build": "nuxt build",
|
|
29
|
+
"dev": "nuxt dev",
|
|
30
|
+
"generate": "nuxt generate",
|
|
31
|
+
"preview": "nuxt preview",
|
|
32
|
+
"start": "nuxt start",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"test-u": "vitest run -u",
|
|
35
|
+
"test-i": "vitest"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -4,18 +4,18 @@ import { describe, expect, test } from 'vitest'
|
|
|
4
4
|
describe('NuxtTestComponent E2E test', async () => {
|
|
5
5
|
// setup app.vue in headless browser
|
|
6
6
|
await setup()
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
test('component renders in browser', async () => {
|
|
9
9
|
// fetch for the rendered value
|
|
10
10
|
const html = await $fetch('/')
|
|
11
|
-
expect(html).toContain('
|
|
11
|
+
expect(html).toContain('Test Component')
|
|
12
12
|
})
|
|
13
13
|
|
|
14
14
|
test('with playwright', async () => {
|
|
15
15
|
// render page in headless browser
|
|
16
16
|
const page = await createPage()
|
|
17
17
|
await page.goto(url('/'), { waitUntil: 'hydration' })
|
|
18
|
-
const hasText = await page.getByText('
|
|
18
|
+
const hasText = await page.getByText('Test Component').isVisible()
|
|
19
19
|
expect(hasText).toBeTruthy()
|
|
20
20
|
})
|
|
21
21
|
})
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { describe, test, expect } from 'vitest'
|
|
2
2
|
import { mount } from '@vue/test-utils'
|
|
3
3
|
import { mountSuspended } from '@nuxt/test-utils/runtime'
|
|
4
|
-
import NuxtTestComponent from '
|
|
5
|
-
|
|
6
|
-
// mockNuxtImport - macro for mimicking external functionality for unit tests
|
|
4
|
+
import NuxtTestComponent from '../../app/components/NuxtTestComponent.vue'
|
|
7
5
|
|
|
8
6
|
const text = 'custom-text'
|
|
9
7
|
|
package/vitest.config.ts
ADDED
package/app.vue
DELETED
package/vitest.config.mts
DELETED
|
File without changes
|
|
File without changes
|