Skip to main content
Version: 5.0

Mocking data for Storybook

Storybook is a great utility to do isolated development and testing, potentially speeding up development time greatly.

\<MockResolver /> enables easy loading of fixtures to see what different network responses might look like. It can be layered, composed, and even used for imperative fetches like create and update.

Setup

export default class ArticleResource extends Resource {
readonly id: number | undefined = undefined;
readonly content: string = '';
readonly author: number | null = null;
readonly contributors: number[] = [];

pk() {
return this.id?.toString();
}
static urlRoot = 'http://test.com/article/';
}

Fixtures

We'll test three cases: some interesting results in the list, an empty list, and data not existing so loading fallback is shown.

fixtures.ts
export default {
full: [
{
endpoint: ArticleResource.list(),
args: [{ maxResults: 10 }] as const,
response: [
{
id: 5,
content: 'have a merry christmas',
author: 2,
contributors: [],
},
{
id: 532,
content: 'never again',
author: 23,
contributors: [5],
},
],
},
{
endpoint: ArticleResource.update(),
args: [{ id: 532 }] as const,
response: {
id: 532,
content: 'updated "never again"',
author: 23,
contributors: [5],
},
},
],
empty: [
{
endpoint: ArticleResource.list(),
args: [{ maxResults: 10 }] as const,
response: [],
},
],
error: [
{
endpoint: ArticleResource.list(),
args: [{ maxResults: 10 }] as const,
response: { message: 'Bad request', status: 400, name: 'Not Found' },
error: true,
},
],
loading: [],
};

Decorators

You'll need to add the appropriate global decorators to establish the correct context.

This should resemble what you have added in initial setup

.storybook/preview.tsx

import { Suspense } from 'react';
import { CacheProvider, NetworkErrorBoundary } from 'rest-hooks';

export const decorators = [
Story => (
<CacheProvider>
<Suspense fallback="loading">
<NetworkErrorBoundary>
<Story />
</NetworkErrorBoundary>
</Suspense>
</CacheProvider>
),
];

Story

Wrapping our component with \<MockResolver /> enables us to declaratively control how Rest Hooks' fetches are resolved.

Here we select which fixtures should be used by storybook controls.

ArticleList.stories.tsx

import { MockResolver } from '@rest-hooks/test';
import type { Fixture } from '@rest-hooks/test';
import { Story } from '@storybook/react/types-6-0';

import ArticleList from 'ArticleList';
import options from './fixtures';

export default {
title: 'Pages/ArticleList',
component: ArticleList,
argTypes: {
result: {
description: 'Results',
defaultValue: 'full',
control: {
type: 'select',
options: Object.keys(options),
},
},
},
};

const Template: Story<{ result: keyof typeof options }> = ({ result }) => (
<MockResolver fixtures={options[result]}>
<ArticleList maxResults={10} />
</MockResolver>
);

export const FullArticleList = Template.bind({});

FullArticleList.args = {
result: 'full',
};