customMatchers.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. const prettier = require('prettier')
  2. const { diff } = require('jest-diff')
  3. const log = require('../src/util/log').default
  4. const { version } = require('../package.json')
  5. function license() {
  6. return `/* ! tailwindcss v${version} | MIT License | https://tailwindcss.com */\n`
  7. }
  8. let warn
  9. beforeEach(() => {
  10. warn = jest.spyOn(log, 'warn')
  11. warn.mockImplementation(() => {})
  12. })
  13. afterEach(() => {
  14. warn.mockRestore()
  15. })
  16. function formatPrettier(input) {
  17. return prettier.format(input, {
  18. parser: 'css',
  19. printWidth: 100,
  20. })
  21. }
  22. function format(input) {
  23. return formatPrettier(input).replace(/\n{2,}/g, '\n')
  24. }
  25. function toMatchFormattedCss(received = '', argument = '') {
  26. let options = {
  27. comment: 'formatCSS(received) === formatCSS(argument)',
  28. isNot: this.isNot,
  29. promise: this.promise,
  30. }
  31. // Drop the license from the tests such that we can purely focus on the actual CSS being
  32. // generated.
  33. received = received.replace(license(), '')
  34. argument = argument.replace(license(), '')
  35. let formattedReceived = format(received)
  36. let formattedArgument = format(argument)
  37. let pass = formattedReceived === formattedArgument
  38. let message = pass
  39. ? () => {
  40. return (
  41. this.utils.matcherHint('toMatchFormattedCss', undefined, undefined, options) +
  42. '\n\n' +
  43. `Expected: not ${this.utils.printExpected(formattedReceived)}\n` +
  44. `Received: ${this.utils.printReceived(formattedArgument)}`
  45. )
  46. }
  47. : () => {
  48. let diffString = diff(formattedArgument, formattedReceived, {
  49. expand: this.expand,
  50. })
  51. return (
  52. this.utils.matcherHint('toMatchFormattedCss', undefined, undefined, options) +
  53. '\n\n' +
  54. (diffString && diffString.includes('- Expect')
  55. ? `Difference:\n\n${diffString}`
  56. : `Expected: ${this.utils.printExpected(formattedArgument)}\n` +
  57. `Received: ${this.utils.printReceived(formattedReceived)}`)
  58. )
  59. }
  60. return { actual: received, message, pass }
  61. }
  62. expect.extend({
  63. toMatchFormattedCss: toMatchFormattedCss,
  64. toIncludeCss(received, argument) {
  65. let options = {
  66. comment: 'formatCSS(received).includes(formatCSS(argument))',
  67. isNot: this.isNot,
  68. promise: this.promise,
  69. }
  70. let pass = format(received).includes(format(argument))
  71. let message = pass
  72. ? () => {
  73. return (
  74. this.utils.matcherHint('toIncludeCss', undefined, undefined, options) +
  75. '\n\n' +
  76. `Expected: not ${this.utils.printExpected(formatPrettier(received))}\n` +
  77. `Received: ${this.utils.printReceived(formatPrettier(argument))}`
  78. )
  79. }
  80. : () => {
  81. let actual = formatPrettier(received)
  82. let expected = formatPrettier(argument)
  83. let diffString = diff(expected, actual, {
  84. expand: this.expand,
  85. })
  86. return (
  87. this.utils.matcherHint('toIncludeCss', undefined, undefined, options) +
  88. '\n\n' +
  89. (diffString && diffString.includes('- Expect')
  90. ? `Difference:\n\n${diffString}`
  91. : `Expected: ${this.utils.printExpected(expected)}\n` +
  92. `Received: ${this.utils.printReceived(actual)}`)
  93. )
  94. }
  95. return { actual: received, message, pass }
  96. },
  97. toHaveBeenWarned() {
  98. let passed = warn.mock.calls.length > 0
  99. if (passed) {
  100. return {
  101. pass: true,
  102. message: () => {
  103. return (
  104. this.utils.matcherHint('toHaveBeenWarned') +
  105. '\n\n' +
  106. `Expected number of calls: >= ${this.utils.printExpected(1)}\n` +
  107. `Received number of calls: ${this.utils.printReceived(actualWarningKeys.length)}`
  108. )
  109. },
  110. }
  111. } else {
  112. return {
  113. pass: false,
  114. message: () => {
  115. return (
  116. this.utils.matcherHint('toHaveBeenWarned') +
  117. '\n\n' +
  118. `Expected number of calls: >= ${this.utils.printExpected(1)}\n` +
  119. `Received number of calls: ${this.utils.printReceived(warn.mock.calls.length)}`
  120. )
  121. },
  122. }
  123. }
  124. },
  125. toHaveBeenWarnedWith(_received, expectedWarningKeys) {
  126. let actualWarningKeys = warn.mock.calls.map((args) => args[0])
  127. let passed = expectedWarningKeys.every((key) => actualWarningKeys.includes(key))
  128. if (passed) {
  129. return {
  130. pass: true,
  131. message: () => {
  132. return (
  133. this.utils.matcherHint('toHaveBeenWarnedWith') +
  134. '\n\n' +
  135. `Expected: not ${this.utils.printExpected(expectedWarningKeys)}\n` +
  136. `Received: ${this.utils.printReceived(actualWarningKeys)}`
  137. )
  138. },
  139. }
  140. } else {
  141. let diffString = diff(expectedWarningKeys, actualWarningKeys)
  142. return {
  143. pass: false,
  144. message: () => {
  145. return (
  146. this.utils.matcherHint('toHaveBeenWarnedWith') +
  147. '\n\n' +
  148. (diffString && diffString.includes('- Expect')
  149. ? `Difference:\n\n${diffString}`
  150. : `Expected: ${this.utils.printExpected(expectedWarningKeys)}\n` +
  151. `Received: ${this.utils.printReceived(actualWarningKeys)}`)
  152. )
  153. },
  154. }
  155. }
  156. },
  157. })