99
1010'use strict' ;
1111
12+ import { enableSymbolFallbackForWWW } from 'shared/ReactFeatureFlags' ;
13+
1214let React ;
1315let ReactDOM ;
1416let ReactTestUtils ;
@@ -20,16 +22,31 @@ let JSXDEVRuntime;
2022// A lot of these tests are pulled from ReactElement-test because
2123// this api is meant to be backwards compatible.
2224describe ( 'ReactElement.jsx' , ( ) => {
25+ let originalSymbol ;
26+
2327 beforeEach ( ( ) => {
2428 jest . resetModules ( ) ;
2529
30+ if ( enableSymbolFallbackForWWW ) {
31+ // Delete the native Symbol if we have one to ensure we test the
32+ // unpolyfilled environment.
33+ originalSymbol = global . Symbol ;
34+ global . Symbol = undefined ;
35+ }
36+
2637 React = require ( 'react' ) ;
2738 JSXRuntime = require ( 'react/jsx-runtime' ) ;
2839 JSXDEVRuntime = require ( 'react/jsx-dev-runtime' ) ;
2940 ReactDOM = require ( 'react-dom' ) ;
3041 ReactTestUtils = require ( 'react-dom/test-utils' ) ;
3142 } ) ;
3243
44+ afterEach ( ( ) => {
45+ if ( enableSymbolFallbackForWWW ) {
46+ global . Symbol = originalSymbol ;
47+ }
48+ } ) ;
49+
3350 it ( 'allows static methods to be called using the type property' , ( ) => {
3451 class StaticMethodComponentClass extends React . Component {
3552 render ( ) {
@@ -42,6 +59,48 @@ describe('ReactElement.jsx', () => {
4259 expect ( element . type . someStaticMethod ( ) ) . toBe ( 'someReturnValue' ) ;
4360 } ) ;
4461
62+ // @gate enableSymbolFallbackForWWW
63+ it ( 'identifies valid elements' , ( ) => {
64+ class Component extends React . Component {
65+ render ( ) {
66+ return JSXRuntime . jsx ( 'div' , { } ) ;
67+ }
68+ }
69+
70+ expect ( React . isValidElement ( JSXRuntime . jsx ( 'div' , { } ) ) ) . toEqual ( true ) ;
71+ expect ( React . isValidElement ( JSXRuntime . jsx ( Component , { } ) ) ) . toEqual ( true ) ;
72+ expect (
73+ React . isValidElement ( JSXRuntime . jsx ( JSXRuntime . Fragment , { } ) ) ,
74+ ) . toEqual ( true ) ;
75+ if ( __DEV__ ) {
76+ expect ( React . isValidElement ( JSXDEVRuntime . jsxDEV ( 'div' , { } ) ) ) . toEqual (
77+ true ,
78+ ) ;
79+ }
80+
81+ expect ( React . isValidElement ( null ) ) . toEqual ( false ) ;
82+ expect ( React . isValidElement ( true ) ) . toEqual ( false ) ;
83+ expect ( React . isValidElement ( { } ) ) . toEqual ( false ) ;
84+ expect ( React . isValidElement ( 'string' ) ) . toEqual ( false ) ;
85+ if ( ! __EXPERIMENTAL__ ) {
86+ let factory ;
87+ expect ( ( ) => {
88+ factory = React . createFactory ( 'div' ) ;
89+ } ) . toWarnDev (
90+ 'Warning: React.createFactory() is deprecated and will be removed in a ' +
91+ 'future major release. Consider using JSX or use React.createElement() ' +
92+ 'directly instead.' ,
93+ { withoutStack : true } ,
94+ ) ;
95+ expect ( React . isValidElement ( factory ) ) . toEqual ( false ) ;
96+ }
97+ expect ( React . isValidElement ( Component ) ) . toEqual ( false ) ;
98+ expect ( React . isValidElement ( { type : 'div' , props : { } } ) ) . toEqual ( false ) ;
99+
100+ const jsonElement = JSON . stringify ( JSXRuntime . jsx ( 'div' , { } ) ) ;
101+ expect ( React . isValidElement ( JSON . parse ( jsonElement ) ) ) . toBe ( true ) ;
102+ } ) ;
103+
45104 it ( 'is indistinguishable from a plain object' , ( ) => {
46105 const element = JSXRuntime . jsx ( 'div' , { className : 'foo' } ) ;
47106 const object = { } ;
@@ -235,6 +294,7 @@ describe('ReactElement.jsx', () => {
235294 ) ;
236295 } ) ;
237296
297+ // @gate !enableSymbolFallbackForWWW
238298 it ( 'identifies elements, but not JSON, if Symbols are supported' , ( ) => {
239299 class Component extends React . Component {
240300 render ( ) {
@@ -276,6 +336,59 @@ describe('ReactElement.jsx', () => {
276336 expect ( React . isValidElement ( JSON . parse ( jsonElement ) ) ) . toBe ( false ) ;
277337 } ) ;
278338
339+ it ( 'identifies elements, but not JSON, if Symbols are polyfilled' , ( ) => {
340+ // Rudimentary polyfill
341+ // Once all jest engines support Symbols natively we can swap this to test
342+ // WITH native Symbols by default.
343+ const REACT_ELEMENT_TYPE = function ( ) { } ; // fake Symbol
344+ const OTHER_SYMBOL = function ( ) { } ; // another fake Symbol
345+ global . Symbol = function ( name ) {
346+ return OTHER_SYMBOL ;
347+ } ;
348+ global . Symbol . for = function ( key ) {
349+ if ( key === 'react.element' ) {
350+ return REACT_ELEMENT_TYPE ;
351+ }
352+ return OTHER_SYMBOL ;
353+ } ;
354+
355+ jest . resetModules ( ) ;
356+
357+ React = require ( 'react' ) ;
358+ JSXRuntime = require ( 'react/jsx-runtime' ) ;
359+
360+ class Component extends React . Component {
361+ render ( ) {
362+ return JSXRuntime . jsx ( 'div' ) ;
363+ }
364+ }
365+
366+ expect ( React . isValidElement ( JSXRuntime . jsx ( 'div' , { } ) ) ) . toEqual ( true ) ;
367+ expect ( React . isValidElement ( JSXRuntime . jsx ( Component , { } ) ) ) . toEqual ( true ) ;
368+
369+ expect ( React . isValidElement ( null ) ) . toEqual ( false ) ;
370+ expect ( React . isValidElement ( true ) ) . toEqual ( false ) ;
371+ expect ( React . isValidElement ( { } ) ) . toEqual ( false ) ;
372+ expect ( React . isValidElement ( 'string' ) ) . toEqual ( false ) ;
373+ if ( ! __EXPERIMENTAL__ ) {
374+ let factory ;
375+ expect ( ( ) => {
376+ factory = React . createFactory ( 'div' ) ;
377+ } ) . toWarnDev (
378+ 'Warning: React.createFactory() is deprecated and will be removed in a ' +
379+ 'future major release. Consider using JSX or use React.createElement() ' +
380+ 'directly instead.' ,
381+ { withoutStack : true } ,
382+ ) ;
383+ expect ( React . isValidElement ( factory ) ) . toEqual ( false ) ;
384+ }
385+ expect ( React . isValidElement ( Component ) ) . toEqual ( false ) ;
386+ expect ( React . isValidElement ( { type : 'div' , props : { } } ) ) . toEqual ( false ) ;
387+
388+ const jsonElement = JSON . stringify ( JSXRuntime . jsx ( 'div' , { } ) ) ;
389+ expect ( React . isValidElement ( JSON . parse ( jsonElement ) ) ) . toBe ( false ) ;
390+ } ) ;
391+
279392 it ( 'should warn when unkeyed children are passed to jsx' , ( ) => {
280393 const container = document . createElement ( 'div' ) ;
281394
0 commit comments