context-reuse.test.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import { css } from './util/run'
  2. const fs = require('fs')
  3. const path = require('path')
  4. const postcss = require('postcss')
  5. const tailwind = require('../src/index.js')
  6. const sharedState = require('../src/lib/sharedState.js')
  7. const configPath = path.resolve(__dirname, './context-reuse.tailwind.config.js')
  8. function run(input, config = {}, from = null) {
  9. let { currentTestName } = expect.getState()
  10. from = `${path.resolve(__filename)}?test=${currentTestName}&${from}`
  11. return postcss(tailwind(config)).process(input, { from })
  12. }
  13. beforeEach(async () => {
  14. let config = {
  15. content: [path.resolve(__dirname, './context-reuse.test.html')],
  16. corePlugins: { preflight: false },
  17. }
  18. await fs.promises.writeFile(configPath, `module.exports = ${JSON.stringify(config)};`)
  19. })
  20. afterEach(async () => {
  21. await fs.promises.unlink(configPath)
  22. })
  23. test('re-uses the context across multiple files with the same config', async () => {
  24. let results = [
  25. await run(`@tailwind utilities;`, configPath, `id=1`),
  26. // Using @apply directives should still re-use the context
  27. // They depend on the config but do not the other way around
  28. await run(`body { @apply bg-blue-400; }`, configPath, `id=2`),
  29. await run(`body { @apply text-red-400; }`, configPath, `id=3`),
  30. await run(`body { @apply mb-4; }`, configPath, `id=4`),
  31. ]
  32. let dependencies = results.map((result) => {
  33. return result.messages
  34. .filter((message) => message.type === 'dependency')
  35. .map((message) => message.file)
  36. })
  37. // The content files don't have any utilities in them so this should be empty
  38. expect(results[0].css).toMatchFormattedCss(css``)
  39. // However, @apply is being used so we want to verify that they're being inlined into the CSS rules
  40. expect(results[1].css).toMatchFormattedCss(css`
  41. body {
  42. --tw-bg-opacity: 1;
  43. background-color: rgb(96 165 250 / var(--tw-bg-opacity));
  44. }
  45. `)
  46. expect(results[2].css).toMatchFormattedCss(css`
  47. body {
  48. --tw-text-opacity: 1;
  49. color: rgb(248 113 113 / var(--tw-text-opacity));
  50. }
  51. `)
  52. expect(results[3].css).toMatchFormattedCss(css`
  53. body {
  54. margin-bottom: 1rem;
  55. }
  56. `)
  57. // Files with @tailwind directives depends on the PostCSS tree, config, AND any content files
  58. expect(dependencies[0]).toEqual([
  59. path.resolve(__dirname, 'context-reuse.test.html'),
  60. path.resolve(__dirname, 'context-reuse.tailwind.config.js'),
  61. ])
  62. // @apply depends only on the containing PostCSS tree *and* the config file but no content files
  63. // as they cannot affect the outcome of the @apply directives
  64. expect(dependencies[1]).toEqual([path.resolve(__dirname, 'context-reuse.tailwind.config.js')])
  65. expect(dependencies[2]).toEqual([path.resolve(__dirname, 'context-reuse.tailwind.config.js')])
  66. expect(dependencies[3]).toEqual([path.resolve(__dirname, 'context-reuse.tailwind.config.js')])
  67. // And none of this should have resulted in multiple contexts being created
  68. expect(sharedState.contextSourcesMap.size).toBe(1)
  69. })
  70. test('updates layers when any CSS containing @tailwind directives changes', async () => {
  71. let result
  72. // Compile the initial version once
  73. let input = css`
  74. @tailwind utilities;
  75. @layer utilities {
  76. .custom-utility {
  77. color: orange;
  78. }
  79. }
  80. `
  81. result = await run(input, configPath, `id=1`)
  82. expect(result.css).toMatchFormattedCss(css`
  83. .only\:custom-utility:only-child {
  84. color: orange;
  85. }
  86. `)
  87. // Save the file with a change
  88. input = css`
  89. @tailwind utilities;
  90. @layer utilities {
  91. .custom-utility {
  92. color: blue;
  93. }
  94. }
  95. `
  96. result = await run(input, configPath, `id=1`)
  97. expect(result.css).toMatchFormattedCss(css`
  98. .only\:custom-utility:only-child {
  99. color: #00f;
  100. }
  101. `)
  102. })