diff options
Diffstat (limited to 'docs/test')
-rw-r--r-- | docs/test/lifecycle.md | 4 | ||||
-rw-r--r-- | docs/test/mocks.md | 55 | ||||
-rw-r--r-- | docs/test/time.md | 106 | ||||
-rw-r--r-- | docs/test/writing.md | 92 |
4 files changed, 250 insertions, 7 deletions
diff --git a/docs/test/lifecycle.md b/docs/test/lifecycle.md index ccb7ce85d..fd804c9bb 100644 --- a/docs/test/lifecycle.md +++ b/docs/test/lifecycle.md @@ -10,7 +10,7 @@ The test runner supports the following lifecycle hooks. This is useful for loadi Perform per-test setup and teardown logic with `beforeEach` and `afterEach`. ```ts -import { expect, test } from "bun:test"; +import { beforeEach, afterEach } from "bun:test"; beforeEach(() => { console.log("running test."); @@ -70,7 +70,7 @@ afterAll(() => { Then use `--preload` to run the setup script before any test files. ```ts -bun test --preload ./setup.ts +$ bun test --preload ./setup.ts ``` To avoid typing `--preload` every time you run tests, it can be added to your `bunfig.toml`: diff --git a/docs/test/mocks.md b/docs/test/mocks.md new file mode 100644 index 000000000..31b5dab41 --- /dev/null +++ b/docs/test/mocks.md @@ -0,0 +1,55 @@ +Create mocks with the `mock` function. + +```ts +import { test, expect, mock } from "bun:test"; +const random = mock(() => Math.random()); + +test("random", async () => { + const val = random(); + expect(val).toBeGreaterThan(0); + expect(random).toHaveBeenCalled(); + expect(random).toHaveBeenCalledTimes(1); +}); +``` + +The result of `mock()` is a new function that's been decorated with some additional properties. + +```ts +import { mock } from "bun:test"; +const random = mock((multiplier: number) => multiplier * Math.random()); + +random(2); +random(10); + +random.mock.calls; +// [[ 2 ], [ 10 ]] + +random.mock.results; +// [ +// { type: "return", value: 0.6533907460954099 }, +// { type: "return", value: 0.6452713933037312 } +// ] +``` + +## `.spyOn()` + +It's possible to track calls to a function without replacing it with a mock. Use `spyOn()` to create a spy; these spies can be passed to `.toHaveBeenCalled()` and `.toHaveBeenCalledTimes()`. + +```ts +import { test, expect, spyOn } from "bun:test"; + +const ringo = { + name: "Ringo", + sayHi() { + console.log(`Hello I'm ${this.name}`); + }, +}; + +const spy = spyOn(ringo, "sayHi"); + +test("spyon", () => { + expect(spy).toHaveBeenCalledTimes(0); + ringo.sayHi(); + expect(spy).toHaveBeenCalledTimes(1); +}); +``` diff --git a/docs/test/time.md b/docs/test/time.md new file mode 100644 index 000000000..4a0f98407 --- /dev/null +++ b/docs/test/time.md @@ -0,0 +1,106 @@ +`bun:test` lets you change what time it is in your tests. This was introduced in Bun v0.6.13. + +This works with any of the following: + +- `Date.now` +- `new Date()` +- `new Intl.DateTimeFormat().format()` + +Timers are not impacted yet, but may be in a future release of Bun. + +## `setSystemTime` + +To change the system time, use `setSystemTime`: + +```ts +import { setSystemTime, beforeAll, test, expect } from "bun:test"; + +beforeAll(() => { + setSystemTime(new Date("2020-01-01T00:00:00.000Z")); +}); + +test("it is 2020", () => { + expect(new Date().getFullYear()).toBe(2020); +}); +``` + +To support existing tests that use Jest's `useFakeTimers` and `useRealTimers`, you can use `useFakeTimers` and `useRealTimers`: + +```ts +test("just like in jest", () => { + jest.useFakeTimers(); + jest.setSystemTime(new Date("2020-01-01T00:00:00.000Z")); + expect(new Date().getFullYear()).toBe(2020); + jest.useRealTimers(); + expect(new Date().getFullYear()).toBeGreaterThan(2020); +}); + +test("unlike in jest", () => { + const OriginalDate = Date; + jest.useFakeTimers(); + if (typeof Bun === "undefined") { + // In Jest, the Date constructor changes + // That can cause all sorts of bugs because suddenly Date !== Date before the test. + expect(Date).not.toBe(OriginalDate); + expect(Date.now).not.toBe(OriginalDate.now); + } else { + // In bun:test, Date constructor does not change when you useFakeTimers + expect(Date).toBe(OriginalDate); + expect(Date.now).toBe(OriginalDate.now); + } +}); +``` + +{% callout %} +**Timers** — Note that we have not implemented builtin support for mocking timers yet, but this is on the roadmap. +{% /callout %} + +### Reset the system time + +To reset the system time, pass no arguments to `setSystemTime`: + +```ts +import { setSystemTime, beforeAll } from "bun:test"; + +test("it was 2020, for a moment.", () => { + // Set it to something! + setSystemTime(new Date("2020-01-01T00:00:00.000Z")); + expect(new Date().getFullYear()).toBe(2020); + + // reset it! + setSystemTime(); + + expect(new Date().getFullYear()).toBeGreaterThan(2020); +}); +``` + +## Set the time zone + +To change the time zone, either pass the `$TZ` environment variable to `bun test`. + +```sh +TZ=America/Los_Angeles bun test +``` + +Or set `process.env.TZ` at runtime: + +```ts +import { test, expect } from "bun:test"; + +test("Welcome to California!", () => { + process.env.TZ = "America/Los_Angeles"; + expect(new Date().getTimezoneOffset()).toBe(420); + expect(new Intl.DateTimeFormat().resolvedOptions().timeZone).toBe( + "America/Los_Angeles", + ); +}); + +test("Welcome to New York!", () => { + // Unlike in Jest, you can set the timezone multiple times at runtime and it will work. + process.env.TZ = "America/New_York"; + expect(new Date().getTimezoneOffset()).toBe(240); + expect(new Intl.DateTimeFormat().resolvedOptions().timeZone).toBe( + "America/New_York", + ); +}); +``` diff --git a/docs/test/writing.md b/docs/test/writing.md index 391ee91c2..6a29bf81f 100644 --- a/docs/test/writing.md +++ b/docs/test/writing.md @@ -63,6 +63,21 @@ test("2 * 2", done => { }); ``` +## Timeouts + +Optionally specify a per-test timeout in milliseconds by passing a number as the third argument to `test`. + +```ts +import { test } from "bun:test"; + +test.skip("wat", async () => { + const data = await slowOperation(); + expect(data).toBe(42); +}, 500); // test must run in <500ms +``` + +## `test.skip` + Skip individual tests with `test.skip`. These tests will not be run. ```ts @@ -74,6 +89,8 @@ test.skip("wat", () => { }); ``` +## `test.todo` + Mark a test as a todo with `test.todo`. These tests _will_ be run, and the test runner will expect them to fail. If they pass, you will be prompted to mark it as a regular test. ```ts @@ -84,6 +101,71 @@ test.todo("fix this", () => { }); ``` +To exlusively run tests marked as _todo_, use `bun test --todo`. + +```sh +$ bun test --todo +``` + +## `test.only` + +To run a particular test or suite of tests use `test.only()` or `describe.only()`. Once declared, running `bun test --skip` will only execute tests/suites that have been marked with `.only()`. + +```ts +import { test, describe } from "bun:test"; + +test("test #1", () => { + // does not run +}); + +test.only("test #2", () => { + // runs +}); + +describe.only("only", () => { + test("test #3", () => { + // runs + }); +}); +``` + +The following command will only execute tests #2 and #3. + +```sh +$ bun test --only +``` + +## `test.if` + +To run a test conditionally, use `test.if()`. The test will run if the condition is truthy. This is particularly useful for tests that should only run on specific architectures or operating systems. + +```ts +test.if(Math.random() > 0.5)("runs half the time", () => { + // ... +}); +``` + +```ts +test.if(Math.random() > 0.5)("runs half the time", () => { + // ... +}); + +const macOS = process.arch === "darwin"; +test.if(macOS)("runs on macOS", () => { + // runs if macOS +}); +``` + +To instead skip a test based on some condition, use `test.skipIf()` or `describe.skipIf()`. + +```ts +const macOS = process.arch === "darwin"; + +test.skipIf(macOS)("runs on non-macOS", () => { + // runs if *not* macOS +}); +``` + ## Matchers Bun implements the following matchers. Full Jest compatibility is on the roadmap; track progress [here](https://github.com/oven-sh/bun/issues/1825). @@ -217,13 +299,13 @@ Bun implements the following matchers. Full Jest compatibility is on the roadmap --- -- 🔴 -- [`.resolves()`](https://jestjs.io/docs/expect#resolves) +- 🟢 +- [`.resolves()`](https://jestjs.io/docs/expect#resolves) (since Bun v0.6.12+) --- -- 🔴 -- [`.rejects()`](https://jestjs.io/docs/expect#rejects) +- 🟢 +- [`.rejects()`](https://jestjs.io/docs/expect#rejects) (since Bun v0.6.12+) --- @@ -277,7 +359,7 @@ Bun implements the following matchers. Full Jest compatibility is on the roadmap --- -- 🔴 +- 🟢 - [`.toBeCloseTo()`](https://jestjs.io/docs/expect#tobeclosetonumber-numdigits) --- |