/
imports.test.ts
164 lines (132 loc) · 5.91 KB
/
imports.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import { mkdir, writeFile } from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
import { resolve } from 'pathe'
import { describe, expect, test, vi } from 'vitest'
import { dynamicRelativeImport } from '../src/relative-import'
// @ts-expect-error module is not typed
import promiseExport from '../src/cjs/promise-export'
test('promise export works correctly', async () => {
await expect(promiseExport).resolves.toEqual({ value: 42 })
})
test('dynamic relative import works', async () => {
const stringTimeoutMod = await import('./../src/timeout')
const timeoutPath = './../src/timeout'
const variableTimeoutMod = await import(timeoutPath)
expect(stringTimeoutMod).toBe(variableTimeoutMod)
})
test('Relative imports in imported modules work', async () => {
const relativeImportFromFile = await dynamicRelativeImport('timeout')
const directImport = await import('./../src/timeout')
expect(relativeImportFromFile).toBe(directImport)
})
test('dynamic aliased import works', async () => {
const stringTimeoutMod = await import('./../src/timeout')
const timeoutPath = '#/timeout'
const variableTimeoutMod = await import(timeoutPath)
expect(stringTimeoutMod).toBe(variableTimeoutMod)
})
test('dynamic absolute from root import works', async () => {
const stringTimeoutMod = await import('./../src/timeout')
const timeoutPath = '/src/timeout'
const variableTimeoutMod = await import(timeoutPath)
expect(stringTimeoutMod).toBe(variableTimeoutMod)
})
test('dynamic absolute with extension import works', async () => {
const stringTimeoutMod = await import('./../src/timeout')
const timeoutPath = '/src/timeout.ts'
const variableTimeoutMod = await import(timeoutPath)
expect(stringTimeoutMod).toBe(variableTimeoutMod)
})
test('data with dynamic import works', async () => {
const dataUri = 'data:text/javascript;charset=utf-8,export default "hi"'
const { default: hi } = await import(dataUri)
expect(hi).toBe('hi')
})
test('dynamic import coerces to string', async () => {
const dataUri = 'data:text/javascript;charset=utf-8,export default "hi"'
const { default: hi } = await import({ toString: () => dataUri } as string)
expect(hi).toBe('hi')
})
test('dynamic import has Module symbol', async () => {
const stringTimeoutMod = await import('./../src/timeout')
// @ts-expect-error The symbol won't exist on the import type
expect(stringTimeoutMod[Symbol.toStringTag]).toBe('Module')
})
test('dynamic import has null prototype', async () => {
const stringTimeoutMod = await import('./../src/timeout')
expect(Object.getPrototypeOf(stringTimeoutMod)).toBe(null)
})
test('dynamic import throws an error', async () => {
const path = './some-unknown-path'
const imported = import(path)
await expect(imported).rejects.toThrowError(/Failed to load url \.\/some-unknown-path/)
// @ts-expect-error path does not exist
await expect(() => import('./some-unknown-path')).rejects.toThrowError(/Failed to load/)
})
test('can import @vite/client', async () => {
const name = '@vite/client'
await expect(import(name)).resolves.not.toThrow()
await expect(import(`/${name}`)).resolves.not.toThrow()
})
describe('importing special files from node_modules', async () => {
const dir = resolve(__dirname, '../src/node_modules')
const wasm = resolve(dir, 'file.wasm')
const css = resolve(dir, 'file.css')
const mp3 = resolve(dir, 'file.mp3')
await mkdir(dir, { recursive: true })
await Promise.all([
writeFile(wasm, '(module)'),
writeFile(css, '.foo { color: red; }'),
writeFile(mp3, ''),
])
const importModule = (path: string) => import(path)
test('importing wasm with ?url query', async () => {
const mod = await importModule('../src/node_modules/file.wasm?url')
expect(mod.default).toBe('/src/node_modules/file.wasm')
})
test('importing wasm with ?raw query', async () => {
const mod = await importModule('../src/node_modules/file.wasm?raw')
expect(mod.default).toBe('(module)')
})
test('importing wasm with ?init query', async () => {
const mod = await importModule('../src/node_modules/file.wasm?init')
expect(mod.default).toBeTypeOf('function')
})
test('importing css with ?inline query', async () => {
const mod = await importModule('../src/node_modules/file.css?inline')
expect(mod.default).toBeTypeOf('string')
})
test('importing asset returns a string', async () => {
const mod = await importModule('../src/node_modules/file.mp3')
expect(mod.default).toBe('/src/node_modules/file.mp3')
})
})
describe.runIf(process.platform === 'win32')('importing files with different drive casing', async () => {
test('importing a local file with different drive casing works', async () => {
const path = new URL('./../src/timeout', import.meta.url)
const filepath = fileURLToPath(path)
const drive = filepath[0].toLowerCase()
const upperDrive = drive.toUpperCase()
const lowercasePath = filepath.replace(`${upperDrive}:`, `${drive}:`)
const uppercasePath = filepath.replace(`${drive}:`, `${upperDrive}:`)
expect(lowercasePath).not.toBe(uppercasePath)
const mod1 = await import(lowercasePath)
const mod2 = await import(uppercasePath)
const mod3 = await import('./../src/timeout')
expect(mod1).toBe(mod2)
expect(mod1).toBe(mod3)
})
test('importing an external file with different drive casing works', async () => {
const path = new URL('./../src/esm/esm.js', import.meta.url)
const filepath = fileURLToPath(path)
const drive = filepath[0].toLowerCase()
const upperDrive = drive.toUpperCase()
const lowercasePath = filepath.replace(`${upperDrive}:`, `${drive}:`)
const uppercasePath = filepath.replace(`${drive}:`, `${upperDrive}:`)
expect(lowercasePath).not.toBe(uppercasePath)
const mod1 = await import(lowercasePath)
vi.resetModules() // since they reference the same global ESM cache, it should not matter
const mod2 = await import(uppercasePath)
expect(mod1).toBe(mod2)
})
})