Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epidemian
GitHub Repository: epidemian/eslint-plugin-import
Path: blob/main/tests/src/rules/namespace.js
829 views
1
import { test, SYNTAX_CASES, getTSParsers, testVersion, testFilePath } from '../utils';
2
import { RuleTester } from 'eslint';
3
import flatMap from 'array.prototype.flatmap';
4
5
const ruleTester = new RuleTester({ env: { es6: true } });
6
const rule = require('rules/namespace');
7
8
9
function error(name, namespace) {
10
return { message: `'${name}' not found in imported namespace '${namespace}'.` };
11
}
12
13
const valid = [
14
test({ code: 'import "./malformed.js"' }),
15
16
test({ code: "import * as foo from './empty-folder';" }),
17
test({ code: 'import * as names from "./named-exports"; ' +
18
'console.log((names.b).c); ' }),
19
20
test({ code: 'import * as names from "./named-exports"; ' +
21
'console.log(names.a);' }),
22
test({ code: 'import * as names from "./re-export-names"; ' +
23
'console.log(names.foo);' }),
24
test({
25
code: "import * as elements from './jsx';",
26
parserOptions: {
27
sourceType: 'module',
28
ecmaFeatures: { jsx: true },
29
ecmaVersion: 2015,
30
},
31
}),
32
test({ code: "import * as foo from './common';" }),
33
34
// destructuring namespaces
35
test({ code: 'import * as names from "./named-exports";' +
36
'const { a } = names' }),
37
test({ code: 'import * as names from "./named-exports";' +
38
'const { d: c } = names' }),
39
test({ code: 'import * as names from "./named-exports";' +
40
'const { c } = foo\n' +
41
' , { length } = "names"\n' +
42
' , alt = names' }),
43
// deep destructuring only cares about top level
44
test({ code: 'import * as names from "./named-exports";' +
45
'const { ExportedClass: { length } } = names' }),
46
47
// detect scope redefinition
48
test({ code: 'import * as names from "./named-exports";' +
49
'function b(names) { const { c } = names }' }),
50
test({ code: 'import * as names from "./named-exports";' +
51
'function b() { let names = null; const { c } = names }' }),
52
test({ code: 'import * as names from "./named-exports";' +
53
'const x = function names() { const { c } = names }' }),
54
55
56
/////////
57
// es7 //
58
/////////
59
test({ code: 'export * as names from "./named-exports"',
60
parser: require.resolve('babel-eslint') }),
61
test({ code: 'export defport, * as names from "./named-exports"',
62
parser: require.resolve('babel-eslint') }),
63
// non-existent is handled by no-unresolved
64
test({ code: 'export * as names from "./does-not-exist"',
65
parser: require.resolve('babel-eslint') }),
66
67
test({
68
code: 'import * as Endpoints from "./issue-195/Endpoints"; console.log(Endpoints.Users)',
69
parser: require.resolve('babel-eslint'),
70
}),
71
72
// respect hoisting
73
test({
74
code:
75
'function x() { console.log((names.b).c); } ' +
76
'import * as names from "./named-exports"; ',
77
}),
78
79
// names.default is valid export
80
test({ code: "import * as names from './default-export';" }),
81
test({ code: "import * as names from './default-export'; console.log(names.default)" }),
82
test({
83
code: 'export * as names from "./default-export"',
84
parser: require.resolve('babel-eslint'),
85
}),
86
test({
87
code: 'export defport, * as names from "./default-export"',
88
parser: require.resolve('babel-eslint'),
89
}),
90
91
// #456: optionally ignore computed references
92
test({
93
code: `import * as names from './named-exports'; console.log(names['a']);`,
94
options: [{ allowComputed: true }],
95
}),
96
97
// #656: should handle object-rest properties
98
test({
99
code: `import * as names from './named-exports'; const {a, b, ...rest} = names;`,
100
parserOptions: {
101
ecmaVersion: 2018,
102
},
103
}),
104
test({
105
code: `import * as names from './named-exports'; const {a, b, ...rest} = names;`,
106
parser: require.resolve('babel-eslint'),
107
}),
108
109
// #1144: should handle re-export CommonJS as namespace
110
test({
111
code: `import * as ns from './re-export-common'; const {foo} = ns;`,
112
}),
113
114
// JSX
115
test({
116
code: 'import * as Names from "./named-exports"; const Foo = <Names.a/>',
117
parserOptions: {
118
ecmaFeatures: {
119
jsx: true,
120
},
121
},
122
}),
123
124
// Typescript
125
...flatMap(getTSParsers(), (parser) => [
126
test({
127
code: `
128
import * as foo from "./typescript-declare-nested"
129
foo.bar.MyFunction()
130
`,
131
parser,
132
settings: {
133
'import/parsers': { [parser]: ['.ts'] },
134
'import/resolver': { 'eslint-import-resolver-typescript': true },
135
},
136
}),
137
138
test({
139
code: `import { foobar } from "./typescript-declare-interface"`,
140
parser,
141
settings: {
142
'import/parsers': { [parser]: ['.ts'] },
143
'import/resolver': { 'eslint-import-resolver-typescript': true },
144
},
145
}),
146
147
test({
148
code: 'export * from "typescript/lib/typescript.d"',
149
parser,
150
settings: {
151
'import/parsers': { [parser]: ['.ts'] },
152
'import/resolver': { 'eslint-import-resolver-typescript': true },
153
},
154
}),
155
156
test({
157
code: 'export = function name() {}',
158
parser,
159
settings: {
160
'import/parsers': { [parser]: ['.ts'] },
161
'import/resolver': { 'eslint-import-resolver-typescript': true },
162
},
163
}),
164
]),
165
166
...SYNTAX_CASES,
167
168
test({
169
code: `
170
import * as color from './color';
171
export const getBackgroundFromColor = (color) => color.bg;
172
export const getExampleColor = () => color.example
173
`,
174
}),
175
176
...[].concat(testVersion('>= 6', () => ({
177
code: `
178
import * as middle from './middle';
179
180
console.log(middle.myName);
181
`,
182
filename: testFilePath('export-star-2/downstream.js'),
183
parserOptions: {
184
ecmaVersion: 2020,
185
},
186
})) || []),
187
];
188
189
const invalid = [
190
test({ code: "import * as names from './named-exports'; " +
191
' console.log(names.c);',
192
errors: [error('c', 'names')] }),
193
194
test({ code: "import * as names from './named-exports';" +
195
" console.log(names['a']);",
196
errors: ["Unable to validate computed reference to imported namespace 'names'."] }),
197
198
// assignment warning (from no-reassign)
199
test({ code: 'import * as foo from \'./bar\'; foo.foo = \'y\';',
200
errors: [{ message: 'Assignment to member of namespace \'foo\'.' }] }),
201
test({ code: 'import * as foo from \'./bar\'; foo.x = \'y\';',
202
errors: ['Assignment to member of namespace \'foo\'.', "'x' not found in imported namespace 'foo'."] }),
203
204
// invalid destructuring
205
test({
206
code: 'import * as names from "./named-exports"; const { c } = names',
207
errors: [{ type: 'Property', message: "'c' not found in imported namespace 'names'." }],
208
}),
209
test({
210
code: 'import * as names from "./named-exports"; function b() { const { c } = names }',
211
errors: [{ type: 'Property', message: "'c' not found in imported namespace 'names'." }],
212
}),
213
test({
214
code: 'import * as names from "./named-exports"; const { c: d } = names',
215
errors: [{ type: 'Property', message: "'c' not found in imported namespace 'names'." }],
216
}),
217
test({
218
code: 'import * as names from "./named-exports";' +
219
'const { c: { d } } = names',
220
errors: [{ type: 'Property', message: "'c' not found in imported namespace 'names'." }],
221
}),
222
223
/////////
224
// es7 //
225
/////////
226
227
test({
228
code: 'import * as Endpoints from "./issue-195/Endpoints"; console.log(Endpoints.Foo)',
229
parser: require.resolve('babel-eslint'),
230
errors: ["'Foo' not found in imported namespace 'Endpoints'."],
231
}),
232
233
// parse errors
234
test({
235
code: "import * as namespace from './malformed.js';",
236
errors: [{
237
message: "Parse errors in imported module './malformed.js': 'return' outside of function (1:1)",
238
type: 'Literal',
239
}],
240
}),
241
242
test({
243
code: "import b from './deep/default'; console.log(b.e)",
244
errors: [ "'e' not found in imported namespace 'b'." ],
245
}),
246
247
// respect hoisting
248
test({
249
code:
250
'console.log(names.c);' +
251
"import * as names from './named-exports'; ",
252
errors: [error('c', 'names')],
253
}),
254
test({
255
code:
256
'function x() { console.log(names.c) } ' +
257
"import * as names from './named-exports'; ",
258
errors: [error('c', 'names')],
259
}),
260
261
// #328: * exports do not include default
262
test({
263
code: 'import * as ree from "./re-export"; console.log(ree.default)',
264
errors: [`'default' not found in imported namespace 'ree'.`],
265
}),
266
267
// JSX
268
test({
269
code: 'import * as Names from "./named-exports"; const Foo = <Names.e/>',
270
errors: [error('e', 'Names')],
271
parserOptions: {
272
ecmaFeatures: {
273
jsx: true,
274
},
275
},
276
}),
277
278
]
279
280
///////////////////////
281
// deep dereferences //
282
//////////////////////
283
;[['deep', require.resolve('espree')], ['deep-es7', require.resolve('babel-eslint')]].forEach(function ([folder, parser]) { // close over params
284
valid.push(
285
test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.c.d.e)` }),
286
test({ parser, code: `import { b } from "./${folder}/a"; console.log(b.c.d.e)` }),
287
test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.c.d.e.f)` }),
288
test({ parser, code: `import * as a from "./${folder}/a"; var {b:{c:{d:{e}}}} = a` }),
289
test({ parser, code: `import { b } from "./${folder}/a"; var {c:{d:{e}}} = b` }));
290
291
// deep namespaces should include explicitly exported defaults
292
test({ parser, code: `import * as a from "./${folder}/a"; console.log(a.b.default)` }),
293
294
invalid.push(
295
test({
296
parser,
297
code: `import * as a from "./${folder}/a"; console.log(a.b.e)`,
298
errors: [ "'e' not found in deeply imported namespace 'a.b'." ],
299
}),
300
test({
301
parser,
302
code: `import { b } from "./${folder}/a"; console.log(b.e)`,
303
errors: [ "'e' not found in imported namespace 'b'." ],
304
}),
305
test({
306
parser,
307
code: `import * as a from "./${folder}/a"; console.log(a.b.c.e)`,
308
errors: [ "'e' not found in deeply imported namespace 'a.b.c'." ],
309
}),
310
test({
311
parser,
312
code: `import { b } from "./${folder}/a"; console.log(b.c.e)`,
313
errors: [ "'e' not found in deeply imported namespace 'b.c'." ],
314
}),
315
test({
316
parser,
317
code: `import * as a from "./${folder}/a"; var {b:{ e }} = a`,
318
errors: [ "'e' not found in deeply imported namespace 'a.b'." ],
319
}),
320
test({
321
parser,
322
code: `import * as a from "./${folder}/a"; var {b:{c:{ e }}} = a`,
323
errors: [ "'e' not found in deeply imported namespace 'a.b.c'." ],
324
}));
325
});
326
327
ruleTester.run('namespace', rule, { valid, invalid });
328
329