Skip to content

Instantly share code, notes, and snippets.

@thebuilder
Last active November 5, 2020 10:34
Show Gist options
  • Save thebuilder/81301f27371416b49c3e5a920d86a6b9 to your computer and use it in GitHub Desktop.
Save thebuilder/81301f27371416b49c3e5a920d86a6b9 to your computer and use it in GitHub Desktop.
Mock Fetch requests in Storybook
import React from 'react'
import { storiesOf } from '@storybook/react'
import FetchStory from './FetchStory'
storiesOf('Fetch Example', module)
.add('Plain', () => (
<FetchStory mocks={{
matcher: '/api/signup',
response: {
body: {
value: 'success',
},
},
options: {
method: 'POST',
},
}]}>
<div>Add your components here</div>
</FetchStory>
))
/* eslint-disable import/no-extraneous-dependencies */
import React from 'react'
import PropTypes from 'prop-types'
import fetchMock from 'fetch-mock'
class FetchStory extends React.Component {
static displayName = 'FetchStory'
static propTypes = {
silent: PropTypes.bool,
/** Time in ms to delay the request */
throttle: PropTypes.number,
mocks: PropTypes.arrayOf(
PropTypes.shape({
/** The url to match against */
matcher: PropTypes.string.isRequired,
response: PropTypes.any,
options: PropTypes.shape({
method: PropTypes.string,
headers: PropTypes.object,
}),
}),
).isRequired,
}
static defaultProps = {
throttle: 300,
}
componentWillMount() {
this.mock()
}
componentWillUnmount() {
if (fetchMock.__prevProxy === this) {
this.unmock()
}
}
mock() {
// Clear mocks from a previous FetchStory
this.unmock()
const mocks = this.props.mocks
if (mocks) {
mocks.forEach(mock => {
fetchMock.mock({
...mock,
response: (url, opts) => {
if (!this.props.silent) {
console.info('fetch', url, opts)
}
let result = {
body: mock.response,
headers: new Headers({
'content-type': 'application/json',
}),
}
if (
mock.response.hasOwnProperty('body') ||
mock.response.hasOwnProperty('status') ||
mock.response.hasOwnProperty('headers')
) {
result = {
...result,
...mock.response,
}
}
return this.props.throttle
? new Promise(resolve => {
setTimeout(() => resolve(result), this.props.throttle)
})
: result
},
})
})
// Allow unmocked requests to fall through
fetchMock.catch((...args) => fetchMock.realFetch.apply(window, args))
fetchMock.__prevProxy = this
}
}
unmock() {
if (typeof fetchMock.restore === 'function') {
fetchMock.restore()
delete fetchMock.__prevProxy
}
}
render() {
return this.props.children
}
}
export default FetchStory
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment