Skip to content

Add MswServer and shortcut functions #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jun 4, 2024
127 changes: 119 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ npm install msw@latest --save-dev
npx msw init <PUBLIC_DIR> # eg: public
```

Then configure it:

```js
// in ./src/msw.js
import { setupWorker } from "msw/browser";
Expand Down Expand Up @@ -44,7 +46,7 @@ export const worker = setupWorker(...getMswHandlers({
}));
```

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

```js
import React from "react";
Expand All @@ -57,8 +59,67 @@ worker.start().then(() => {
});
```

Another option is to use the `MswServer` class. This is useful if you must conditionally include data:

```js
// in ./src/msw.js
import { setupWorker } from "msw/browser";
import { MswServer } from "fakerest";

const 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',
}
};

const restServer = new MswServer();
restServer.init(data);

export const worker = setupWorker(...restServer.getHandlers());
```

### Sinon

```html
<script src="/path/to/FakeRest.min.js"></script>
<script src="/path/to/sinon.js"></script>
<script type="text/javascript">
var 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
var server = sinon.fakeServer.create();
server.respondWith(FakeRest.getSinonHandler({ data }));
</script>
```

Another option is to use the `SinonServer` class. This is useful if you must conditionally include data or interceptors:

```html
<script src="/path/to/FakeRest.min.js"></script>
<script src="/path/to/sinon.js"></script>
Expand All @@ -80,7 +141,7 @@ var data = {
}
};
// initialize fake REST server
var restServer = new FakeRest.Server();
var restServer = new FakeRest.SinonServer();
restServer.init(data);

// use sinon.js to monkey-patch XmlHttpRequest
Expand Down Expand Up @@ -111,7 +172,36 @@ const data = {
preferred_format: 'hardback',
}
};
const restServer = new FakeRest.FetchServer('http://localhost:3000');

fetchMock.mock(
'begin:http://localhost:3000',
FakeRest.getFetchMockHandler({ baseUrl: 'http://localhost:3000', data })
);
```

Another option is to use the `FetchMockServer` class. This is useful if you must conditionally include data or interceptors:

```js
import fetchMock from 'fetch-mock';
import FakeRest from 'fakerest';

const 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',
}
};
const restServer = new FakeRest.FetchMockServer({ baseUrl: 'http://localhost:3000' });
restServer.init(data);
fetchMock.mock('begin:http://localhost:3000', restServer.getHandler());
```
Expand Down Expand Up @@ -366,7 +456,7 @@ Operators are specified as suffixes on each filtered field. For instance, applyi

```js
// initialize a rest server with a custom base URL
var restServer = new FakeRest.Server('http://my.custom.domain'); // // only URLs starting with my.custom.domain will be intercepted
const restServer = new FakeRest.SinonServer({ baseUrl: 'http://my.custom.domain' }); // only URLs starting with my.custom.domain will be intercepted
restServer.toggleLogging(); // logging is off by default, enable it to see network calls in the console
// Set all JSON data at once - only if identifier name is 'id'
restServer.init(json);
Expand Down Expand Up @@ -406,24 +496,45 @@ restServer.setDefaultQuery(function(resourceName) {
restServer.setBatchUrl('/batch');

// you can create more than one fake server to listen to several domains
var restServer2 = new FakeRest.Server('http://my.other.domain');
const restServer2 = new FakeRest.SinonServer({ baseUrl: 'http://my.other.domain' });
// Set data collection by collection - allows to customize the identifier name
var authorsCollection = new FakeRest.Collection([], '_id');
const authorsCollection = new FakeRest.Collection({ items: [], identifierName: '_id' });
authorsCollection.addOne({ first_name: 'Leo', last_name: 'Tolstoi' }); // { _id: 0, first_name: 'Leo', last_name: 'Tolstoi' }
authorsCollection.addOne({ first_name: 'Jane', last_name: 'Austen' }); // { _id: 1, first_name: 'Jane', last_name: 'Austen' }
// collections have autoincremented identifier but accept identifiers already set
// collections have auto incremented identifiers by default but accept identifiers already set
authorsCollection.addOne({ _id: 3, first_name: 'Marcel', last_name: 'Proust' }); // { _id: 3, first_name: 'Marcel', last_name: 'Proust' }
restServer2.addCollection('authors', authorsCollection);
// collections are mutable
authorsCollection.updateOne(1, { last_name: 'Doe' }); // { _id: 1, first_name: 'Jane', last_name: 'Doe' }
authorsCollection.removeOne(3); // { _id: 3, first_name: 'Marcel', last_name: 'Proust' }

var server = sinon.fakeServer.create();
const server = sinon.fakeServer.create();
server.autoRespond = true;
server.respondWith(restServer.getHandler());
server.respondWith(restServer2.getHandler());
```

## Configure Identifiers Generation

By default, FakeRest uses an auto incremented sequence for the items identifiers. If you'd rather use UUIDs for instance but would like to avoid providing them when you insert new items, you can provide your own function:

```js
import FakeRest from 'fakerest';
import uuid from 'uuid';

const restServer = new FakeRest.SinonServer({ baseUrl: 'http://my.custom.domain', getNewId: () => uuid.v5() });
```

This can also be specified at the collection level:

```js
import FakeRest from 'fakerest';
import uuid from 'uuid';

const restServer = new FakeRest.SinonServer({ baseUrl: 'http://my.custom.domain' });
const authorsCollection = new FakeRest.Collection({ items: [], identifierName: '_id', getNewId: () => uuid.v5() });
```

## Development

```sh
Expand Down
42 changes: 42 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Upgrading to 4.0.0

## Constructors Of `FetchServer` and `Server` Take An Object

For `Server`:

```diff
import { Server } from 'fakerest';
import { data } from './data';

-const server = new Server('http://myapi.com');
+const server = new Server({ baseUrl: 'http://myapi.com' });
server.init(data);
```

For `FetchServer`:

```diff
import { FetchServer } from 'fakerest';
import { data } from './data';

-const server = new FetchServer('http://myapi.com');
+const server = new FetchServer({ baseUrl: 'http://myapi.com' });
server.init(data);
```

## Constructor Of `Collection` Take An Object

```diff
-const posts = new Collection([
- { id: 1, title: 'baz' },
- { id: 2, title: 'biz' },
- { id: 3, title: 'boz' },
-]);
+const posts = new Collection({
+ items: [
+ { id: 1, title: 'baz' },
+ { id: 2, title: 'biz' },
+ { id: 3, title: 'boz' },
+ ],
+});
```
35 changes: 32 additions & 3 deletions example/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,41 @@
import React from 'react';
import { Admin, ListGuesser, Resource } from 'react-admin';
import {
Admin,
Create,
EditGuesser,
ListGuesser,
Resource,
ShowGuesser,
} from 'react-admin';
import { dataProvider } from './dataProvider';

export const App = () => {
return (
<Admin dataProvider={dataProvider}>
<Resource name="books" list={ListGuesser} />
<Resource name="authors" list={ListGuesser} />
<Resource
name="books"
list={ListGuesser}
create={BookCreate}
edit={EditGuesser}
show={ShowGuesser}
/>
<Resource
name="authors"
list={ListGuesser}
edit={EditGuesser}
show={ShowGuesser}
/>
</Admin>
);
};

import { Edit, ReferenceInput, SimpleForm, TextInput } from 'react-admin';

export const BookCreate = () => (
<Create>
<SimpleForm>
<ReferenceInput source="author_id" reference="authors" />
<TextInput source="title" />
</SimpleForm>
</Create>
);
4 changes: 3 additions & 1 deletion example/fetchMock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import FakeRest from 'fakerest';
import { data } from './data';

export const initializeFetchMock = () => {
const restServer = new FakeRest.FetchServer('http://localhost:3000');
const restServer = new FakeRest.FetchServer({
baseUrl: 'http://localhost:3000',
});
if (window) {
// @ts-ignore
window.restServer = restServer; // give way to update data in the console
Expand Down
1 change: 1 addition & 0 deletions example/msw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { data } from './data';

export const worker = setupWorker(
...getMswHandlers({
baseUrl: 'http://localhost:3000',
data,
}),
);
Loading