diff --git a/packages/coverage-istanbul/src/provider.ts b/packages/coverage-istanbul/src/provider.ts index 3bc5c78f5b32..08af60ee9f9e 100644 --- a/packages/coverage-istanbul/src/provider.ts +++ b/packages/coverage-istanbul/src/provider.ts @@ -79,6 +79,8 @@ export class IstanbulCoverageProvider implements CoverageProvider { return const sourceMap = pluginCtx.getCombinedSourcemap() + sourceMap.sources = sourceMap.sources.map(removeQueryParameters) + const code = this.instrumenter.instrumentSync(sourceCode, id, sourceMap as any) const map = this.instrumenter.lastSourceMap() as any @@ -227,3 +229,12 @@ function resolveIstanbulOptions(options: CoverageIstanbulOptions, root: string) return resolved as ResolvedCoverageOptions & { provider: 'istanbul' } } + +/** + * Remove possible query parameters from filenames + * - From `/src/components/Header.component.ts?vue&type=script&src=true&lang.ts` + * - To `/src/components/Header.component.ts` + */ +function removeQueryParameters(filename: string) { + return filename.split('?')[0] +} diff --git a/packages/vite-node/src/client.ts b/packages/vite-node/src/client.ts index 8563230b0e86..b9456f7da684 100644 --- a/packages/vite-node/src/client.ts +++ b/packages/vite-node/src/client.ts @@ -247,24 +247,21 @@ export class ViteNodeRunner { return Reflect.get(exports, p, receiver) }, set(_, p, value) { - // Node also allows access of named exports via exports.default - // https://nodejs.org/api/esm.html#commonjs-namespaces - if (p !== 'default') { - if (!Reflect.has(exports, 'default')) - exports.default = {} - - // returns undefined, when accessing named exports, if default is not an object - // but is still present inside hasOwnKeys, this is Node behaviour for CJS - if (exports.default === null || typeof exports.default !== 'object') { - defineExport(exports, p, () => undefined) - return true - } - - exports.default[p] = value - defineExport(exports, p, () => value) + if (!Reflect.has(exports, 'default')) + exports.default = {} + + // returns undefined, when accessing named exports, if default is not an object + // but is still present inside hasOwnKeys, this is Node behaviour for CJS + if (exports.default === null || typeof exports.default !== 'object') { + defineExport(exports, p, () => undefined) return true } - return Reflect.set(exports, p, value) + + exports.default[p] = value + if (p !== 'default') + defineExport(exports, p, () => value) + + return true }, }) @@ -274,7 +271,7 @@ export class ViteNodeRunner { const moduleProxy = { set exports(value) { exportAll(cjsExports, value) - cjsExports.default = value + exports.default = value }, get exports() { return cjsExports diff --git a/packages/vite-node/src/utils.ts b/packages/vite-node/src/utils.ts index d0b33edeb4cf..138778195921 100644 --- a/packages/vite-node/src/utils.ts +++ b/packages/vite-node/src/utils.ts @@ -1,4 +1,5 @@ import { fileURLToPath, pathToFileURL } from 'url' +import { existsSync } from 'fs' import { relative, resolve } from 'pathe' import type { TransformResult } from 'vite' import { isNodeBuiltin } from 'mlly' @@ -75,13 +76,18 @@ export function pathFromRoot(root: string, filename: string) { } export function toFilePath(id: string, root: string): string { - let absolute = id.startsWith('/@fs/') - ? id.slice(4) - : id.startsWith(root) - ? id - : id.startsWith('/') - ? resolve(root, id.slice(1)) - : id + let absolute = (() => { + if (id.startsWith('/@fs/')) + return id.slice(4) + if (!id.startsWith(root) && id.startsWith('/')) { + const resolved = resolve(root, id.slice(1)) + // The resolved path can have query values. Remove them before checking + // the file path. + if (existsSync(resolved.replace(/\?.*$/, ''))) + return resolved + } + return id + })() if (absolute.startsWith('//')) absolute = absolute.slice(1) diff --git a/packages/vitest/src/node/cli-wrapper.ts b/packages/vitest/src/node/cli-wrapper.ts index f218f51689cd..904445c4c700 100644 --- a/packages/vitest/src/node/cli-wrapper.ts +++ b/packages/vitest/src/node/cli-wrapper.ts @@ -61,6 +61,13 @@ async function main() { } } + // if not specified, don't run through spawn, + // because it prints stderr messages in the wrong order compared to stdout + if (retries <= 0) { + await import('./cli') + return + } + const nodeArgs: string[] = [] const vitestArgs: string[] = [] diff --git a/packages/vitest/src/node/cli.ts b/packages/vitest/src/node/cli.ts index 2650ca6481c5..2b09917730df 100644 --- a/packages/vitest/src/node/cli.ts +++ b/packages/vitest/src/node/cli.ts @@ -1,3 +1,4 @@ +import { normalize } from 'pathe' import cac from 'cac' import c from 'picocolors' import { version } from '../../package.json' @@ -92,9 +93,16 @@ async function benchmark(cliFilters: string[], options: CliOptions): Promise { try { - if (await startVitest(mode, cliFilters, options) === false) + if (await startVitest(mode, cliFilters.map(normalize), normalizeOptions(options)) === false) process.exit() } catch (e) { diff --git a/packages/vitest/src/node/logger.ts b/packages/vitest/src/node/logger.ts index a651f1256ad8..961728751ad1 100644 --- a/packages/vitest/src/node/logger.ts +++ b/packages/vitest/src/node/logger.ts @@ -47,14 +47,12 @@ export class Logger { } private _clearScreen() { - if (!this._clearScreenPending) + if (this._clearScreenPending == null) return const log = this._clearScreenPending this._clearScreenPending = undefined - // equivalent to ansi-escapes: - // stdout.write(ansiEscapes.cursorTo(0, 0) + ansiEscapes.eraseDown + log) - this.console.log(`\u001B[1;1H\u001B[J${log}`) + this.console.log(`\x1Bc${log}`) } printError(err: unknown, fullStack = false, type?: string) { @@ -84,7 +82,7 @@ export class Logger { } printBanner() { - this.log() + this.clearScreen('', true) const versionTest = this.ctx.config.watch ? c.blue(`v${version}`) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e6e0912f9280..3f8e9a3e061b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1030,6 +1030,21 @@ importers: devDependencies: vitest: link:../../packages/vitest + test/path-resolution: + specifiers: + '@edge-runtime/vm': 1.1.0-beta.26 + '@vitest/test-path-resolution-target': workspace:* + '@vitest/web-worker': workspace:* + vitest: workspace:* + devDependencies: + '@edge-runtime/vm': 1.1.0-beta.26 + '@vitest/test-path-resolution-target': link:../path-resolution-target + '@vitest/web-worker': link:../../packages/web-worker + vitest: link:../../packages/vitest + + test/path-resolution-target: + specifiers: {} + test/related: specifiers: execa: ^6.1.0 @@ -1388,14 +1403,9 @@ packages: dependencies: '@babel/highlight': 7.18.6 - /@babel/compat-data/7.18.13: - resolution: {integrity: sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==} - engines: {node: '>=6.9.0'} - /@babel/compat-data/7.20.0: resolution: {integrity: sha512-Gt9jszFJYq7qzXVK4slhc6NzJXnOVmRECWcVjF/T23rNXD9NtWQ0W3qxdg+p9wWIB+VQw3GYV/U2Ha9bRTfs4w==} engines: {node: '>=6.9.0'} - dev: true /@babel/core/7.12.9: resolution: {integrity: sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==} @@ -1470,7 +1480,7 @@ packages: resolution: {integrity: sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.18.13 + '@babel/types': 7.20.0 '@jridgewell/gen-mapping': 0.3.2 jsesc: 2.5.2 @@ -1481,7 +1491,6 @@ packages: '@babel/types': 7.20.0 '@jridgewell/gen-mapping': 0.3.2 jsesc: 2.5.2 - dev: true /@babel/helper-annotate-as-pure/7.18.6: resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} @@ -1504,7 +1513,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/compat-data': 7.18.13 + '@babel/compat-data': 7.20.0 '@babel/core': 7.18.13 '@babel/helper-validator-option': 7.18.6 browserslist: 4.21.3 @@ -1655,20 +1664,12 @@ packages: '@babel/types': 7.20.0 dev: true - /@babel/helper-function-name/7.18.9: - resolution: {integrity: sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.18.10 - '@babel/types': 7.20.0 - /@babel/helper-function-name/7.19.0: resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.18.10 '@babel/types': 7.20.0 - dev: true /@babel/helper-hoist-variables/7.18.6: resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} @@ -1702,12 +1703,12 @@ packages: dependencies: '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-module-imports': 7.18.6 - '@babel/helper-simple-access': 7.18.6 + '@babel/helper-simple-access': 7.19.4 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/helper-validator-identifier': 7.18.6 + '@babel/helper-validator-identifier': 7.19.1 '@babel/template': 7.18.10 - '@babel/traverse': 7.18.13 - '@babel/types': 7.18.13 + '@babel/traverse': 7.20.0 + '@babel/types': 7.20.0 transitivePeerDependencies: - supports-color @@ -1738,11 +1739,6 @@ packages: resolution: {integrity: sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==} dev: true - /@babel/helper-plugin-utils/7.18.9: - resolution: {integrity: sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==} - engines: {node: '>=6.9.0'} - dev: true - /@babel/helper-plugin-utils/7.19.0: resolution: {integrity: sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==} engines: {node: '>=6.9.0'} @@ -1790,18 +1786,11 @@ packages: - supports-color dev: true - /@babel/helper-simple-access/7.18.6: - resolution: {integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.0 - /@babel/helper-simple-access/7.19.4: resolution: {integrity: sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==} engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.20.0 - dev: true /@babel/helper-skip-transparent-expression-wrappers/7.18.9: resolution: {integrity: sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==} @@ -1816,18 +1805,10 @@ packages: dependencies: '@babel/types': 7.20.0 - /@babel/helper-string-parser/7.18.10: - resolution: {integrity: sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==} - engines: {node: '>=6.9.0'} - /@babel/helper-string-parser/7.19.4: resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier/7.18.6: - resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==} - engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier/7.19.1: resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} engines: {node: '>=6.9.0'} @@ -1853,8 +1834,8 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/template': 7.18.10 - '@babel/traverse': 7.18.13 - '@babel/types': 7.18.13 + '@babel/traverse': 7.20.0 + '@babel/types': 7.20.0 transitivePeerDependencies: - supports-color @@ -1882,7 +1863,7 @@ packages: engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.18.13 + '@babel/types': 7.20.0 /@babel/parser/7.20.0: resolution: {integrity: sha512-G9VgAhEaICnz8iiJeGJQyVl6J2nTjbW0xeisva0PK6XcKsga7BIaqm4ZF8Rg1Wbaqmy6znspNqhPaPkyukujzg==} @@ -3351,7 +3332,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.18.13 - '@babel/helper-plugin-utils': 7.18.9 + '@babel/helper-plugin-utils': 7.19.0 dev: true /@babel/plugin-transform-react-jsx-source/7.19.6_@babel+core@7.19.6: @@ -3373,9 +3354,9 @@ packages: '@babel/core': 7.18.13 '@babel/helper-annotate-as-pure': 7.18.6 '@babel/helper-module-imports': 7.18.6 - '@babel/helper-plugin-utils': 7.18.9 + '@babel/helper-plugin-utils': 7.19.0 '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.18.13 - '@babel/types': 7.18.13 + '@babel/types': 7.20.0 dev: true /@babel/plugin-transform-react-jsx/7.19.0_@babel+core@7.18.13: @@ -3957,21 +3938,21 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.18.6 - '@babel/parser': 7.18.13 - '@babel/types': 7.18.13 + '@babel/parser': 7.20.0 + '@babel/types': 7.20.0 /@babel/traverse/7.18.13: resolution: {integrity: sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==} engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.18.6 - '@babel/generator': 7.18.13 + '@babel/generator': 7.20.0 '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.18.9 + '@babel/helper-function-name': 7.19.0 '@babel/helper-hoist-variables': 7.18.6 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.18.13 - '@babel/types': 7.18.13 + '@babel/parser': 7.20.0 + '@babel/types': 7.20.0 debug: 4.3.4 globals: 11.12.0 transitivePeerDependencies: @@ -3993,14 +3974,13 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true /@babel/types/7.18.13: resolution: {integrity: sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-string-parser': 7.18.10 - '@babel/helper-validator-identifier': 7.18.6 + '@babel/helper-string-parser': 7.19.4 + '@babel/helper-validator-identifier': 7.19.1 to-fast-properties: 2.0.0 /@babel/types/7.20.0: @@ -6294,10 +6274,10 @@ packages: /@storybook/mdx1-csf/0.0.4_u2aypivye4tius5ftakppbroiy: resolution: {integrity: sha512-xxUEMy0D+0G1aSYxbeVNbs+XBU5nCqW4I7awpBYSTywXDv/MJWeC6FDRpj5P1pgfq8j8jWDD5ZDvBQ7syFg0LQ==} dependencies: - '@babel/generator': 7.18.13 - '@babel/parser': 7.18.13 + '@babel/generator': 7.20.0 + '@babel/parser': 7.20.0 '@babel/preset-env': 7.18.10_@babel+core@7.18.13 - '@babel/types': 7.18.13 + '@babel/types': 7.20.0 '@mdx-js/mdx': 1.6.22 '@mdx-js/react': 1.6.22_react@17.0.2 '@types/lodash': 4.14.186 @@ -7831,7 +7811,7 @@ packages: /@vue/compiler-sfc/3.2.39: resolution: {integrity: sha512-fqAQgFs1/BxTUZkd0Vakn3teKUt//J3c420BgnYgEOoVdTwYpBTSXCMJ88GOBCylmUBbtquGPli9tVs7LzsWIA==} dependencies: - '@babel/parser': 7.18.13 + '@babel/parser': 7.20.0 '@vue/compiler-core': 3.2.39 '@vue/compiler-dom': 3.2.39 '@vue/compiler-ssr': 3.2.39 @@ -7839,7 +7819,7 @@ packages: '@vue/shared': 3.2.39 estree-walker: 2.0.2 magic-string: 0.25.9 - postcss: 8.4.16 + postcss: 8.4.18 source-map: 0.6.1 /@vue/compiler-sfc/3.2.41: @@ -7853,7 +7833,7 @@ packages: '@vue/shared': 3.2.41 estree-walker: 2.0.2 magic-string: 0.25.9 - postcss: 8.4.16 + postcss: 8.4.18 source-map: 0.6.1 /@vue/compiler-ssr/3.2.39: @@ -16776,14 +16756,6 @@ packages: source-map: 0.6.1 dev: true - /postcss/8.4.16: - resolution: {integrity: sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.4 - picocolors: 1.0.0 - source-map-js: 1.0.2 - /postcss/8.4.18: resolution: {integrity: sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==} engines: {node: ^10 || ^12 || >=14} @@ -17215,7 +17187,7 @@ packages: hasBin: true dependencies: '@babel/core': 7.19.6 - '@babel/generator': 7.18.13 + '@babel/generator': 7.20.0 ast-types: 0.14.2 commander: 2.20.3 doctrine: 3.0.0 @@ -18419,9 +18391,9 @@ packages: peerDependencies: solid-js: ^1.3 dependencies: - '@babel/generator': 7.18.13 + '@babel/generator': 7.20.0 '@babel/helper-module-imports': 7.18.6 - '@babel/types': 7.18.13 + '@babel/types': 7.20.0 solid-js: 1.5.2 dev: true diff --git a/test/cjs/src/other.cjs b/test/cjs/src/other.cjs new file mode 100644 index 000000000000..35e3bd6e77f9 --- /dev/null +++ b/test/cjs/src/other.cjs @@ -0,0 +1,2 @@ +'use strict' +exports.default = 2 diff --git a/test/cjs/src/other.d.cts b/test/cjs/src/other.d.cts new file mode 100644 index 000000000000..6a16fde0c615 --- /dev/null +++ b/test/cjs/src/other.d.cts @@ -0,0 +1,5 @@ +declare const defaultExports: { + default: number +} + +export default defaultExports diff --git a/test/cjs/test/named-default.test.ts b/test/cjs/test/named-default.test.ts new file mode 100644 index 000000000000..5e7cd5d01d60 --- /dev/null +++ b/test/cjs/test/named-default.test.ts @@ -0,0 +1,15 @@ +import { describe, expect, it } from 'vitest' + +import * as other from '../src/other.cjs' +import defaultOther from '../src/other.cjs' + +describe('correctly identified named default', () => { + it('default should be on default', () => { + expect(other.default).toBe(defaultOther) + }) + + it('default is an object with default', () => { + expect(other.default).toMatchObject({ default: 2 }) + expect(defaultOther).toMatchObject({ default: 2 }) + }) +}) diff --git a/test/core/test/file-path.test.ts b/test/core/test/file-path.test.ts index 2a8f0b629e88..4f4271ce2a9e 100644 --- a/test/core/test/file-path.test.ts +++ b/test/core/test/file-path.test.ts @@ -1,6 +1,9 @@ +import { existsSync } from 'fs' import { describe, expect, it, vi } from 'vitest' import { isWindows, slash, toFilePath } from '../../../packages/vite-node/src/utils' +vi.mock('fs') + describe('toFilePath', () => { // the following tests will work incorrectly on unix systems if (isWindows) { @@ -37,8 +40,10 @@ describe('toFilePath', () => { const expected = '/path/to/project/node_modules/pkg/file.js' const processSpy = vi.spyOn(process, 'cwd').mockReturnValue(root) + const existsSpy = vi.mocked(existsSync).mockReturnValue(true) const filePath = toFilePath(id, root) processSpy.mockRestore() + existsSpy.mockRestore() expect(slash(filePath)).toEqual(expected) }) @@ -49,8 +54,11 @@ describe('toFilePath', () => { const expected = '/path/to/project/node_modules/pkg/file.js' const processSpy = vi.spyOn(process, 'cwd').mockReturnValue(root) + const existsSpy = vi.mocked(existsSync).mockReturnValue(true) const filePath = toFilePath(id, root) processSpy.mockRestore() + existsSpy.mockRestore() + expect(slash(filePath)).toEqual(expected) }) @@ -60,8 +68,10 @@ describe('toFilePath', () => { const expected = '/root/node_modules/pkg/file.js' const processSpy = vi.spyOn(process, 'cwd').mockReturnValue(root) + const existsSpy = vi.mocked(existsSync).mockReturnValue(true) const filePath = toFilePath(id, root) processSpy.mockRestore() + existsSpy.mockRestore() expect(slash(filePath)).toEqual(expected) }) @@ -72,8 +82,10 @@ describe('toFilePath', () => { const expected = '/root/node_modules/pkg/file.js' const processSpy = vi.spyOn(process, 'cwd').mockReturnValue(root) + const existsSpy = vi.mocked(existsSync).mockReturnValue(true) const filePath = toFilePath(id, root) processSpy.mockRestore() + existsSpy.mockRestore() expect(slash(filePath)).toEqual(expected) }) @@ -84,10 +96,25 @@ describe('toFilePath', () => { const expected = '/root/path/to/file.js' const processSpy = vi.spyOn(process, 'cwd').mockReturnValue(root) + const existsSpy = vi.mocked(existsSync).mockReturnValue(true) const filePath = toFilePath(id, root) processSpy.mockRestore() + existsSpy.mockRestore() expect(slash(filePath)).toEqual(expected) }) + + it('unix with sibling path', () => { + const root = '/path/to/first/package' + const id = '/path/to/second/package/file.js' + + const processSpy = vi.spyOn(process, 'cwd').mockReturnValue(root) + const existsSpy = vi.mocked(existsSync).mockReturnValue(false) + const filePath = toFilePath(id, root) + processSpy.mockRestore() + existsSpy.mockRestore() + + expect(slash(filePath)).toEqual(id) + }) } }) diff --git a/test/coverage-test/coverage-test/coverage.istanbul.test.ts b/test/coverage-test/coverage-test/coverage.istanbul.test.ts index 45d58fd6a521..46780cd9e5c7 100644 --- a/test/coverage-test/coverage-test/coverage.istanbul.test.ts +++ b/test/coverage-test/coverage-test/coverage.istanbul.test.ts @@ -3,7 +3,7 @@ import { resolve } from 'pathe' import { expect, test } from 'vitest' test('istanbul html report', async () => { - const coveragePath = resolve('./coverage') + const coveragePath = resolve('./coverage/src') const files = fs.readdirSync(coveragePath) expect(files).toContain('index.html') @@ -24,8 +24,18 @@ test('istanbul lcov report', async () => { }) test('all includes untested files', () => { - const coveragePath = resolve('./coverage') + const coveragePath = resolve('./coverage/src') const files = fs.readdirSync(coveragePath) expect(files).toContain('untested-file.ts.html') }) + +test('files should not contain query parameters', () => { + const coveragePath = resolve('./coverage/src/Counter') + const files = fs.readdirSync(coveragePath) + + expect(files).toContain('index.html') + expect(files).toContain('Counter.vue.html') + expect(files).toContain('Counter.component.ts.html') + expect(files).not.toContain('Counter.component.ts?vue&type=script&src=true&lang.ts.html') +}) diff --git a/test/coverage-test/src/Counter/Counter.component.ts b/test/coverage-test/src/Counter/Counter.component.ts new file mode 100644 index 000000000000..86cc4db9cbb1 --- /dev/null +++ b/test/coverage-test/src/Counter/Counter.component.ts @@ -0,0 +1,21 @@ +import { defineComponent, ref } from 'vue' + +export default defineComponent({ + name: 'Counter', + + setup() { + const count = ref(0) + return { count } + }, + + methods: { + uncoveredMethod() { + return 'This line should not be covered' + }, + + coveredMethod() { + return 'This line should be covered' + }, + }, +}) + diff --git a/test/coverage-test/src/Counter/Counter.vue b/test/coverage-test/src/Counter/Counter.vue new file mode 100644 index 000000000000..601de54b7689 --- /dev/null +++ b/test/coverage-test/src/Counter/Counter.vue @@ -0,0 +1,15 @@ + + + + diff --git a/test/coverage-test/src/Counter/index.ts b/test/coverage-test/src/Counter/index.ts new file mode 100644 index 000000000000..378476d78d22 --- /dev/null +++ b/test/coverage-test/src/Counter/index.ts @@ -0,0 +1,4 @@ +import CounterComponent from './Counter.component' +import CounterVue from './Counter.vue' + +export { CounterComponent, CounterVue } diff --git a/test/coverage-test/test/vue.test.ts b/test/coverage-test/test/vue.test.ts index 1dd265ca61ea..171e11c1aadc 100644 --- a/test/coverage-test/test/vue.test.ts +++ b/test/coverage-test/test/vue.test.ts @@ -6,6 +6,7 @@ import { expect, test } from 'vitest' import { mount } from '@vue/test-utils' import Hello from '../src/Hello.vue' import Defined from '../src/Defined.vue' +import { CounterVue } from '../src/Counter' test('vue 3 coverage', async () => { expect(Hello).toBeTruthy() @@ -35,3 +36,10 @@ test('define package in vm', () => { expect(wrapper.text()).toContain(MY_CONSTANT) }) + +test('vue non-SFC, uses query parameters in file imports', async () => { + const wrapper = mount(CounterVue) + + await wrapper.find('button').trigger('click') + expect(wrapper.text()).contain(1) +}) diff --git a/test/path-resolution-target/.eslintignore b/test/path-resolution-target/.eslintignore new file mode 100644 index 000000000000..af18ca9559d2 --- /dev/null +++ b/test/path-resolution-target/.eslintignore @@ -0,0 +1 @@ +!dist/ diff --git a/test/path-resolution-target/.gitignore b/test/path-resolution-target/.gitignore new file mode 100644 index 000000000000..af18ca9559d2 --- /dev/null +++ b/test/path-resolution-target/.gitignore @@ -0,0 +1 @@ +!dist/ diff --git a/test/path-resolution-target/README.md b/test/path-resolution-target/README.md new file mode 100644 index 000000000000..79839556fa38 --- /dev/null +++ b/test/path-resolution-target/README.md @@ -0,0 +1,2 @@ +This package is here just to be a sibling package to `path-resolution`. It +contains no tests of its own. diff --git a/test/path-resolution-target/dist/index.d.ts b/test/path-resolution-target/dist/index.d.ts new file mode 100644 index 000000000000..3b9981e05940 --- /dev/null +++ b/test/path-resolution-target/dist/index.d.ts @@ -0,0 +1 @@ +export function sub(a: number, b: number): number diff --git a/test/path-resolution-target/dist/index.js b/test/path-resolution-target/dist/index.js new file mode 100644 index 000000000000..cb92ed2e794b --- /dev/null +++ b/test/path-resolution-target/dist/index.js @@ -0,0 +1,3 @@ +export function sub(a, b) { + return a - b; +} diff --git a/test/path-resolution-target/package.json b/test/path-resolution-target/package.json new file mode 100644 index 000000000000..8b66a23ae3c1 --- /dev/null +++ b/test/path-resolution-target/package.json @@ -0,0 +1,6 @@ +{ + "name": "@vitest/test-path-resolution-target", + "type": "module", + "private": true, + "main": "./dist/index.js" +} diff --git a/test/path-resolution/package.json b/test/path-resolution/package.json new file mode 100644 index 000000000000..8e9d53a622e1 --- /dev/null +++ b/test/path-resolution/package.json @@ -0,0 +1,15 @@ +{ + "name": "@vitest/test-path-resolution", + "type": "module", + "private": true, + "scripts": { + "test": "vitest", + "coverage": "vitest run --coverage" + }, + "devDependencies": { + "@edge-runtime/vm": "1.1.0-beta.26", + "@vitest/test-path-resolution-target": "workspace:*", + "@vitest/web-worker": "workspace:*", + "vitest": "workspace:*" + } +} diff --git a/test/path-resolution/test/sister-package.test.ts b/test/path-resolution/test/sister-package.test.ts new file mode 100644 index 000000000000..abc20c44e2eb --- /dev/null +++ b/test/path-resolution/test/sister-package.test.ts @@ -0,0 +1,17 @@ +import { expect, it, vitest } from 'vitest' + +import { sub } from '@vitest/test-path-resolution-target' + +vitest.mock('@vitest/test-path-resolution-target') + +it('should be mocked', () => { + expect(sub).toHaveProperty('mock') + expect(sub(5, 3)).toBeUndefined() +}) + +it('should import actual', async () => { + const { sub } = await vitest.importActual('@vitest/test-path-resolution-target') + + expect(sub).not.toHaveProperty('mock') + expect(sub(5, 3)).toBe(2) +}) diff --git a/test/path-resolution/vitest.config.ts b/test/path-resolution/vitest.config.ts new file mode 100644 index 000000000000..41bc8c0ff39f --- /dev/null +++ b/test/path-resolution/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' + +export default defineConfig({ + test: { + include: ['test/*.test.ts'], + }, +}) diff --git a/test/stacktraces/test/runner.test.ts b/test/stacktraces/test/runner.test.ts index f5110934e39f..748cf22cae5a 100644 --- a/test/stacktraces/test/runner.test.ts +++ b/test/stacktraces/test/runner.test.ts @@ -31,6 +31,6 @@ describe('stacktraces should respect sourcemaps', async () => { const index = lines.findIndex(val => val.includes(`${file}:`)) const msg = lines.slice(index, index + 8).join('\n') expect(msg).toMatchSnapshot(file) - }, 10000) + }, 30000) } })