setup-vitest.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import type { MockInstance } from 'vitest'
  2. declare module 'vitest' {
  3. interface Assertion<T = any> extends CustomMatchers<T> {}
  4. interface AsymmetricMatchersContaining extends CustomMatchers {}
  5. }
  6. interface CustomMatchers<R = unknown> {
  7. toHaveBeenWarned(): R
  8. toHaveBeenWarnedLast(): R
  9. toHaveBeenWarnedTimes(n: number): R
  10. }
  11. vi.stubGlobal('MathMLElement', class MathMLElement {})
  12. expect.extend({
  13. toHaveBeenWarned(received: string) {
  14. const passed = warn.mock.calls.some(args => args[0].includes(received))
  15. if (passed) {
  16. asserted.add(received)
  17. return {
  18. pass: true,
  19. message: () => `expected "${received}" not to have been warned.`,
  20. }
  21. } else {
  22. const msgs = warn.mock.calls.map(args => args[0]).join('\n - ')
  23. return {
  24. pass: false,
  25. message: () =>
  26. `expected "${received}" to have been warned` +
  27. (msgs.length
  28. ? `.\n\nActual messages:\n\n - ${msgs}`
  29. : ` but no warning was recorded.`),
  30. }
  31. }
  32. },
  33. toHaveBeenWarnedLast(received: string) {
  34. const passed =
  35. warn.mock.calls[warn.mock.calls.length - 1][0].includes(received)
  36. if (passed) {
  37. asserted.add(received)
  38. return {
  39. pass: true,
  40. message: () => `expected "${received}" not to have been warned last.`,
  41. }
  42. } else {
  43. const msgs = warn.mock.calls.map(args => args[0]).join('\n - ')
  44. return {
  45. pass: false,
  46. message: () =>
  47. `expected "${received}" to have been warned last.\n\nActual messages:\n\n - ${msgs}`,
  48. }
  49. }
  50. },
  51. toHaveBeenWarnedTimes(received: string, n: number) {
  52. let found = 0
  53. warn.mock.calls.forEach(args => {
  54. if (args[0].includes(received)) {
  55. found++
  56. }
  57. })
  58. if (found === n) {
  59. asserted.add(received)
  60. return {
  61. pass: true,
  62. message: () => `expected "${received}" to have been warned ${n} times.`,
  63. }
  64. } else {
  65. return {
  66. pass: false,
  67. message: () =>
  68. `expected "${received}" to have been warned ${n} times but got ${found}.`,
  69. }
  70. }
  71. },
  72. })
  73. let warn: MockInstance
  74. const asserted: Set<string> = new Set()
  75. beforeEach(() => {
  76. asserted.clear()
  77. warn = vi.spyOn(console, 'warn')
  78. warn.mockImplementation(() => {})
  79. })
  80. afterEach(() => {
  81. const assertedArray = Array.from(asserted)
  82. const nonAssertedWarnings = warn.mock.calls
  83. .map(args => args[0])
  84. .filter(received => {
  85. return !assertedArray.some(assertedMsg => {
  86. return received.includes(assertedMsg)
  87. })
  88. })
  89. warn.mockRestore()
  90. if (nonAssertedWarnings.length) {
  91. throw new Error(
  92. `test case threw unexpected warnings:\n - ${nonAssertedWarnings.join(
  93. '\n - ',
  94. )}`,
  95. )
  96. }
  97. })