From af1af19d395ee23f1947eadf57eccf5500db71ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Thu, 19 Jun 2014 15:14:54 -0400 Subject: [PATCH] Sync out transform tests --- .../transforms/__tests__/react-test.js | 360 ++++++++++++++++++ .../__tests__/reactDisplayName-test.js | 150 ++++++++ 2 files changed, 510 insertions(+) create mode 100644 vendor/fbtransform/transforms/__tests__/react-test.js create mode 100644 vendor/fbtransform/transforms/__tests__/reactDisplayName-test.js diff --git a/vendor/fbtransform/transforms/__tests__/react-test.js b/vendor/fbtransform/transforms/__tests__/react-test.js new file mode 100644 index 0000000000..546db630d7 --- /dev/null +++ b/vendor/fbtransform/transforms/__tests__/react-test.js @@ -0,0 +1,360 @@ +/** + * Copyright 2013-2014 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @emails javascript@lists.facebook.com + */ +"use strict"; + +require('mock-modules').autoMockOff(); + +describe('react jsx', function() { + var transformAll = require('../../syntax.js').transformAll; + + var transform = function(code, options, excludes) { + return transformAll( + code, + options, + (excludes || []).concat(['sourcemeta', 'allocate']) + ); + }; + + it('should convert simple tags', function() { + var code = [ + '/**@jsx React.DOM*/', + 'var x =
;' + ].join('\n'); + var result = [ + '/**@jsx React.DOM*/', + 'var x = React.DOM.div(null);' + ].join('\n'); + + expect(transform(code).code).toEqual(result); + }); + + it('should convert simple text', function() { + var code = [ + '/**@jsx React.DOM*/\n' + + 'var x =
text
;' + ].join('\n'); + var result = [ + '/**@jsx React.DOM*/', + 'var x = React.DOM.div(null, "text");' + ].join('\n'); + + expect(transform(code).code).toEqual(result); + }); + + it('should have correct comma in nested children', function() { + var code = [ + '/**@jsx React.DOM*/', + 'var x =
', + '

', + ' {foo}
{bar}
', + '
', + '
;' + ].join('\n'); + var result = [ + '/**@jsx React.DOM*/', + 'var x = React.DOM.div(null, ', + ' React.DOM.div(null, React.DOM.br(null)), ', + ' Component(null, foo, React.DOM.br(null), bar), ', + ' React.DOM.br(null)', + ');' + ].join('\n'); + + expect(transform(code).code).toEqual(result); + }); + + it('should avoid wrapping in extra parens if not needed', function() { + // Try with a single composite child, wrapped in a div. + var code = [ + '/**@jsx React.DOM*/', + 'var x =
', + ' ', + '
;' + ].join('\n'); + var result = [ + '/**@jsx React.DOM*/', + 'var x = React.DOM.div(null, ', + ' Component(null)', + ');' + ].join('\n'); + + expect(transform(code).code).toEqual(result); + + // Try with a single interpolated child, wrapped in a div. + code = [ + '/**@jsx React.DOM*/', + 'var x =
', + ' {this.props.children}', + '
;' + ].join('\n'); + result = [ + '/**@jsx React.DOM*/', + 'var x = React.DOM.div(null, ', + ' this.props.children', + ');' + ].join('\n'); + expect(transform(code).code).toEqual(result); + + // Try with a single interpolated child, wrapped in a composite. + code = [ + '/**@jsx React.DOM*/', + 'var x = ', + ' {this.props.children}', + ';' + ].join('\n'); + result = [ + '/**@jsx React.DOM*/', + 'var x = Composite(null, ', + ' this.props.children', + ');' + ].join('\n'); + expect(transform(code).code).toEqual(result); + + // Try with a single composite child, wrapped in a composite. + code = [ + '/**@jsx React.DOM*/', + 'var x = ', + ' ', + ';' + ].join('\n'); + result = [ + '/**@jsx React.DOM*/', + 'var x = Composite(null, ', + ' Composite2(null)', + ');' + ].join('\n'); + expect(transform(code).code).toEqual(result); + }); + + it('should insert commas after expressions before whitespace', function() { + var code = [ + '/**@jsx React.DOM*/', + 'var x =', + ' ', + ' ;' + ].join('\n'); + var result = [ + '/**@jsx React.DOM*/', + 'var x =', + ' React.DOM.div({', + ' attr1: ', + ' "foo" + "bar", ', + ' ', + ' attr2: ', + ' "foo" + "bar" +', + ' ', + ' "baz" + "bug", ', + ' ', + ' attr3: ', + ' "foo" + "bar" +', + ' "baz" + "bug", ', + ' // Extra line here.', + ' ', + ' attr4: "baz"}', + ' );' + ].join('\n'); + + expect(transform(code).code).toEqual(result); + }); + + it('should properly handle comments adjacent to children', function() { + var code = [ + '/**', + ' * @jsx React.DOM', + ' */', + '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 */}', + '
', + ');' + ].join('\n'); + var result = [ + '/**', + ' * @jsx React.DOM', + ' */', + 'var x = (', + ' React.DOM.div(null, ', + ' /* A comment at the beginning */', + ' /* A second comment at the beginning */', + ' React.DOM.span(null', + ' /* A nested comment */', + ' ), ', + ' /* A sandwiched comment */', + ' React.DOM.br(null)', + ' /* A comment at the end */', + ' /* A second comment at the end */', + ' )', + ');' + ].join('\n'); + + expect(transform(code).code).toBe(result); + }); + + it('should properly handle comments between props', function() { + var code = [ + '/**', + ' * @jsx React.DOM', + ' */', + 'var x = (', + ' ', + ' ', + ' ', + ');' + ].join('\n'); + var result = [ + '/**', + ' * @jsx React.DOM', + ' */', + 'var x = (', + ' React.DOM.div({', + ' /* a multi-line', + ' comment */', + ' attr1: "foo"}, ', + ' React.DOM.span({// a double-slash comment', + ' attr2: "bar"}', + ' )', + ' )', + ');' + ].join('\n'); + + expect(transform(code).code).toBe(result); + }); + + it('should not strip tags with a single child of  ', function() { + var code = [ + '/**', + ' * @jsx React.DOM', + ' */', + '
 
;' + ].join('\n'); + var result = [ + '/**', + ' * @jsx React.DOM', + ' */', + 'React.DOM.div(null, "\u00A0");' + ].join('\n'); + + expect(transform(code).code).toBe(result); + }); + + it('should not strip   even coupled with other whitespace', function() { + var code = [ + '/**', + ' * @jsx React.DOM', + ' */', + '
 
;' + ].join('\n'); + var result = [ + '/**', + ' * @jsx React.DOM', + ' */', + 'React.DOM.div(null, "\u00A0 ");' + ].join('\n'); + + expect(transform(code).code).toBe(result); + }); + + it('should handle hasOwnProperty correctly', function() { + var code = [ + '/**', + ' * @jsx React.DOM', + ' */', + 'testing;' + ].join('\n'); + var result = [ + '/**', + ' * @jsx React.DOM', + ' */', + 'hasOwnProperty(null, "testing");' + ].join('\n'); + + expect(transform(code).code).toBe(result); + }); + + it('should allow constructor as prop', function() { + var code = [ + '/**', + ' * @jsx React.DOM', + ' */', + ';' + ].join('\n'); + var result = [ + '/**', + ' * @jsx React.DOM', + ' */', + 'Component({constructor: "foo"});' + ].join('\n'); + + expect(transform(code).code).toBe(result); + }); + + it('should allow JS namespacing', function() { + var code = [ + '/**', + ' * @jsx React.DOM', + ' */', + ';' + ].join('\n'); + var result = [ + '/**', + ' * @jsx React.DOM', + ' */', + 'Namespace.Component(null);' + ].join('\n'); + + expect(transform(code).code).toBe(result); + }); + + it('should disallow XML namespacing', function() { + var code = [ + '/**', + ' * @jsx React.DOM', + ' */', + ';' + ].join('\n'); + + expect(() => transform(code)).toThrow(); + }); + +}); diff --git a/vendor/fbtransform/transforms/__tests__/reactDisplayName-test.js b/vendor/fbtransform/transforms/__tests__/reactDisplayName-test.js new file mode 100644 index 0000000000..f833f268e8 --- /dev/null +++ b/vendor/fbtransform/transforms/__tests__/reactDisplayName-test.js @@ -0,0 +1,150 @@ +/** + * Copyright 2013-2014 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @emails javascript@lists.facebook.com + */ +"use strict"; + +require('mock-modules').autoMockOff(); + +var transformAll = require('../../syntax.js').transformAll; + +function transform(source) { + return transformAll(source, {}, ['allocate']); +} + +describe('react displayName jsx', function() { + + it('should only inject displayName if missing', function() { + var code = [ + '/** @jsx React.DOM */', + '"use strict";', + 'var Whateva = React.createClass({', + ' displayName: \'Whateva\',', + ' render: function() {', + ' return
...whateva.
;', + ' }', + '});' + ].join('\n'); + + var result = [ + '/** @jsx React.DOM */', + '"use strict";', + 'var Whateva = React.createClass({', + ' displayName: \'Whateva\',', + ' render: function() {', + ' return React.DOM.div({className: "whateva"}, "...whateva.");', + ' }', + '});' + ].join('\n'); + + expect(transform(code).code).toEqual(result); + }); + + it('should inject displayName in simple assignment', () => { + var code = [ + '/** @jsx React.DOM */', + 'var Component = React.createClass({', + ' render: function() {', + ' return
;', + ' }', + '});' + ].join('\n'); + + var result = [ + '/** @jsx React.DOM */', + 'var Component = React.createClass({displayName: \'Component\',', + ' render: function() {', + ' return React.DOM.div(null);', + ' }', + '});' + ].join('\n'); + + expect(transform(code).code).toEqual(result); + }); + + it('should inject displayName in simple assignment without var', () => { + var code = [ + '/** @jsx React.DOM */', + 'var Component;', + 'Component = React.createClass({', + ' render: function() {', + ' return
;', + ' }', + '});' + ].join('\n'); + + var result = [ + '/** @jsx React.DOM */', + 'var Component;', + 'Component = React.createClass({displayName: \'Component\',', + ' render: function() {', + ' return React.DOM.div(null);', + ' }', + '});' + ].join('\n'); + + expect(transform(code).code).toEqual(result); + }); + + it('should inject displayName in property assignment', () => { + var code = [ + '/** @jsx React.DOM */', + 'exports.Component = React.createClass({', + ' render: function() {', + ' return
;', + ' }', + '});' + ].join('\n'); + + var result = [ + '/** @jsx React.DOM */', + 'exports.Component = React.createClass({displayName: \'Component\',', + ' render: function() {', + ' return React.DOM.div(null);', + ' }', + '});' + ].join('\n'); + + expect(transform(code).code).toEqual(result); + }); + + it('should inject displayName in object declaration', () => { + var code = [ + '/** @jsx React.DOM */', + 'exports = {', + ' Component: React.createClass({', + ' render: function() {', + ' return
;', + ' }', + ' })', + '};' + ].join('\n'); + + var result = [ + '/** @jsx React.DOM */', + 'exports = {', + ' Component: React.createClass({displayName: \'Component\',', + ' render: function() {', + ' return React.DOM.div(null);', + ' }', + ' })', + '};' + ].join('\n'); + + expect(transform(code).code).toEqual(result); + }); + +});