Skip to content
On this page

Unit tests

INFO

For better testing experience, we recommend reading article about SIDs

Farfetched offers a couple of features to simplify writing unit tests.

Foremost, it allows mocking any fetcher function of any Query without special instruments. Let us see 👇

ts
const locationQuery = createQuery({ handler: /* some fetcher function */ })

test('let us mock function', async () => {
    const scope = fork({ handlers: [
        [locationQuery.__.executeFx, () => 'Mocked'],
    ]})

    // in returned scope locationQuery will be using provided function as a handler
})

What is "scope"?

Scope is an isolated instance of the whole application. It can be used for SSR and testing purposes.

To create new Scope you can use fork function.

ts
const scope = fork();

This API has an important feature for testing. You can replace any handler in the application during fork. Let us use it for replacing handlers in tests.

ts
const locationQuery = createQuery({ handler: /* some fetcher function */ })

test('let us mock function', async () => {
    const scope = fork({ handlers: [
        [locationQuery.__.executeFx, () => 'Mocked'],
    ]})

    // in returned scope locationQuery will be using provided function as a handler
})

Wait for all computations

So, we have created an isolated instance of our application with fake handlers. Now we have to start Query and wait for all computations settled. There is special function for this purpose — allSettled.

ts
const locationQuery = createQuery({ handler: /* some fetcher function */ })

test('let us mock function', async () => {
    const scope = fork({ handlers: [
        [locationQuery.__.executeFx, () => 'Mocked'],
    ]})

    await allSettled(locationQuery.refresh, { scope })

    // all computations are settled
})

It does not matter how many Queries you have connected to the original one. allSetteld provides a guarantee that all computations are settled. It means you can read values from the Scope and compare it with expected ones.

ts
const locationQuery = createQuery({ handler: /* some fetcher function */ })

test('let us mock function', async () => {
    const scope = fork({ handlers: [
        [locationQuery.__.executeFx, () => 'Mocked'],
    ]})

    await allSettled(locationQuery.refresh, { scope })

    expect(scope.getState(locationQuery.$data)).toBe('Mocked')
})

Isolation

As was mentioned before, Scope is a completely isolated instance of the application. So, you can run as many tests as you want in parallel, they will not affect each other.

Released under the MIT License.