| 21 | // Extend Vitest with the custom matchers, this file needs to be imported in the vitest.setup.ts file or the test file |
| 22 | expect.extend({ |
| 23 | toLog( |
| 24 | transaction: Debuggable, |
| 25 | match?: RegExp | string, |
| 26 | ) { |
| 27 | const loggerSpy = testFramework.spyOn(console, 'log'); |
| 28 | |
| 29 | // Clear any previous calls (if spy reused accidentally) |
| 30 | loggerSpy.mockClear(); |
| 31 | |
| 32 | // silence actual stdout output |
| 33 | loggerSpy.mockImplementation(() => { }); |
| 34 | |
| 35 | // Run debug, ignoring any errors because we only care about the logs, even if the transaction fails |
| 36 | try { |
| 37 | transaction.debug(); |
| 38 | } catch (error) { } |
| 39 | |
| 40 | // We concatenate all the logs into a single string - if no logs are present, we set received to undefined |
| 41 | const receivedBase = loggerSpy.mock.calls.reduce((acc, [log]) => `${acc}\n${log}`, '').trim(); |
| 42 | const received = receivedBase === '' ? undefined : receivedBase; |
| 43 | |
| 44 | const matcherHint = this.utils.matcherHint('toLog', 'received', 'expected', { isNot: this.isNot }); |
| 45 | const expectedText = `Expected: ${this.isNot ? 'not ' : ''}${this.utils.printExpected(match)}`; |
| 46 | const receivedText = `Received: ${this.utils.printReceived(received)}`; |
| 47 | const message = (): string => `${matcherHint}\n\n${expectedText}\n${receivedText}`; |
| 48 | |
| 49 | try { |
| 50 | // We first check if the expected string is present in any of the individual console.log calls |
| 51 | expect(loggerSpy).toHaveBeenCalledWith(match ? expect.stringMatching(match) : expect.anything()); |
| 52 | } catch { |
| 53 | try { |
| 54 | // We add this extra check to allow expect().toLog() to check multiple console.log calls in a single test |
| 55 | // (e.g. for log ordering), which would fail the first check because that compares the individual console.log calls |
| 56 | expect(receivedBase).toMatch(match ? match : expect.anything()); |
| 57 | } catch { |
| 58 | return { message, pass: false }; |
| 59 | } |
| 60 | } finally { |
| 61 | // Restore the original console.log implementation |
| 62 | loggerSpy.mockRestore(); |
| 63 | } |
| 64 | |
| 65 | return { message, pass: true }; |
| 66 | }, |
| 67 | toFailRequire( |
| 68 | transaction: Debuggable, |
| 69 | ) { |