MCPcopy
hub / github.com/vitest-dev/vitest / automockModule

Function automockModule

packages/mocker/src/node/automock.ts:17–214  ·  view source on GitHub ↗
(
  code: string,
  mockType: 'automock' | 'autospy',
  parse: (code: string) => any,
  options: AutomockOptions = {},
)

Source from the content-addressed store, hash-verified

15
16// TODO: better source map replacement
17export function automockModule(
18 code: string,
19 mockType: 'automock' | 'autospy',
20 parse: (code: string) => any,
21 options: AutomockOptions = {},
22): MagicString {
23 const globalThisAccessor = options.globalThisAccessor || '"__vitest_mocker__"'
24 let ast: Program
25 try {
26 ast = parse(code) as Program
27 }
28 catch (cause) {
29 if (options.id) {
30 throw new Error(`failed to parse ${options.id}`, { cause })
31 }
32 throw cause
33 }
34
35 const m = new MagicString(code)
36
37 const allSpecifiers: { name: string; alias?: string }[] = []
38 const replacers: (() => void)[] = []
39 let importIndex = 0
40 for (const _node of ast.body) {
41 if (_node.type === 'ExportAllDeclaration') {
42 const node = _node as Positioned<ExportAllDeclaration>
43 // TODO: pass it down in the browser mode
44 if (!options.id) {
45 throw new Error(
46 `automocking files with \`export *\` is not supported because it cannot be easily statically analysed`,
47 )
48 }
49
50 const source = node.source.value
51 if (typeof source !== 'string') {
52 throw new TypeError(`unknown source type while automocking: ${source}`)
53 }
54
55 const moduleUrl = import.meta.resolve(source, pathToFileURL(options.id).toString())
56 const modulePath = fileURLToPath(moduleUrl)
57 const moduleContent = readFileSync(modulePath, 'utf-8')
58 const transformedCode = transformCode(moduleContent, moduleUrl)
59 const moduleFormat = resolveModuleFormat(moduleUrl, transformedCode)
60 const moduleExports = collectModuleExports(modulePath, transformedCode, moduleFormat || 'module')
61 replacers.push(() => {
62 const importNames: string[] = []
63 moduleExports.forEach((exportName) => {
64 const isReexported = allSpecifiers.some(({ name, alias }) => name === exportName || alias === exportName)
65 if (!isReexported) {
66 importNames.push(exportName)
67 allSpecifiers.push({ name: exportName })
68 }
69 })
70
71 const importString = `import { ${importNames.join(', ')} } from '${source}';`
72
73 m.overwrite(node.start, node.end, importString)
74 })

Callers 4

transformFunction · 0.90
handlerFunction · 0.90
automockFunction · 0.90
loadAutomockMethod · 0.85

Calls 9

transformCodeFunction · 0.90
resolveModuleFormatFunction · 0.90
collectModuleExportsFunction · 0.90
readFileSyncFunction · 0.85
traversePatternFunction · 0.85
parseFunction · 0.50
resolveMethod · 0.45
toStringMethod · 0.45

Tested by 1

automockFunction · 0.72