parseObjectStyles.test.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. import parseObjectStyles from '../src/util/parseObjectStyles'
  2. import postcss from 'postcss'
  3. import { css } from './util/run'
  4. function toCss(nodes) {
  5. return postcss.root({ nodes }).toString()
  6. }
  7. test('it parses simple single class definitions', () => {
  8. let result = parseObjectStyles({
  9. '.foobar': {
  10. backgroundColor: 'red',
  11. color: 'white',
  12. padding: '1rem',
  13. },
  14. })
  15. expect(toCss(result)).toMatchFormattedCss(css`
  16. .foobar {
  17. background-color: red;
  18. color: white;
  19. padding: 1rem;
  20. }
  21. `)
  22. })
  23. test('it parses multiple class definitions', () => {
  24. let result = parseObjectStyles({
  25. '.foo': {
  26. backgroundColor: 'red',
  27. color: 'white',
  28. padding: '1rem',
  29. },
  30. '.bar': {
  31. width: '200px',
  32. height: '100px',
  33. },
  34. })
  35. expect(toCss(result)).toMatchFormattedCss(css`
  36. .foo {
  37. background-color: red;
  38. color: white;
  39. padding: 1rem;
  40. }
  41. .bar {
  42. width: 200px;
  43. height: 100px;
  44. }
  45. `)
  46. })
  47. test('it parses nested pseudo-selectors', () => {
  48. let result = parseObjectStyles({
  49. '.foo': {
  50. backgroundColor: 'red',
  51. color: 'white',
  52. padding: '1rem',
  53. '&:hover': {
  54. backgroundColor: 'orange',
  55. },
  56. '&:focus': {
  57. backgroundColor: 'blue',
  58. },
  59. },
  60. })
  61. expect(toCss(result)).toMatchFormattedCss(css`
  62. .foo {
  63. background-color: red;
  64. color: white;
  65. padding: 1rem;
  66. }
  67. .foo:hover {
  68. background-color: orange;
  69. }
  70. .foo:focus {
  71. background-color: blue;
  72. }
  73. `)
  74. })
  75. test('it parses top-level media queries', () => {
  76. let result = parseObjectStyles({
  77. '@media (min-width: 200px)': {
  78. '.foo': {
  79. backgroundColor: 'orange',
  80. },
  81. },
  82. })
  83. expect(toCss(result)).toMatchFormattedCss(css`
  84. @media (min-width: 200px) {
  85. .foo {
  86. background-color: orange;
  87. }
  88. }
  89. `)
  90. })
  91. test('it parses nested media queries', () => {
  92. let result = parseObjectStyles({
  93. '.foo': {
  94. backgroundColor: 'red',
  95. color: 'white',
  96. padding: '1rem',
  97. '@media (min-width: 200px)': {
  98. backgroundColor: 'orange',
  99. },
  100. },
  101. })
  102. expect(toCss(result)).toMatchFormattedCss(css`
  103. .foo {
  104. background-color: red;
  105. color: white;
  106. padding: 1rem;
  107. }
  108. @media (min-width: 200px) {
  109. .foo {
  110. background-color: orange;
  111. }
  112. }
  113. `)
  114. })
  115. test('it bubbles nested screen rules', () => {
  116. let result = parseObjectStyles({
  117. '.foo': {
  118. backgroundColor: 'red',
  119. color: 'white',
  120. padding: '1rem',
  121. '@screen sm': {
  122. backgroundColor: 'orange',
  123. },
  124. },
  125. })
  126. expect(toCss(result)).toMatchFormattedCss(css`
  127. .foo {
  128. background-color: red;
  129. color: white;
  130. padding: 1rem;
  131. }
  132. @screen sm {
  133. .foo {
  134. background-color: orange;
  135. }
  136. }
  137. `)
  138. })
  139. test('it parses pseudo-selectors in nested media queries', () => {
  140. let result = parseObjectStyles({
  141. '.foo': {
  142. backgroundColor: 'red',
  143. color: 'white',
  144. padding: '1rem',
  145. '&:hover': {
  146. '@media (min-width: 200px)': {
  147. backgroundColor: 'orange',
  148. },
  149. },
  150. },
  151. })
  152. expect(toCss(result)).toMatchFormattedCss(css`
  153. .foo {
  154. background-color: red;
  155. color: white;
  156. padding: 1rem;
  157. }
  158. @media (min-width: 200px) {
  159. .foo:hover {
  160. background-color: orange;
  161. }
  162. }
  163. `)
  164. })
  165. test('it parses descendant selectors', () => {
  166. let result = parseObjectStyles({
  167. '.foo': {
  168. backgroundColor: 'red',
  169. color: 'white',
  170. padding: '1rem',
  171. '.bar': {
  172. backgroundColor: 'orange',
  173. },
  174. },
  175. })
  176. expect(toCss(result)).toMatchFormattedCss(css`
  177. .foo {
  178. background-color: red;
  179. color: white;
  180. padding: 1rem;
  181. }
  182. .foo .bar {
  183. background-color: orange;
  184. }
  185. `)
  186. })
  187. test('it parses nested multi-class selectors', () => {
  188. let result = parseObjectStyles({
  189. '.foo': {
  190. backgroundColor: 'red',
  191. color: 'white',
  192. padding: '1rem',
  193. '&.bar': {
  194. backgroundColor: 'orange',
  195. },
  196. },
  197. })
  198. expect(toCss(result)).toMatchFormattedCss(css`
  199. .foo {
  200. background-color: red;
  201. color: white;
  202. padding: 1rem;
  203. }
  204. .foo.bar {
  205. background-color: orange;
  206. }
  207. `)
  208. })
  209. test('it parses nested multi-class selectors in media queries', () => {
  210. let result = parseObjectStyles({
  211. '.foo': {
  212. backgroundColor: 'red',
  213. color: 'white',
  214. padding: '1rem',
  215. '@media (min-width: 200px)': {
  216. '&.bar': {
  217. backgroundColor: 'orange',
  218. },
  219. },
  220. },
  221. })
  222. expect(toCss(result)).toMatchFormattedCss(css`
  223. .foo {
  224. background-color: red;
  225. color: white;
  226. padding: 1rem;
  227. }
  228. @media (min-width: 200px) {
  229. .foo.bar {
  230. background-color: orange;
  231. }
  232. }
  233. `)
  234. })
  235. test('it strips empty selectors when nesting', () => {
  236. let result = parseObjectStyles({
  237. '.foo': {
  238. '.bar': {
  239. backgroundColor: 'orange',
  240. },
  241. },
  242. })
  243. expect(toCss(result)).toMatchFormattedCss(css`
  244. .foo .bar {
  245. background-color: orange;
  246. }
  247. `)
  248. })
  249. test('it can parse an array of styles', () => {
  250. let result = parseObjectStyles([
  251. {
  252. '.foo': {
  253. backgroundColor: 'orange',
  254. },
  255. },
  256. {
  257. '.bar': {
  258. backgroundColor: 'red',
  259. },
  260. },
  261. {
  262. '.foo': {
  263. backgroundColor: 'blue',
  264. },
  265. },
  266. ])
  267. expect(toCss(result)).toMatchFormattedCss(css`
  268. .foo {
  269. background-color: orange;
  270. }
  271. .bar {
  272. background-color: red;
  273. }
  274. .foo {
  275. background-color: blue;
  276. }
  277. `)
  278. })
  279. test('custom properties preserve their case', () => {
  280. let result = parseObjectStyles({
  281. ':root': {
  282. '--colors-aColor-500': '0',
  283. },
  284. })
  285. expect(toCss(result)).toMatchFormattedCss(css`
  286. :root {
  287. --colors-aColor-500: 0;
  288. }
  289. `)
  290. })