Skip to content

Testing

The first thing you need to do is install the test helpers

npm i @reatom/testing

Let’s test this code:

// main.js
import { action, atom } from '@reatom/core'

export const countAtom = atom(0)
export const add = action((ctx, payload) => {
  countAtom(ctx, (state) => state + payload)
})
// main.test.js
import { assert, expect, test } from 'vitest'
import { createTestCtx } from '@reatom/testing'

import { add, countAtom } from './main'

test('Test main module', () => {
  const ctx = createTestCtx() // Create test context
  const track = ctx.subscribeTrack(countAtom) // Record atom changes

  // Check initial state
  expect(track.calls.length).toBe(1)
  expect(track.lastInput()).toBe(0)

  // Call some actions
  add(ctx, 5)
  add(ctx, 10)

  // Check that action "add" work properly
  expect(track.calls.length).toBe(3)
  expect(track.lastInput()).toBe(15)
  // same as
  // expect(ctx.get(countAtom)).toBe(15)
})

Also you can mock actions if needed. In next example we have an async api.

Note: In real code, we recommend using the @reatom/async to work with asynchronous APIs

import { action, atom } from '@reatom/core'

export const todoAtom = atom(null)
export const isLoadingAtom = atom(false);

export const fetchTodo = action(async (ctx) => {
  const response = await ctx.schedule(() => fetch('https://jsonplaceholder.typicode.com/todos/1'))
  return await response.json();
})

export const loadTodo = action(async (ctx) => {
  try {
    isLoadingAtom(ctx, true)
    const data = await ctx.schedule((ctx) => fetchTodo(ctx))
    todoAtom(ctx, data);
  } catch (e) {
    console.error(e)
  } finally {
    isLoadingAtom(ctx, false)
  }
})

Let’s test it without calling real api

import { expect, test } from 'vitest';
import { createTestCtx } from '@reatom/testing';
import { loadTodo, fetchTodo, todoAtom } from './main';

test('Test loadData atom', async () => {
  const ctx = createTestCtx()
  const track = ctx.subscribeTrack(todoAtom) 

  // Mock action with call
  ctx.mockAction(fetchTodo, (ctx) => Promise.resolve([{ id: 'foo' }]))

  await loadTodo(ctx)
  expect(track.lastInput()).toStrictEqual([{ id: 'foo' }])
})

Play live at stackblitz