CSSPropertyOperations-test.js 8.4 KB

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