nuxt-spec 0.4.0-alpha.2 → 0.4.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +13 -13
  3. package/app/app.vue +10 -10
  4. package/app/components/NuxtSpecApiTestComponent.vue +24 -24
  5. package/app/components/NuxtSpecTestComponent.vue +9 -9
  6. package/app/components/index.d.ts +7 -7
  7. package/app/components/index.ts +2 -2
  8. package/app/utils/vitest-utils.ts +5 -5
  9. package/config/index.d.ts +36 -36
  10. package/config/index.mjs +147 -147
  11. package/config/report/report-entry.html +6 -6
  12. package/config/report/report-head.html +34 -34
  13. package/config/report/report-screenshot.html +8 -8
  14. package/config/report/report-tail.html +4 -4
  15. package/config/templates/.github/workflows/ci-test-update.yml.template +105 -105
  16. package/config/templates/.github/workflows/ci-test-verify.yml.template +68 -68
  17. package/config/templates/.gitlab/ci/ci-test-update.yml.template +69 -69
  18. package/config/templates/.gitlab/ci/ci-test-verify.yml.template +41 -41
  19. package/config/templates/.gitlab-ci.yml.template +6 -6
  20. package/config/templates/pnpm-workspace.yaml.template +19 -19
  21. package/config/templates/vitest.config.ts.template +5 -5
  22. package/config/utils/merge.mjs +43 -43
  23. package/config/utils/options.d.mts +59 -59
  24. package/config/utils/options.mjs +116 -116
  25. package/config/utils/reporter.mjs +409 -409
  26. package/config/utils/warnings.mjs +38 -38
  27. package/modules/spec-options.ts +23 -23
  28. package/nuxt.config.ts +20 -20
  29. package/package.json +17 -23
  30. package/utils/e2e.ts +131 -131
  31. package/utils/helpers/check-params.ts +44 -44
  32. package/utils/helpers/location-hint.ts +30 -30
  33. package/utils/helpers/screenshot-utils.ts +27 -27
  34. package/utils/index.ts +12 -12
  35. package/utils/playwright.ts +28 -28
  36. package/utils/screenshot.ts +201 -201
  37. package/bin/_internal/prepublish-check.js +0 -16
  38. package/bin/cli.js +0 -53
  39. package/bin/commands/ci.js +0 -124
  40. package/bin/commands/setup.js +0 -367
  41. package/bin/commands/update.js +0 -126
  42. package/bin/helpers/commands.js +0 -82
  43. package/bin/helpers/constants.js +0 -8
  44. package/bin/helpers/git.js +0 -73
@@ -1,5 +1,5 @@
1
- import { loadVitestConfig } from 'nuxt-spec/config'
2
-
3
- export default loadVitestConfig({
4
- // custom config here
5
- })
1
+ import { loadVitestConfig } from 'nuxt-spec/config'
2
+
3
+ export default loadVitestConfig({
4
+ // custom config here
5
+ })
@@ -1,43 +1,43 @@
1
- // custom merger function based on defu
2
- // allows working with the "projects" array properly
3
- // user-defined config overrides are merged by "name"
4
-
5
- // for consistent and predictable results, passing "include" or "browser.instances"
6
- // will result in OVERRIDE instead of merging with nuxt-spec defaults
7
-
8
- import { createDefu } from 'defu'
9
-
10
- // in real Vitest config, "name" is nested inside another "test" object
11
- const getProjectName = project => project?.name ?? project?.test?.name
12
-
13
- export const mergeConfig = createDefu((obj, key, value) => {
14
- if (key === 'projects' && Array.isArray(obj[key]) && Array.isArray(value)) {
15
- const defaults = obj[key]
16
- const overrides = value
17
-
18
- // override default values if user-defined config specifies them
19
- obj[key] = defaults.map((defaultProject) => {
20
- const override = overrides.find(o => getProjectName(o) === getProjectName(defaultProject))
21
- return override ? mergeProject(override, defaultProject) : defaultProject
22
- })
23
-
24
- // add any user projects that don't exist in defaults
25
- for (const override of overrides) {
26
- if (!defaults.some(d => getProjectName(d) === getProjectName(override))) {
27
- obj[key].push(override)
28
- }
29
- }
30
-
31
- return true
32
- }
33
- })
34
-
35
- // Keys where user value should fully replace the default, not merge
36
- const overrideKeys = new Set(['include', 'instances'])
37
-
38
- const mergeProject = createDefu((obj, key, value) => {
39
- if (overrideKeys.has(key)) {
40
- obj[key] = value
41
- return true
42
- }
43
- })
1
+ // custom merger function based on defu
2
+ // allows working with the "projects" array properly
3
+ // user-defined config overrides are merged by "name"
4
+
5
+ // for consistent and predictable results, passing "include" or "browser.instances"
6
+ // will result in OVERRIDE instead of merging with nuxt-spec defaults
7
+
8
+ import { createDefu } from 'defu'
9
+
10
+ // in real Vitest config, "name" is nested inside another "test" object
11
+ const getProjectName = project => project?.name ?? project?.test?.name
12
+
13
+ export const mergeConfig = createDefu((obj, key, value) => {
14
+ if (key === 'projects' && Array.isArray(obj[key]) && Array.isArray(value)) {
15
+ const defaults = obj[key]
16
+ const overrides = value
17
+
18
+ // override default values if user-defined config specifies them
19
+ obj[key] = defaults.map((defaultProject) => {
20
+ const override = overrides.find(o => getProjectName(o) === getProjectName(defaultProject))
21
+ return override ? mergeProject(override, defaultProject) : defaultProject
22
+ })
23
+
24
+ // add any user projects that don't exist in defaults
25
+ for (const override of overrides) {
26
+ if (!defaults.some(d => getProjectName(d) === getProjectName(override))) {
27
+ obj[key].push(override)
28
+ }
29
+ }
30
+
31
+ return true
32
+ }
33
+ })
34
+
35
+ // Keys where user value should fully replace the default, not merge
36
+ const overrideKeys = new Set(['include', 'instances'])
37
+
38
+ const mergeProject = createDefu((obj, key, value) => {
39
+ if (overrideKeys.has(key)) {
40
+ obj[key] = value
41
+ return true
42
+ }
43
+ })
@@ -1,59 +1,59 @@
1
- export type HtmlReportOpenMode = 'always' | 'failed' | 'never'
2
-
3
- /**
4
- * Nuxt Spec options set via `spec` key in nuxt.config.ts.
5
- * Each option can also be set via respective NUXT_SPEC_* env variable,
6
- * which takes precedence over the value from nuxt.config.ts.
7
- */
8
- export interface NuxtSpecOptions {
9
- /**
10
- * Include `@nuxt/hints` module.
11
- * Env: `NUXT_SPEC_HINTS_ENABLED`
12
- * @default true
13
- */
14
- hints?: boolean
15
- /**
16
- * WebSocket endpoint of an external Playwright server used by `e2e` and `browser` projects.
17
- * Env: `NUXT_SPEC_EXTERNAL_PLAYWRIGHT`
18
- */
19
- externalPlaywright?: string
20
- /** HTML test report settings */
21
- htmlReport?: {
22
- /**
23
- * Generate HTML report after each test run.
24
- * Env: `NUXT_SPEC_HTML_REPORT`
25
- * @default true
26
- */
27
- enabled?: boolean
28
- /**
29
- * When to open the report in the default browser.
30
- * Env: `NUXT_SPEC_HTML_REPORT_OPEN`
31
- * @default 'failed'
32
- */
33
- open?: HtmlReportOpenMode
34
- }
35
- /**
36
- * Plain text patterns of log messages that should be omitted.
37
- * Env: `NUXT_SPEC_MESSAGE_FILTERS` (comma-separated, added to values from nuxt.config.ts)
38
- */
39
- messageFilters?: string[]
40
- }
41
-
42
- export interface ResolvedNuxtSpecOptions {
43
- hints: boolean
44
- externalPlaywright: string | undefined
45
- htmlReport: {
46
- enabled: boolean
47
- open: HtmlReportOpenMode
48
- }
49
- messageFilters: string[]
50
- }
51
-
52
- export declare const NUXT_SPEC_DEFAULTS: ResolvedNuxtSpecOptions
53
-
54
- export declare function resolveSpecOptions(
55
- fromConfig?: NuxtSpecOptions | false | null,
56
- env?: Record<string, string | undefined>,
57
- ): ResolvedNuxtSpecOptions
58
-
59
- export declare function loadSpecOptions(cwd?: string): Promise<ResolvedNuxtSpecOptions>
1
+ export type HtmlReportOpenMode = 'always' | 'failed' | 'never'
2
+
3
+ /**
4
+ * Nuxt Spec options set via `spec` key in nuxt.config.ts.
5
+ * Each option can also be set via respective NUXT_SPEC_* env variable,
6
+ * which takes precedence over the value from nuxt.config.ts.
7
+ */
8
+ export interface NuxtSpecOptions {
9
+ /**
10
+ * Include `@nuxt/hints` module.
11
+ * Env: `NUXT_SPEC_HINTS_ENABLED`
12
+ * @default true
13
+ */
14
+ hints?: boolean
15
+ /**
16
+ * WebSocket endpoint of an external Playwright server used by `e2e` and `browser` projects.
17
+ * Env: `NUXT_SPEC_EXTERNAL_PLAYWRIGHT`
18
+ */
19
+ externalPlaywright?: string
20
+ /** HTML test report settings */
21
+ htmlReport?: {
22
+ /**
23
+ * Generate HTML report after each test run.
24
+ * Env: `NUXT_SPEC_HTML_REPORT`
25
+ * @default true
26
+ */
27
+ enabled?: boolean
28
+ /**
29
+ * When to open the report in the default browser.
30
+ * Env: `NUXT_SPEC_HTML_REPORT_OPEN`
31
+ * @default 'failed'
32
+ */
33
+ open?: HtmlReportOpenMode
34
+ }
35
+ /**
36
+ * Plain text patterns of log messages that should be omitted.
37
+ * Env: `NUXT_SPEC_MESSAGE_FILTERS` (comma-separated, added to values from nuxt.config.ts)
38
+ */
39
+ messageFilters?: string[]
40
+ }
41
+
42
+ export interface ResolvedNuxtSpecOptions {
43
+ hints: boolean
44
+ externalPlaywright: string | undefined
45
+ htmlReport: {
46
+ enabled: boolean
47
+ open: HtmlReportOpenMode
48
+ }
49
+ messageFilters: string[]
50
+ }
51
+
52
+ export declare const NUXT_SPEC_DEFAULTS: ResolvedNuxtSpecOptions
53
+
54
+ export declare function resolveSpecOptions(
55
+ fromConfig?: NuxtSpecOptions | false | null,
56
+ env?: Record<string, string | undefined>,
57
+ ): ResolvedNuxtSpecOptions
58
+
59
+ export declare function loadSpecOptions(cwd?: string): Promise<ResolvedNuxtSpecOptions>
@@ -1,116 +1,116 @@
1
- // Nuxt Spec options resolution
2
- // - values can be set via `spec` key in nuxt.config.ts or via NUXT_SPEC_* env variables
3
- // - precedence: env variables > nuxt.config.ts > defaults
4
-
5
- import { loadNuxtConfig } from 'nuxt/kit'
6
-
7
- export const NUXT_SPEC_DEFAULTS = {
8
- hints: true,
9
- externalPlaywright: undefined,
10
- htmlReport: {
11
- enabled: true,
12
- open: 'failed',
13
- },
14
- messageFilters: [],
15
- }
16
-
17
- const HTML_REPORT_OPEN_MODES = ['always', 'failed', 'never']
18
-
19
- // raw `spec` values per cwd - nuxt.config.ts is only loaded once
20
- const specCache = new Map()
21
-
22
- // options are resolved by both the Nuxt module and the Vitest config in the same process
23
- const reportedWarnings = new Set()
24
-
25
- /**
26
- * Resolve final Nuxt Spec options.
27
- * @param {import('./options.d.mts').NuxtSpecOptions | false | null} [fromConfig] - `spec` key from nuxt.config.ts
28
- * @param {Record<string, string | undefined>} [env] - env variables
29
- * @returns {import('./options.d.mts').ResolvedNuxtSpecOptions}
30
- */
31
- export function resolveSpecOptions(fromConfig, env = process.env) {
32
- const config = isObject(fromConfig) ? fromConfig : {}
33
- const htmlReport = checkType('htmlReport', config.htmlReport, 'object') ?? {}
34
- return {
35
- hints: toBoolean(env.NUXT_SPEC_HINTS_ENABLED)
36
- ?? checkType('hints', config.hints, 'boolean')
37
- ?? NUXT_SPEC_DEFAULTS.hints,
38
- externalPlaywright: env.NUXT_SPEC_EXTERNAL_PLAYWRIGHT
39
- || checkType('externalPlaywright', config.externalPlaywright, 'string')
40
- || NUXT_SPEC_DEFAULTS.externalPlaywright,
41
- htmlReport: {
42
- enabled: toBoolean(env.NUXT_SPEC_HTML_REPORT)
43
- ?? checkType('htmlReport.enabled', htmlReport.enabled, 'boolean')
44
- ?? NUXT_SPEC_DEFAULTS.htmlReport.enabled,
45
- open: env.NUXT_SPEC_HTML_REPORT_OPEN
46
- ? toOpenMode('NUXT_SPEC_HTML_REPORT_OPEN', env.NUXT_SPEC_HTML_REPORT_OPEN)
47
- : toOpenMode('htmlReport.open', htmlReport.open),
48
- },
49
- messageFilters: [
50
- ...(checkType('messageFilters', config.messageFilters, 'array') ?? []),
51
- ...(env.NUXT_SPEC_MESSAGE_FILTERS?.split(',') ?? []),
52
- ]
53
- .filter((f) => {
54
- if (typeof f === 'string') return true
55
- warnInvalid('messageFilters', f, 'string', 'Value is ignored.')
56
- return false
57
- })
58
- .map(f => f.trim())
59
- // empty pattern would match (and swallow) every message
60
- .filter(Boolean),
61
- }
62
- }
63
-
64
- /**
65
- * Load `spec` key from nuxt.config.ts (including extended layers)
66
- * and resolve final Nuxt Spec options.
67
- * @param {string} [cwd] - directory with nuxt.config.ts
68
- * @returns {Promise<import('./options.d.mts').ResolvedNuxtSpecOptions>}
69
- */
70
- export async function loadSpecOptions(cwd = process.cwd()) {
71
- if (!specCache.has(cwd)) {
72
- specCache.set(cwd, loadNuxtConfig({ cwd })
73
- .then(config => config.spec)
74
- .catch((error) => {
75
- console.warn(`[Nuxt Spec] Failed to read \`spec\` options from nuxt.config: ${error?.message ?? error}`)
76
- return undefined
77
- }))
78
- }
79
- return resolveSpecOptions(await specCache.get(cwd))
80
- }
81
-
82
- function isObject(value) {
83
- return typeof value === 'object' && value !== null && !Array.isArray(value)
84
- }
85
-
86
- // returns the value if it matches the expected type, otherwise warns and returns undefined
87
- function checkType(option, value, type) {
88
- if (value === undefined) return undefined
89
- const matches = type === 'object'
90
- ? isObject(value)
91
- : type === 'array' ? Array.isArray(value) : typeof value === type
92
- if (matches) return value
93
- warnInvalid(option, value, type)
94
- return undefined
95
- }
96
-
97
- function toOpenMode(option, value) {
98
- if (value === undefined) return NUXT_SPEC_DEFAULTS.htmlReport.open
99
- const normalized = typeof value === 'string' ? value.trim().toLowerCase() : value
100
- if (HTML_REPORT_OPEN_MODES.includes(normalized)) return normalized
101
- warnInvalid(option, value, HTML_REPORT_OPEN_MODES.map(m => `'${m}'`).join(' | '))
102
- return NUXT_SPEC_DEFAULTS.htmlReport.open
103
- }
104
-
105
- function warnInvalid(option, value, expected, outcome = 'Falling back to default.') {
106
- const message = `[Nuxt Spec] Invalid value ${JSON.stringify(value) ?? String(value)} for \`${option}\` (expected ${expected}). ${outcome}`
107
- if (reportedWarnings.has(message)) return
108
- reportedWarnings.add(message)
109
- console.warn(message)
110
- }
111
-
112
- // unset or empty = not defined, only explicit 'false' disables
113
- function toBoolean(value) {
114
- if (value === undefined || value === '') return undefined
115
- return value !== 'false'
116
- }
1
+ // Nuxt Spec options resolution
2
+ // - values can be set via `spec` key in nuxt.config.ts or via NUXT_SPEC_* env variables
3
+ // - precedence: env variables > nuxt.config.ts > defaults
4
+
5
+ import { loadNuxtConfig } from 'nuxt/kit'
6
+
7
+ export const NUXT_SPEC_DEFAULTS = {
8
+ hints: true,
9
+ externalPlaywright: undefined,
10
+ htmlReport: {
11
+ enabled: true,
12
+ open: 'failed',
13
+ },
14
+ messageFilters: [],
15
+ }
16
+
17
+ const HTML_REPORT_OPEN_MODES = ['always', 'failed', 'never']
18
+
19
+ // raw `spec` values per cwd - nuxt.config.ts is only loaded once
20
+ const specCache = new Map()
21
+
22
+ // options are resolved by both the Nuxt module and the Vitest config in the same process
23
+ const reportedWarnings = new Set()
24
+
25
+ /**
26
+ * Resolve final Nuxt Spec options.
27
+ * @param {import('./options.d.mts').NuxtSpecOptions | false | null} [fromConfig] - `spec` key from nuxt.config.ts
28
+ * @param {Record<string, string | undefined>} [env] - env variables
29
+ * @returns {import('./options.d.mts').ResolvedNuxtSpecOptions}
30
+ */
31
+ export function resolveSpecOptions(fromConfig, env = process.env) {
32
+ const config = isObject(fromConfig) ? fromConfig : {}
33
+ const htmlReport = checkType('htmlReport', config.htmlReport, 'object') ?? {}
34
+ return {
35
+ hints: toBoolean(env.NUXT_SPEC_HINTS_ENABLED)
36
+ ?? checkType('hints', config.hints, 'boolean')
37
+ ?? NUXT_SPEC_DEFAULTS.hints,
38
+ externalPlaywright: env.NUXT_SPEC_EXTERNAL_PLAYWRIGHT
39
+ || checkType('externalPlaywright', config.externalPlaywright, 'string')
40
+ || NUXT_SPEC_DEFAULTS.externalPlaywright,
41
+ htmlReport: {
42
+ enabled: toBoolean(env.NUXT_SPEC_HTML_REPORT)
43
+ ?? checkType('htmlReport.enabled', htmlReport.enabled, 'boolean')
44
+ ?? NUXT_SPEC_DEFAULTS.htmlReport.enabled,
45
+ open: env.NUXT_SPEC_HTML_REPORT_OPEN
46
+ ? toOpenMode('NUXT_SPEC_HTML_REPORT_OPEN', env.NUXT_SPEC_HTML_REPORT_OPEN)
47
+ : toOpenMode('htmlReport.open', htmlReport.open),
48
+ },
49
+ messageFilters: [
50
+ ...(checkType('messageFilters', config.messageFilters, 'array') ?? []),
51
+ ...(env.NUXT_SPEC_MESSAGE_FILTERS?.split(',') ?? []),
52
+ ]
53
+ .filter((f) => {
54
+ if (typeof f === 'string') return true
55
+ warnInvalid('messageFilters', f, 'string', 'Value is ignored.')
56
+ return false
57
+ })
58
+ .map(f => f.trim())
59
+ // empty pattern would match (and swallow) every message
60
+ .filter(Boolean),
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Load `spec` key from nuxt.config.ts (including extended layers)
66
+ * and resolve final Nuxt Spec options.
67
+ * @param {string} [cwd] - directory with nuxt.config.ts
68
+ * @returns {Promise<import('./options.d.mts').ResolvedNuxtSpecOptions>}
69
+ */
70
+ export async function loadSpecOptions(cwd = process.cwd()) {
71
+ if (!specCache.has(cwd)) {
72
+ specCache.set(cwd, loadNuxtConfig({ cwd })
73
+ .then(config => config.spec)
74
+ .catch((error) => {
75
+ console.warn(`[Nuxt Spec] Failed to read \`spec\` options from nuxt.config: ${error?.message ?? error}`)
76
+ return undefined
77
+ }))
78
+ }
79
+ return resolveSpecOptions(await specCache.get(cwd))
80
+ }
81
+
82
+ function isObject(value) {
83
+ return typeof value === 'object' && value !== null && !Array.isArray(value)
84
+ }
85
+
86
+ // returns the value if it matches the expected type, otherwise warns and returns undefined
87
+ function checkType(option, value, type) {
88
+ if (value === undefined) return undefined
89
+ const matches = type === 'object'
90
+ ? isObject(value)
91
+ : type === 'array' ? Array.isArray(value) : typeof value === type
92
+ if (matches) return value
93
+ warnInvalid(option, value, type)
94
+ return undefined
95
+ }
96
+
97
+ function toOpenMode(option, value) {
98
+ if (value === undefined) return NUXT_SPEC_DEFAULTS.htmlReport.open
99
+ const normalized = typeof value === 'string' ? value.trim().toLowerCase() : value
100
+ if (HTML_REPORT_OPEN_MODES.includes(normalized)) return normalized
101
+ warnInvalid(option, value, HTML_REPORT_OPEN_MODES.map(m => `'${m}'`).join(' | '))
102
+ return NUXT_SPEC_DEFAULTS.htmlReport.open
103
+ }
104
+
105
+ function warnInvalid(option, value, expected, outcome = 'Falling back to default.') {
106
+ const message = `[Nuxt Spec] Invalid value ${JSON.stringify(value) ?? String(value)} for \`${option}\` (expected ${expected}). ${outcome}`
107
+ if (reportedWarnings.has(message)) return
108
+ reportedWarnings.add(message)
109
+ console.warn(message)
110
+ }
111
+
112
+ // unset or empty = not defined, only explicit 'false' disables
113
+ function toBoolean(value) {
114
+ if (value === undefined || value === '') return undefined
115
+ return value !== 'false'
116
+ }