Skip to content

Commit

Permalink
fix(vitest): correctly resolve mocked node:* imports in __mocks__ fol…
Browse files Browse the repository at this point in the history
…der (#6204)
  • Loading branch information
sheremet-va authored Jul 23, 2024
1 parent 3aab8a1 commit a48be6f
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 16 deletions.
10 changes: 5 additions & 5 deletions docs/guide/mocking.md
Original file line number Diff line number Diff line change
Expand Up @@ -383,19 +383,19 @@ module.exports = fs.promises
:::

```ts
// hello-world.js
// read-hello-world.js
import { readFileSync } from 'node:fs'

export function readHelloWorld(path) {
return readFileSync('./hello-world.txt')
return readFileSync(path)
}
```

```ts
// hello-world.test.js
import { beforeEach, expect, it, vi } from 'vitest'
import { fs, vol } from 'memfs'
import { readHelloWorld } from './hello-world.js'
import { readHelloWorld } from './read-hello-world.js'

// tell vitest to use fs mock from __mocks__ folder
// this can be done in a setup file if fs should always be mocked
Expand All @@ -408,7 +408,7 @@ beforeEach(() => {
})

it('should return correct text', () => {
const path = './hello-world.txt'
const path = '/hello-world.txt'
fs.writeFileSync(path, 'hello world')

const text = readHelloWorld(path)
Expand All @@ -423,7 +423,7 @@ it('can return a value multiple times', () => {
'./dir2/hw.txt': 'hello dir2',
},
// default cwd
'/tmp'
'/tmp',
)

expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1')
Expand Down
30 changes: 22 additions & 8 deletions packages/vitest/src/runtime/mocker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ export class VitestMocker {
return {
id,
fsPath,
external,
external: external ? this.normalizePath(external) : external,
}
}

Expand Down Expand Up @@ -315,14 +315,28 @@ export class VitestMocker {
const files = readdirSync(mockFolder)
const baseOriginal = basename(path)

for (const file of files) {
const baseFile = basename(file, extname(file))
if (baseFile === baseOriginal) {
return resolve(mockFolder, file)
function findFile(files: string[], baseOriginal: string): string | null {
for (const file of files) {
const baseFile = basename(file, extname(file))
if (baseFile === baseOriginal) {
const path = resolve(mockFolder, file)
// if the same name, return the file
if (fs.statSync(path).isFile()) {
return path
}
else {
// find folder/index.{js,ts}
const indexFile = findFile(readdirSync(path), 'index')
if (indexFile) {
return indexFile
}
}
}
}
return null
}

return null
return findFile(files, baseOriginal)
}

const dir = dirname(path)
Expand Down Expand Up @@ -517,7 +531,7 @@ export class VitestMocker {
const mocks = this.mockMap.get(suitefile) || {}
const resolves = this.resolveCache.get(suitefile) || {}

mocks[id] = factory || this.resolveMockPath(path, external)
mocks[id] = factory || this.resolveMockPath(id, external)
resolves[id] = originalId

this.mockMap.set(suitefile, mocks)
Expand Down Expand Up @@ -546,7 +560,7 @@ export class VitestMocker {
let mock = this.getDependencyMock(normalizedId)

if (mock === undefined) {
mock = this.resolveMockPath(fsPath, external)
mock = this.resolveMockPath(normalizedId, external)
}

if (mock === null) {
Expand Down
23 changes: 21 additions & 2 deletions pnpm-lock.yaml

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

6 changes: 6 additions & 0 deletions test/core/__mocks__/fs.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// we can also use `import`, but then
// every export should be explicitly defined

const { fs } = require('memfs')

module.exports = fs
6 changes: 6 additions & 0 deletions test/core/__mocks__/fs/promises.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// we can also use `import`, but then
// every export should be explicitly defined

const { fs } = require('memfs')

module.exports = fs.promises
1 change: 1 addition & 0 deletions test/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"axios": "^0.26.1",
"debug": "^4.3.4",
"immutable": "5.0.0-beta.5",
"memfs": "^4.8.2",
"strip-ansi": "^7.1.0",
"sweetalert2": "^11.6.16",
"tinyrainbow": "^1.2.0",
Expand Down
6 changes: 6 additions & 0 deletions test/core/src/read-hello-world.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// hello-world.js
import { readFileSync } from 'node:fs'

export function readHelloWorld(path: string) {
return readFileSync(path, 'utf-8')
}
6 changes: 5 additions & 1 deletion test/core/test/file-path.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { existsSync } from 'node:fs'
import { describe, expect, it, vi } from 'vitest'
import { isWindows, slash, toFilePath } from '../../../packages/vite-node/src/utils'

vi.mock('fs')
vi.mock('fs', () => {
return {
existsSync: vi.fn(),
}
})

describe('current url', () => {
it('__filename is equal to import.meta.url', () => {
Expand Down
37 changes: 37 additions & 0 deletions test/core/test/mock-fs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// hello-world.test.js
import { beforeEach, expect, it, vi } from 'vitest'
import { fs, vol } from 'memfs'
import { readHelloWorld } from '../src/read-hello-world'

// tell vitest to use fs mock from __mocks__ folder
// this can be done in a setup file if fs should always be mocked
vi.mock('node:fs')
vi.mock('node:fs/promises')

beforeEach(() => {
// reset the state of in-memory fs
vol.reset()
})

it('should return correct text', () => {
const path = '/hello-world.txt'
fs.writeFileSync(path, 'hello world')

const text = readHelloWorld(path)
expect(text).toBe('hello world')
})

it('can return a value multiple times', () => {
// you can use vol.fromJSON to define several files
vol.fromJSON(
{
'./dir1/hw.txt': 'hello dir1',
'./dir2/hw.txt': 'hello dir2',
},
// default cwd
'/tmp',
)

expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1')
expect(readHelloWorld('/tmp/dir2/hw.txt')).toBe('hello dir2')
})

0 comments on commit a48be6f

Please sign in to comment.