Switching fetch
Easily mock your real API data, simply by using your app.
Swetch replaces any fetch
. Use the exported function to set up your swetch instance.
We need something that can save the request data.
npx @taywa/swetch
Needs node 14+ for latest syntax. We recommend running this in a docker container.
const fetch = swetch({ record: process.env.SWETCH_RECORD })
When
record
is truthy, requests are passed through and response data is saved. When falsy, saved response data is returned instead.
const testFetch = swetch(/* swetch config */)
testFetch('http://your.app/some/resource', {
method: 'post',
mode: 'cors',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: 'cool',
}),
})
.then(response => response.json())
.then(json => {})
.catch(error => {})
const testClient = new ApolloClient({
link: new HttpLink({
fetch: swetch(/* swetch config */),
}),
})
const testInstance = axios.create()
testInstance.interceptors.request.use(axiosInterceptor(/* swetch config */))
Configuring these clients might vary slightly when using versions made for specific frameworks.
This package doesn't provide a main entry point, since it provides separate server and browser modules (f.e. server uses fs
, which isn't available in browsers and would brick browser imports). There are several exports for this package, pick the one that works best for you.
// latest syntax es modules
import swetch from '@taywa/swetch/src/lib/swetch'
import axiosInterceptor from '@taywa/swetch/src/lib/axiosInterceptor'
import server from '@taywa/swetch/src/lib/server'
// transpiled es modules
import swetch from '@taywa/swetch/dist/esm/swetch'
import axiosInterceptor from '@taywa/swetch/dist/esm/axiosInterceptor'
import server from '@taywa/swetch/dist/esm/server'
// transpiled common js
const swetch = require('@taywa/swetch/dist/cjs/swetch')
const axiosInterceptor = require('@taywa/swetch/dist/cjs/axiosInterceptor')
const server = require('@taywa/swetch/dist/cjs/server')
When you're recording, run the parts of your app you want to mock (f.e. visit the pages you want to test) and you should see swetch saving the responses (in .swetch
by default).
When not recording, that data is used instead of passing the request on.
Note that only exact same requests will return the same data. Passing different variables in the post body of a request to the same URL will result in a 404 response, if not specifically recorded.
Property | Default | Info |
---|---|---|
port | 8008 |
The port the server should listen on. |
dataDirectory | '.swetch' |
The directory to save data to. |
ignoreHeaders | ['date', 'expires', 'age', 'content-encoding'] |
The headers to discard before saving data. All lowercase, not merged with defaults. |
getRequestHash | getRequestHash.mjs | A function taking a request URL string & an init object, and returning a string identifying that request. Allows for customization if requests contain timestamped data. Not available via cli/npx. |
getRelativeResourceDirectory | getRelativeResourceDirectory.mjs | A function taking a URL string & an init object, and returning a directory path string. Allows for customization of subfolders. Not available via cli/npx. |
serializeResponse | serializeResponse.mjs | A function taking the server config object and a Response, and returning a json string to be saved. Can be async. Not available via cli/npx. |
respond | respond.mjs | A function taking the server config object, the Koa ctx , a json string (originally returned from serializeResponse ) and an errors array to set a response on ctx . Not available via cli/npx. |
server({
port: 8009,
dataDirectory: '.responses',
ignoreHeaders: ['date', 'expires', 'connection'],
getRequestHash: (resource, init) => resource.replace(/\/+/g, '-'),
getRelativeResourceDirectory: (resource, init) => '/',
serializeResponse: async (config, response) => await response.text(),
respond: (config, ctx, data, errors) => {
ctx.body = 'Hello Swetch'
},
})
Property | Default | Info |
---|---|---|
server | 'http://127.0.0.1:8008' |
The swetch server address |
record | false |
Whether to save requests made by this instance |
origin | The host where your data resides (falls back onto location.host ). Only required if swetch server doesn't run on the origin, f.e. if it runs in a docker container. |
const testFetch = swetch({
server: 'http://127.0.0.1:8009',
record: !process.env.IS_CI,
origin: 'http://mycontainer',
})
const testInterceptor = axiosInterceptor({
server: 'http://127.0.0.1:8009',
record: !process.env.IS_CI,
origin: 'http://mycontainer',
})
Swetch stands between your app and your API. Whenever your app would make a request, swetch sends that request's details to the swetch server instead, which then makes that request and returns the result to swetch, which in turn returns it to your app. Swetch is basically a proxy.
What this enables you to do is record these requests with the swetch server and at another time return them directly, removing the need for real infrastructure.
Swetch unintrusively ties into your preferred API client. Just replace your fetch with what's returned from the swetch setup function.
Swetch uses isomorphic-fetch and can be used on server and client side.
Requests are identified by the hash of the arguments passed to the "fetch" replacement.
It's exclusively intended for real-world-data mocking during testing and doesn't guarantee performance or security.