From dd9cf354e21785d0f78687ae28cb9cb14a4f5192 Mon Sep 17 00:00:00 2001 From: Artur Charaev Date: Thu, 31 May 2018 22:34:25 +0300 Subject: [PATCH 1/3] attempt on tests --- package.json | 6 ++++-- test/index.js | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 test/index.js diff --git a/package.json b/package.json index aa67b02..c0a24f0 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "clean": "rimraf lib", "lint": "eslint src", "prepublish": "npm run lint && npm run clean && npm run build", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "babel-node test/index.js" }, "keywords": [ "redux", @@ -36,7 +36,9 @@ "eslint": "^3.13.1", "eslint-config-airbnb-base": "^11.0.1", "eslint-plugin-import": "^2.2.0", - "rimraf": "^2.5.4" + "rimraf": "^2.5.4", + "sinon": "^5.0.10", + "tape": "^4.9.0" }, "files": [ "README.md", diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..b7b07e1 --- /dev/null +++ b/test/index.js @@ -0,0 +1,38 @@ +import test from 'tape'; +import sinon from 'sinon'; +import createApiMiddleware, { + CALL_API, + CALL_API_PHASE, + callApiPhases, + actionWith, +} from '../src/index'; + +function sleep(ms, shouldResolve, response) { + return new Promise((resolve, reject) => ( + shouldResolve ? resolve(response) : reject(response) + )); +} + +// test('Tests ara running', (t) => { +// t.end(); +// }); + +test('Calls fetch function', (t) => { + const spy = sinon.spy(); + const apiMiddleware = createApiMiddleware({ callApi: spy }); + const doGetState = () => {}; + const doDispatch = () => {}; + const nextHandler = apiMiddleware({ getState: doGetState, dispatch: doDispatch }); + const doNext = () => {}; + const actionHandler = nextHandler(doNext); + actionHandler({ + [CALL_API]: { + types: ['REQUEST', 'SUCCESS', 'FAILURE'], + endpoint: 'endpoint', + options: {}, + }, + }); + console.log(spy.args); + t.true(spy.calledOnce); + t.end(); +}); From 5a3445ab0910609c6dd1f70e09a52183e4f2775b Mon Sep 17 00:00:00 2001 From: Artur Charaev Date: Tue, 5 Jun 2018 22:02:36 +0300 Subject: [PATCH 2/3] more tests --- test/index.js | 151 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 140 insertions(+), 11 deletions(-) diff --git a/test/index.js b/test/index.js index b7b07e1..3dc81ac 100644 --- a/test/index.js +++ b/test/index.js @@ -7,17 +7,39 @@ import createApiMiddleware, { actionWith, } from '../src/index'; -function sleep(ms, shouldResolve, response) { - return new Promise((resolve, reject) => ( - shouldResolve ? resolve(response) : reject(response) - )); +function makeSleep(ms, shouldResolve, response) { + return () => + new Promise((resolve, reject) => ( + setTimeout(() => ( + shouldResolve ? resolve(response) : reject(response) + ), ms) + ) + ); } -// test('Tests ara running', (t) => { -// t.end(); -// }); +test('Calls fetch function with given endpoint and options', (t) => { + const spy = sinon.spy(); + const apiMiddleware = createApiMiddleware({ callApi: spy }); + const doGetState = () => {}; + const doDispatch = () => {}; + const nextHandler = apiMiddleware({ getState: doGetState, dispatch: doDispatch }); + const doNext = () => {}; + const actionHandler = nextHandler(doNext); + const ENDPOINT = 'ENDPOINT'; + const OPTIONS = {}; + actionHandler({ + [CALL_API]: { + types: ['REQUEST', 'SUCCESS', 'FAILURE'], + endpoint: ENDPOINT, + options: OPTIONS, + }, + }); + t.true(spy.calledOnce); + t.true(spy.calledWith(ENDPOINT, OPTIONS)); + t.end(); +}); -test('Calls fetch function', (t) => { +test('Calls fetch function and makes endpoint and options', (t) => { const spy = sinon.spy(); const apiMiddleware = createApiMiddleware({ callApi: spy }); const doGetState = () => {}; @@ -25,14 +47,121 @@ test('Calls fetch function', (t) => { const nextHandler = apiMiddleware({ getState: doGetState, dispatch: doDispatch }); const doNext = () => {}; const actionHandler = nextHandler(doNext); + const ENDPOINT = 'ENDPOINT'; + const OPTIONS = {}; actionHandler({ [CALL_API]: { types: ['REQUEST', 'SUCCESS', 'FAILURE'], - endpoint: 'endpoint', - options: {}, + endpoint: () => ENDPOINT, + options: () => OPTIONS, }, }); - console.log(spy.args); t.true(spy.calledOnce); + t.true(spy.calledWith(ENDPOINT, OPTIONS)); + t.end(); +}); + +test('Calls batch requests', (t) => { + const spy = sinon.spy(); + const apiMiddleware = createApiMiddleware({ callApi: spy }); + const doGetState = () => {}; + const doDispatch = () => {}; + const nextHandler = apiMiddleware({ getState: doGetState, dispatch: doDispatch }); + const doNext = () => {}; + const actionHandler = nextHandler(doNext); + const ENDPOINT = 'ENDPOINT'; + const OPTIONS = {}; + actionHandler({ + [CALL_API]: { + types: ['REQUEST', 'SUCCESS', 'FAILURE'], + batch: [ + { + endpoint: () => ENDPOINT, + options: () => OPTIONS, + }, + { + endpoint: () => ENDPOINT, + options: () => OPTIONS, + }, + ], + }, + }); + t.true(spy.calledTwice); + t.true(spy.firstCall.calledWith(ENDPOINT, OPTIONS)); + t.true(spy.secondCall.calledWith(ENDPOINT, OPTIONS)); t.end(); }); + +test('Dispatches request action', (t) => { + const apiMiddleware = createApiMiddleware({ callApi: makeSleep(0, true, {}) }); + const doGetState = () => {}; + const doDispatch = sinon.spy(); + const nextHandler = apiMiddleware({ getState: doGetState, dispatch: doDispatch }); + const doNext = () => {}; + const actionHandler = nextHandler(doNext); + actionHandler({ + [CALL_API]: { + types: ['REQUEST', 'SUCCESS', 'FAILURE'], + endpoint: 'endpoint', + options: {}, + }, + }).then(() => { + t.true(doDispatch.firstCall.calledWith({ + type: 'REQUEST', + [CALL_API_PHASE]: callApiPhases.REQUEST, + })); + t.true(doDispatch.calledTwice); + t.end(); + }); +}); + +test('Dispatches success action', (t) => { + const RESPONSE = {}; + const apiMiddleware = createApiMiddleware({ callApi: makeSleep(0, true, RESPONSE) }); + const doGetState = () => {}; + const doDispatch = sinon.spy(); + const nextHandler = apiMiddleware({ getState: doGetState, dispatch: doDispatch }); + const doNext = () => {}; + const actionHandler = nextHandler(doNext); + actionHandler({ + [CALL_API]: { + types: ['REQUEST', 'SUCCESS', 'FAILURE'], + endpoint: 'endpoint', + options: {}, + }, + }).then(() => { + t.true(doDispatch.secondCall.calledWith({ + type: 'SUCCESS', + [CALL_API_PHASE]: callApiPhases.SUCCESS, + payload: RESPONSE, + })); + t.true(doDispatch.calledTwice); + t.end(); + }); +}); + +test('Dispatches failure action', (t) => { + const RESPONSE = new Error(); + const apiMiddleware = createApiMiddleware({ callApi: makeSleep(0, false, RESPONSE) }); + const doGetState = () => {}; + const doDispatch = sinon.spy(); + const nextHandler = apiMiddleware({ getState: doGetState, dispatch: doDispatch }); + const doNext = () => {}; + const actionHandler = nextHandler(doNext); + actionHandler({ + [CALL_API]: { + types: ['REQUEST', 'SUCCESS', 'FAILURE'], + endpoint: 'endpoint', + options: {}, + }, + }).then(() => { + t.true(doDispatch.secondCall.calledWith({ + type: 'FAILURE', + [CALL_API_PHASE]: callApiPhases.FAILURE, + payload: RESPONSE, + error: true, + })); + t.true(doDispatch.calledTwice); + t.end(); + }); +}); From 379e5f85680961a913569e0a7a146cee91f9fc65 Mon Sep 17 00:00:00 2001 From: Artur Charaev Date: Wed, 6 Jun 2018 16:23:12 +0300 Subject: [PATCH 3/3] more tests --- test/index.js | 67 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/test/index.js b/test/index.js index 3dc81ac..6ada580 100644 --- a/test/index.js +++ b/test/index.js @@ -4,7 +4,6 @@ import createApiMiddleware, { CALL_API, CALL_API_PHASE, callApiPhases, - actionWith, } from '../src/index'; function makeSleep(ms, shouldResolve, response) { @@ -108,7 +107,6 @@ test('Dispatches request action', (t) => { }).then(() => { t.true(doDispatch.firstCall.calledWith({ type: 'REQUEST', - [CALL_API_PHASE]: callApiPhases.REQUEST, })); t.true(doDispatch.calledTwice); t.end(); @@ -116,7 +114,7 @@ test('Dispatches request action', (t) => { }); test('Dispatches success action', (t) => { - const RESPONSE = {}; + const RESPONSE = 'RESPONSE'; const apiMiddleware = createApiMiddleware({ callApi: makeSleep(0, true, RESPONSE) }); const doGetState = () => {}; const doDispatch = sinon.spy(); @@ -132,7 +130,6 @@ test('Dispatches success action', (t) => { }).then(() => { t.true(doDispatch.secondCall.calledWith({ type: 'SUCCESS', - [CALL_API_PHASE]: callApiPhases.SUCCESS, payload: RESPONSE, })); t.true(doDispatch.calledTwice); @@ -157,7 +154,67 @@ test('Dispatches failure action', (t) => { }).then(() => { t.true(doDispatch.secondCall.calledWith({ type: 'FAILURE', - [CALL_API_PHASE]: callApiPhases.FAILURE, + payload: RESPONSE, + error: true, + })); + t.true(doDispatch.calledTwice); + t.end(); + }); +}); + +test('Dispatches single typed action with request and success action phase', (t) => { + const ACTION_TYPE = 'ACTION_TYPE'; + const RESPONSE = 'RESPONSE'; + const apiMiddleware = createApiMiddleware({ callApi: makeSleep(0, true, RESPONSE) }); + const doGetState = () => {}; + const doDispatch = sinon.spy(); + const nextHandler = apiMiddleware({ getState: doGetState, dispatch: doDispatch }); + const doNext = () => {}; + const actionHandler = nextHandler(doNext); + actionHandler({ + [CALL_API]: { + type: ACTION_TYPE, + endpoint: 'endpoint', + options: {}, + }, + }).then(() => { + t.true(doDispatch.firstCall.calledWith({ + type: ACTION_TYPE, + [CALL_API_PHASE]: callApiPhases.REQUEST, + })); + t.true(doDispatch.secondCall.calledWith({ + type: ACTION_TYPE, + [CALL_API_PHASE]: callApiPhases.SUCCESS, + payload: RESPONSE, + })); + t.true(doDispatch.calledTwice); + t.end(); + }); +}); + +test('Dispatches single typed action with request and failure action phase', (t) => { + const ACTION_TYPE = 'ACTION_TYPE'; + const RESPONSE = new Error(); + const apiMiddleware = createApiMiddleware({ callApi: makeSleep(0, false, RESPONSE) }); + const doGetState = () => {}; + const doDispatch = sinon.spy(); + const nextHandler = apiMiddleware({ getState: doGetState, dispatch: doDispatch }); + const doNext = () => {}; + const actionHandler = nextHandler(doNext); + actionHandler({ + [CALL_API]: { + type: ACTION_TYPE, + endpoint: 'endpoint', + options: {}, + }, + }).then(() => { + t.true(doDispatch.firstCall.calledWith({ + type: ACTION_TYPE, + [CALL_API_PHASE]: callApiPhases.REQUEST, + })); + t.true(doDispatch.secondCall.calledWith({ + type: ACTION_TYPE, + [CALL_API_PHASE]: callApiPhases.FALIURE, payload: RESPONSE, error: true, }));