Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/guide/cli-generated.md
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,13 @@ Allow JavaScript files to be typechecked. By default takes the value from tsconf

Ignore type errors from source files

### typecheck.build

- **CLI:** `--typecheck.build`
- **Config:** [typecheck.build](/config/typecheck#typecheck-build)

Use TypeScript build mode

### typecheck.tsconfig

- **CLI:** `--typecheck.tsconfig <path>`
Expand Down
5 changes: 4 additions & 1 deletion packages/browser/src/node/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,10 @@ export default (parentServer: ParentBrowserProject, base = '/'): Plugin[] => {
BrowserContext(parentServer),
dynamicImportPlugin({
globalThisAccessor: '"__vitest_browser_runner__"',
filter(id) {
filter(id, environment) {
if (environment.name !== 'client') {
return false
}
if (id.includes(distRoot)) {
return false
}
Expand Down
6 changes: 3 additions & 3 deletions packages/mocker/src/node/dynamicImportPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { SourceMap } from 'magic-string'
import type { Plugin, Rollup } from 'vite'
import type { Environment, Plugin, Rollup } from 'vite'
import type { Expression, Positioned } from './esmWalker'
import MagicString from 'magic-string'
import { esmWalker } from './esmWalker'
Expand All @@ -11,7 +11,7 @@ export interface DynamicImportPluginOptions {
* @default `"__vitest_mocker__"`
*/
globalThisAccessor?: string
filter?: (id: string) => boolean
filter?: (id: string, environment: Environment) => boolean
}

export function dynamicImportPlugin(options: DynamicImportPluginOptions = {}): Plugin {
Expand All @@ -23,7 +23,7 @@ export function dynamicImportPlugin(options: DynamicImportPluginOptions = {}): P
if (!regexDynamicImport.test(source)) {
return
}
if (options.filter && !options.filter(id)) {
if (options.filter && !options.filter(id, this.environment)) {
return
}
return injectDynamicImport(source, id, this.parse, options)
Expand Down
21 changes: 8 additions & 13 deletions packages/ui/client/components/FileDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type { RunnerTask, RunnerTestCase } from 'vitest'
import type { ModuleGraph } from '~/composables/module-graph'
import type { Params } from '~/composables/params'
import { debouncedWatch } from '@vueuse/core'
import { toJSON } from 'flatted'
import { computed, nextTick, ref } from 'vue'
import DetailsHeaderButtons from '~/components/DetailsHeaderButtons.vue'
import {
Expand Down Expand Up @@ -118,19 +117,15 @@ async function loadModuleGraph(force = false) {
)
// remove node_modules from the graph when enabled
if (hideNodeModules.value) {
// when using static html reporter, we've the meta as global, we need to clone it
if (isReport) {
moduleGraph
= typeof window.structuredClone !== 'undefined'
? window.structuredClone(moduleGraph)
: toJSON(moduleGraph)
moduleGraph = {
...moduleGraph,
inlined: moduleGraph.inlined.filter(
n => !nodeModuleRegex.test(n),
),
externalized: moduleGraph.externalized.filter(
n => !nodeModuleRegex.test(n),
),
}
moduleGraph.inlined = moduleGraph.inlined.filter(
n => !nodeModuleRegex.test(n),
)
moduleGraph.externalized = moduleGraph.externalized.filter(
n => !nodeModuleRegex.test(n),
)
}
graph.value = getModuleGraph(
moduleGraph,
Expand Down
3 changes: 3 additions & 0 deletions packages/vitest/src/node/cli/cli-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,9 @@ export const cliOptionsConfig: VitestCLIOptions = {
ignoreSourceErrors: {
description: 'Ignore type errors from source files',
},
build: {
description: 'Use TypeScript build mode',
},
tsconfig: {
description: 'Path to a custom tsconfig file',
argument: '<path>',
Expand Down
2 changes: 1 addition & 1 deletion packages/vitest/src/node/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ export class Vitest {
const specifications: TestSpecification[] = []
for (const file of files) {
const project = this.getProjectByName(file.projectName || '')
const specification = project.createSpecification(file.filepath, undefined, file.pool, file.meta)
const specification = project.createSpecification(file.filepath, undefined, file.pool, file.id)
specifications.push(specification)
}

Expand Down
5 changes: 2 additions & 3 deletions packages/vitest/src/node/project.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { TaskMeta } from '@vitest/runner/types'
import type { GlobOptions } from 'tinyglobby'
import type { DevEnvironment, ViteDevServer, InlineConfig as ViteInlineConfig } from 'vite'
import type { ModuleRunner } from 'vite/module-runner'
Expand Down Expand Up @@ -154,14 +153,14 @@ export class TestProject {
/** @internal */
pool?: string,
/** @internal */
metaOverride?: TaskMeta,
taskIdOverride?: string,
): TestSpecification {
return new TestSpecification(
this,
moduleId,
pool || getFilePoolName(this),
locationsOrOptions,
metaOverride,
taskIdOverride,
)
}

Expand Down
9 changes: 4 additions & 5 deletions packages/vitest/src/node/test-specification.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { TaskMeta } from '@vitest/runner/types'
import type { SerializedTestSpecification } from '../runtime/types/utils'
import type { TestProject } from './project'
import type { TestModule } from './reporters/reported-tasks'
Expand Down Expand Up @@ -56,14 +55,14 @@ export class TestSpecification {
moduleId: string,
pool: Pool,
testLinesOrOptions?: number[] | TestSpecificationOptions | undefined,
// merge-reports uses the original `file.meta` from the test run
metaOverride?: TaskMeta,
// merge-reports forces the original task id from the test run
taskIdOverride?: string,
) {
const projectName = project.config.name
this.taskId = generateFileHash(
this.taskId = taskIdOverride ?? generateFileHash(
relative(project.config.root, moduleId),
projectName,
metaOverride ?? { typecheck: pool === 'typescript', __vitest_label__: project.config.mergeReportsLabel },
{ typecheck: pool === 'typescript', __vitest_label__: project.config.mergeReportsLabel },
)
this.project = project
this.moduleId = moduleId
Expand Down
4 changes: 4 additions & 0 deletions packages/vitest/src/node/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,10 @@ export interface TypecheckConfig {
* Do not fail, if Vitest found errors outside the test files.
*/
ignoreSourceErrors?: boolean
/**
* Use TypeScript build mode.
*/
build?: boolean
/**
* Path to tsconfig, relative to the project root.
*/
Expand Down
29 changes: 21 additions & 8 deletions packages/vitest/src/typecheck/typechecker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,16 +294,25 @@ export class Typechecker {
const { root, watch, typecheck } = this.project.config

const args = [
'--noEmit',
'--pretty',
'false',
'--incremental',
'--tsBuildInfoFile',
join(
process.versions.pnp ? join(os.tmpdir(), this.project.hash) : distDir,
'tsconfig.tmp.tsbuildinfo',
),
]

if (typecheck.build) {
args.unshift('--build')
}
else {
args.push(
'--noEmit',
'--incremental',
'--tsBuildInfoFile',
join(
process.versions.pnp ? join(os.tmpdir(), this.project.hash) : distDir,
'tsconfig.tmp.tsbuildinfo',
),
)
}

// use builtin watcher because it's faster
if (watch) {
args.push('--watch')
Expand All @@ -312,7 +321,11 @@ export class Typechecker {
args.push('--allowJs', '--checkJs')
}
if (typecheck.tsconfig) {
args.push('-p', resolve(root, typecheck.tsconfig))
if (!typecheck.build) {
args.push('-p')
}

args.push(resolve(root, typecheck.tsconfig))
}
this._output = ''
this._startTime = performance.now()
Expand Down
7 changes: 7 additions & 0 deletions test/browser/test/server/entry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default async (url: URL) => {
if (url.pathname === '/api/ssr-dep') {
const lib = await import('./ssr-dep')
return lib.default
}
return 'not-found'
}
1 change: 1 addition & 0 deletions test/browser/test/server/ssr-dep.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 'ssr-dep'
7 changes: 7 additions & 0 deletions test/browser/test/ssr.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { expect, test } from 'vitest'

test('ssr dynamic import', async () => {
const res = await fetch('/api/ssr-dep')
const text = await res.json()
expect(text).toBe('ssr-dep')
})
21 changes: 21 additions & 0 deletions test/browser/vitest.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,26 @@ export default defineConfig({
await server.ssrLoadModule('/package.json')
},
},
{
name: 'my-ssr',
configureServer(server) {
server.middlewares.use(async (req, res, next) => {
const url = new URL(req.url || '', 'http://localhost')
if (url.pathname.startsWith('/api/')) {
try {
const mod = await server.ssrLoadModule('./test/server/entry.ts')
const result = await mod.default(url)
res.end(JSON.stringify(result))
return
}
catch (e) {
next(e)
return
}
}
next()
})
},
},
],
})
1 change: 1 addition & 0 deletions test/e2e/project-references/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!/packages/project-b/node_modules
14 changes: 14 additions & 0 deletions test/e2e/project-references/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "@vitest/test-integration-project-references",
"type": "module",
"private": true,
"scripts": {
"test": "(rm -rf packages/*/dist || true) && vitest run"
},
"devDependencies": {
"vitest": "workspace:*"
},
"workspaces": [
"packages/*"
]
}
6 changes: 6 additions & 0 deletions test/e2e/project-references/packages/project-a/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "project-a",
"type": "module",
"private": true,
"exports": "./src/index.ts"
}
2 changes: 2 additions & 0 deletions test/e2e/project-references/packages/project-a/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type A = number
export const a: A = 1
17 changes: 17 additions & 0 deletions test/e2e/project-references/packages/project-a/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"composite": true,
"target": "esnext",
"lib": ["DOM", "ESNext"],
"module": "nodenext",
"types": [],
"strict": true,
"declaration": true,
"declarationMap": true,
"outDir": "dist",
"sourceMap": true,
"verbatimModuleSyntax": true,
"skipLibCheck": false
},
"files": ["src/index.ts"]
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions test/e2e/project-references/packages/project-b/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "project-b",
"type": "module",
"private": true,
"dependencies": {
"project-a": "workspace:*"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { A } from 'project-a'
import { a } from 'project-a'
import { describe, expectTypeOf, it } from 'vitest'

describe('Import types from project references', () => {
it('should import value and type from project references', () => {
expectTypeOf(a).toEqualTypeOf<A>()
})
})
21 changes: 21 additions & 0 deletions test/e2e/project-references/packages/project-b/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"compilerOptions": {
"composite": true,
"target": "esnext",
"lib": ["DOM", "ESNext"],
"module": "nodenext",
"types": [],
"strict": true,
"declaration": true,
"declarationMap": true,
"outDir": "dist",
"sourceMap": true,
"verbatimModuleSyntax": true,
"skipLibCheck": false
},
"references": [
{ "path": "../project-a" }
],
"files": ["src/b.test-d.ts"],
"exclude": ["node_modules"]
}
7 changes: 7 additions & 0 deletions test/e2e/project-references/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"references": [
{ "path": "./packages/project-a" },
{ "path": "./packages/project-b" }
],
"include": []
}
16 changes: 16 additions & 0 deletions test/e2e/project-references/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { defineConfig } from 'vitest/config'

export default defineConfig({
test: {
projects: [{
test: {
name: 'project-b',
dir: 'packages/project-b',
typecheck: {
enabled: true,
build: true,
},
},
}],
},
})
Loading
Loading