1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @emails react-core
    
  8.  */
    
  9. 
    
  10. 'use strict';
    
  11. 
    
  12. const React = require('react');
    
  13. const ReactDOM = require('react-dom');
    
  14. const ReactDOMServer = require('react-dom/server');
    
  15. 
    
  16. describe('CSSPropertyOperations', () => {
    
  17.   it('should automatically append `px` to relevant styles', () => {
    
  18.     const styles = {
    
  19.       left: 0,
    
  20.       margin: 16,
    
  21.       opacity: 0.5,
    
  22.       padding: '4px',
    
  23.     };
    
  24.     const div = <div style={styles} />;
    
  25.     const html = ReactDOMServer.renderToString(div);
    
  26.     expect(html).toContain('"left:0;margin:16px;opacity:0.5;padding:4px"');
    
  27.   });
    
  28. 
    
  29.   it('should trim values', () => {
    
  30.     const styles = {
    
  31.       left: '16 ',
    
  32.       opacity: 0.5,
    
  33.       right: ' 4 ',
    
  34.     };
    
  35.     const div = <div style={styles} />;
    
  36.     const html = ReactDOMServer.renderToString(div);
    
  37.     expect(html).toContain('"left:16;opacity:0.5;right:4"');
    
  38.   });
    
  39. 
    
  40.   it('should not append `px` to styles that might need a number', () => {
    
  41.     const styles = {
    
  42.       flex: 0,
    
  43.       opacity: 0.5,
    
  44.     };
    
  45.     const div = <div style={styles} />;
    
  46.     const html = ReactDOMServer.renderToString(div);
    
  47.     expect(html).toContain('"flex:0;opacity:0.5"');
    
  48.   });
    
  49. 
    
  50.   it('should create vendor-prefixed markup correctly', () => {
    
  51.     const styles = {
    
  52.       msTransition: 'none',
    
  53.       MozTransition: 'none',
    
  54.     };
    
  55.     const div = <div style={styles} />;
    
  56.     const html = ReactDOMServer.renderToString(div);
    
  57.     expect(html).toContain('"-ms-transition:none;-moz-transition:none"');
    
  58.   });
    
  59. 
    
  60.   it('should not hyphenate custom CSS property', () => {
    
  61.     const styles = {
    
  62.       '--someColor': '#000000',
    
  63.     };
    
  64.     const div = <div style={styles} />;
    
  65.     const html = ReactDOMServer.renderToString(div);
    
  66.     expect(html).toContain('"--someColor:#000000"');
    
  67.   });
    
  68. 
    
  69.   it('should set style attribute when styles exist', () => {
    
  70.     const styles = {
    
  71.       backgroundColor: '#000',
    
  72.       display: 'none',
    
  73.     };
    
  74.     let div = <div style={styles} />;
    
  75.     const root = document.createElement('div');
    
  76.     div = ReactDOM.render(div, root);
    
  77.     expect(/style=".*"/.test(root.innerHTML)).toBe(true);
    
  78.   });
    
  79. 
    
  80.   it('should not set style attribute when no styles exist', () => {
    
  81.     const styles = {
    
  82.       backgroundColor: null,
    
  83.       display: null,
    
  84.     };
    
  85.     const div = <div style={styles} />;
    
  86.     const html = ReactDOMServer.renderToString(div);
    
  87.     expect(/style=/.test(html)).toBe(false);
    
  88.   });
    
  89. 
    
  90.   it('should warn when using hyphenated style names', () => {
    
  91.     class Comp extends React.Component {
    
  92.       static displayName = 'Comp';
    
  93. 
    
  94.       render() {
    
  95.         return <div style={{'background-color': 'crimson'}} />;
    
  96.       }
    
  97.     }
    
  98. 
    
  99.     const root = document.createElement('div');
    
  100. 
    
  101.     expect(() => ReactDOM.render(<Comp />, root)).toErrorDev(
    
  102.       'Warning: Unsupported style property background-color. Did you mean backgroundColor?' +
    
  103.         '\n    in div (at **)' +
    
  104.         '\n    in Comp (at **)',
    
  105.     );
    
  106.   });
    
  107. 
    
  108.   it('should warn when updating hyphenated style names', () => {
    
  109.     class Comp extends React.Component {
    
  110.       static displayName = 'Comp';
    
  111. 
    
  112.       render() {
    
  113.         return <div style={this.props.style} />;
    
  114.       }
    
  115.     }
    
  116. 
    
  117.     const styles = {
    
  118.       '-ms-transform': 'translate3d(0, 0, 0)',
    
  119.       '-webkit-transform': 'translate3d(0, 0, 0)',
    
  120.     };
    
  121.     const root = document.createElement('div');
    
  122.     ReactDOM.render(<Comp />, root);
    
  123. 
    
  124.     expect(() => ReactDOM.render(<Comp style={styles} />, root)).toErrorDev([
    
  125.       'Warning: Unsupported style property -ms-transform. Did you mean msTransform?' +
    
  126.         '\n    in div (at **)' +
    
  127.         '\n    in Comp (at **)',
    
  128.       'Warning: Unsupported style property -webkit-transform. Did you mean WebkitTransform?' +
    
  129.         '\n    in div (at **)' +
    
  130.         '\n    in Comp (at **)',
    
  131.     ]);
    
  132.   });
    
  133. 
    
  134.   it('warns when miscapitalizing vendored style names', () => {
    
  135.     class Comp extends React.Component {
    
  136.       static displayName = 'Comp';
    
  137. 
    
  138.       render() {
    
  139.         return (
    
  140.           <div
    
  141.             style={{
    
  142.               msTransform: 'translate3d(0, 0, 0)',
    
  143.               oTransform: 'translate3d(0, 0, 0)',
    
  144.               webkitTransform: 'translate3d(0, 0, 0)',
    
  145.             }}
    
  146.           />
    
  147.         );
    
  148.       }
    
  149.     }
    
  150. 
    
  151.     const root = document.createElement('div');
    
  152. 
    
  153.     expect(() => ReactDOM.render(<Comp />, root)).toErrorDev([
    
  154.       // msTransform is correct already and shouldn't warn
    
  155.       'Warning: Unsupported vendor-prefixed style property oTransform. ' +
    
  156.         'Did you mean OTransform?' +
    
  157.         '\n    in div (at **)' +
    
  158.         '\n    in Comp (at **)',
    
  159.       'Warning: Unsupported vendor-prefixed style property webkitTransform. ' +
    
  160.         'Did you mean WebkitTransform?' +
    
  161.         '\n    in div (at **)' +
    
  162.         '\n    in Comp (at **)',
    
  163.     ]);
    
  164.   });
    
  165. 
    
  166.   it('should warn about style having a trailing semicolon', () => {
    
  167.     class Comp extends React.Component {
    
  168.       static displayName = 'Comp';
    
  169. 
    
  170.       render() {
    
  171.         return (
    
  172.           <div
    
  173.             style={{
    
  174.               fontFamily: 'Helvetica, arial',
    
  175.               backgroundImage: 'url(foo;bar)',
    
  176.               backgroundColor: 'blue;',
    
  177.               color: 'red;   ',
    
  178.             }}
    
  179.           />
    
  180.         );
    
  181.       }
    
  182.     }
    
  183. 
    
  184.     const root = document.createElement('div');
    
  185. 
    
  186.     expect(() => ReactDOM.render(<Comp />, root)).toErrorDev([
    
  187.       "Warning: Style property values shouldn't contain a semicolon. " +
    
  188.         'Try "backgroundColor: blue" instead.' +
    
  189.         '\n    in div (at **)' +
    
  190.         '\n    in Comp (at **)',
    
  191.       "Warning: Style property values shouldn't contain a semicolon. " +
    
  192.         'Try "color: red" instead.' +
    
  193.         '\n    in div (at **)' +
    
  194.         '\n    in Comp (at **)',
    
  195.     ]);
    
  196.   });
    
  197. 
    
  198.   it('should warn about style containing a NaN value', () => {
    
  199.     class Comp extends React.Component {
    
  200.       static displayName = 'Comp';
    
  201. 
    
  202.       render() {
    
  203.         return <div style={{fontSize: NaN}} />;
    
  204.       }
    
  205.     }
    
  206. 
    
  207.     const root = document.createElement('div');
    
  208. 
    
  209.     expect(() => ReactDOM.render(<Comp />, root)).toErrorDev(
    
  210.       'Warning: `NaN` is an invalid value for the `fontSize` css style property.' +
    
  211.         '\n    in div (at **)' +
    
  212.         '\n    in Comp (at **)',
    
  213.     );
    
  214.   });
    
  215. 
    
  216.   it('should not warn when setting CSS custom properties', () => {
    
  217.     class Comp extends React.Component {
    
  218.       render() {
    
  219.         return <div style={{'--foo-primary': 'red', backgroundColor: 'red'}} />;
    
  220.       }
    
  221.     }
    
  222. 
    
  223.     const root = document.createElement('div');
    
  224.     ReactDOM.render(<Comp />, root);
    
  225.   });
    
  226. 
    
  227.   it('should warn about style containing an Infinity value', () => {
    
  228.     class Comp extends React.Component {
    
  229.       static displayName = 'Comp';
    
  230. 
    
  231.       render() {
    
  232.         return <div style={{fontSize: 1 / 0}} />;
    
  233.       }
    
  234.     }
    
  235. 
    
  236.     const root = document.createElement('div');
    
  237. 
    
  238.     expect(() => ReactDOM.render(<Comp />, root)).toErrorDev(
    
  239.       'Warning: `Infinity` is an invalid value for the `fontSize` css style property.' +
    
  240.         '\n    in div (at **)' +
    
  241.         '\n    in Comp (at **)',
    
  242.     );
    
  243.   });
    
  244. 
    
  245.   it('should not add units to CSS custom properties', () => {
    
  246.     class Comp extends React.Component {
    
  247.       render() {
    
  248.         return <div style={{'--foo': '5'}} />;
    
  249.       }
    
  250.     }
    
  251. 
    
  252.     const root = document.createElement('div');
    
  253.     ReactDOM.render(<Comp />, root);
    
  254. 
    
  255.     expect(root.children[0].style.getPropertyValue('--foo')).toEqual('5');
    
  256.   });
    
  257. });