Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# data-mocks

# modified by aiden for websocket support.
# will hopefully be deleted soon when merged in to upstream

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do this

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also write usage

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you fix this up?

[![GitHub license](https://img.shields.io/github/license/ovotech/data-mocks.svg)](https://github.com/grug/data-mocks)
![npm](https://img.shields.io/npm/dm/data-mocks.svg)

Expand Down
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom'
testEnvironment: 'jsdom',
};
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "data-mocks",
"version": "4.1.0",
"name": "@ovotech/data-mocks",
"version": "4.2.1",
"main": "dist/mocks.js",
"types": "dist/types.d.ts",
"repository": "git@github.com:grug/data-mocks.git",
"repository": "git@github.com:aidenscott2016/data-mocks.git",
"author": "Dave Cooper <dave@davecooper.dev>",
"license": "MIT",
"homepage": "https://github.com/grug/data-mocks",
"homepage": "https://github.com/aidenscott2016/data-mocks",
"scripts": {
"clean": "rimraf dist",
"prepublishOnly": "yarn build",
Expand All @@ -23,6 +23,7 @@
},
"dependencies": {
"fetch-mock": "^9.4.0",
"mock-socket": "^9.0.3",
"query-string": "^5.1.1",
"xhr-mock": "^2.5.1"
},
Expand Down
127 changes: 121 additions & 6 deletions src/mocks.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,65 @@
import 'isomorphic-fetch';
import axios from 'axios';
import fetchMock from 'fetch-mock';
import 'isomorphic-fetch';
import { Server as MockSever } from 'mock-socket';
import XHRMock, { proxy } from 'xhr-mock';
import {
injectMocks,
extractScenarioFromLocation,
injectMocks,
reduceAllMocksForScenario,
} from './mocks';
import { HttpMethod, Scenarios, MockConfig } from './types';
import XHRMock, { proxy } from 'xhr-mock';
import fetchMock from 'fetch-mock';
import { HttpMethod, MockConfig, Scenarios } from './types';

describe('data-mocks', () => {
beforeEach(() => {
fetchMock.resetHistory();
});

describe('Websockets', () => {
const testURL = 'ws://localhost/foo';
it('Spawns a working websocket server', async () => {
const onMessage = jest.fn();
const onConnect = jest.fn();
const scenarios: Scenarios = {
default: [
{
url: testURL,
method: 'WEBSOCKET',
server: (s) => {
s.on('connection', (socket) => {
console.log('conneted');
onConnect();
socket.on('message', (req) => {
onMessage();
socket.send(req.toString());
s.close();
});
});
},
},
],
};
injectMocks(scenarios, 'default');

const socket = new WebSocket(testURL);
let res;
socket.addEventListener('message', (data) => {
res = data.data;
socket.close();
});

await awaitSocket(socket, WebSocket.OPEN);
expect(onConnect).toBeCalled();

const message = 'hello world';
socket.send(message);
await awaitSocket(socket, WebSocket.CLOSED);
expect(onMessage).toBeCalled();

expect(res).toEqual(message);
});
});

describe('REST', () => {
describe('HTTP methods', () => {
const httpMethods: HttpMethod[] = [
Expand Down Expand Up @@ -50,7 +96,6 @@ describe('data-mocks', () => {
const xhrSpy = jest.spyOn(XHRMock, httpMethod.toLowerCase() as any);

injectMocks(scenarios, 'default');

expect(fetchSpy).toHaveBeenCalledTimes(2);
expect(fetchSpy.mock.calls[0][0]).toEqual(/foo/);
expect(fetchSpy.mock.calls[1][0]).toEqual(/bar/);
Expand Down Expand Up @@ -282,6 +327,8 @@ describe('data-mocks', () => {
});

describe('Scenarios', () => {
const websocketServerFn = jest.fn();
const anotherServerFn = jest.fn();
const scenarios: Scenarios = {
default: [
{
Expand All @@ -299,6 +346,22 @@ describe('data-mocks', () => {
responseHeaders: { token: 'bar' },
},
{ url: /bar/, method: 'POST', response: {}, responseCode: 200 },
{
url: /graphql/,
method: 'GRAPHQL',
operations: [
{
operationName: 'Query',
type: 'query',
response: { data: { test: 'data' } },
},
],
},
{
url: 'ws://localhost',
method: 'WEBSOCKET',
server: websocketServerFn,
},
],
someScenario: [
{
Expand All @@ -308,6 +371,18 @@ describe('data-mocks', () => {
responseCode: 401,
},
{ url: /baz/, method: 'POST', response: {}, responseCode: 200 },
{
url: /graphql/,
method: 'GRAPHQL',
operations: [
{
operationName: 'Query',
type: 'query',
response: { data: { test: 'different data' } },
},
],
},
{ url: 'ws://localhost', method: 'WEBSOCKET', server: anotherServerFn },
],
};

Expand Down Expand Up @@ -340,6 +415,22 @@ describe('data-mocks', () => {
responseHeaders: { token: 'bar' },
},
{ url: /bar/, method: 'POST', response: {}, responseCode: 200 },
{
url: /graphql/,
method: 'GRAPHQL',
operations: [
{
operationName: 'Query',
type: 'query',
response: { data: { test: 'data' } },
},
],
},
{
url: 'ws://localhost',
method: 'WEBSOCKET',
server: websocketServerFn,
},
]);
});

Expand Down Expand Up @@ -367,6 +458,18 @@ describe('data-mocks', () => {
responseCode: 200,
},
{ url: /baz/, method: 'POST', response: {}, responseCode: 200 },
{
url: /graphql/,
method: 'GRAPHQL',
operations: [
{
operationName: 'Query',
type: 'query',
response: { data: { test: 'different data' } },
},
],
},
{ url: 'ws://localhost', method: 'WEBSOCKET', server: anotherServerFn },
]);
});

Expand Down Expand Up @@ -536,3 +639,15 @@ describe('data-mocks', () => {
});
});
});

const awaitSocket = (socket, state) => {
return new Promise(function (resolve) {
setTimeout(function () {
if (socket.readyState === state) {
resolve(true);
} else {
awaitSocket(socket, state).then(resolve);
}
}, 1000);
});
};
33 changes: 30 additions & 3 deletions src/mocks.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import fetchMock from 'fetch-mock';
import XHRMock, { delay as xhrMockDelay, proxy } from 'xhr-mock';
import { parse } from 'query-string';
import { Server as MockServer } from 'mock-socket';
import {
Scenarios,
MockConfig,
Mock,
HttpMock,
GraphQLMock,
Operation,
WebSocketMock,
} from './types';

/**
Expand Down Expand Up @@ -44,13 +46,20 @@ export const injectMocks = (
throw new Error('Unable to instantiate mocks');
}

const restMocks = mocks.filter((m) => m.method !== 'GRAPHQL') as HttpMock[];
const restMocks = mocks.filter(
(m) => !['GRAPHQL', 'WEBSOCKET'].includes(m.method)
) as HttpMock[];
const graphQLMocks = mocks.filter(
(m) => m.method === 'GRAPHQL'
) as GraphQLMock[];

const webSocketMocks = mocks.filter(
(m) => m.method === 'WEBSOCKET'
) as WebSocketMock[];

restMocks.forEach(handleRestMock);
graphQLMocks.forEach(handleGraphQLMock);
webSocketMocks.forEach(handleWebsocketMock);

if (config?.allowXHRPassthrough) {
XHRMock.use(proxy);
Expand Down Expand Up @@ -79,12 +88,24 @@ export const reduceAllMocksForScenario = (
const mocks = defaultMocks.concat(scenarioMocks);

const initialHttpMocks = mocks.filter(
({ method }) => method !== 'GRAPHQL'
(m) => !['GRAPHQL', 'WEBSOCKET'].includes(m.method)
) as HttpMock[];
const initialGraphQlMocks = mocks.filter(
({ method }) => method === 'GRAPHQL'
) as GraphQLMock[];

const initialWebsocketMocks = mocks.filter(
(m) => m.method === 'WEBSOCKET'
) as WebSocketMock[];

const websocketMocksByUrl = initialWebsocketMocks.reduce<
Record<string, WebSocketMock>
>((result, mock) => {
const { url } = mock;
result[url] = mock;
return result;
}, {});

const httpMocksByUrlAndMethod = initialHttpMocks.reduce<
Record<string, HttpMock>
>((result, mock) => {
Expand Down Expand Up @@ -130,7 +151,9 @@ export const reduceAllMocksForScenario = (
}
) as GraphQLMock[];

return (httpMocks as any).concat(graphQlMocks);
const websocketMocks = Object.values(websocketMocksByUrl);

return [...httpMocks, ...graphQlMocks, ...websocketMocks];
};

/**
Expand Down Expand Up @@ -281,6 +304,10 @@ function handleGraphQLMock({ url, operations }: GraphQLMock) {
});
}

const handleWebsocketMock = ({ url, server }: WebSocketMock) => {
server(new MockServer(url));
};

/**
* Adds delay (in ms) before resolving a promise.
*/
Expand Down
10 changes: 9 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export {
injectMocks,
reduceAllMocksForScenario,
} from './mocks';
import { Server as MockServer } from 'mock-socket';

export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';

Expand All @@ -27,6 +28,13 @@ export type GraphQLMock = {
operations: Array<Operation>;
};

export type WebSocketServerMock = (mockServer: MockServer) => void;
export type WebSocketMock = {
url: string;
method: 'WEBSOCKET';
server: WebSocketServerMock;
};

export type Operation = {
type: 'query' | 'mutation';
operationName: string;
Expand All @@ -36,7 +44,7 @@ export type Operation = {
delay?: number;
};

export type Mock = HttpMock | GraphQLMock;
export type Mock = HttpMock | GraphQLMock | WebSocketMock;

export type Scenarios = {
default: Mock[];
Expand Down
4 changes: 2 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"removeComments": true /* Do not emit comments to output. */,
"strict": true /* Enable all strict type-checking options. */,
"noImplicitAny": false /* Raise error on expressions and declarations with an implied 'any' type. */,
"noUnusedLocals": true /* Report errors on unused locals. */,
"noUnusedParameters": true /* Report errors on unused parameters. */,
"noUnusedLocals": false /* Report errors on unused locals. */,
"noUnusedParameters": false /* Report errors on unused parameters. */,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change me

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change comes from within, brother 😌

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inshallah

"lib": ["es2017", "dom"],
"esModuleInterop": true
},
Expand Down
Loading