@@ -22,109 +22,122 @@ describe('isStatelessComponent', () => {
22
22
( { statement, parse} = require ( '../../../tests/utils' ) ) ;
23
23
} ) ;
24
24
25
- describe ( 'Stateless Function Components with JSX' , ( ) => {
26
- it ( 'accepts simple arrow function components' , ( ) => {
27
- var def = parse (
28
- 'var Foo = () => <div />'
29
- ) . get ( 'body' , 0 ) . get ( 'declarations' , [ 0 ] ) . get ( 'init' ) ;
30
- expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
31
- } ) ;
32
-
33
- it ( 'accepts simple function expressions components' , ( ) => {
34
- var def = parse (
35
- 'let Foo = function() { return <div />; };'
36
- ) . get ( 'body' , 0 ) . get ( 'declarations' , [ 0 ] ) . get ( 'init' ) ;
37
- expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
38
- } ) ;
39
-
40
- it ( 'accepts simple function declaration components' , ( ) => {
41
- var def = parse ( 'function Foo () { return <div /> }' ) . get ( 'body' , 0 ) ;
42
- expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
43
- } ) ;
44
- } ) ;
45
-
46
- describe ( 'Stateless Function Components with React.createElement' , ( ) => {
47
- it ( 'accepts simple arrow function components' , ( ) => {
48
- var def = parse ( `
49
- var AlphaBetters = require('react');
50
- var Foo = () => AlphaBetters.createElement("div", null);
51
- ` ) . get ( 'body' , 1 ) . get ( 'declarations' , [ 0 ] ) . get ( 'init' ) ;
52
-
53
- expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
54
- } ) ;
55
-
56
- it ( 'accepts simple function expressions components' , ( ) => {
57
- var def = parse ( `
25
+ const componentIdentifiers = {
26
+ 'JSX' : '<div />' ,
27
+ 'React.createElement' : 'React.createElement("div", null)' ,
28
+ 'React.cloneElement' : 'React.cloneElement(children, null)' ,
29
+ 'React.Children.only()' : 'React.Children.only(children, null)' ,
30
+ } ;
31
+
32
+ const componentStyle = {
33
+ 'ArrowExpression' : [
34
+ ( name , expr ) => `var ${ name } = () => (${ expr } );` ,
35
+ [ 'declarations' , 0 , 'init' ] ,
36
+ ] ,
37
+ 'ArrowBlock' : [
38
+ ( name , expr ) => `var ${ name } = () => { return (${ expr } ); };` ,
39
+ [ 'declarations' , 0 , 'init' ] ,
40
+ ] ,
41
+ 'FunctionExpression' : [
42
+ ( name , expr ) => `var ${ name } = function () { return (${ expr } ); }` ,
43
+ [ 'declarations' , 0 , 'init' ] ,
44
+ ] ,
45
+ 'FunctionDeclaration' : [
46
+ ( name , expr ) => `function ${ name } () { return (${ expr } ); }` ,
47
+ [ ] ,
48
+ ] ,
49
+ } ;
50
+
51
+ const modifiers = {
52
+ 'default' : ( expr ) => expr ,
53
+ 'conditional consequent' : ( expr ) => `x ? ${ expr } : null` ,
54
+ 'conditional alternate' : ( expr ) => `x ? null : ${ expr } ` ,
55
+ 'OR left' : ( expr ) => `${ expr } || null` ,
56
+ 'AND right' : ( expr ) => `x && ${ expr } ` ,
57
+ } ;
58
+
59
+ const cases = {
60
+ 'no reference' : [
61
+ ( expr , componentFactory ) => `
58
62
var React = require('react');
59
- let Foo = function() { return React.createElement("div", null); };
60
- ` ) . get ( 'body' , 1 ) . get ( 'declarations' , [ 0 ] ) . get ( 'init' ) ;
61
-
62
- expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
63
- } ) ;
64
-
65
- it ( 'accepts simple function declaration components' , ( ) => {
66
- var def = parse ( `
63
+ ${ componentFactory ( 'Foo' , expr ) }
64
+ ` ,
65
+ [ 'body' , 1 ] ,
66
+ ] ,
67
+ 'with Identifier reference' : [
68
+ ( expr , componentFactory ) => `
67
69
var React = require('react');
68
- function Foo () { return React.createElement("div", null); }
69
- ` ) . get ( 'body' , 1 ) ;
70
- expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
71
- } ) ;
72
- } ) ;
73
-
74
- describe ( 'Stateless Function Components with React.cloneElement' , ( ) => {
75
- it ( 'accepts simple arrow function components' , ( ) => {
76
- var def = parse ( `
77
- var AlphaBetters = require('react');
78
- var Foo = ({ children }) => AlphaBetters.cloneElement(children, null);
79
- ` ) . get ( 'body' , 1 ) . get ( 'declarations' , [ 0 ] ) . get ( 'init' ) ;
80
-
81
- expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
82
- } ) ;
83
-
84
- it ( 'accepts simple function expressions components' , ( ) => {
85
- var def = parse ( `
70
+ var jsx = (${ expr } );
71
+ ${ componentFactory ( 'Foo' , 'jsx' ) }
72
+ ` ,
73
+ [ 'body' , 2 ] ,
74
+ ] ,
75
+ } ;
76
+
77
+ Object . keys ( componentStyle ) . forEach ( ( name ) => {
78
+ cases [ `with ${ name } reference` ] = [
79
+ ( expr , componentFactory ) => `
86
80
var React = require('react');
87
- let Foo = function({ children }) { return React.cloneElement(children, null); };
88
- ` ) . get ( 'body' , 1 ) . get ( 'declarations' , [ 0 ] ) . get ( 'init' ) ;
89
-
90
- expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
91
- } ) ;
92
-
93
- it ( 'accepts simple function declaration components' , ( ) => {
94
- var def = parse ( `
95
- var React = require('react');
96
- function Foo ({ children }) { return React.cloneElement(children, null); }
97
- ` ) . get ( 'body' , 1 ) ;
98
- expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
99
- } ) ;
81
+ ${ componentStyle [ name ] [ 0 ] ( 'jsx' , expr ) }
82
+ ${ componentFactory ( 'Foo' , 'jsx()' ) }
83
+ ` ,
84
+ [ 'body' , 2 ] ,
85
+ ]
100
86
} ) ;
101
87
102
- describe ( 'Stateless Function Components with React.Children.only' , ( ) => {
103
- it ( 'accepts simple arrow function components' , ( ) => {
104
- var def = parse ( `
105
- var React = require('react');
106
- var Foo = ({ children }) => React.Children.only(children, null);
107
- ` ) . get ( 'body' , 1 ) . get ( 'declarations' , [ 0 ] ) . get ( 'init' ) ;
108
-
109
- expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
88
+ const negativeModifiers = {
89
+ 'nested ArrowExpression' : ( expr ) => `() => ${ expr } ` ,
90
+ 'nested ArrowBlock' : ( expr ) => `() => { return ${ expr } }` ,
91
+ 'nested FunctionExpression' : ( expr ) => `function () { return ${ expr } }` ,
92
+ } ;
93
+
94
+ Object . keys ( cases ) . forEach ( ( name ) => {
95
+ const [ caseFactory , caseSelector ] = cases [ name ] ;
96
+
97
+ describe ( name , ( ) => {
98
+ Object . keys ( componentIdentifiers ) . forEach ( ( componentIdentifierName ) => {
99
+
100
+ const returnExpr = componentIdentifiers [ componentIdentifierName ] ;
101
+ describe ( componentIdentifierName , ( ) => {
102
+ Object . keys ( componentStyle ) . forEach ( ( componentName ) => {
103
+ const [ componentFactory , componentSelector ] = componentStyle [ componentName ] ;
104
+ describe ( componentName , ( ) => {
105
+
106
+ Object . keys ( modifiers ) . forEach ( ( modifierName ) => {
107
+ const modifierFactory = modifiers [ modifierName ] ;
108
+
109
+ it ( modifierName , ( ) => {
110
+ const code = caseFactory ( modifierFactory ( returnExpr ) , componentFactory ) ;
111
+ const def = parse ( code ) . get ( ...caseSelector , ...componentSelector ) ;
112
+ expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
113
+ } ) ;
114
+ } ) ;
115
+
116
+ Object . keys ( negativeModifiers ) . forEach ( ( modifierName ) => {
117
+ const modifierFactory = negativeModifiers [ modifierName ] ;
118
+
119
+ it ( modifierName , ( ) => {
120
+ const code = caseFactory ( modifierFactory ( returnExpr ) , componentFactory ) ;
121
+ const def = parse ( code ) . get ( ...caseSelector , ...componentSelector ) ;
122
+ expect ( isStatelessComponent ( def ) ) . toBe ( false ) ;
123
+ } ) ;
124
+ } ) ;
125
+ } ) ;
126
+ } ) ;
127
+ } ) ;
128
+ } ) ;
110
129
} ) ;
130
+ } ) ;
111
131
112
- it ( 'accepts simple function expressions components' , ( ) => {
132
+ describe ( 'Stateless Function Components with React.createElement' , ( ) => {
133
+ it ( 'accepts different name than React' , ( ) => {
113
134
var def = parse ( `
114
- var React = require('react');
115
- let Foo = function({ children }) { return React.Children.only(children , null); } ;
135
+ var AlphaBetters = require('react');
136
+ var Foo = () => AlphaBetters.createElement("div" , null);
116
137
` ) . get ( 'body' , 1 ) . get ( 'declarations' , [ 0 ] ) . get ( 'init' ) ;
117
138
118
139
expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
119
140
} ) ;
120
-
121
- it ( 'accepts simple function declaration components' , ( ) => {
122
- var def = parse ( `
123
- var React = require('react');
124
- function Foo ({ children }) { return React.Children.only(children, null); }
125
- ` ) . get ( 'body' , 1 ) ;
126
- expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
127
- } ) ;
128
141
} ) ;
129
142
130
143
describe ( 'Stateless Function Components inside module pattern' , ( ) => {
@@ -190,21 +203,6 @@ describe('isStatelessComponent', () => {
190
203
191
204
expect ( isStatelessComponent ( def ) ) . toBe ( false ) ;
192
205
} ) ;
193
-
194
- it ( 'does not mark containing functions as StatelessComponents' , ( ) => {
195
- var def = parse ( `
196
- var React = require('react');
197
- function Foo (props) {
198
- function Bar() {
199
- return React.createElement("div", props);
200
- }
201
-
202
- return {Bar}
203
- }
204
- ` ) . get ( 'body' , 1 ) ;
205
-
206
- expect ( isStatelessComponent ( def ) ) . toBe ( false ) ;
207
- } ) ;
208
206
} ) ;
209
207
210
208
describe ( 'resolving return values' , ( ) => {
@@ -216,6 +214,18 @@ describe('isStatelessComponent', () => {
216
214
} ) ;
217
215
}
218
216
217
+ it ( 'does not see ifs as separate block' , ( ) => {
218
+ var def = statement ( `
219
+ function Foo (props) {
220
+ if (x) {
221
+ return <div />;
222
+ }
223
+ }
224
+ ` ) ;
225
+
226
+ expect ( isStatelessComponent ( def ) ) . toBe ( true ) ;
227
+ } ) ;
228
+
219
229
test ( 'handles simple resolves' , `
220
230
var React = require('react');
221
231
function Foo (props) {
@@ -282,20 +292,6 @@ describe('isStatelessComponent', () => {
282
292
}
283
293
` ) ;
284
294
285
- test ( 'handles external reference member call expression resolves' , `
286
- var React = require('react');
287
- function Foo (props) {
288
- var member = () => <div />;
289
- var obj = {
290
- deep: {
291
- member: member
292
- }
293
- };
294
-
295
- return obj.deep.member();
296
- }
297
- ` ) ;
298
-
299
295
test ( 'handles all sorts of JavaScript things' , `
300
296
var React = require('react');
301
297
function Foo (props) {
0 commit comments