Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
20 changes: 18 additions & 2 deletions src/middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ function apiMiddleware({ getState }) {

// Parse the validated RSAA action
const callAPI = action[CALL_API];
var { endpoint, headers } = callAPI;
const { method, body, credentials, bailout, types } = callAPI;
var { endpoint, body, headers } = callAPI;
const { method, credentials, bailout, types } = callAPI;
const [requestType, successType, failureType] = normalizeTypeDescriptors(types);

// Should we bail out?
Expand Down Expand Up @@ -76,6 +76,22 @@ function apiMiddleware({ getState }) {
}
}

// Process [CALL_API].body function
if (typeof body === 'function') {
try {
body = body(getState());
} catch (e) {
return next(await actionWith(
{
...requestType,
payload: new RequestError('[CALL_API].body function failed'),
error: true
},
[action, getState()]
));
}
}

// Process [CALL_API].headers function
if (typeof headers === 'function') {
try {
Expand Down
73 changes: 73 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,55 @@ test('apiMiddleware must dispatch an error request FSA when [CALL_API].endpoint
actionHandler(anAction);
});

test('apiMiddleware must dispatch an error request FSA when [CALL_API].body fails', (t) => {
const anAction = {
[CALL_API]: {
endpoint: 'http://127.0.0.1/api/users/1',
body: () => {
throw new Error
},
method: 'GET',
types: [
{
type: 'REQUEST',
payload: 'ignoredPayload',
meta: 'someMeta'
},
'SUCCESS',
'FAILURE'
]
}
};
const doGetState = () => {};
const nextHandler = apiMiddleware({ getState: doGetState });
const doNext = (action) => {
t.pass('next handler called');
t.equal(
action.type,
'REQUEST',
'dispatched FSA has correct type property'
);
t.equal(
action.payload.message,
'[CALL_API].body function failed',
'dispatched FSA has correct payload property'
);
t.equal(
action.meta,
'someMeta',
'dispatched FSA has correct meta property'
);
t.ok(
action.error,
'dispatched FSA has correct error property'
);
};
const actionHandler = nextHandler(doNext);

t.plan(5);
actionHandler(anAction);
});

test('apiMiddleware must dispatch an error request FSA when [CALL_API].headers fails', (t) => {
const anAction = {
[CALL_API]: {
Expand Down Expand Up @@ -1231,6 +1280,30 @@ test('apiMiddleware must use an [CALL_API].endpoint function when present', (t)
actionHandler(anAction);
});

test('apiMiddleware must use an [CALL_API].body function when present', (t) => {
const api = nock('http://127.0.0.1')
.get('/api/users/1')
.reply(200);
const anAction = {
[CALL_API]: {
endpoint: 'http://127.0.0.1/api/users/1',
body: () => {
t.pass('[CALL_API].body function called');
return 'body';
},
method: 'GET',
types: ['REQUEST', 'SUCCESS', 'FAILURE']
}
};
const doGetState = () => {};
const nextHandler = apiMiddleware({ getState: doGetState });
const doNext = (action) => {};
const actionHandler = nextHandler(doNext);

t.plan(1);
actionHandler(anAction);
});

test('apiMiddleware must use an [CALL_API].headers function when present', (t) => {
const api = nock('http://127.0.0.1')
.get('/api/users/1')
Expand Down