safelist.test.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. import { run, html, css } from './util/run'
  2. it('should not safelist anything', () => {
  3. let config = {
  4. content: [{ raw: html`<div class="uppercase"></div>` }],
  5. }
  6. return run('@tailwind utilities', config).then((result) => {
  7. return expect(result.css).toMatchCss(css`
  8. .uppercase {
  9. text-transform: uppercase;
  10. }
  11. `)
  12. })
  13. })
  14. it('should safelist strings', () => {
  15. let config = {
  16. content: [{ raw: html`<div class="uppercase"></div>` }],
  17. safelist: ['mt-[20px]', 'font-bold', 'text-gray-200', 'hover:underline'],
  18. }
  19. return run('@tailwind utilities', config).then((result) => {
  20. return expect(result.css).toMatchCss(css`
  21. .mt-\[20px\] {
  22. margin-top: 20px;
  23. }
  24. .font-bold {
  25. font-weight: 700;
  26. }
  27. .uppercase {
  28. text-transform: uppercase;
  29. }
  30. .text-gray-200 {
  31. --tw-text-opacity: 1;
  32. color: rgb(229 231 235 / var(--tw-text-opacity));
  33. }
  34. .hover\:underline:hover {
  35. text-decoration-line: underline;
  36. }
  37. `)
  38. })
  39. })
  40. it('should safelist based on a pattern regex', () => {
  41. let config = {
  42. content: [{ raw: html`<div class="uppercase"></div>` }],
  43. safelist: [
  44. {
  45. pattern: /^bg-(red)-(100|200)$/,
  46. variants: ['hover'],
  47. },
  48. ],
  49. }
  50. return run('@tailwind utilities', config).then((result) => {
  51. return expect(result.css).toMatchCss(css`
  52. .bg-red-100 {
  53. --tw-bg-opacity: 1;
  54. background-color: rgb(254 226 226 / var(--tw-bg-opacity));
  55. }
  56. .bg-red-200 {
  57. --tw-bg-opacity: 1;
  58. background-color: rgb(254 202 202 / var(--tw-bg-opacity));
  59. }
  60. .uppercase {
  61. text-transform: uppercase;
  62. }
  63. .hover\:bg-red-100:hover {
  64. --tw-bg-opacity: 1;
  65. background-color: rgb(254 226 226 / var(--tw-bg-opacity));
  66. }
  67. .hover\:bg-red-200:hover {
  68. --tw-bg-opacity: 1;
  69. background-color: rgb(254 202 202 / var(--tw-bg-opacity));
  70. }
  71. `)
  72. })
  73. })
  74. it('should not generate duplicates', () => {
  75. let config = {
  76. content: [{ raw: html`<div class="uppercase"></div>` }],
  77. safelist: [
  78. 'uppercase',
  79. {
  80. pattern: /^bg-(red)-(100|200)$/,
  81. variants: ['hover'],
  82. },
  83. {
  84. pattern: /^bg-(red)-(100|200)$/,
  85. variants: ['hover'],
  86. },
  87. {
  88. pattern: /^bg-(red)-(100|200)$/,
  89. variants: ['hover'],
  90. },
  91. ],
  92. }
  93. return run('@tailwind utilities', config).then((result) => {
  94. return expect(result.css).toMatchCss(css`
  95. .bg-red-100 {
  96. --tw-bg-opacity: 1;
  97. background-color: rgb(254 226 226 / var(--tw-bg-opacity));
  98. }
  99. .bg-red-200 {
  100. --tw-bg-opacity: 1;
  101. background-color: rgb(254 202 202 / var(--tw-bg-opacity));
  102. }
  103. .uppercase {
  104. text-transform: uppercase;
  105. }
  106. .hover\:bg-red-100:hover {
  107. --tw-bg-opacity: 1;
  108. background-color: rgb(254 226 226 / var(--tw-bg-opacity));
  109. }
  110. .hover\:bg-red-200:hover {
  111. --tw-bg-opacity: 1;
  112. background-color: rgb(254 202 202 / var(--tw-bg-opacity));
  113. }
  114. `)
  115. })
  116. })
  117. it('should safelist when using a custom prefix', () => {
  118. let config = {
  119. prefix: 'tw-',
  120. content: [{ raw: html`<div class="tw-uppercase"></div>` }],
  121. safelist: [
  122. {
  123. pattern: /^tw-bg-red-(100|200)$/g,
  124. },
  125. ],
  126. }
  127. return run('@tailwind utilities', config).then((result) => {
  128. return expect(result.css).toMatchCss(css`
  129. .tw-bg-red-100 {
  130. --tw-bg-opacity: 1;
  131. background-color: rgb(254 226 226 / var(--tw-bg-opacity));
  132. }
  133. .tw-bg-red-200 {
  134. --tw-bg-opacity: 1;
  135. background-color: rgb(254 202 202 / var(--tw-bg-opacity));
  136. }
  137. .tw-uppercase {
  138. text-transform: uppercase;
  139. }
  140. `)
  141. })
  142. })
  143. it('should not safelist when an empty list is provided', () => {
  144. let config = {
  145. content: [{ raw: html`<div class="uppercase"></div>` }],
  146. safelist: [],
  147. }
  148. return run('@tailwind utilities', config).then((result) => {
  149. return expect(result.css).toMatchCss(css`
  150. .uppercase {
  151. text-transform: uppercase;
  152. }
  153. `)
  154. })
  155. })
  156. it('should not safelist when an sparse/holey list is provided', () => {
  157. let config = {
  158. content: [{ raw: html`<div class="uppercase"></div>` }],
  159. safelist: [, , ,],
  160. }
  161. return run('@tailwind utilities', config).then((result) => {
  162. return expect(result.css).toMatchCss(css`
  163. .uppercase {
  164. text-transform: uppercase;
  165. }
  166. `)
  167. })
  168. })
  169. it('should safelist negatives based on a pattern regex', () => {
  170. let config = {
  171. content: [{ raw: html`<div class="uppercase"></div>` }],
  172. safelist: [
  173. {
  174. pattern: /^-top-1$/,
  175. variants: ['hover'],
  176. },
  177. ],
  178. }
  179. return run('@tailwind utilities', config).then((result) => {
  180. return expect(result.css).toMatchCss(css`
  181. .-top-1 {
  182. top: -0.25rem;
  183. }
  184. .uppercase {
  185. text-transform: uppercase;
  186. }
  187. .hover\:-top-1:hover {
  188. top: -0.25rem;
  189. }
  190. `)
  191. })
  192. })
  193. it('should safelist negatives based on a pattern regex', () => {
  194. let config = {
  195. content: [{ raw: html`<div class="uppercase"></div>` }],
  196. safelist: [
  197. {
  198. pattern: /^bg-red-(400|500)(\/(40|50))?$/,
  199. variants: ['hover'],
  200. },
  201. {
  202. pattern: /^(fill|ring|text)-red-200\/50$/,
  203. variants: ['hover'],
  204. },
  205. ],
  206. }
  207. return run('@tailwind utilities', config).then((result) => {
  208. return expect(result.css).toMatchCss(css`
  209. .bg-red-400 {
  210. --tw-bg-opacity: 1;
  211. background-color: rgb(248 113 113 / var(--tw-bg-opacity));
  212. }
  213. .bg-red-500 {
  214. --tw-bg-opacity: 1;
  215. background-color: rgb(239 68 68 / var(--tw-bg-opacity));
  216. }
  217. .bg-red-400\/40 {
  218. background-color: rgb(248 113 113 / 0.4);
  219. }
  220. .bg-red-400\/50 {
  221. background-color: rgb(248 113 113 / 0.5);
  222. }
  223. .bg-red-500\/40 {
  224. background-color: rgb(239 68 68 / 0.4);
  225. }
  226. .bg-red-500\/50 {
  227. background-color: rgb(239 68 68 / 0.5);
  228. }
  229. .fill-red-200\/50 {
  230. fill: rgb(254 202 202 / 0.5);
  231. }
  232. .uppercase {
  233. text-transform: uppercase;
  234. }
  235. .text-red-200\/50 {
  236. color: rgb(254 202 202 / 0.5);
  237. }
  238. .ring-red-200\/50 {
  239. --tw-ring-color: rgb(254 202 202 / 0.5);
  240. }
  241. .hover\:bg-red-400:hover {
  242. --tw-bg-opacity: 1;
  243. background-color: rgb(248 113 113 / var(--tw-bg-opacity));
  244. }
  245. .hover\:bg-red-500:hover {
  246. --tw-bg-opacity: 1;
  247. background-color: rgb(239 68 68 / var(--tw-bg-opacity));
  248. }
  249. .hover\:bg-red-400\/40:hover {
  250. background-color: rgb(248 113 113 / 0.4);
  251. }
  252. .hover\:bg-red-400\/50:hover {
  253. background-color: rgb(248 113 113 / 0.5);
  254. }
  255. .hover\:bg-red-500\/40:hover {
  256. background-color: rgb(239 68 68 / 0.4);
  257. }
  258. .hover\:bg-red-500\/50:hover {
  259. background-color: rgb(239 68 68 / 0.5);
  260. }
  261. .hover\:fill-red-200\/50:hover {
  262. fill: rgb(254 202 202 / 0.5);
  263. }
  264. .hover\:text-red-200\/50:hover {
  265. color: rgb(254 202 202 / 0.5);
  266. }
  267. .hover\:ring-red-200\/50:hover {
  268. --tw-ring-color: rgb(254 202 202 / 0.5);
  269. }
  270. `)
  271. })
  272. })