Environment variables

Another kind of global dependency your code may have is on the environment. This is often done via environment variables, which, in JavaScript, are often exposed to the process via the process.env object.
You use environment variables for tasks like managing API secrets, feature flags, or implementing environment-specific logic. Consequently, environment variables are another dependency you need to know how to mock to properly orchestrate your tests.
One of the most common usages of environment variables is the dependency on the current process' environment, i.e. process.env.NODE_ENV. That's precisely what our Emitter class does to imbue its methods with logging capabilities if run in development:
function isDevelopment() {
  return process.env.NODE_ENV === 'development'
}

export class Emitter<EventMap extends Record<string, Array<unknown>>> {
  // ...

  public on<Event extends keyof EventMap>(
    event: Event,
    listener: (...args: EventMap[Event]) => void,
  ): this {
    if (isDevelopment()) {
      console.log(`adding listener for "${event.toString()}" event`)
    }

    const prevListeners = this.listeners.get(event) || []
    const nextListeners = prevListeners.concat(listener)
    this.listeners.set(event, nextListeners)
    return this
  }

  public emit<Event extends keyof EventMap>(
    event: Event,
    ...data: EventMap[Event]
  ): boolean {
    const listeners = this.listeners.get(event) || []

    if (isDevelopment()) {
      console.log(
        `emitting listeners for "${event.toString()}" event (${
          listeners.length
        })`,
      )
    }

    for (const listener of listeners) {
      listener.apply(this, data)
    }
    return listeners.length > 0
  }
}
First, it determines the environment on runtime via the isDevelopment() function, and then implements additional logic in the .on() and .emit() methods of the Emitter based on result of the isDevelopment() function call.
But how do you test this?
You can, of course, set a different NODE_ENV environment variable when running the test script itself:
NODE_ENV=development npm test
But this won't play nicely on different operating systems, and will affect the entire test run instead of focusing on a single test suite. The worst part is that you won’t be able to change the NODE_ENV value only for specific test cases to see how your code behaves.
Alternatively, you can mock process.env.NODE_ENV as a global value, like you did in the previous exercise. That would work, but you would have to remember to forward all existing environment variables on process.env before mocking your own variables. This can easily be forgotten, leading to unreliable or even broken tests.
You can use vi.stubEnv()!
πŸ‘¨β€πŸ’Ό The time has come for you to get to know vi.stubEnv(). In this exercise, add new test cases for the test suite by mocking the value of process.env.NODE_ENV using the built-in Vitest vi.stubEnv() API. Verify your solution by running npm test. And remember, you will be asserting on console.log calls too!

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.