|
6 | 6 | *
|
7 | 7 | */
|
8 | 8 |
|
9 |
| -import * as utils from '../../../tests/utils'; |
| 9 | +import { |
| 10 | + getParser, |
| 11 | + parse as parseSource, |
| 12 | + statement, |
| 13 | + noopImporter, |
| 14 | + makeMockImporter, |
| 15 | +} from '../../../tests/utils'; |
10 | 16 | import findExportedComponentDefinition from '../findExportedComponentDefinition';
|
11 | 17 |
|
12 | 18 | describe('findExportedComponentDefinition', () => {
|
13 |
| - function parse(source, importer = utils.noopImporter) { |
| 19 | + function parse(source, importer = noopImporter) { |
14 | 20 | return findExportedComponentDefinition(
|
15 |
| - utils.parse(source), |
16 |
| - utils.getParser(), |
| 21 | + parseSource(source), |
| 22 | + getParser(), |
17 | 23 | importer,
|
18 | 24 | );
|
19 | 25 | }
|
20 | 26 |
|
| 27 | + const mockImporter = makeMockImporter({ |
| 28 | + createClass: statement(` |
| 29 | + export default React.createClass({}); |
| 30 | + import React from 'react'; |
| 31 | + `).get('declaration'), |
| 32 | + |
| 33 | + classDec: statement(` |
| 34 | + export default class Component extends React.Component {}; |
| 35 | + import React from 'react'; |
| 36 | + `).get('declaration'), |
| 37 | + |
| 38 | + classExpr: statement(` |
| 39 | + export default Component; |
| 40 | + var Component = class extends React.Component {}; |
| 41 | + import React from 'react'; |
| 42 | + `).get('declaration'), |
| 43 | + |
| 44 | + statelessJsx: statement(` |
| 45 | + export default () => <div />; |
| 46 | + `).get('declaration'), |
| 47 | + |
| 48 | + statelessCreateElement: statement(` |
| 49 | + export default () => React.createElement('div', {}); |
| 50 | + import React from 'react'; |
| 51 | + `).get('declaration'), |
| 52 | + |
| 53 | + forwardRef: statement(` |
| 54 | + export default React.forwardRef((props, ref) => ( |
| 55 | + <div ref={ref} style={{backgroundColor: props.color}} /> |
| 56 | + )); |
| 57 | + import React from 'react'; |
| 58 | + `).get('declaration'), |
| 59 | + }); |
| 60 | + |
21 | 61 | describe('CommonJS module exports', () => {
|
22 | 62 | describe('React.createClass', () => {
|
23 | 63 | it('finds React.createClass', () => {
|
@@ -95,6 +135,15 @@ describe('findExportedComponentDefinition', () => {
|
95 | 135 |
|
96 | 136 | expect(parse(source)).toBeUndefined();
|
97 | 137 | });
|
| 138 | + |
| 139 | + it('resolves an imported variable to React.createClass', () => { |
| 140 | + const source = ` |
| 141 | + import Component from 'createClass'; |
| 142 | + module.exports = Component; |
| 143 | + `; |
| 144 | + |
| 145 | + expect(parse(source, mockImporter)).toBeDefined(); |
| 146 | + }); |
98 | 147 | });
|
99 | 148 |
|
100 | 149 | describe('class definitions', () => {
|
@@ -133,6 +182,28 @@ describe('findExportedComponentDefinition', () => {
|
133 | 182 | expect(result).toBeDefined();
|
134 | 183 | expect(result.node.type).toBe('ClassDeclaration');
|
135 | 184 | });
|
| 185 | + |
| 186 | + it('resolves an imported variable to class declaration', () => { |
| 187 | + const source = ` |
| 188 | + import Component from 'classDec'; |
| 189 | + module.exports = Component; |
| 190 | + `; |
| 191 | + |
| 192 | + const result = parse(source, mockImporter); |
| 193 | + expect(result).toBeDefined(); |
| 194 | + expect(result.node.type).toBe('ClassDeclaration'); |
| 195 | + }); |
| 196 | + |
| 197 | + it('resolves an imported variable to class expression', () => { |
| 198 | + const source = ` |
| 199 | + import Component from 'classExpr'; |
| 200 | + module.exports = Component; |
| 201 | + `; |
| 202 | + |
| 203 | + const result = parse(source, mockImporter); |
| 204 | + expect(result).toBeDefined(); |
| 205 | + expect(result.node.type).toBe('ClassExpression'); |
| 206 | + }); |
136 | 207 | });
|
137 | 208 |
|
138 | 209 | describe('stateless components', () => {
|
@@ -165,6 +236,24 @@ describe('findExportedComponentDefinition', () => {
|
165 | 236 |
|
166 | 237 | expect(parse(source)).toBeUndefined();
|
167 | 238 | });
|
| 239 | + |
| 240 | + it('resolves an imported stateless component with JSX', () => { |
| 241 | + const source = ` |
| 242 | + import Component from 'statelessJsx'; |
| 243 | + module.exports = Component; |
| 244 | + `; |
| 245 | + |
| 246 | + expect(parse(source, mockImporter)).toBeDefined(); |
| 247 | + }); |
| 248 | + |
| 249 | + it('resolves an imported stateless component with React.createElement', () => { |
| 250 | + const source = ` |
| 251 | + import Component from 'statelessCreateElement'; |
| 252 | + module.exports = Component; |
| 253 | + `; |
| 254 | + |
| 255 | + expect(parse(source, mockImporter)).toBeDefined(); |
| 256 | + }); |
168 | 257 | });
|
169 | 258 |
|
170 | 259 | describe('module.exports = <C>; / exports.foo = <C>;', () => {
|
@@ -211,6 +300,15 @@ describe('findExportedComponentDefinition', () => {
|
211 | 300 |
|
212 | 301 | expect(parse(source)).toBeDefined();
|
213 | 302 | });
|
| 303 | + |
| 304 | + it('supports imported components', () => { |
| 305 | + const source = ` |
| 306 | + import Component from 'createClass'; |
| 307 | + exports.ComponentB = Component; |
| 308 | + `; |
| 309 | + |
| 310 | + expect(parse(source, mockImporter)).toBeDefined(); |
| 311 | + }); |
214 | 312 | });
|
215 | 313 |
|
216 | 314 | describe('class definition', () => {
|
@@ -262,6 +360,17 @@ describe('findExportedComponentDefinition', () => {
|
262 | 360 | expect(result).toBeDefined();
|
263 | 361 | expect(result.node.type).toBe('ClassDeclaration');
|
264 | 362 | });
|
| 363 | + |
| 364 | + it('supports imported components', () => { |
| 365 | + const source = ` |
| 366 | + import Component from 'classDec'; |
| 367 | + exports.ComponentB = Component; |
| 368 | + `; |
| 369 | + |
| 370 | + const result = parse(source, mockImporter); |
| 371 | + expect(result).toBeDefined(); |
| 372 | + expect(result.node.type).toBe('ClassDeclaration'); |
| 373 | + }); |
265 | 374 | });
|
266 | 375 | });
|
267 | 376 | });
|
@@ -312,6 +421,15 @@ describe('findExportedComponentDefinition', () => {
|
312 | 421 |
|
313 | 422 | expect(parse(source)).toBeDefined();
|
314 | 423 | });
|
| 424 | + |
| 425 | + it('supports imported components', () => { |
| 426 | + const source = ` |
| 427 | + import Component from 'createClass'; |
| 428 | + export default Component; |
| 429 | + `; |
| 430 | + |
| 431 | + expect(parse(source, mockImporter)).toBeDefined(); |
| 432 | + }); |
315 | 433 | });
|
316 | 434 |
|
317 | 435 | describe('class definition', () => {
|
@@ -402,6 +520,17 @@ describe('findExportedComponentDefinition', () => {
|
402 | 520 | expect(result).toBeDefined();
|
403 | 521 | expect(result.node.type).toBe('ClassDeclaration');
|
404 | 522 | });
|
| 523 | + |
| 524 | + it('supports imported components', () => { |
| 525 | + const source = ` |
| 526 | + import Component from 'classDec'; |
| 527 | + export default Component; |
| 528 | + `; |
| 529 | + |
| 530 | + const result = parse(source, mockImporter); |
| 531 | + expect(result).toBeDefined(); |
| 532 | + expect(result.node.type).toBe('ClassDeclaration'); |
| 533 | + }); |
405 | 534 | });
|
406 | 535 | });
|
407 | 536 |
|
@@ -464,6 +593,15 @@ describe('findExportedComponentDefinition', () => {
|
464 | 593 |
|
465 | 594 | expect(parse(source)).toBeDefined();
|
466 | 595 | });
|
| 596 | + |
| 597 | + it('supports imported components', () => { |
| 598 | + const source = ` |
| 599 | + import Component from 'createClass'; |
| 600 | + export let ComponentB = Component; |
| 601 | + `; |
| 602 | + |
| 603 | + expect(parse(source, mockImporter)).toBeDefined(); |
| 604 | + }); |
467 | 605 | });
|
468 | 606 |
|
469 | 607 | describe('class definition', () => {
|
@@ -533,6 +671,17 @@ describe('findExportedComponentDefinition', () => {
|
533 | 671 | expect(result).toBeDefined();
|
534 | 672 | expect(result.node.type).toBe('ClassExpression');
|
535 | 673 | });
|
| 674 | + |
| 675 | + it('supports imported components', () => { |
| 676 | + const source = ` |
| 677 | + import Component from 'classDec'; |
| 678 | + export let ComponentB = Component; |
| 679 | + `; |
| 680 | + |
| 681 | + const result = parse(source, mockImporter); |
| 682 | + expect(result).toBeDefined(); |
| 683 | + expect(result.node.type).toBe('ClassDeclaration'); |
| 684 | + }); |
536 | 685 | });
|
537 | 686 |
|
538 | 687 | describe('stateless components', () => {
|
@@ -602,6 +751,26 @@ describe('findExportedComponentDefinition', () => {
|
602 | 751 | expect(result).toBeDefined();
|
603 | 752 | expect(result.node.type).toBe('FunctionExpression');
|
604 | 753 | });
|
| 754 | + |
| 755 | + it('supports imported components', () => { |
| 756 | + let source = ` |
| 757 | + import Component from 'statelessJsx'; |
| 758 | + export var ComponentA = Component; |
| 759 | + `; |
| 760 | + |
| 761 | + let result = parse(source, mockImporter); |
| 762 | + expect(result).toBeDefined(); |
| 763 | + expect(result.node.type).toBe('ArrowFunctionExpression'); |
| 764 | + |
| 765 | + source = ` |
| 766 | + import Component from 'statelessCreateElement'; |
| 767 | + export var ComponentB = Component; |
| 768 | + `; |
| 769 | + |
| 770 | + result = parse(source, mockImporter); |
| 771 | + expect(result).toBeDefined(); |
| 772 | + expect(result.node.type).toBe('ArrowFunctionExpression'); |
| 773 | + }); |
605 | 774 | });
|
606 | 775 | });
|
607 | 776 |
|
@@ -655,6 +824,15 @@ describe('findExportedComponentDefinition', () => {
|
655 | 824 |
|
656 | 825 | expect(parse(source)).toBeDefined();
|
657 | 826 | });
|
| 827 | + |
| 828 | + it('supports imported components', () => { |
| 829 | + const source = ` |
| 830 | + import Component from 'createClass'; |
| 831 | + export { Component }; |
| 832 | + `; |
| 833 | + |
| 834 | + expect(parse(source, mockImporter)).toBeDefined(); |
| 835 | + }); |
658 | 836 | });
|
659 | 837 |
|
660 | 838 | describe('class definition', () => {
|
@@ -713,6 +891,17 @@ describe('findExportedComponentDefinition', () => {
|
713 | 891 | expect(result).toBeDefined();
|
714 | 892 | expect(result.node.type).toBe('ClassExpression');
|
715 | 893 | });
|
| 894 | + |
| 895 | + it('supports imported components', () => { |
| 896 | + const source = ` |
| 897 | + import Component from 'classDec'; |
| 898 | + export { Component }; |
| 899 | + `; |
| 900 | + |
| 901 | + const result = parse(source, mockImporter); |
| 902 | + expect(result).toBeDefined(); |
| 903 | + expect(result.node.type).toBe('ClassDeclaration'); |
| 904 | + }); |
716 | 905 | });
|
717 | 906 |
|
718 | 907 | describe('stateless components', () => {
|
@@ -771,6 +960,26 @@ describe('findExportedComponentDefinition', () => {
|
771 | 960 | expect(result).toBeDefined();
|
772 | 961 | expect(result.node.type).toBe('ArrowFunctionExpression');
|
773 | 962 | });
|
| 963 | + |
| 964 | + it('supports imported components', () => { |
| 965 | + let source = ` |
| 966 | + import Component from 'statelessJsx'; |
| 967 | + export { Component as ComponentA }; |
| 968 | + `; |
| 969 | + |
| 970 | + let result = parse(source, mockImporter); |
| 971 | + expect(result).toBeDefined(); |
| 972 | + expect(result.node.type).toBe('ArrowFunctionExpression'); |
| 973 | + |
| 974 | + source = ` |
| 975 | + import Component from 'statelessCreateElement'; |
| 976 | + export { Component as ComponentB }; |
| 977 | + `; |
| 978 | + |
| 979 | + result = parse(source, mockImporter); |
| 980 | + expect(result).toBeDefined(); |
| 981 | + expect(result.node.type).toBe('ArrowFunctionExpression'); |
| 982 | + }); |
774 | 983 | });
|
775 | 984 | });
|
776 | 985 |
|
|
0 commit comments