/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ /* eslint-disable quotes */ 'use strict'; const babel = require('@babel/core'); const codeFrame = require('@babel/code-frame'); const {wrap} = require('jest-snapshot-serializer-raw'); function transform(input, options) { return wrap( babel.transform(input, { configFile: false, plugins: [ '@babel/plugin-syntax-jsx', '@babel/plugin-transform-arrow-functions', ...(options && options.development ? [ '@babel/plugin-transform-react-jsx-source', '@babel/plugin-transform-react-jsx-self', ] : []), [ './packages/babel-plugin-react-jsx', { development: __DEV__, useBuiltIns: true, useCreateElement: true, ...options, }, ], ], }).code ); } describe('transform react to jsx', () => { it('fragment with no children', () => { expect(transform(`var x = <>`)).toMatchSnapshot(); }); it('React.Fragment to set keys and source', () => { expect( transform(`var x =
`, { development: true, }) ).toMatchSnapshot(); }); it('normal fragments not to set key and source', () => { expect( transform(`var x = <>
`, { development: true, }) ).toMatchSnapshot(); }); it('should properly handle comments adjacent to children', () => { expect( transform(` var x = (
{/* A comment at the beginning */} {/* A second comment at the beginning */} {/* A nested comment */} {/* A sandwiched comment */}
{/* A comment at the end */} {/* A second comment at the end */}
); `) ).toMatchSnapshot(); }); it('adds appropriate new lines when using spread attribute', () => { expect(transform(``)).toMatchSnapshot(); }); it('arrow functions', () => { expect( transform(` var foo = function () { return () => ; }; var bar = function () { return () => ; }; `) ).toMatchSnapshot(); }); it('assignment', () => { expect( transform(`var div = `) ).toMatchSnapshot(); }); it('concatenates adjacent string literals', () => { expect( transform(` var x =
foo {"bar"} baz
buz bang
qux {null} quack
`) ).toMatchSnapshot(); }); it('should allow constructor as prop', () => { expect(transform(`;`)).toMatchSnapshot(); }); it('should allow deeper js namespacing', () => { expect( transform(`;`) ).toMatchSnapshot(); }); it('should allow elements as attributes', () => { expect(transform(`
/>`)).toMatchSnapshot(); }); it('should allow js namespacing', () => { expect(transform(`;`)).toMatchSnapshot(); }); it('should allow nested fragments', () => { expect( transform(`
< > <> Hello world <> Goodbye world
`) ).toMatchSnapshot(); }); it('should avoid wrapping in extra parens if not needed', () => { expect( transform(` var x =
; var x =
{props.children}
; var x = {props.children} ; var x = ; `) ).toMatchSnapshot(); }); it('should convert simple tags', () => { expect(transform(`var x =
;`)).toMatchSnapshot(); }); it('should convert simple text', () => { expect(transform(`var x =
text
;`)).toMatchSnapshot(); }); it('should disallow spread children', () => { let _error; const code = `
{...children}
;`; try { transform(code); } catch (error) { _error = error; } expect(_error).toEqual( new SyntaxError( 'undefined: Spread children are not supported in React.' + '\n' + codeFrame.codeFrameColumns( code, {start: {line: 1, column: 6}}, {highlightCode: true} ) ) ); }); it('should escape xhtml jsxattribute', () => { expect( transform(`
;
;
; `) ).toMatchSnapshot(); }); it('should escape xhtml jsxtext', () => { /* eslint-disable no-irregular-whitespace */ expect( transform(`
wow
;
wôw
;
w & w
;
w & w
;
w   w
;
this should not parse as unicode: \u00a0
;
this should parse as nbsp:  
;
this should parse as unicode: {'\u00a0 '}
;
w < w
; `) ).toMatchSnapshot(); /*eslint-enable */ }); it('should handle attributed elements', () => { expect( transform(` var HelloMessage = React.createClass({ render: function() { return
Hello {this.props.name}
; } }); React.render( Sebastian } />, mountNode); `) ).toMatchSnapshot(); }); it('should handle has own property correctly', () => { expect( transform(`testing;`) ).toMatchSnapshot(); }); it('should have correct comma in nested children', () => { expect( transform(` var x =

{foo}
{bar}

; `) ).toMatchSnapshot(); }); it('should insert commas after expressions before whitespace', () => { expect( transform(` var x =
`) ).toMatchSnapshot(); }); it('should not add quotes to identifier names', () => { expect( transform(`var e = ;`) ).toMatchSnapshot(); }); it('should not strip nbsp even couple with other whitespace', () => { expect(transform(`
 
;`)).toMatchSnapshot(); }); it('should not strip tags with a single child of nbsp', () => { expect(transform(`
 
;`)).toMatchSnapshot(); }); it('should properly handle comments between props', () => { expect( transform(` var x = (
); `) ).toMatchSnapshot(); }); it('should quote jsx attributes', () => { expect( transform(``) ).toMatchSnapshot(); }); it('should support xml namespaces if flag', () => { expect( transform('', {throwIfNamespace: false}) ).toMatchSnapshot(); }); it('should throw error namespaces if not flag', () => { let _error; const code = ``; try { transform(code); } catch (error) { _error = error; } expect(_error).toEqual( new SyntaxError( "undefined: Namespace tags are not supported by default. React's " + "JSX doesn't support namespace tags. You can turn on the " + "'throwIfNamespace' flag to bypass this warning." + '\n' + codeFrame.codeFrameColumns( code, {start: {line: 1, column: 2}}, {highlightCode: true} ) ) ); }); it('should transform known hyphenated tags', () => { expect(transform(``)).toMatchSnapshot(); }); it('wraps props in react spread for first spread attributes', () => { expect(transform(``)).toMatchSnapshot(); }); it('wraps props in react spread for last spread attributes', () => { expect(transform(``)).toMatchSnapshot(); }); it('wraps props in react spread for middle spread attributes', () => { expect(transform(``)).toMatchSnapshot(); }); it('useBuiltIns false uses extend instead of Object.assign', () => { expect( transform(``, {useBuiltIns: false}) ).toMatchSnapshot(); }); });