SkillAgentSearch skills...

FakeRest

Patch fetch/XMLHttpRequest to fake a REST API server in the browser, based on JSON data.

Install / Use

/learn @marmelab/FakeRest
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

FakeRest

A browser library that intercepts AJAX calls to mock a REST server based on JSON data.

Use it in conjunction with MSW, fetch-mock, or Sinon.js to test JavaScript REST clients on the client side (e.g. single page apps) without a server.

See it in action in the react-admin demo (source code).

Installation

npm install fakerest --save-dev

Usage

FakeRest lets you create a handler function that you can pass to an API mocking library. FakeRest supports MSW, fetch-mock, and Sinon. If you have the choice, we recommend using MSW, as it will allow you to inspect requests as you usually do in the dev tools network tab.

MSW

Install MSW and initialize it:

npm install msw@latest --save-dev
npx msw init <PUBLIC_DIR> # eg: public

Then configure an MSW worker:

// in ./src/fakeServer.js
import { http } from 'msw';
import { setupWorker } from "msw/browser";
import { getMswHandler } from "fakerest";

const handler = getMswHandler({
    baseUrl: 'http://localhost:3000',
    data: {
        'authors': [
            { id: 0, first_name: 'Leo', last_name: 'Tolstoi' },
            { id: 1, first_name: 'Jane', last_name: 'Austen' }
        ],
        'books': [
            { id: 0, author_id: 0, title: 'Anna Karenina' },
            { id: 1, author_id: 0, title: 'War and Peace' },
            { id: 2, author_id: 1, title: 'Pride and Prejudice' },
            { id: 3, author_id: 1, title: 'Sense and Sensibility' }
        ],
        'settings': {
            language: 'english',
            preferred_format: 'hardback',
        }
    }
});
export const worker = setupWorker(
    // Make sure you use a RegExp to target all calls to the API
    http.all(/http:\/\/localhost:3000/, handler)
);

Finally, call the worker.start() method before rendering your application. For instance, in a Vite React application:

import React from "react";
import ReactDom from "react-dom";
import { App } from "./App";
import { worker } from "./fakeServer";

worker.start({
    quiet: true, // Instruct MSW to not log requests in the console
    onUnhandledRequest: 'bypass', // Instruct MSW to ignore requests we don't handle
}).then(() => {
  ReactDom.render(<App />, document.getElementById("root"));
});

FakeRest will now intercept every fetch request to the REST server.

fetch-mock

Install fetch-mock:

npm install fetch-mock --save-dev

You can then create a handler and pass it to fetch-mock:

import fetchMock from 'fetch-mock';
import { getFetchMockHandler } from "fakerest";

const handler = getFetchMockHandler({
    baseUrl: 'http://localhost:3000',
    data: {
        'authors': [
            { id: 0, first_name: 'Leo', last_name: 'Tolstoi' },
            { id: 1, first_name: 'Jane', last_name: 'Austen' }
        ],
        'books': [
            { id: 0, author_id: 0, title: 'Anna Karenina' },
            { id: 1, author_id: 0, title: 'War and Peace' },
            { id: 2, author_id: 1, title: 'Pride and Prejudice' },
            { id: 3, author_id: 1, title: 'Sense and Sensibility' }
        ],
        'settings': {
            language: 'english',
            preferred_format: 'hardback',
        }
    }
});

fetchMock.mock('begin:http://localhost:3000', handler);

FakeRest will now intercept every fetch request to the REST server.

Sinon

Install Sinon:

npm install sinon --save-dev

Then, configure a Sinon server:

import sinon from 'sinon';
import { getSinonHandler } from "fakerest";

const handler = getSinonHandler({
    baseUrl: 'http://localhost:3000',
    data: {
        'authors': [
            { id: 0, first_name: 'Leo', last_name: 'Tolstoi' },
            { id: 1, first_name: 'Jane', last_name: 'Austen' }
        ],
        'books': [
            { id: 0, author_id: 0, title: 'Anna Karenina' },
            { id: 1, author_id: 0, title: 'War and Peace' },
            { id: 2, author_id: 1, title: 'Pride and Prejudice' },
            { id: 3, author_id: 1, title: 'Sense and Sensibility' }
        ],
        'settings': {
            language: 'english',
            preferred_format: 'hardback',
        }
    },
});

// use sinon.js to monkey-patch XmlHttpRequest
const sinonServer = sinon.fakeServer.create();
// this is required when doing asynchronous XmlHttpRequest
sinonServer.autoRespond = true;
sinonServer.respondWith(handler);

FakeRest will now intercept every XMLHttpRequest request to the REST server.

REST Syntax

FakeRest uses a simple REST syntax described below.

Get A Collection of records

GET /[name] returns an array of records in the name collection. It accepts 4 query parameters: filter, sort, range, and embed. It responds with a status 200 if there is no pagination, or 206 if the list of items is paginated. The response mentions the total count in the Content-Range header.

GET /books?filter={"author_id":1}&embed=["author"]&sort=["title","desc"]&range=[0-9]

HTTP 1.1 200 OK
Content-Range: items 0-1/2
Content-Type: application/json
[
    { "id": 3, "author_id": 1, "title": "Sense and Sensibility", "author": { "id": 1, "first_name": "Jane", "last_name": "Austen" } },
    { "id": 2, "author_id": 1, "title": "Pride and Prejudice", "author": { "id": 1, "first_name": "Jane", "last_name": "Austen" } }
]

The filter param must be a serialized object literal describing the criteria to apply to the search query. See the supported filters for more details.

GET /books?filter={"author_id":1} // return books where author_id is equal to 1
HTTP 1.1 200 OK
Content-Range: items 0-1/2
Content-Type: application/json
[
    { "id": 2, "author_id": 1, "title": "Pride and Prejudice" },
    { "id": 3, "author_id": 1, "title": "Sense and Sensibility" }
]

// array values are possible
GET /books?filter={"id":[2,3]} // return books where id is in [2,3]
HTTP 1.1 200 OK
Content-Range: items 0-1/2
Content-Type: application/json
[
    { "id": 2, "author_id": 1, "title": "Pride and Prejudice" },
    { "id": 3, "author_id": 1, "title": "Sense and Sensibility" }
]

// use the special "q" filter to make a full-text search on all text fields
GET /books?filter={"q":"and"} // return books where any of the book properties contains the string 'and'

HTTP 1.1 200 OK
Content-Range: items 0-2/3
Content-Type: application/json
[
    { "id": 1, "author_id": 0, "title": "War and Peace" },
    { "id": 2, "author_id": 1, "title": "Pride and Prejudice" },
    { "id": 3, "author_id": 1, "title": "Sense and Sensibility" }
]

// use _gt, _gte, _lte, _lt, or _neq suffix on filter names to make range queries
GET /books?filter={"price_lte":20} // return books where the price is less than or equal to 20
GET /books?filter={"price_gt":20} // return books where the price is greater than 20

// when the filter object contains more than one property, the criteria combine with an AND logic
GET /books?filter={"published_at_gte":"2015-06-12","published_at_lte":"2015-06-15"} // return books published between two dates

You can also filter by relationship fields when using embed:

GET /books?embed=["author"]&filter={"author.name":"Leo Tolstoi"} // return books by Leo Tolstoi
GET /books?embed=["author"]&filter={"author.age_gte":50} // return books by authors aged 50 or more

The sort param must be a serialized array literal defining first the property used for sorting, then the sorting direction.

GET /author?sort=["date_of_birth","asc"]  // return authors, the oldest first
GET /author?sort=["date_of_birth","desc"]  // return authors, the youngest first

You can also sort by relationship fields when using embed:

GET /books?embed=["author"]&sort=["author.name","asc"]  // return books sorted by author name
GET /books?embed=["author"]&sort=["author.name","desc"] // return books sorted by author name in reverse order

The range param defines the number of results by specifying the rank of the first and last results. The first result is #0.

GET /books?range=[0-9] // return the first 10 books
GET /books?range=[10-19] // return the 10 next books

The embed param sets the related objects or collections to be embedded in the response.

// embed author in books
GET /books?embed=["author"]
HTTP 1.1 200 OK
Content-Range: items 0-3/4
Content-Type: application/json
[
    { "id": 0, "author_id": 0, "title": "Anna Karenina", "author": { "id": 0, "first_name": "Leo", "last_name": "Tolstoi" } },
    { "id": 1, "author_id": 0, "title": "War and Peace", "author": { "id": 0, "first_name": "Leo", "last_name": "Tolstoi" } },
    { "id": 2, "author_id": 1, "title": "Pride and Prejudice", "author": { "id": 1, "first_name": "Jane", "last_name": "Austen" } },
    { "id": 3, "author_id": 1, "title": "Sense and Sensibility", "author": { "id": 1, "first_name": "Jane", "last_name": "Austen" } }
]

// embed books in author
GET /authors?embed=["books"]
HTTP 1.1 200 OK
Content-Range: items 0-1/2
Content-Type: application/json
[
    { id: 0, first_name: 'Leo', last_name: 'Tolstoi', books: [{ id: 0, author_id: 0, title: 'Anna Karenina' }, { id: 1, author_id: 0, title: 'War and Peace' }] },
    { id: 1, first_name: 'Jane', last_name: 'Austen', books: [{ id: 2, author_id: 1, title: 'Pride 
View on GitHub
GitHub Stars451
CategoryDevelopment
Updated11h ago
Forks50

Languages

TypeScript

Security Score

100/100

Audited on Mar 27, 2026

No findings