Skip to content

Commit

Permalink
#110 add support for getContext and setContext side effects
Browse files Browse the repository at this point in the history
  • Loading branch information
matoilic committed Mar 24, 2018
1 parent 7023474 commit f3ef457
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 0 deletions.
35 changes: 35 additions & 0 deletions __tests__/expectSaga/assertions/get-context.test.js
@@ -0,0 +1,35 @@
import { getContext } from 'redux-saga/effects';
import expectSaga from 'expectSaga';
import { errorRegex, unreachableError } from './_helper';

function* saga() {
yield getContext('theAnswer');
}

test('getContext assertion passes', () =>
expectSaga(saga)
.getContext('theAnswer')
.run());

test('negative getContext assertion passes with wrong property name', () =>
expectSaga(saga)
.not.getContext('wrongAnswer')
.run());

test('getContext assertion fails with wrong property name', () =>
expectSaga(saga)
.getContext('wrongAnswer')
.run()
.then(unreachableError)
.catch(e => {
expect(e.message).toMatch(errorRegex);
}));

test('negative getContext assertion fails with correct property name', () =>
expectSaga(saga)
.not.getContext('theAnswer')
.run()
.then(unreachableError)
.catch(e => {
expect(e.message).toMatch(errorRegex);
}));
35 changes: 35 additions & 0 deletions __tests__/expectSaga/assertions/set-context.test.js
@@ -0,0 +1,35 @@
import { setContext } from 'redux-saga/effects';
import expectSaga from 'expectSaga';
import { errorRegex, unreachableError } from './_helper';

function* saga() {
yield setContext({ answer: 42 });
}

test('setContext assertion passes', () =>
expectSaga(saga)
.setContext({ answer: 42 })
.run());

test('negative setContext assertion passes with wrong properties', () =>
expectSaga(saga)
.not.setContext({ answer: 41 })
.run());

test('setContext assertion fails with wrong properties', () =>
expectSaga(saga)
.setContext({ answer: 41 })
.run()
.then(unreachableError)
.catch(e => {
expect(e.message).toMatch(errorRegex);
}));

test('negative setContext assertion fails with correct properties', () =>
expectSaga(saga)
.not.setContext({ answer: 42 })
.run()
.then(unreachableError)
.catch(e => {
expect(e.message).toMatch(errorRegex);
}));
53 changes: 53 additions & 0 deletions __tests__/expectSaga/providers/get-context.test.js
@@ -0,0 +1,53 @@
// @flow
import { getContext, put } from 'redux-saga/effects';
import expectSaga from 'expectSaga';
import * as m from 'expectSaga/matchers';
import { dynamic } from 'expectSaga/providers';

const contextVar = 'contextValue';

function* saga() {
const value = yield getContext(contextVar);

yield put({ type: 'DONE', payload: value });
}

test('uses provided value for `getContext`', () =>
expectSaga(saga)
.provide({
getContext(property, next) {
if (property === contextVar) {
return 42;
}

return next();
},
})
.put({ type: 'DONE', payload: 42 })
.run());

test('uses static provided values from redux-saga/effects', () =>
expectSaga(saga)
.provide([[getContext(contextVar), 42]])
.put({ type: 'DONE', payload: 42 })
.run());

test('uses static provided values from matchers', () =>
expectSaga(saga)
.provide([[m.getContext(contextVar), 42]])
.put({ type: 'DONE', payload: 42 })
.run());

test('dynamic values have access to effect', () =>
expectSaga(saga)
.provide([
[
m.getContext(contextVar),
dynamic(property => {
expect(property).toBe(contextVar);
return 42;
}),
],
])
.put({ type: 'DONE', payload: 42 })
.run());
17 changes: 17 additions & 0 deletions __tests__/expectSaga/providers/set-context.test.js
@@ -0,0 +1,17 @@
// @flow
import { setContext } from 'redux-saga/effects';
import expectSaga from 'expectSaga';

function* saga() {
yield setContext({ answer: 42 });
}

test('dynamic values have access to effect', () =>
expectSaga(saga)
.provide({
setContext(properties, next) {
expect(properties.answer).toBe(42);
return next();
},
})
.run());
2 changes: 2 additions & 0 deletions decls/index.js
Expand Up @@ -228,10 +228,12 @@ type Providers = {
cps?: Provider,
flush?: Provider,
fork?: Provider,
getContext?: Provider,
join?: Provider,
put?: Provider,
race?: Provider,
select?: Provider,
setContext?: Provider,
spawn?: Provider,
take?: Provider,
};
Expand Down
16 changes: 16 additions & 0 deletions src/expectSaga/index.js
Expand Up @@ -35,9 +35,11 @@ import {
CALL,
CPS,
FORK,
GET_CONTEXT,
PUT,
RACE,
SELECT,
SET_CONTEXT,
TAKE,
} from '../shared/keys';

Expand Down Expand Up @@ -83,7 +85,9 @@ const exposableEffects = {
[CALL]: 'call',
[CPS]: 'cps',
[FORK]: 'fork',
[GET_CONTEXT]: 'getContext',
[SELECT]: 'select',
[SET_CONTEXT]: 'setContext',
[ACTION_CHANNEL]: 'actionChannel',
};

Expand All @@ -99,6 +103,8 @@ export default function expectSaga(
[CALL]: new ArraySet(),
[CPS]: new ArraySet(),
[FORK]: new ArraySet(),
[GET_CONTEXT]: new ArraySet(),
[SET_CONTEXT]: new ArraySet(),
[SELECT]: new ArraySet(),
[ACTION_CHANNEL]: new ArraySet(),
};
Expand Down Expand Up @@ -484,10 +490,20 @@ export default function expectSaga(
call: createEffectTesterFromEffects('call', CALL, asEffect.call),
cps: createEffectTesterFromEffects('cps', CPS, asEffect.cps),
fork: createEffectTesterFromEffects('fork', FORK, asEffect.fork),
getContext: createEffectTesterFromEffects(
'getContext',
GET_CONTEXT,
asEffect.getContext,
),
put: createEffectTesterFromEffects('put', PUT, asEffect.put),
race: createEffectTesterFromEffects('race', RACE, asEffect.race),
select: createEffectTesterFromEffects('select', SELECT, asEffect.select),
spawn: createEffectTesterFromEffects('spawn', FORK, asEffect.fork),
setContext: createEffectTesterFromEffects(
'setContext',
SET_CONTEXT,
asEffect.setContext,
),
take: createEffectTesterFromEffects('take', TAKE, asEffect.take),
};

Expand Down
2 changes: 2 additions & 0 deletions src/expectSaga/matchers/index.js
Expand Up @@ -9,11 +9,13 @@ export const cancel = wrapEffectCreator(effects.cancel);
export const cancelled = wrapEffectCreator(effects.cancelled);
export const cps = wrapEffectCreator(effects.cps);
export const flush = wrapEffectCreator(effects.flush);
export const getContext = wrapEffectCreator(effects.getContext);
export const fork = wrapEffectCreator(effects.fork);
export const join = wrapEffectCreator(effects.join);
export const put = wrapEffectCreator(effects.put);
export const race = wrapEffectCreator(effects.race);
export const select = wrapEffectCreator(effects.select);
export const setContext = wrapEffectCreator(effects.setContext);
export const spawn = wrapEffectCreator(effects.spawn);
export const take = wrapEffectCreator(effects.take);

Expand Down
16 changes: 16 additions & 0 deletions src/expectSaga/parseEffect.js
Expand Up @@ -11,11 +11,13 @@ import {
CPS,
FLUSH,
FORK,
GET_CONTEXT,
JOIN,
NONE,
PUT,
RACE,
SELECT,
SET_CONTEXT,
TAKE,
} from '../shared/keys';

Expand Down Expand Up @@ -98,6 +100,13 @@ export default function parseEffect(effect: Object): Object {
providerKey: parsedEffect.detached ? 'spawn' : 'fork',
};

case is.notUndef((parsedEffect = asEffect.getContext(effect))):
return {
type: GET_CONTEXT,
effect: parsedEffect,
providerKey: 'getContext',
};

case is.notUndef((parsedEffect = asEffect.join(effect))):
return {
type: JOIN,
Expand All @@ -112,6 +121,13 @@ export default function parseEffect(effect: Object): Object {
providerKey: 'select',
};

case is.notUndef((parsedEffect = asEffect.setContext(effect))):
return {
type: SET_CONTEXT,
effect: parsedEffect,
providerKey: 'setContext',
};

case is.notUndef((parsedEffect = asEffect.actionChannel(effect))):
return {
type: ACTION_CHANNEL,
Expand Down
4 changes: 4 additions & 0 deletions src/expectSaga/provideValue.js
Expand Up @@ -11,10 +11,12 @@ import {
CPS,
FLUSH,
FORK,
GET_CONTEXT,
JOIN,
PUT,
RACE,
SELECT,
SET_CONTEXT,
TAKE,
} from '../shared/keys';

Expand Down Expand Up @@ -50,10 +52,12 @@ export const handlers = {

return NEXT;
},
[GET_CONTEXT]: 'getContext',
[JOIN]: 'join',
[PUT]: 'put',
[RACE]: 'race',
[SELECT]: 'select',
[SET_CONTEXT]: 'setContext',
[TAKE]: 'take',
};

Expand Down
2 changes: 2 additions & 0 deletions src/shared/keys.js
Expand Up @@ -7,10 +7,12 @@ export const CANCELLED = 'CANCELLED';
export const CPS = 'CPS';
export const FLUSH = 'FLUSH';
export const FORK = 'FORK';
export const GET_CONTEXT = 'GET_CONTEXT';
export const JOIN = 'JOIN';
export const NONE = 'NONE';
export const PUT = 'PUT';
export const RACE = 'RACE';
export const SELECT = 'SELECT';
export const SET_CONTEXT = 'SET_CONTEXT';
export const TAKE = 'TAKE';
export const HELPER = '@@redux-saga/HELPER';

0 comments on commit f3ef457

Please sign in to comment.