Skip to content

Commit

Permalink
feat: Add createDemoClient to help with demo
Browse files Browse the repository at this point in the history
This new function will create a client like createMockClient but without
the jest mock. It will be useful for demo in documentation because isn't
defined in there context. Two usecases are in storybook and in the
cozy-ui documentation.
  • Loading branch information
cballevre committed Dec 14, 2023
1 parent ece1e7d commit cdc7c87
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 17 deletions.
35 changes: 33 additions & 2 deletions docs/api/cozy-client/README.md
Expand Up @@ -201,9 +201,39 @@ Rejects with canceled: true as soon as cancel is called

***

### createFakeClient

**createFakeClient**(`options?`): [`CozyClient`](classes/CozyClient.md)

Creates a client with pre-filled store
This can be useful for demo in documentation (e.g. storybook)

* client.{query,save} are replaced with empty functions
* client.stackClient.fetchJSON is replaced with empty functions

*Parameters*

| Name | Type | Description |
| :------ | :------ | :------ |
| `options` | `Object` | Options |
| `options.clientFunctions` | `any` | - |
| `options.clientOptions` | `any` | - |
| `options.queries` | `any` | - |
| `options.remote` | `any` | - |

*Returns*

[`CozyClient`](classes/CozyClient.md)

*Defined in*

[packages/cozy-client/src/mock.js:92](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/mock.js#L92)

***

### createMockClient

**createMockClient**(`options`): [`CozyClient`](classes/CozyClient.md)
**createMockClient**(`options?`): [`CozyClient`](classes/CozyClient.md)

Creates a client suitable for use in tests

Expand All @@ -215,6 +245,7 @@ Creates a client suitable for use in tests
| Name | Type | Description |
| :------ | :------ | :------ |
| `options` | `Object` | Options |
| `options.clientFunctions` | `any` | - |
| `options.clientOptions` | `any` | - |
| `options.queries` | `any` | - |
| `options.remote` | `any` | - |
Expand All @@ -225,7 +256,7 @@ Creates a client suitable for use in tests

*Defined in*

[packages/cozy-client/src/mock.js:45](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/mock.js#L45)
[packages/cozy-client/src/mock.js:48](https://github.com/cozy/cozy-client/blob/master/packages/cozy-client/src/mock.js#L48)

***

Expand Down
66 changes: 57 additions & 9 deletions packages/cozy-client/src/mock.js
@@ -1,3 +1,5 @@
import merge from 'lodash/merge'

import CozyClient from './CozyClient'
import { receiveQueryResult, receiveQueryError, initQuery } from './store'
import { normalizeDoc } from 'cozy-stack-client'
Expand All @@ -19,7 +21,7 @@ const fillQueryInsideClient = (client, queryName, queryOptions) => {
}
}

const mockedQueryFromMockedRemoteData = remoteData => qdef => {
const mockedQueryFromMockedRemoteData = remoteData => async qdef => {
if (!remoteData) {
return { data: null }
}
Expand All @@ -40,25 +42,71 @@ const mockedQueryFromMockedRemoteData = remoteData => qdef => {
* @param {object} [options.queries] Prefill queries inside the store
* @param {object} [options.remote] Mock data from the server
* @param {object} [options.clientOptions] Options passed to the client
* @param {object} [options.clientFunctions] Functions to overide client functions
* @returns {CozyClient}
*/
const createMockClient = ({
queries,
remote,
clientOptions,
clientFunctions
} = {}) => {
const mockedQuery = jest
.fn()
.mockImplementation(mockedQueryFromMockedRemoteData(remote))

const clientFunctionsMerge = merge(
{
query: mockedQuery,
save: jest.fn(),
saveAll: jest.fn(),
stackClient: {
fetchJSON: jest.fn()
}
},
clientFunctions
)

return createFakeClient({
queries,
remote,
clientOptions,
clientFunctions: clientFunctionsMerge
})
}

/**
* Creates a client with pre-filled store
* This can be useful for demo in documentation (e.g. storybook)
*
* - client.{query,save} are replaced with empty functions
* - client.stackClient.fetchJSON is replaced with empty functions
*
* @param {object} options Options
* @param {object} [options.queries] Prefill queries inside the store
* @param {object} [options.remote] Mock data from the server
* @param {object} [options.clientOptions] Options passed to the client
* @param {object} [options.clientFunctions] Functions to overide client functions useful for testing
* @returns {CozyClient}
*/
const createMockClient = ({ queries, remote, clientOptions }) => {
const createFakeClient = ({
queries,
remote,
clientOptions,
clientFunctions
} = {}) => {
const client = new CozyClient(clientOptions || {})
client.ensureStore()

for (let [queryName, queryOptions] of Object.entries(queries || {})) {
fillQueryInsideClient(client, queryName, queryOptions)
}

client.query = jest
.fn()
.mockImplementation(mockedQueryFromMockedRemoteData(remote))
client.query = mockedQueryFromMockedRemoteData(remote)

client.save = jest.fn()
client.saveAll = jest.fn()
client.stackClient.fetchJSON = jest.fn()
merge(client, clientFunctions)

return client
}

export { createMockClient }
export { createMockClient, createFakeClient }
37 changes: 32 additions & 5 deletions packages/cozy-client/src/mock.spec.js
@@ -1,15 +1,15 @@
import { createMockClient } from './mock'
import { createFakeClient, createMockClient } from './mock'

import { Q } from 'cozy-client'

describe('createMockClient', () => {
describe('createFakeClient', () => {
const simpsonsFixture = [
{ _id: 'homer', name: 'Homer' },
{ _id: 'marge', name: 'Marge' }
]

it('should mock queries inside the store', () => {
const client = createMockClient({
const client = createFakeClient({
queries: {
simpsons: {
data: simpsonsFixture,
Expand All @@ -34,7 +34,7 @@ describe('createMockClient', () => {
})

it('should mock query with data passed in "remote" option', async () => {
const client = createMockClient({
const client = createFakeClient({
remote: {
'io.cozy.simpsons': simpsonsFixture
}
Expand All @@ -44,12 +44,39 @@ describe('createMockClient', () => {
})

it('should mock query even if the doctype has not been mocked', async () => {
const client = createMockClient({
const client = createFakeClient({
remote: {
'io.cozy.simpsons': simpsonsFixture
}
})
const simpsons = await client.query(Q('io.cozy.adams'))
await expect(simpsons.data.map(x => x._id)).toEqual([])
})

it('should mock function with clientFunctions', async () => {
const client = createFakeClient({
clientFunctions: {
stackClient: {
fetchJSON: () =>
Promise.resolve({ data: [{ _id: 'homer', name: 'Homer' }] })
}
}
})

const simpsons = await client.stackClient.fetchJSON('io.cozy.simpsons')
expect(simpsons.data).toEqual([{ _id: 'homer', name: 'Homer' }])
})

describe('createMockClient', () => {
it('should mock basic client functions', async () => {
const client = createMockClient()

expect(JSON.stringify(client.query)).toEqual(JSON.stringify(jest.fn()))
expect(JSON.stringify(client.save)).toEqual(JSON.stringify(jest.fn()))
expect(JSON.stringify(client.saveAll)).toEqual(JSON.stringify(jest.fn()))
expect(JSON.stringify(client.stackClient.fetchJSON)).toEqual(
JSON.stringify(jest.fn())
)
})
})
})
24 changes: 23 additions & 1 deletion packages/cozy-client/types/mock.d.ts
Expand Up @@ -8,11 +8,33 @@
* @param {object} [options.queries] Prefill queries inside the store
* @param {object} [options.remote] Mock data from the server
* @param {object} [options.clientOptions] Options passed to the client
* @param {object} [options.clientFunctions] Functions to overide client functions
* @returns {CozyClient}
*/
export function createMockClient({ queries, remote, clientOptions }: {
export function createMockClient({ queries, remote, clientOptions, clientFunctions }?: {
queries: object;
remote: object;
clientOptions: object;
clientFunctions: object;
}): CozyClient;
/**
* Creates a client with pre-filled store
* This can be useful for demo in documentation (e.g. storybook)
*
* - client.{query,save} are replaced with empty functions
* - client.stackClient.fetchJSON is replaced with empty functions
*
* @param {object} options Options
* @param {object} [options.queries] Prefill queries inside the store
* @param {object} [options.remote] Mock data from the server
* @param {object} [options.clientOptions] Options passed to the client
* @param {object} [options.clientFunctions] Functions to overide client functions useful for testing
* @returns {CozyClient}
*/
export function createFakeClient({ queries, remote, clientOptions, clientFunctions }?: {
queries: object;
remote: object;
clientOptions: object;
clientFunctions: object;
}): CozyClient;
import CozyClient from "./CozyClient";

0 comments on commit cdc7c87

Please sign in to comment.