Global methods

I start by going to the beforeAll() hook and adding a spy on the console.log method using the vi.spyOn() utility:
beforeAll(() => {
  vi.spyOn(console, 'log').mockImplementation(() => {})
})
I'm overriding the implementation of console.log for this test suite by using .mockImplementation() and providing it an empty function. With this, I can still assert on the console.log calls without it actually printing anything to the terminal output.
From this moment forward, all console.log calls are recorded and I can assert on them in any test!
Next, I need to reset the recorded state of the spy function for each test run. I will use vi.resetAllMocks() for that:
afterEach(() => {
  vi.resetAllMocks()
})
vi.resetAllMocks() targets all mocks created in this test suite, not just the spy for console.log. Instead of resetting an individual spy, I prefer resetting all mocks because none of them should leak their state to irrelevant tests.
And, finally, restore the original implementation of console.log once the tests are done:
afterAll(() => {
  vi.restoreAllMocks()
})
This concludes the testing setup changes but we still have some assertions to adjust.
Since I am spying on a global method, I can write assertions on that global method directly:
expect(console.log).toHaveBeenCalledWith(
  'Sever is listening at http://127.0.0.1/',
)
expect(console.log).toHaveBeenCalledOnce()
expect(console.log).toHaveBeenCalledWith(
  'Sever is listening at http://127.0.0.1:5639/',
)
expect(console.log).toHaveBeenCalledOnce()
The only thing remaining is to run the tests and make sure they are passing:
 โœ“ print-server-url.test.ts (2)
   โœ“ prints the server message for url with host and no port
   โœ“ prints the server message for url with host and port

Bonus: Type-safe global spies

Although Vitest reassigns the value of console.log to a spy function on runtime, TypeScript doesn't know about that. In fact, if you attempt to read some of the spy function's properties, you'll be greeted with a type error:
console.log.mock.calls
// Property 'mock' does not exist on type '...'
To fix this, you need to extend the type of Console['log'] in your test and mark it as a mock instance.
import { MockInstance } from 'vitest'

declare namespace console {
  var log: Console['log'] &
    MockInstance<Parameters<Console['log']>, ReturnType<Console['log']>>
}
console.log.mock.calls
// [["Server is listening at http://localhost:5639/"]]
The way you extend the global type will depend on the declaration for that type. The type of console.log happened to be declared in a global namespace console so that's the namespace we extend above. Inspect the type declaration of the global you want to extend to ensure it's done correctly.

Access Denied

You must login or register for the workshop to view the diff.

Check out this video to see how the diff tab works.