match-variants.test.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. import { run, html, css } from './util/run'
  2. test('partial arbitrary variants', () => {
  3. let config = {
  4. experimental: { matchVariant: true },
  5. content: [
  6. {
  7. raw: html`<div class="potato-[yellow]:bg-yellow-200 potato-[baked]:w-3"></div> `,
  8. },
  9. ],
  10. corePlugins: { preflight: false },
  11. plugins: [
  12. ({ matchVariant }) => {
  13. matchVariant({
  14. potato: (flavor) => `.potato-${flavor} &`,
  15. })
  16. },
  17. ],
  18. }
  19. let input = css`
  20. @tailwind utilities;
  21. `
  22. return run(input, config).then((result) => {
  23. expect(result.css).toMatchFormattedCss(css`
  24. .potato-baked .potato-\[baked\]\:w-3 {
  25. width: 0.75rem;
  26. }
  27. .potato-yellow .potato-\[yellow\]\:bg-yellow-200 {
  28. --tw-bg-opacity: 1;
  29. background-color: rgb(254 240 138 / var(--tw-bg-opacity));
  30. }
  31. `)
  32. })
  33. })
  34. test('partial arbitrary variants with at-rules', () => {
  35. let config = {
  36. experimental: { matchVariant: true },
  37. content: [
  38. {
  39. raw: html`<div class="potato-[yellow]:bg-yellow-200 potato-[baked]:w-3"></div> `,
  40. },
  41. ],
  42. corePlugins: { preflight: false },
  43. plugins: [
  44. ({ matchVariant }) => {
  45. matchVariant({
  46. potato: (flavor) => `@media (potato: ${flavor})`,
  47. })
  48. },
  49. ],
  50. }
  51. let input = css`
  52. @tailwind utilities;
  53. `
  54. return run(input, config).then((result) => {
  55. expect(result.css).toMatchFormattedCss(css`
  56. @media (potato: baked) {
  57. .potato-\[baked\]\:w-3 {
  58. width: 0.75rem;
  59. }
  60. }
  61. @media (potato: yellow) {
  62. .potato-\[yellow\]\:bg-yellow-200 {
  63. --tw-bg-opacity: 1;
  64. background-color: rgb(254 240 138 / var(--tw-bg-opacity));
  65. }
  66. }
  67. `)
  68. })
  69. })
  70. test('partial arbitrary variants with at-rules and placeholder', () => {
  71. let config = {
  72. experimental: { matchVariant: true },
  73. content: [
  74. {
  75. raw: html`<div class="potato-[yellow]:bg-yellow-200 potato-[baked]:w-3"></div> `,
  76. },
  77. ],
  78. corePlugins: { preflight: false },
  79. plugins: [
  80. ({ matchVariant }) => {
  81. matchVariant({
  82. potato: (flavor) => `@media (potato: ${flavor}) { &:potato }`,
  83. })
  84. },
  85. ],
  86. }
  87. let input = css`
  88. @tailwind utilities;
  89. `
  90. return run(input, config).then((result) => {
  91. expect(result.css).toMatchFormattedCss(css`
  92. @media (potato: baked) {
  93. .potato-\[baked\]\:w-3:potato {
  94. width: 0.75rem;
  95. }
  96. }
  97. @media (potato: yellow) {
  98. .potato-\[yellow\]\:bg-yellow-200:potato {
  99. --tw-bg-opacity: 1;
  100. background-color: rgb(254 240 138 / var(--tw-bg-opacity));
  101. }
  102. }
  103. `)
  104. })
  105. })
  106. test('partial arbitrary variants with default values', () => {
  107. let config = {
  108. experimental: { matchVariant: true },
  109. content: [
  110. {
  111. raw: html`<div class="tooltip-bottom:mt-2 tooltip-top:mb-2"></div>`,
  112. },
  113. ],
  114. corePlugins: { preflight: false },
  115. plugins: [
  116. ({ matchVariant }) => {
  117. matchVariant(
  118. {
  119. tooltip: (side) => `&${side}`,
  120. },
  121. {
  122. values: {
  123. bottom: '[data-location="bottom"]',
  124. top: '[data-location="top"]',
  125. },
  126. }
  127. )
  128. },
  129. ],
  130. }
  131. let input = css`
  132. @tailwind utilities;
  133. `
  134. return run(input, config).then((result) => {
  135. expect(result.css).toMatchFormattedCss(css`
  136. .tooltip-bottom\:mt-2[data-location='bottom'] {
  137. margin-top: 0.5rem;
  138. }
  139. .tooltip-top\:mb-2[data-location='top'] {
  140. margin-bottom: 0.5rem;
  141. }
  142. `)
  143. })
  144. })
  145. test('matched variant values maintain the sort order they are registered in', () => {
  146. let config = {
  147. experimental: { matchVariant: true },
  148. content: [
  149. {
  150. raw: html`<div
  151. class="alphabet-c:underline alphabet-a:underline alphabet-d:underline alphabet-b:underline"
  152. ></div>`,
  153. },
  154. ],
  155. corePlugins: { preflight: false },
  156. plugins: [
  157. ({ matchVariant }) => {
  158. matchVariant(
  159. {
  160. alphabet: (side) => `&${side}`,
  161. },
  162. {
  163. values: {
  164. a: '[data-value="a"]',
  165. b: '[data-value="b"]',
  166. c: '[data-value="c"]',
  167. d: '[data-value="d"]',
  168. },
  169. }
  170. )
  171. },
  172. ],
  173. }
  174. let input = css`
  175. @tailwind utilities;
  176. `
  177. return run(input, config).then((result) => {
  178. expect(result.css).toMatchFormattedCss(css`
  179. .alphabet-a\:underline[data-value='a'] {
  180. text-decoration-line: underline;
  181. }
  182. .alphabet-b\:underline[data-value='b'] {
  183. text-decoration-line: underline;
  184. }
  185. .alphabet-c\:underline[data-value='c'] {
  186. text-decoration-line: underline;
  187. }
  188. .alphabet-d\:underline[data-value='d'] {
  189. text-decoration-line: underline;
  190. }
  191. `)
  192. })
  193. })
  194. test('matchVariant can return an array of format strings from the function', () => {
  195. let config = {
  196. experimental: { matchVariant: true },
  197. content: [
  198. {
  199. raw: html`<div class="test-[a,b,c]:underline"></div>`,
  200. },
  201. ],
  202. corePlugins: { preflight: false },
  203. plugins: [
  204. ({ matchVariant }) => {
  205. matchVariant({
  206. test: (selector) => selector.split(',').map((selector) => `&.${selector} > *`),
  207. })
  208. },
  209. ],
  210. }
  211. let input = css`
  212. @tailwind utilities;
  213. `
  214. return run(input, config).then((result) => {
  215. expect(result.css).toMatchFormattedCss(css`
  216. .test-\[a\2c b\2c c\]\:underline.a > * {
  217. text-decoration-line: underline;
  218. }
  219. .test-\[a\2c b\2c c\]\:underline.b > * {
  220. text-decoration-line: underline;
  221. }
  222. .test-\[a\2c b\2c c\]\:underline.c > * {
  223. text-decoration-line: underline;
  224. }
  225. `)
  226. })
  227. })