1 |
|
2 |
|
3 | import assert from 'assert';
|
4 | import path from 'path';
|
5 | import tempy from 'tempy';
|
6 | import {inputFS as fs} from '@parcel/test-utils';
|
7 | import {DEFAULT_OPTIONS} from './utils';
|
8 |
|
9 | import TargetResolver from '../src/TargetResolver';
|
10 |
|
11 | const COMMON_TARGETS_FIXTURE_PATH = path.join(
|
12 | __dirname,
|
13 | 'fixtures/common-targets'
|
14 | );
|
15 |
|
16 | const CUSTOM_TARGETS_FIXTURE_PATH = path.join(
|
17 | __dirname,
|
18 | 'fixtures/custom-targets'
|
19 | );
|
20 |
|
21 | const INVALID_TARGETS_FIXTURE_PATH = path.join(
|
22 | __dirname,
|
23 | 'fixtures/invalid-targets'
|
24 | );
|
25 |
|
26 | const INVALID_ENGINES_FIXTURE_PATH = path.join(
|
27 | __dirname,
|
28 | 'fixtures/invalid-engines'
|
29 | );
|
30 |
|
31 | const INVALID_DISTPATH_FIXTURE_PATH = path.join(
|
32 | __dirname,
|
33 | 'fixtures/invalid-distpath'
|
34 | );
|
35 |
|
36 | const CONTEXT_FIXTURE_PATH = path.join(__dirname, 'fixtures/context');
|
37 |
|
38 | describe('TargetResolver', () => {
|
39 | let cacheDir;
|
40 | beforeEach(() => {
|
41 | cacheDir = tempy.directory();
|
42 | });
|
43 |
|
44 | afterEach(() => {
|
45 | return fs.rimraf(cacheDir);
|
46 | });
|
47 |
|
48 | it('resolves exactly specified targets', async () => {
|
49 | let targetResolver = new TargetResolver({
|
50 | ...DEFAULT_OPTIONS,
|
51 | targets: {
|
52 | customA: {
|
53 | context: 'browser',
|
54 | distDir: 'customA'
|
55 | },
|
56 | customB: {
|
57 | distDir: 'customB',
|
58 | engines: {
|
59 | node: '>= 8.0.0'
|
60 | }
|
61 | }
|
62 | }
|
63 | });
|
64 |
|
65 | assert.deepEqual(
|
66 | await targetResolver.resolve(COMMON_TARGETS_FIXTURE_PATH),
|
67 | {
|
68 | files: [],
|
69 | targets: [
|
70 | {
|
71 | name: 'customA',
|
72 | publicUrl: undefined,
|
73 | distDir: path.resolve('customA'),
|
74 | env: {
|
75 | context: 'browser',
|
76 | includeNodeModules: true,
|
77 | engines: {
|
78 | browsers: ['> 0.25%']
|
79 | },
|
80 | outputFormat: 'global',
|
81 | isLibrary: false
|
82 | },
|
83 | sourceMap: undefined
|
84 | },
|
85 | {
|
86 | name: 'customB',
|
87 | publicUrl: undefined,
|
88 | distDir: path.resolve('customB'),
|
89 | env: {
|
90 | context: 'node',
|
91 | includeNodeModules: false,
|
92 | engines: {
|
93 | node: '>= 8.0.0'
|
94 | },
|
95 | outputFormat: 'commonjs',
|
96 | isLibrary: false
|
97 | },
|
98 | sourceMap: undefined
|
99 | }
|
100 | ]
|
101 | }
|
102 | );
|
103 | });
|
104 |
|
105 | it('resolves common targets from package.json', async () => {
|
106 | let targetResolver = new TargetResolver(DEFAULT_OPTIONS);
|
107 |
|
108 | assert.deepEqual(
|
109 | await targetResolver.resolve(COMMON_TARGETS_FIXTURE_PATH),
|
110 | {
|
111 | files: [
|
112 | {filePath: path.join(COMMON_TARGETS_FIXTURE_PATH, 'package.json')}
|
113 | ],
|
114 | targets: [
|
115 | {
|
116 | name: 'main',
|
117 | distDir: path.join(__dirname, 'fixtures/common-targets/dist/main'),
|
118 | distEntry: 'index.js',
|
119 | publicUrl: '/',
|
120 | env: {
|
121 | context: 'node',
|
122 | engines: {
|
123 | node: '>= 8.0.0'
|
124 | },
|
125 | includeNodeModules: false,
|
126 | outputFormat: 'commonjs',
|
127 | isLibrary: true
|
128 | },
|
129 | sourceMap: undefined
|
130 | },
|
131 | {
|
132 | name: 'module',
|
133 | distDir: path.join(
|
134 | __dirname,
|
135 | 'fixtures/common-targets/dist/module'
|
136 | ),
|
137 | distEntry: 'index.js',
|
138 | publicUrl: '/',
|
139 | env: {
|
140 | context: 'browser',
|
141 | engines: {
|
142 | browsers: ['last 1 version']
|
143 | },
|
144 | includeNodeModules: false,
|
145 | outputFormat: 'esmodule',
|
146 | isLibrary: true
|
147 | },
|
148 | sourceMap: {
|
149 | inlineSources: true
|
150 | }
|
151 | },
|
152 | {
|
153 | name: 'browser',
|
154 | distDir: path.join(
|
155 | __dirname,
|
156 | 'fixtures/common-targets/dist/browser'
|
157 | ),
|
158 | distEntry: 'index.js',
|
159 | publicUrl: '/assets',
|
160 | env: {
|
161 | context: 'browser',
|
162 | engines: {
|
163 | browsers: ['last 1 version']
|
164 | },
|
165 | includeNodeModules: false,
|
166 | outputFormat: 'commonjs',
|
167 | isLibrary: true
|
168 | },
|
169 | sourceMap: undefined
|
170 | }
|
171 | ]
|
172 | }
|
173 | );
|
174 | });
|
175 |
|
176 | it('resolves custom targets from package.json', async () => {
|
177 | let targetResolver = new TargetResolver(DEFAULT_OPTIONS);
|
178 | assert.deepEqual(
|
179 | await targetResolver.resolve(CUSTOM_TARGETS_FIXTURE_PATH),
|
180 | {
|
181 | files: [
|
182 | {filePath: path.join(CUSTOM_TARGETS_FIXTURE_PATH, 'package.json')}
|
183 | ],
|
184 | targets: [
|
185 | {
|
186 | name: 'main',
|
187 | distDir: path.join(__dirname, 'fixtures/custom-targets/dist/main'),
|
188 | distEntry: 'index.js',
|
189 | publicUrl: '/',
|
190 | env: {
|
191 | context: 'node',
|
192 | engines: {
|
193 | node: '>= 8.0.0'
|
194 | },
|
195 | includeNodeModules: false,
|
196 | outputFormat: 'commonjs',
|
197 | isLibrary: true
|
198 | },
|
199 | sourceMap: undefined
|
200 | },
|
201 | {
|
202 | name: 'browserModern',
|
203 | distDir: path.join(
|
204 | __dirname,
|
205 | 'fixtures/custom-targets/dist/browserModern'
|
206 | ),
|
207 | distEntry: 'index.js',
|
208 | publicUrl: '/',
|
209 | env: {
|
210 | context: 'browser',
|
211 | engines: {
|
212 | browsers: ['last 1 version']
|
213 | },
|
214 | includeNodeModules: true,
|
215 | outputFormat: 'global',
|
216 | isLibrary: false
|
217 | },
|
218 | sourceMap: undefined
|
219 | },
|
220 | {
|
221 | name: 'browserLegacy',
|
222 | distDir: path.join(
|
223 | __dirname,
|
224 | 'fixtures/custom-targets/dist/browserLegacy'
|
225 | ),
|
226 | distEntry: 'index.js',
|
227 | publicUrl: '/',
|
228 | env: {
|
229 | context: 'browser',
|
230 | engines: {
|
231 | browsers: ['ie11']
|
232 | },
|
233 | includeNodeModules: true,
|
234 | outputFormat: 'global',
|
235 | isLibrary: false
|
236 | },
|
237 | sourceMap: undefined
|
238 | }
|
239 | ]
|
240 | }
|
241 | );
|
242 | });
|
243 |
|
244 | it('resolves main target with context from package.json', async () => {
|
245 | let targetResolver = new TargetResolver(DEFAULT_OPTIONS);
|
246 | assert.deepEqual(await targetResolver.resolve(CONTEXT_FIXTURE_PATH), {
|
247 | files: [{filePath: path.join(CONTEXT_FIXTURE_PATH, 'package.json')}],
|
248 | targets: [
|
249 | {
|
250 | name: 'main',
|
251 | distDir: path.join(__dirname, 'fixtures/context/dist/main'),
|
252 | distEntry: 'index.js',
|
253 | publicUrl: '/',
|
254 | env: {
|
255 | context: 'node',
|
256 | engines: {
|
257 | browsers: [
|
258 | 'last 1 Chrome version',
|
259 | 'last 1 Safari version',
|
260 | 'last 1 Firefox version',
|
261 | 'last 1 Edge version'
|
262 | ]
|
263 | },
|
264 | includeNodeModules: false,
|
265 | isLibrary: true,
|
266 | outputFormat: 'commonjs'
|
267 | },
|
268 | sourceMap: undefined
|
269 | }
|
270 | ]
|
271 | });
|
272 | });
|
273 |
|
274 | it('resolves a subset of package.json targets when given a list of names', async () => {
|
275 | let targetResolver = new TargetResolver({
|
276 | ...DEFAULT_OPTIONS,
|
277 | targets: ['main', 'browser']
|
278 | });
|
279 |
|
280 | assert.deepEqual(
|
281 | await targetResolver.resolve(COMMON_TARGETS_FIXTURE_PATH),
|
282 | {
|
283 | files: [
|
284 | {filePath: path.join(COMMON_TARGETS_FIXTURE_PATH, 'package.json')}
|
285 | ],
|
286 | targets: [
|
287 | {
|
288 | name: 'main',
|
289 | distDir: path.join(__dirname, 'fixtures/common-targets/dist/main'),
|
290 | distEntry: 'index.js',
|
291 | publicUrl: '/',
|
292 | env: {
|
293 | context: 'node',
|
294 | engines: {
|
295 | node: '>= 8.0.0'
|
296 | },
|
297 | includeNodeModules: false,
|
298 | outputFormat: 'commonjs',
|
299 | isLibrary: true
|
300 | },
|
301 | sourceMap: undefined
|
302 | },
|
303 | {
|
304 | name: 'browser',
|
305 | distDir: path.join(
|
306 | __dirname,
|
307 | 'fixtures/common-targets/dist/browser'
|
308 | ),
|
309 | distEntry: 'index.js',
|
310 | publicUrl: '/assets',
|
311 | env: {
|
312 | context: 'browser',
|
313 | engines: {
|
314 | browsers: ['last 1 version']
|
315 | },
|
316 | includeNodeModules: false,
|
317 | outputFormat: 'commonjs',
|
318 | isLibrary: true
|
319 | },
|
320 | sourceMap: undefined
|
321 | }
|
322 | ]
|
323 | }
|
324 | );
|
325 | });
|
326 |
|
327 | it('rejects invalid or unknown fields', async () => {
|
328 | let code =
|
329 | '{\n' +
|
330 | '\t"targets": {\n' +
|
331 | '\t\t"main": {\n' +
|
332 | '\t\t\t"includeNodeModules": [\n' +
|
333 | '\t\t\t\t"react",\n' +
|
334 | '\t\t\t\ttrue\n' +
|
335 | '\t\t\t],\n' +
|
336 | '\t\t\t"context": "nodes",\n' +
|
337 | '\t\t\t"outputFormat": "module",\n' +
|
338 | '\t\t\t"sourceMap": {\n' +
|
339 | '\t\t\t\t"sourceRoot": "asd",\n' +
|
340 | '\t\t\t\t"inline": "false",\n' +
|
341 | '\t\t\t\t"verbose": true\n' +
|
342 | '\t\t\t},\n' +
|
343 | '\t\t\t"engines": {\n' +
|
344 | '\t\t\t\t"node": "12",\n' +
|
345 | '\t\t\t\t"browser": "Chrome 70"\n' +
|
346 | '\t\t\t}\n' +
|
347 | '\t\t}\n' +
|
348 | '\t}\n' +
|
349 | '}';
|
350 | let targetResolver = new TargetResolver({
|
351 | ...DEFAULT_OPTIONS,
|
352 | ...JSON.parse(code)
|
353 | });
|
354 |
|
355 |
|
356 | await assert.rejects(
|
357 | () => targetResolver.resolve(COMMON_TARGETS_FIXTURE_PATH),
|
358 | {
|
359 | message: 'Invalid target descriptor for target "main"',
|
360 | diagnostics: [
|
361 | {
|
362 | message: 'Invalid target descriptor for target "main"',
|
363 | origin: '@parcel/core',
|
364 | filePath: undefined,
|
365 | language: 'json',
|
366 | codeFrame: {
|
367 | code,
|
368 | codeHighlights: [
|
369 | {
|
370 | start: {line: 6, column: 5},
|
371 | end: {line: 6, column: 8},
|
372 | message: 'Expected a wildcard or filepath'
|
373 | },
|
374 | {
|
375 | start: {line: 8, column: 15},
|
376 | end: {line: 8, column: 21},
|
377 | message: 'Did you mean "node"?'
|
378 | },
|
379 | {
|
380 | start: {line: 9, column: 20},
|
381 | end: {line: 9, column: 27},
|
382 | message: 'Did you mean "esmodule"?'
|
383 | },
|
384 | {
|
385 | start: {line: 12, column: 15},
|
386 | end: {line: 12, column: 21},
|
387 | message: 'Expected type boolean'
|
388 | },
|
389 | {
|
390 | start: {line: 13, column: 5},
|
391 | end: {line: 13, column: 13},
|
392 | message: 'Possible values: "inlineSources"'
|
393 | },
|
394 | {
|
395 | start: {line: 17, column: 5},
|
396 | end: {line: 17, column: 13},
|
397 | message: 'Did you mean "browsers"?'
|
398 | }
|
399 | ]
|
400 | }
|
401 | }
|
402 | ]
|
403 | }
|
404 | );
|
405 | });
|
406 |
|
407 | it('rejects invalid or unknown fields in package.json', async () => {
|
408 | let targetResolver = new TargetResolver(DEFAULT_OPTIONS);
|
409 | let code = await fs.readFileSync(
|
410 | path.join(INVALID_TARGETS_FIXTURE_PATH, 'package.json'),
|
411 | 'utf8'
|
412 | );
|
413 |
|
414 | await assert.rejects(
|
415 | () => targetResolver.resolve(INVALID_TARGETS_FIXTURE_PATH),
|
416 | {
|
417 | diagnostics: [
|
418 | {
|
419 | message: 'Invalid target descriptor for target "module"',
|
420 | origin: '@parcel/core',
|
421 | filePath: path.join(INVALID_TARGETS_FIXTURE_PATH, 'package.json'),
|
422 | language: 'json',
|
423 | codeFrame: {
|
424 | code,
|
425 | codeHighlights: [
|
426 | {
|
427 | start: {line: 9, column: 29},
|
428 | end: {line: 9, column: 35},
|
429 | message: 'Expected type boolean'
|
430 | },
|
431 | {
|
432 | start: {line: 11, column: 7},
|
433 | end: {line: 11, column: 17},
|
434 | message: 'Did you mean "publicUrl"?'
|
435 | }
|
436 | ]
|
437 | }
|
438 | }
|
439 | ]
|
440 | }
|
441 | );
|
442 | });
|
443 |
|
444 | it('rejects invalid engines in package.json', async () => {
|
445 | let targetResolver = new TargetResolver(DEFAULT_OPTIONS);
|
446 | let code = await fs.readFileSync(
|
447 | path.join(INVALID_ENGINES_FIXTURE_PATH, 'package.json'),
|
448 | 'utf8'
|
449 | );
|
450 |
|
451 | await assert.rejects(
|
452 | () => targetResolver.resolve(INVALID_ENGINES_FIXTURE_PATH),
|
453 | {
|
454 | diagnostics: [
|
455 | {
|
456 | message: 'Invalid engines in package.json',
|
457 | origin: '@parcel/core',
|
458 | filePath: path.join(INVALID_ENGINES_FIXTURE_PATH, 'package.json'),
|
459 | language: 'json',
|
460 | codeFrame: {
|
461 | code,
|
462 | codeHighlights: [
|
463 | {
|
464 | end: {
|
465 | column: 13,
|
466 | line: 8
|
467 | },
|
468 | message: 'Did you mean "browsers"?',
|
469 | start: {
|
470 | column: 5,
|
471 | line: 8
|
472 | }
|
473 | },
|
474 | {
|
475 | end: {
|
476 | column: 5,
|
477 | line: 7
|
478 | },
|
479 | message: 'Expected type string',
|
480 | start: {
|
481 | column: 13,
|
482 | line: 5
|
483 | }
|
484 | }
|
485 | ]
|
486 | }
|
487 | }
|
488 | ]
|
489 | }
|
490 | );
|
491 | });
|
492 |
|
493 | it('rejects target distpath in package.json', async () => {
|
494 | let targetResolver = new TargetResolver(DEFAULT_OPTIONS);
|
495 | let code = await fs.readFileSync(
|
496 | path.join(INVALID_DISTPATH_FIXTURE_PATH, 'package.json'),
|
497 | 'utf8'
|
498 | );
|
499 |
|
500 | await assert.rejects(
|
501 | () => targetResolver.resolve(INVALID_DISTPATH_FIXTURE_PATH),
|
502 | {
|
503 | diagnostics: [
|
504 | {
|
505 | message: 'Invalid distPath for target "legacy"',
|
506 | origin: '@parcel/core',
|
507 | filePath: path.join(INVALID_DISTPATH_FIXTURE_PATH, 'package.json'),
|
508 | language: 'json',
|
509 | codeFrame: {
|
510 | code,
|
511 | codeHighlights: [
|
512 | {
|
513 | end: {
|
514 | column: 13,
|
515 | line: 2
|
516 | },
|
517 | message: 'Expected type string',
|
518 | start: {
|
519 | column: 13,
|
520 | line: 2
|
521 | }
|
522 | }
|
523 | ]
|
524 | }
|
525 | }
|
526 | ]
|
527 | }
|
528 | );
|
529 | });
|
530 | });
|