Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epidemian
GitHub Repository: epidemian/eslint-plugin-import
Path: blob/main/tests/src/rules/no-unresolved.js
829 views
1
import * as path from 'path';
2
3
import { getTSParsers, test, SYNTAX_CASES, testVersion } from '../utils';
4
5
import { CASE_SENSITIVE_FS } from 'eslint-module-utils/resolve';
6
7
import { RuleTester } from 'eslint';
8
9
const ruleTester = new RuleTester();
10
const rule = require('rules/no-unresolved');
11
12
function runResolverTests(resolver) {
13
// redefine 'test' to set a resolver
14
// thus 'rest'. needed something 4-chars-long for formatting simplicity
15
function rest(specs) {
16
specs.settings = Object.assign({},
17
specs.settings,
18
{ 'import/resolver': resolver, 'import/cache': { lifetime: 0 } },
19
);
20
21
return test(specs);
22
}
23
24
ruleTester.run(`no-unresolved (${resolver})`, rule, {
25
valid: [].concat(
26
test({ code: 'import "./malformed.js"' }),
27
28
rest({ code: 'import foo from "./bar";' }),
29
rest({ code: "import bar from './bar.js';" }),
30
rest({ code: "import {someThing} from './test-module';" }),
31
rest({ code: "import fs from 'fs';" }),
32
rest({ code: "import('fs');",
33
parser: require.resolve('babel-eslint') }),
34
35
// check with eslint parser
36
testVersion('>= 7', () => rest({
37
code: "import('fs');",
38
parserOptions: { ecmaVersion: 2021 },
39
})) || [],
40
41
rest({ code: 'import * as foo from "a"' }),
42
43
rest({ code: 'export { foo } from "./bar"' }),
44
rest({ code: 'export * from "./bar"' }),
45
rest({ code: 'let foo; export { foo }' }),
46
47
// stage 1 proposal for export symmetry,
48
rest({ code: 'export * as bar from "./bar"',
49
parser: require.resolve('babel-eslint') }),
50
rest({ code: 'export bar from "./bar"',
51
parser: require.resolve('babel-eslint') }),
52
rest({ code: 'import foo from "./jsx/MyUnCoolComponent.jsx"' }),
53
54
// commonjs setting
55
rest({ code: 'var foo = require("./bar")',
56
options: [{ commonjs: true }] }),
57
rest({ code: 'require("./bar")',
58
options: [{ commonjs: true }] }),
59
rest({ code: 'require("./does-not-exist")',
60
options: [{ commonjs: false }] }),
61
rest({ code: 'require("./does-not-exist")' }),
62
63
// amd setting
64
rest({ code: 'require(["./bar"], function (bar) {})',
65
options: [{ amd: true }] }),
66
rest({ code: 'define(["./bar"], function (bar) {})',
67
options: [{ amd: true }] }),
68
rest({ code: 'require(["./does-not-exist"], function (bar) {})',
69
options: [{ amd: false }] }),
70
// magic modules: https://git.io/vByan
71
rest({ code: 'define(["require", "exports", "module"], function (r, e, m) { })',
72
options: [{ amd: true }] }),
73
74
// don't validate without callback param
75
rest({ code: 'require(["./does-not-exist"])',
76
options: [{ amd: true }] }),
77
rest({ code: 'define(["./does-not-exist"], function (bar) {})' }),
78
79
// stress tests
80
rest({ code: 'require("./does-not-exist", "another arg")',
81
options: [{ commonjs: true, amd: true }] }),
82
rest({ code: 'proxyquire("./does-not-exist")',
83
options: [{ commonjs: true, amd: true }] }),
84
rest({ code: '(function() {})("./does-not-exist")',
85
options: [{ commonjs: true, amd: true }] }),
86
rest({ code: 'define([0, foo], function (bar) {})',
87
options: [{ amd: true }] }),
88
rest({ code: 'require(0)',
89
options: [{ commonjs: true }] }),
90
rest({ code: 'require(foo)',
91
options: [{ commonjs: true }] }),
92
),
93
94
invalid: [].concat(
95
rest({
96
code: 'import reallyfake from "./reallyfake/module"',
97
settings: { 'import/ignore': ['^\\./fake/'] },
98
errors: [{ message: 'Unable to resolve path to module ' +
99
'\'./reallyfake/module\'.' }],
100
}),
101
102
rest({
103
code: "import bar from './baz';",
104
errors: [{ message: "Unable to resolve path to module './baz'.",
105
type: 'Literal' }],
106
}),
107
rest({ code: "import bar from './baz';",
108
errors: [{ message: "Unable to resolve path to module './baz'.",
109
type: 'Literal',
110
}] }),
111
rest({
112
code: "import bar from './empty-folder';",
113
errors: [{ message: "Unable to resolve path to module './empty-folder'.",
114
type: 'Literal',
115
}] }),
116
117
// sanity check that this module is _not_ found without proper settings
118
rest({
119
code: "import { DEEP } from 'in-alternate-root';",
120
errors: [{ message: 'Unable to resolve path to ' +
121
"module 'in-alternate-root'.",
122
type: 'Literal',
123
}] }),
124
rest({
125
code: "import('in-alternate-root').then(function({DEEP}) {});",
126
errors: [{
127
message: 'Unable to resolve path to module \'in-alternate-root\'.',
128
type: 'Literal',
129
}],
130
parser: require.resolve('babel-eslint') }),
131
132
rest({ code: 'export { foo } from "./does-not-exist"',
133
errors: ["Unable to resolve path to module './does-not-exist'."] }),
134
rest({
135
code: 'export * from "./does-not-exist"',
136
errors: ["Unable to resolve path to module './does-not-exist'."],
137
}),
138
139
// check with eslint parser
140
testVersion('>= 7', () => rest({
141
code: "import('in-alternate-root').then(function({DEEP}) {});",
142
errors: [{
143
message: 'Unable to resolve path to module \'in-alternate-root\'.',
144
type: 'Literal',
145
}],
146
parserOptions: { ecmaVersion: 2021 },
147
})) || [],
148
149
// export symmetry proposal
150
rest({ code: 'export * as bar from "./does-not-exist"',
151
parser: require.resolve('babel-eslint'),
152
errors: ["Unable to resolve path to module './does-not-exist'."],
153
}),
154
rest({ code: 'export bar from "./does-not-exist"',
155
parser: require.resolve('babel-eslint'),
156
errors: ["Unable to resolve path to module './does-not-exist'."],
157
}),
158
159
// commonjs setting
160
rest({
161
code: 'var bar = require("./baz")',
162
options: [{ commonjs: true }],
163
errors: [{
164
message: "Unable to resolve path to module './baz'.",
165
type: 'Literal',
166
}],
167
}),
168
rest({
169
code: 'require("./baz")',
170
options: [{ commonjs: true }],
171
errors: [{
172
message: "Unable to resolve path to module './baz'.",
173
type: 'Literal',
174
}],
175
}),
176
177
// amd
178
rest({
179
code: 'require(["./baz"], function (bar) {})',
180
options: [{ amd: true }],
181
errors: [{
182
message: "Unable to resolve path to module './baz'.",
183
type: 'Literal',
184
}],
185
}),
186
rest({
187
code: 'define(["./baz"], function (bar) {})',
188
options: [{ amd: true }],
189
errors: [{
190
message: "Unable to resolve path to module './baz'.",
191
type: 'Literal',
192
}],
193
}),
194
rest({
195
code: 'define(["./baz", "./bar", "./does-not-exist"], function (bar) {})',
196
options: [{ amd: true }],
197
errors: [{
198
message: "Unable to resolve path to module './baz'.",
199
type: 'Literal',
200
},{
201
message: "Unable to resolve path to module './does-not-exist'.",
202
type: 'Literal',
203
}],
204
}),
205
),
206
});
207
208
ruleTester.run(`issue #333 (${resolver})`, rule, {
209
valid: [
210
rest({ code: 'import foo from "./bar.json"' }),
211
rest({ code: 'import foo from "./bar"' }),
212
rest({
213
code: 'import foo from "./bar.json"',
214
settings: { 'import/extensions': ['.js'] },
215
}),
216
rest({
217
code: 'import foo from "./bar"',
218
settings: { 'import/extensions': ['.js'] },
219
}),
220
],
221
invalid: [
222
rest({
223
code: 'import bar from "./foo.json"',
224
errors: ["Unable to resolve path to module './foo.json'."],
225
}),
226
],
227
});
228
229
if (!CASE_SENSITIVE_FS) {
230
const relativePath = './tests/files/jsx/MyUnCoolComponent.jsx';
231
const cwd = process.cwd();
232
const mismatchedPath = path.join(cwd.toUpperCase(), relativePath).replace(/\\/g, '/');
233
234
ruleTester.run('case sensitivity', rule, {
235
valid: [
236
rest({ // test with explicit flag
237
code: 'import foo from "./jsx/MyUncoolComponent.jsx"',
238
options: [{ caseSensitive: false }],
239
}),
240
],
241
242
invalid: [
243
rest({ // test default
244
code: 'import foo from "./jsx/MyUncoolComponent.jsx"',
245
errors: [`Casing of ./jsx/MyUncoolComponent.jsx does not match the underlying filesystem.`],
246
}),
247
rest({ // test with explicit flag
248
code: 'import foo from "./jsx/MyUncoolComponent.jsx"',
249
options: [{ caseSensitive: true }],
250
errors: [`Casing of ./jsx/MyUncoolComponent.jsx does not match the underlying filesystem.`],
251
}),
252
],
253
});
254
255
ruleTester.run('case sensitivity strict', rule, {
256
valid: [
257
// #1259 issue
258
rest({ // caseSensitiveStrict is disabled by default
259
code: `import foo from "${mismatchedPath}"`,
260
}),
261
],
262
263
invalid: [
264
// #1259 issue
265
rest({ // test with enabled caseSensitiveStrict option
266
code: `import foo from "${mismatchedPath}"`,
267
options: [{ caseSensitiveStrict: true }],
268
errors: [`Casing of ${mismatchedPath} does not match the underlying filesystem.`],
269
}),
270
rest({ // test with enabled caseSensitiveStrict option and disabled caseSensitive
271
code: `import foo from "${mismatchedPath}"`,
272
options: [{ caseSensitiveStrict: true, caseSensitive: false }],
273
errors: [`Casing of ${mismatchedPath} does not match the underlying filesystem.`],
274
}),
275
],
276
});
277
}
278
279
}
280
281
['node', 'webpack'].forEach(runResolverTests);
282
283
ruleTester.run('no-unresolved (import/resolve legacy)', rule, {
284
valid: [
285
test({
286
code: "import { DEEP } from 'in-alternate-root';",
287
settings: {
288
'import/resolve': {
289
'paths': [path.join( process.cwd()
290
, 'tests', 'files', 'alternate-root')],
291
},
292
},
293
}),
294
295
test({
296
code: "import { DEEP } from 'in-alternate-root'; " +
297
"import { bar } from 'src-bar';",
298
settings: { 'import/resolve': { 'paths': [
299
path.join('tests', 'files', 'src-root'),
300
path.join('tests', 'files', 'alternate-root'),
301
] } } }),
302
303
test({
304
code: 'import * as foo from "jsx-module/foo"',
305
settings: { 'import/resolve': { 'extensions': ['.jsx'] } },
306
}),
307
],
308
309
invalid: [
310
test({
311
code: 'import * as foo from "jsx-module/foo"',
312
errors: [ "Unable to resolve path to module 'jsx-module/foo'." ],
313
}),
314
],
315
});
316
317
ruleTester.run('no-unresolved (webpack-specific)', rule, {
318
valid: [
319
test({
320
// default webpack config in files/webpack.config.js knows about jsx
321
code: 'import * as foo from "jsx-module/foo"',
322
settings: { 'import/resolver': 'webpack' },
323
}),
324
test({
325
// should ignore loaders
326
code: 'import * as foo from "some-loader?with=args!jsx-module/foo"',
327
settings: { 'import/resolver': 'webpack' },
328
}),
329
],
330
invalid: [
331
test({
332
// default webpack config in files/webpack.config.js knows about jsx
333
code: 'import * as foo from "jsx-module/foo"',
334
settings: {
335
'import/resolver': { 'webpack': { 'config': 'webpack.empty.config.js' } },
336
},
337
errors: [ "Unable to resolve path to module 'jsx-module/foo'." ],
338
}),
339
],
340
});
341
342
343
ruleTester.run('no-unresolved ignore list', rule, {
344
valid: [
345
test({
346
code: 'import "./malformed.js"',
347
options: [{ ignore: ['.png$', '.gif$'] }],
348
}),
349
test({
350
code: 'import "./test.giffy"',
351
options: [{ ignore: ['.png$', '.gif$'] }],
352
}),
353
354
test({
355
code: 'import "./test.gif"',
356
options: [{ ignore: ['.png$', '.gif$'] }],
357
}),
358
359
test({
360
code: 'import "./test.png"',
361
options: [{ ignore: ['.png$', '.gif$'] }],
362
}),
363
],
364
365
invalid:[
366
test({
367
code: 'import "./test.gif"',
368
options: [{ ignore: ['.png$'] }],
369
errors: [ "Unable to resolve path to module './test.gif'." ],
370
}),
371
372
test({
373
code: 'import "./test.png"',
374
options: [{ ignore: ['.gif$'] }],
375
errors: [ "Unable to resolve path to module './test.png'." ],
376
}),
377
],
378
});
379
380
ruleTester.run('no-unresolved unknown resolver', rule, {
381
valid: [],
382
383
invalid:[
384
385
// logs resolver load error
386
test({
387
code: 'import "./malformed.js"',
388
settings: { 'import/resolver': 'doesnt-exist' },
389
errors: [
390
`Resolve error: unable to load resolver "doesnt-exist".`,
391
`Unable to resolve path to module './malformed.js'.`,
392
],
393
}),
394
395
// only logs resolver message once
396
test({
397
code: 'import "./malformed.js"; import "./fake.js"',
398
settings: { 'import/resolver': 'doesnt-exist' },
399
errors: [
400
`Resolve error: unable to load resolver "doesnt-exist".`,
401
`Unable to resolve path to module './malformed.js'.`,
402
`Unable to resolve path to module './fake.js'.`,
403
],
404
}),
405
],
406
});
407
408
ruleTester.run('no-unresolved electron', rule, {
409
valid: [
410
test({
411
code: 'import "electron"',
412
settings: { 'import/core-modules': ['electron'] },
413
}),
414
],
415
invalid:[
416
test({
417
code: 'import "electron"',
418
errors: [`Unable to resolve path to module 'electron'.`],
419
}),
420
],
421
});
422
423
ruleTester.run('no-unresolved syntax verification', rule, {
424
valid: SYNTAX_CASES,
425
invalid:[],
426
});
427
428
// https://github.com/import-js/eslint-plugin-import/issues/2024
429
ruleTester.run('import() with built-in parser', rule, {
430
valid: [].concat(
431
testVersion('>=7', () => ({
432
code: "import('fs');",
433
parserOptions: { ecmaVersion: 2021 },
434
})) || [],
435
),
436
invalid: [].concat(
437
testVersion('>=7', () => ({
438
code: 'import("./does-not-exist-l0w9ssmcqy9").then(() => {})',
439
parserOptions: { ecmaVersion: 2021 },
440
errors: ["Unable to resolve path to module './does-not-exist-l0w9ssmcqy9'."],
441
})) || [],
442
),
443
});
444
445
context('TypeScript', () => {
446
// Type-only imports were added in TypeScript ESTree 2.23.0
447
getTSParsers().filter(x => x !== require.resolve('typescript-eslint-parser')).forEach((parser) => {
448
ruleTester.run(`${parser}: no-unresolved ignore type-only`, rule, {
449
valid: [
450
test({
451
code: 'import type { JSONSchema7Type } from "@types/json-schema";',
452
parser,
453
}),
454
],
455
invalid: [
456
test({
457
code: 'import { JSONSchema7Type } from "@types/json-schema";',
458
errors: [ "Unable to resolve path to module '@types/json-schema'." ],
459
parser,
460
}),
461
],
462
});
463
});
464
});
465
466