diff --git a/packages/nuxt/src/core/builder.ts b/packages/nuxt/src/core/builder.ts index 55bdd9344b..e1c24ee5a7 100644 --- a/packages/nuxt/src/core/builder.ts +++ b/packages/nuxt/src/core/builder.ts @@ -63,8 +63,11 @@ export async function build (nuxt: Nuxt) { return } - if (nuxt.options.dev) { - checkForExternalConfigurationFiles() + if (nuxt.options.dev && !nuxt.options.test) { + nuxt.hooks.hookOnce('build:done', () => { + checkForExternalConfigurationFiles() + .catch(e => logger.warn('Problem checking for external configuration files.', e)) + }) } await bundle(nuxt) diff --git a/packages/nuxt/src/core/nuxt.ts b/packages/nuxt/src/core/nuxt.ts index c98561830b..fd4a9829d5 100644 --- a/packages/nuxt/src/core/nuxt.ts +++ b/packages/nuxt/src/core/nuxt.ts @@ -79,7 +79,7 @@ const nightlies = { '@nuxt/kit': '@nuxt/kit-nightly', } -const keyDependencies = [ +export const keyDependencies = [ '@nuxt/kit', '@nuxt/schema', ] @@ -801,8 +801,13 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise { const nuxt = createNuxt(options) - for (const dep of keyDependencies) { - checkDependencyVersion(dep, nuxt._version) + if (nuxt.options.dev && !nuxt.options.test) { + nuxt.hooks.hookOnce('build:done', () => { + for (const dep of keyDependencies) { + checkDependencyVersion(dep, nuxt._version) + .catch(e => logger.warn(`Problem checking \`${dep}\` version.`, e)) + } + }) } // We register hooks layer-by-layer so any overrides need to be registered separately @@ -821,7 +826,7 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise { return nuxt } -async function checkDependencyVersion (name: string, nuxtVersion: string): Promise { +export async function checkDependencyVersion (name: string, nuxtVersion: string): Promise { const path = await resolvePath(name, { fallbackToOriginal: true }).catch(() => null) if (!path || path === name) { return } diff --git a/packages/nuxt/test/check-dependencies.test.ts b/packages/nuxt/test/check-dependencies.test.ts new file mode 100644 index 0000000000..eca39ed639 --- /dev/null +++ b/packages/nuxt/test/check-dependencies.test.ts @@ -0,0 +1,62 @@ +import { afterEach, describe, expect, it, vi } from 'vitest' +import { readPackageJSON } from 'pkg-types' +import { inc } from 'semver' +import { version } from '../package.json' +import { checkDependencyVersion, keyDependencies } from '../src/core/nuxt' + +vi.stubGlobal('console', { + ...console, + error: vi.fn(console.error), + warn: vi.fn(console.warn), +}) + +vi.mock('pkg-types', async (og) => { + const originalPkgTypes = (await og()) + return { + ...originalPkgTypes, + readPackageJSON: vi.fn(originalPkgTypes.readPackageJSON), + } +}) + +afterEach(() => { + vi.clearAllMocks() +}) + +describe('dependency mismatch', () => { + it.sequential('expect mismatched dependency to log a warning', async () => { + vi.mocked(readPackageJSON).mockReturnValue(Promise.resolve({ + version: '3.0.0', + })) + + for (const dep of keyDependencies) { + await checkDependencyVersion(dep, version) + } + + // @nuxt/kit is explicitly installed in repo root but @nuxt/schema isn't, so we only + // get warnings about @nuxt/schema + expect(console.warn).toHaveBeenCalledWith(`[nuxt] Expected \`@nuxt/kit\` to be at least \`${version}\` but got \`3.0.0\`. This might lead to unexpected behavior. Check your package.json or refresh your lockfile.`) + + vi.mocked(readPackageJSON).mockRestore() + }) + it.sequential.each([ + { + name: 'nuxt version is lower', + depVersion: inc(version, 'minor'), + }, + { + name: 'version matches', + depVersion: version, + }, + ])('expect no warning when $name.', async ({ depVersion }) => { + vi.mocked(readPackageJSON).mockReturnValue(Promise.resolve({ + depVersion, + })) + + for (const dep of keyDependencies) { + await checkDependencyVersion(dep, version) + } + + expect(console.warn).not.toHaveBeenCalled() + vi.mocked(readPackageJSON).mockRestore() + }) +}) diff --git a/packages/nuxt/test/load-nuxt.test.ts b/packages/nuxt/test/load-nuxt.test.ts index dffcdf7130..96fd8723cf 100644 --- a/packages/nuxt/test/load-nuxt.test.ts +++ b/packages/nuxt/test/load-nuxt.test.ts @@ -2,10 +2,7 @@ import { fileURLToPath } from 'node:url' import { afterEach, describe, expect, it, vi } from 'vitest' import { normalize } from 'pathe' import { withoutTrailingSlash } from 'ufo' -import { readPackageJSON } from 'pkg-types' -import { inc } from 'semver' import { loadNuxt } from '../src' -import { version } from '../package.json' const repoRoot = withoutTrailingSlash(normalize(fileURLToPath(new URL('../../../', import.meta.url)))) @@ -45,45 +42,3 @@ describe('loadNuxt', () => { expect(hookRan).toBe(true) }) }) - -describe('dependency mismatch', () => { - it('expect mismatched dependency to log a warning', async () => { - vi.mocked(readPackageJSON).mockReturnValue(Promise.resolve({ - version: '3.0.0', - })) - - const nuxt = await loadNuxt({ - cwd: repoRoot, - }) - - // @nuxt/kit is explicitly installed in repo root but @nuxt/schema isn't, so we only - // get warnings about @nuxt/schema - expect(console.warn).toHaveBeenCalledWith(`[nuxt] Expected \`@nuxt/kit\` to be at least \`${version}\` but got \`3.0.0\`. This might lead to unexpected behavior. Check your package.json or refresh your lockfile.`) - - vi.mocked(readPackageJSON).mockRestore() - await nuxt.close() - }) - it.each([ - { - name: 'nuxt version is lower', - depVersion: inc(version, 'minor'), - }, - { - name: 'version matches', - depVersion: version, - }, - ])('expect no warning when $name.', async ({ depVersion }) => { - vi.mocked(readPackageJSON).mockReturnValue(Promise.resolve({ - depVersion, - })) - - const nuxt = await loadNuxt({ - cwd: repoRoot, - }) - - expect(console.warn).not.toHaveBeenCalled() - - await nuxt.close() - vi.mocked(readPackageJSON).mockRestore() - }) -})