Part of making good code is making that code easy to test.

### Implement logic in pure functions when possible

The more of your logic that is written in deterministic functions (i.e. no
side-effects, same inputs always result in same outputs) the easier it is to
test. Just load up the functions and supply suitable test inputs.

There is almost definitely no such thing as a well-written 1000 line function.
Most of whatever happened in that thing was probably deterministic and can be
broken up into easily testable chunks.

### Wrap native browser resources in a function so they can be easily mocked

If your javascript needs to talk to the window object, or navigator, etc. wrap
that in a function call so that it can be easily mocked during testing.

#### Your Module

```js static
// myModule.js

// ... other code

export function redirectTo(url) {
    window.location = url;
}

export function theThingYouReallyCareAbout() {
    .....
    redirectTo(somePlace);
    ....
}
```

#### Your test file

```js static
// myModule.test.js
import { vi } from "vitest";
import { theThingYouReallyCareAbout, redirectTo } from "./myModule";

// calling vi.mock on the appropriate import path wraps the exports and gives
// access to new testing methods like mockImplementation
vi.mock("./myModule");
redirectTo.mockImplementation((url) => {
    console.log(`I would have gone to: ${url}`);
});

// You are testing theThingYouReallyCareAbout, but that function needs
// to call a window.relocate, By wrapping redirectTo as a function it was easy to mock
// and avoid errors in your test, because native browser objects do not even exist
// in the unit-testing environment.
describe("theThingYouReallyCareAbout", () => {
    it("Performs a redirect when Foo is clicked"){
        const result = theThingYouReallyCareAbout(abc123);
        expect(result).toBe(1);
    }
});
```
