Testing
Testing a component or code using CoreQL could be done with the Jest Fetch Mock package or mirage.js.
Mirage is the recommended way for projects, however, Jest Fetch Mock is better for simple projects or projects with a big API that will require more work to recreate it using Mirage.
Using Jest Fetch Mock
This library is the easiest way to do it, it requires little setup and you can set what every fetch should reply on a per-test basis.
First, install it.
yarn add jest-fetch-mockIn your setup tests file, create one if you don't have it, add the following:
import fetch from 'jest-fetch-mock';global.fetch = fetch;If you are using TypeScript add this:
import { GlobalWithFetchMock } from 'jest-fetch-mock';const customGlobal: GlobalWithFetchMock = global as GlobalWithFetchMock;customGlobal.fetch = require('jest-fetch-mock');customGlobal.fetchMock = customGlobal.fetch;Now in your tests, before rendering a component using useResource or useCollection, or before calling a function using some API Client method add the following line:
fetch.once(JSON.stringify(mockData));This will use mockData as the response of the next fetch call.
For more information and features read the package readme.
Mirage.js
Mirage is more complex than Jest Fetch Mock but at the same time is more powerful. The idea of this library is to create a mocked API in-memory which will intercept all your requests, this way you could configure it to reply to certain endpoints using fake data.
First, install it with:
yarn add miragejsThen create a make-server.js file somewhere in your application with something similar to this one:
import { Server, Model, Factory, JSONAPISerializer } from 'miragejs';import { camelize } from "inflected";import faker from 'faker';
export default function makeServer({ environment = 'development', trackRequests = false,}) { return new Server({ environment, trackRequests,
serializers: { // use the JSONAPISerializer to make Mirage follow the JSON:API spec application: JSONAPISerializer.extend({ alwaysIncludeLinkageData: true, keyForAttribute(attr) { // use camel case for attribute keys return camelize(attr); }, }), },
models: { users: Model, },
factories: { // A factory to create new users users: Factory.extend({ avatarUrl() { return faker.internet.avatar(); }, firstName() { return faker.name.firstName(); }, lastName() { return faker.name.lastName(); }, fullName() { return faker.name.findName(this.firstName, this.lastName); }, email() { return faker.internet.email(this.firstName, this.lastName, 'able.co'); }, }), },
routes() { // by default CoreQL uses api/v2 but you could change this // using an environment variable this.namespace = 'api/v2';
// handle all possible /users route this.resource('users');
// any other route will passthrough Mirage and reach the network this.passthrough(); }, });}Now in your tests import it.
import makeServer from './make-server';And then create a new instance per test using beforeEach and afterEach.
let server;
beforeEach(() => { // create a new server before each test // with the test environment this will // reduce latency to 0 server = makeServer({ environment: 'test' });});
afterEach(() => { // shutdown the server after each test server.shutdown();});And in each test ask the server to create users.
test('Render list of users', () => { server.createList('user', 10); // here test your component fetching `/api/users`});With this, you don't need to think anymore about the data you will need a per-test basis, instead Mirage is creating it for you when you request it to do it.