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,38 +1,38 @@
1
- const messageFilters = [
2
- // Node+Windows false positive
3
- // https://github.com/nuxt/icon/issues/140
4
- 'Use of deprecated trailing slash pattern mapping',
5
- // remove once Vue stops considering <Suspense> experimental
6
- '<Suspense> is an experimental feature',
7
- ]
8
-
9
- // merge user-defined filters (`spec.messageFilters` / NUXT_SPEC_MESSAGE_FILTERS) with defaults
10
- export function addMessageFilters(filters) {
11
- for (const filter of filters) {
12
- if (filter && !messageFilters.includes(filter)) {
13
- messageFilters.push(filter)
14
- }
15
- }
16
- }
17
-
18
- // 1) filter-out unnecessary stderr/stdout logs coming from Vitest
19
- // (applied as side-effect on import)
20
-
21
- const _stderrWrite = process.stderr.write.bind(process.stderr)
22
- process.stderr.write = (chunk, ...args) => {
23
- if (typeof chunk === 'string' && messageFilters.some(f => chunk.includes(f))) return true
24
- return _stderrWrite(chunk, ...args)
25
- }
26
-
27
- const _stdoutWrite = process.stdout.write.bind(process.stdout)
28
- process.stdout.write = (chunk, ...args) => {
29
- if (typeof chunk === 'string' && messageFilters.some(f => chunk.includes(f))) return true
30
- return _stdoutWrite(chunk, ...args)
31
- }
32
-
33
- // 2) filter-out unnecessary console logs coming from Vitest
34
- // (used as Vitest onConsoleLog hook)
35
-
36
- export function onConsoleLog(log) {
37
- if (messageFilters.some(f => log.includes(f))) return false
38
- }
1
+ const messageFilters = [
2
+ // Node+Windows false positive
3
+ // https://github.com/nuxt/icon/issues/140
4
+ 'Use of deprecated trailing slash pattern mapping',
5
+ // remove once Vue stops considering <Suspense> experimental
6
+ '<Suspense> is an experimental feature',
7
+ ]
8
+
9
+ // merge user-defined filters (`spec.messageFilters` / NUXT_SPEC_MESSAGE_FILTERS) with defaults
10
+ export function addMessageFilters(filters) {
11
+ for (const filter of filters) {
12
+ if (filter && !messageFilters.includes(filter)) {
13
+ messageFilters.push(filter)
14
+ }
15
+ }
16
+ }
17
+
18
+ // 1) filter-out unnecessary stderr/stdout logs coming from Vitest
19
+ // (applied as side-effect on import)
20
+
21
+ const _stderrWrite = process.stderr.write.bind(process.stderr)
22
+ process.stderr.write = (chunk, ...args) => {
23
+ if (typeof chunk === 'string' && messageFilters.some(f => chunk.includes(f))) return true
24
+ return _stderrWrite(chunk, ...args)
25
+ }
26
+
27
+ const _stdoutWrite = process.stdout.write.bind(process.stdout)
28
+ process.stdout.write = (chunk, ...args) => {
29
+ if (typeof chunk === 'string' && messageFilters.some(f => chunk.includes(f))) return true
30
+ return _stdoutWrite(chunk, ...args)
31
+ }
32
+
33
+ // 2) filter-out unnecessary console logs coming from Vitest
34
+ // (used as Vitest onConsoleLog hook)
35
+
36
+ export function onConsoleLog(log) {
37
+ if (messageFilters.some(f => log.includes(f))) return false
38
+ }
@@ -1,23 +1,23 @@
1
- import { defineNuxtModule } from 'nuxt/kit'
2
- import type { ModuleDependencies, NuxtModule } from 'nuxt/schema'
3
- import { resolveSpecOptions } from '../config/utils/options.mjs'
4
- import type { NuxtSpecOptions } from '../config/utils/options.mjs'
5
-
6
- // registers typed `spec` key for nuxt.config.ts and applies its Nuxt-related options
7
- // options related to Vitest are resolved in `loadVitestConfig` (config/index.mjs)
8
- // (explicit types break circular reference with module types generated by Nuxt)
9
- const specOptionsModule: NuxtModule<NuxtSpecOptions> = defineNuxtModule<NuxtSpecOptions>({
10
- meta: {
11
- name: 'nuxt-spec',
12
- configKey: 'spec',
13
- // used as `@see` link in generated types (fallback would be a broken npm URL)
14
- docs: 'https://nuxt-spec.netlify.app/2-1-configuration.html#nuxt-spec-options',
15
- },
16
- moduleDependencies: (nuxt): ModuleDependencies => {
17
- // `spec` is typed only after Nuxt generates module types
18
- const { spec } = nuxt.options as unknown as { spec?: NuxtSpecOptions | false }
19
- return resolveSpecOptions(spec).hints ? { '@nuxt/hints': {} } : {}
20
- },
21
- })
22
-
23
- export default specOptionsModule
1
+ import { defineNuxtModule } from 'nuxt/kit'
2
+ import type { ModuleDependencies, NuxtModule } from 'nuxt/schema'
3
+ import { resolveSpecOptions } from '../config/utils/options.mjs'
4
+ import type { NuxtSpecOptions } from '../config/utils/options.mjs'
5
+
6
+ // registers typed `spec` key for nuxt.config.ts and applies its Nuxt-related options
7
+ // options related to Vitest are resolved in `loadVitestConfig` (config/index.mjs)
8
+ // (explicit types break circular reference with module types generated by Nuxt)
9
+ const specOptionsModule: NuxtModule<NuxtSpecOptions> = defineNuxtModule<NuxtSpecOptions>({
10
+ meta: {
11
+ name: 'nuxt-spec',
12
+ configKey: 'spec',
13
+ // used as `@see` link in generated types (fallback would be a broken npm URL)
14
+ docs: 'https://nuxt-spec.netlify.app/2-1-configuration.html#nuxt-spec-options',
15
+ },
16
+ moduleDependencies: (nuxt): ModuleDependencies => {
17
+ // `spec` is typed only after Nuxt generates module types
18
+ const { spec } = nuxt.options as unknown as { spec?: NuxtSpecOptions | false }
19
+ return resolveSpecOptions(spec).hints ? { '@nuxt/hints': {} } : {}
20
+ },
21
+ })
22
+
23
+ export default specOptionsModule
package/nuxt.config.ts CHANGED
@@ -1,20 +1,20 @@
1
- export default defineNuxtConfig({
2
- modules: [
3
- '@nuxt/eslint',
4
- '@nuxt/test-utils/module',
5
- // @nuxt/hints module is handled in `modules/spec-options.ts`
6
- ],
7
-
8
- // exclude file used for explicit exports (nuxt-spec/components) from Nuxt resolution
9
- components: {
10
- dirs: [{ path: '~/components', ignore: ['index.ts'] }],
11
- },
12
-
13
- compatibilityDate: '2026-10-13',
14
-
15
- eslint: {
16
- config: {
17
- stylistic: true,
18
- },
19
- },
20
- })
1
+ export default defineNuxtConfig({
2
+ modules: [
3
+ '@nuxt/eslint',
4
+ '@nuxt/test-utils/module',
5
+ // @nuxt/hints module is handled in `modules/spec-options.ts`
6
+ ],
7
+
8
+ // exclude file used for explicit exports (nuxt-spec/components) from Nuxt resolution
9
+ components: {
10
+ dirs: [{ path: '~/components', ignore: ['index.ts'] }],
11
+ },
12
+
13
+ compatibilityDate: '2026-10-13',
14
+
15
+ eslint: {
16
+ config: {
17
+ stylistic: true,
18
+ },
19
+ },
20
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-spec",
3
- "version": "0.4.0-alpha.2",
3
+ "version": "0.4.0-alpha.3",
4
4
  "description": "Test-pack layer for Nuxt Applications",
5
5
  "repository": {
6
6
  "type": "git",
@@ -9,24 +9,6 @@
9
9
  "license": "MIT",
10
10
  "type": "module",
11
11
  "main": "./nuxt.config.ts",
12
- "scripts": {
13
- "analyze": "nuxt analyze",
14
- "eslint": "eslint .",
15
- "typecheck": "nuxi typecheck",
16
- "build": "nuxt build",
17
- "dev": "nuxt dev",
18
- "generate": "nuxt generate",
19
- "prepublishOnly": "node bin/_internal/prepublish-check.js",
20
- "preview": "nuxt preview",
21
- "start": "nuxt start",
22
- "test": "vitest run",
23
- "test-u": "vitest run -u",
24
- "test-c": "vitest run --coverage",
25
- "test-i": "vitest"
26
- },
27
- "bin": {
28
- "nuxt-spec": "bin/cli.js"
29
- },
30
12
  "exports": {
31
13
  ".": "./nuxt.config.ts",
32
14
  "./config": {
@@ -46,7 +28,6 @@
46
28
  },
47
29
  "files": [
48
30
  "app",
49
- "bin",
50
31
  "config",
51
32
  "modules",
52
33
  "public",
@@ -65,7 +46,6 @@
65
46
  "@vitest/coverage-v8": "5.0.3",
66
47
  "@vitest/ui": "5.0.3",
67
48
  "@vue/test-utils": "2.5.1",
68
- "elrh-cosca": "0.4.3",
69
49
  "fast-png": "~8.0.0",
70
50
  "happy-dom": "~20.14.5",
71
51
  "nuxt": "4.6.1",
@@ -79,5 +59,19 @@
79
59
  "vue-router": "~5.3.1",
80
60
  "vue-tsc": "~3.3.12"
81
61
  },
82
- "packageManager": "pnpm@12.11.2"
83
- }
62
+ "scripts": {
63
+ "analyze": "nuxt analyze",
64
+ "eslint": "eslint .",
65
+ "typecheck": "nuxi typecheck",
66
+ "build": "nuxt build",
67
+ "dev": "nuxt dev",
68
+ "generate": "nuxt generate",
69
+ "preview": "nuxt preview",
70
+ "release": "node scripts/release.js",
71
+ "start": "nuxt start",
72
+ "test": "vitest run",
73
+ "test-u": "vitest run -u",
74
+ "test-c": "vitest run --coverage",
75
+ "test-i": "vitest"
76
+ }
77
+ }
package/utils/e2e.ts CHANGED
@@ -1,131 +1,131 @@
1
- import { createPage, url } from '@nuxt/test-utils/e2e'
2
- import type { GotoOptions, NuxtPage } from '@nuxt/test-utils'
3
- import { checkPageParam, checkStringParam } from './helpers/check-params'
4
-
5
- /**
6
- * Extra settings object for `gotoPage()` function.
7
- * All properties are optional.
8
- */
9
- export type GotoPageOptions = {
10
- /** Event to be awaited before NuxtPage instance is returned (defaults to `'hydration'`) */
11
- waitUntil?: GotoOptions['waitUntil']
12
- }
13
-
14
- /**
15
- * Visit a specified URL and return the page instance for further interaction.
16
- *
17
- * @param pageName - Path segment appended to the base URL (e.g. `'about'` → `/<about>`)
18
- * @param options - Optional extra settings (see `GotoPageOptions`)
19
- * @returns Playwright page instance after navigation and `hydration` event
20
- */
21
- export async function gotoPage(pageName: string, options?: GotoPageOptions): Promise<NuxtPage> {
22
- const { waitUntil } = options ?? {}
23
-
24
- // verify params
25
- checkStringParam('gotoPage:pageName', pageName)
26
- if (waitUntil) {
27
- checkStringParam('gotoPage:options.waitUntil', waitUntil)
28
- }
29
-
30
- // construct NuxtPage instance
31
- const page = await createPage()
32
- const urlPath = pageName.startsWith('/') ? url(pageName) : url(`/${pageName}`)
33
- await page.goto(urlPath, { waitUntil: waitUntil ?? 'hydration' })
34
-
35
- return page
36
- }
37
-
38
- /**
39
- * Extra settings object for `getDataHtml()` function.
40
- * All properties are optional.
41
- */
42
- export type GetDataHtmlOptions = {
43
- /** Event to be awaited before NuxtPage instance is returned (defaults to `'hydration'`) */
44
- waitUntil?: GotoOptions['waitUntil']
45
- /** CSS selector identifying the target element (defaults to `<body>` tag) */
46
- element?: string
47
- }
48
-
49
- /**
50
- * Extract inner HTML content from a specified element on a given page.
51
- * If no element is specified via `options.element`, the entire `<body>` content is returned.
52
- *
53
- * @param page - Playwright page instance, or a page name string (will call `gotoPage` internally)
54
- * @param options - Optional extra settings (see `GetDataHtmlOptions`)
55
- * @returns The inner HTML of the matched element
56
- */
57
- export async function getDataHtml(page: NuxtPage | string, options?: GetDataHtmlOptions): Promise<string> {
58
- const { waitUntil, element } = options ?? {}
59
-
60
- // verify params
61
- if (typeof page === 'string') {
62
- checkStringParam('getDataHtml:page', page)
63
- }
64
- if (waitUntil) {
65
- checkStringParam('getDataHtml:options.waitUntil', waitUntil)
66
- }
67
- if (element) {
68
- checkStringParam('getDataHtml:options.element', element)
69
- }
70
-
71
- // get NuxtPage instance
72
- const pageInstance = typeof page === 'string' ? await gotoPage(page, { waitUntil }) : page
73
- checkPageParam('getDataHtml:pageInstance', pageInstance)
74
-
75
- // extract target HTML
76
- const dataElement = pageInstance.locator(element ?? 'body')
77
- return await dataElement.innerHTML()
78
- }
79
-
80
- /**
81
- * Extra settings object for `getAPIResultHtml()` function.
82
- * Due to nature of the function, `triggerElement`, `targetUrl`, and `responseElement` are required.
83
- */
84
- export type GetAPIResultHtmlOptions = {
85
- /** Event to be awaited before NuxtPage instance is returned (defaults to `'hydration'`) */
86
- waitUntil?: GotoOptions['waitUntil']
87
- /** CSS selector for the clickable element that triggers the API request (required) */
88
- triggerElement: string
89
- /** Substring matched against the response URL to identify the expected API call (required) */
90
- targetUrl: string
91
- /** CSS selector for the element displaying the API response (required) */
92
- responseElement: string
93
- }
94
-
95
- /**
96
- * Execute an API call by clicking a trigger element, wait for a successful
97
- * response matching the target URL, then extract the inner HTML from the
98
- * response element.
99
- *
100
- * @param page - Playwright page instance, or a page name string (will call `gotoPage` internally)
101
- * @param options - Extra settings (see `GetAPIResultHtmlOptions`)
102
- * @returns The inner HTML of the response element
103
- */
104
- export async function getAPIResultHtml(page: NuxtPage | string, options: GetAPIResultHtmlOptions) {
105
- const { waitUntil, triggerElement, targetUrl, responseElement } = options
106
-
107
- // verify params
108
- if (typeof page === 'string') {
109
- checkStringParam('getAPIResultHtml:page', page)
110
- }
111
- if (waitUntil) {
112
- checkStringParam('getAPIResultHtml:options.waitUntil', waitUntil)
113
- }
114
- checkStringParam('getAPIResultHtml:triggerElement', triggerElement)
115
- checkStringParam('getAPIResultHtml:targetUrl', targetUrl)
116
- checkStringParam('getAPIResultHtml:responseElement', responseElement)
117
-
118
- // get NuxtPage instance
119
- const pageInstance = typeof page === 'string' ? await gotoPage(page, { waitUntil }) : page
120
- checkPageParam('getAPIResultHtml:pageInstance', pageInstance)
121
-
122
- // trigger API call
123
- await pageInstance.click(triggerElement)
124
- await pageInstance.waitForResponse(response =>
125
- response.url().includes(targetUrl) && response.ok(),
126
- )
127
-
128
- // extract target HTML
129
- const dataElement = pageInstance.locator(responseElement)
130
- return await dataElement.innerHTML()
131
- }
1
+ import { createPage, url } from '@nuxt/test-utils/e2e'
2
+ import type { GotoOptions, NuxtPage } from '@nuxt/test-utils'
3
+ import { checkPageParam, checkStringParam } from './helpers/check-params'
4
+
5
+ /**
6
+ * Extra settings object for `gotoPage()` function.
7
+ * All properties are optional.
8
+ */
9
+ export type GotoPageOptions = {
10
+ /** Event to be awaited before NuxtPage instance is returned (defaults to `'hydration'`) */
11
+ waitUntil?: GotoOptions['waitUntil']
12
+ }
13
+
14
+ /**
15
+ * Visit a specified URL and return the page instance for further interaction.
16
+ *
17
+ * @param pageName - Path segment appended to the base URL (e.g. `'about'` → `/<about>`)
18
+ * @param options - Optional extra settings (see `GotoPageOptions`)
19
+ * @returns Playwright page instance after navigation and `hydration` event
20
+ */
21
+ export async function gotoPage(pageName: string, options?: GotoPageOptions): Promise<NuxtPage> {
22
+ const { waitUntil } = options ?? {}
23
+
24
+ // verify params
25
+ checkStringParam('gotoPage:pageName', pageName)
26
+ if (waitUntil) {
27
+ checkStringParam('gotoPage:options.waitUntil', waitUntil)
28
+ }
29
+
30
+ // construct NuxtPage instance
31
+ const page = await createPage()
32
+ const urlPath = pageName.startsWith('/') ? url(pageName) : url(`/${pageName}`)
33
+ await page.goto(urlPath, { waitUntil: waitUntil ?? 'hydration' })
34
+
35
+ return page
36
+ }
37
+
38
+ /**
39
+ * Extra settings object for `getDataHtml()` function.
40
+ * All properties are optional.
41
+ */
42
+ export type GetDataHtmlOptions = {
43
+ /** Event to be awaited before NuxtPage instance is returned (defaults to `'hydration'`) */
44
+ waitUntil?: GotoOptions['waitUntil']
45
+ /** CSS selector identifying the target element (defaults to `<body>` tag) */
46
+ element?: string
47
+ }
48
+
49
+ /**
50
+ * Extract inner HTML content from a specified element on a given page.
51
+ * If no element is specified via `options.element`, the entire `<body>` content is returned.
52
+ *
53
+ * @param page - Playwright page instance, or a page name string (will call `gotoPage` internally)
54
+ * @param options - Optional extra settings (see `GetDataHtmlOptions`)
55
+ * @returns The inner HTML of the matched element
56
+ */
57
+ export async function getDataHtml(page: NuxtPage | string, options?: GetDataHtmlOptions): Promise<string> {
58
+ const { waitUntil, element } = options ?? {}
59
+
60
+ // verify params
61
+ if (typeof page === 'string') {
62
+ checkStringParam('getDataHtml:page', page)
63
+ }
64
+ if (waitUntil) {
65
+ checkStringParam('getDataHtml:options.waitUntil', waitUntil)
66
+ }
67
+ if (element) {
68
+ checkStringParam('getDataHtml:options.element', element)
69
+ }
70
+
71
+ // get NuxtPage instance
72
+ const pageInstance = typeof page === 'string' ? await gotoPage(page, { waitUntil }) : page
73
+ checkPageParam('getDataHtml:pageInstance', pageInstance)
74
+
75
+ // extract target HTML
76
+ const dataElement = pageInstance.locator(element ?? 'body')
77
+ return await dataElement.innerHTML()
78
+ }
79
+
80
+ /**
81
+ * Extra settings object for `getAPIResultHtml()` function.
82
+ * Due to nature of the function, `triggerElement`, `targetUrl`, and `responseElement` are required.
83
+ */
84
+ export type GetAPIResultHtmlOptions = {
85
+ /** Event to be awaited before NuxtPage instance is returned (defaults to `'hydration'`) */
86
+ waitUntil?: GotoOptions['waitUntil']
87
+ /** CSS selector for the clickable element that triggers the API request (required) */
88
+ triggerElement: string
89
+ /** Substring matched against the response URL to identify the expected API call (required) */
90
+ targetUrl: string
91
+ /** CSS selector for the element displaying the API response (required) */
92
+ responseElement: string
93
+ }
94
+
95
+ /**
96
+ * Execute an API call by clicking a trigger element, wait for a successful
97
+ * response matching the target URL, then extract the inner HTML from the
98
+ * response element.
99
+ *
100
+ * @param page - Playwright page instance, or a page name string (will call `gotoPage` internally)
101
+ * @param options - Extra settings (see `GetAPIResultHtmlOptions`)
102
+ * @returns The inner HTML of the response element
103
+ */
104
+ export async function getAPIResultHtml(page: NuxtPage | string, options: GetAPIResultHtmlOptions) {
105
+ const { waitUntil, triggerElement, targetUrl, responseElement } = options
106
+
107
+ // verify params
108
+ if (typeof page === 'string') {
109
+ checkStringParam('getAPIResultHtml:page', page)
110
+ }
111
+ if (waitUntil) {
112
+ checkStringParam('getAPIResultHtml:options.waitUntil', waitUntil)
113
+ }
114
+ checkStringParam('getAPIResultHtml:triggerElement', triggerElement)
115
+ checkStringParam('getAPIResultHtml:targetUrl', targetUrl)
116
+ checkStringParam('getAPIResultHtml:responseElement', responseElement)
117
+
118
+ // get NuxtPage instance
119
+ const pageInstance = typeof page === 'string' ? await gotoPage(page, { waitUntil }) : page
120
+ checkPageParam('getAPIResultHtml:pageInstance', pageInstance)
121
+
122
+ // trigger API call
123
+ await pageInstance.click(triggerElement)
124
+ await pageInstance.waitForResponse(response =>
125
+ response.url().includes(targetUrl) && response.ok(),
126
+ )
127
+
128
+ // extract target HTML
129
+ const dataElement = pageInstance.locator(responseElement)
130
+ return await dataElement.innerHTML()
131
+ }
@@ -1,44 +1,44 @@
1
- import type { NuxtPage } from '@nuxt/test-utils'
2
- import { locationHint } from './location-hint'
3
-
4
- // given string param must be an actual non-empty string
5
- export function checkStringParam(paramName: string, paramValue?: string) {
6
- if (!paramValue) {
7
- console.warn(`[Nuxt Spec] Passed value '${paramName}' is missing or empty.\n${locationHint()}`)
8
- return
9
- }
10
- if (typeof paramValue !== 'string') {
11
- console.warn(`[Nuxt Spec] Passed value '${paramName}' is not a string.\n${locationHint()}`)
12
- }
13
- }
14
-
15
- // given string param must be an actual number
16
- export function checkNumberParam(paramName: string, paramValue?: number) {
17
- if (paramValue === undefined || paramValue === null) {
18
- console.warn(`[Nuxt Spec] Passed value '${paramName}' is missing or empty.\n${locationHint()}`)
19
- return
20
- }
21
- if (typeof paramValue !== 'number') {
22
- console.warn(`[Nuxt Spec] Passed value '${paramName}' is not a number.\n${locationHint()}`)
23
- }
24
- }
25
-
26
- // given NuxtPage param must be an actual non-nullish NuxtPage instance
27
- export function checkPageParam(paramName: string, paramValue?: NuxtPage) {
28
- if (!paramValue) {
29
- console.warn(`[Nuxt Spec] Passed value '${paramName}' is missing or empty.\n${locationHint()}`)
30
- return
31
- }
32
- if (typeof paramValue !== 'object') {
33
- console.warn(`[Nuxt Spec] Passed value '${paramName}' is not a NuxtPage.\n${locationHint()}`)
34
- } else {
35
- const pageInstance = paramValue as unknown as Record<string, unknown>
36
- if (
37
- typeof pageInstance.goto !== 'function'
38
- || typeof pageInstance.locator !== 'function'
39
- || typeof pageInstance.waitForResponse !== 'function'
40
- ) {
41
- console.warn(`[Nuxt Spec] Passed value '${paramName}' is not a NuxtPage.\n${locationHint()}`)
42
- }
43
- }
44
- }
1
+ import type { NuxtPage } from '@nuxt/test-utils'
2
+ import { locationHint } from './location-hint'
3
+
4
+ // given string param must be an actual non-empty string
5
+ export function checkStringParam(paramName: string, paramValue?: string) {
6
+ if (!paramValue) {
7
+ console.warn(`[Nuxt Spec] Passed value '${paramName}' is missing or empty.\n${locationHint()}`)
8
+ return
9
+ }
10
+ if (typeof paramValue !== 'string') {
11
+ console.warn(`[Nuxt Spec] Passed value '${paramName}' is not a string.\n${locationHint()}`)
12
+ }
13
+ }
14
+
15
+ // given string param must be an actual number
16
+ export function checkNumberParam(paramName: string, paramValue?: number) {
17
+ if (paramValue === undefined || paramValue === null) {
18
+ console.warn(`[Nuxt Spec] Passed value '${paramName}' is missing or empty.\n${locationHint()}`)
19
+ return
20
+ }
21
+ if (typeof paramValue !== 'number') {
22
+ console.warn(`[Nuxt Spec] Passed value '${paramName}' is not a number.\n${locationHint()}`)
23
+ }
24
+ }
25
+
26
+ // given NuxtPage param must be an actual non-nullish NuxtPage instance
27
+ export function checkPageParam(paramName: string, paramValue?: NuxtPage) {
28
+ if (!paramValue) {
29
+ console.warn(`[Nuxt Spec] Passed value '${paramName}' is missing or empty.\n${locationHint()}`)
30
+ return
31
+ }
32
+ if (typeof paramValue !== 'object') {
33
+ console.warn(`[Nuxt Spec] Passed value '${paramName}' is not a NuxtPage.\n${locationHint()}`)
34
+ } else {
35
+ const pageInstance = paramValue as unknown as Record<string, unknown>
36
+ if (
37
+ typeof pageInstance.goto !== 'function'
38
+ || typeof pageInstance.locator !== 'function'
39
+ || typeof pageInstance.waitForResponse !== 'function'
40
+ ) {
41
+ console.warn(`[Nuxt Spec] Passed value '${paramName}' is not a NuxtPage.\n${locationHint()}`)
42
+ }
43
+ }
44
+ }
@@ -1,30 +1,30 @@
1
- import { createRequire } from 'node:module'
2
- import { dirname } from 'node:path'
3
-
4
- // shows "(at path-to-file:line:column)" hint to locate cause from stack trace
5
- // this syntax allow tools like VS Code to create clickable link directly to the source
6
- export function locationHint(): string {
7
- return ` (at ${getCallSite()})`
8
- }
9
-
10
- // path to nuxt-spec/utils directory computed on runtime
11
- const pkgUtilsDir = normalizePath(dirname(createRequire(import.meta.url).resolve('nuxt-spec/utils')))
12
-
13
- // handle possible Win backslashes
14
- function normalizePath(path: string): string {
15
- return path.replace(/^file:\/\//, '').replace(/\\/g, '/')
16
- }
17
-
18
- // locate first stack frame outside of nuxt-spec utils
19
- // which will the place where the utility function is being called from
20
- function getCallSite(): string | undefined {
21
- const stack = new Error().stack?.split('\n').slice(1) ?? []
22
- for (const raw of stack) {
23
- const match = raw.match(/\(?((?:file:\/\/)?[^()\s]+:\d+:\d+)\)?\s*$/)
24
- if (!match?.[1]) continue
25
- const location = normalizePath(match[1])
26
- if (location.includes(pkgUtilsDir)) continue
27
- return location
28
- }
29
- return undefined
30
- }
1
+ import { createRequire } from 'node:module'
2
+ import { dirname } from 'node:path'
3
+
4
+ // shows "(at path-to-file:line:column)" hint to locate cause from stack trace
5
+ // this syntax allow tools like VS Code to create clickable link directly to the source
6
+ export function locationHint(): string {
7
+ return ` (at ${getCallSite()})`
8
+ }
9
+
10
+ // path to nuxt-spec/utils directory computed on runtime
11
+ const pkgUtilsDir = normalizePath(dirname(createRequire(import.meta.url).resolve('nuxt-spec/utils')))
12
+
13
+ // handle possible Win backslashes
14
+ function normalizePath(path: string): string {
15
+ return path.replace(/^file:\/\//, '').replace(/\\/g, '/')
16
+ }
17
+
18
+ // locate first stack frame outside of nuxt-spec utils
19
+ // which will the place where the utility function is being called from
20
+ function getCallSite(): string | undefined {
21
+ const stack = new Error().stack?.split('\n').slice(1) ?? []
22
+ for (const raw of stack) {
23
+ const match = raw.match(/\(?((?:file:\/\/)?[^()\s]+:\d+:\d+)\)?\s*$/)
24
+ if (!match?.[1]) continue
25
+ const location = normalizePath(match[1])
26
+ if (location.includes(pkgUtilsDir)) continue
27
+ return location
28
+ }
29
+ return undefined
30
+ }