Security News
Cloudflare Adds Security.txt Setup Wizard
Cloudflare has launched a setup wizard allowing users to easily create and manage a security.txt file for vulnerability disclosure on their websites.
redux-mock-store-await-actions
Advanced tools
Waits for specific actions to be dispatched or a timeout expires.
Waits for specific actions to be dispatched or a timeout expires.
NOTE: This module only works with redux-mock-store and shall only be used for testing purposes. Support for real Redux store is not provided.
$ npm install redux-mock-store-await-actions --save-dev
Consider the following example:
function login(username, password) {
return async (dispatch) => {
dispatch({ type: 'LOGIN_START', payload: { username, password } });
try {
const user = await fetch('/login', {
headers: { 'Content-Type': 'application/json' },
method: 'POST',
body: JSON.stringify({ username, password })
});
dispatch({ type: 'LOGIN_SUCCESS', payload: user });
} catch (err) {
dispatch({ type: 'LOGIN_FAIL', payload: err });
throw err;
}
// Fetch orders asynchronously, not waiting for them to be retrieved
dispatch(fetchOrders());
}
}
function fetchOrders() {
return async (dispatch) => {
dispatch({ type: 'FETCH_ORDERS_START' });
try {
const orders = await fetch('/account/orders');
dispatch({ type: 'FETCH_ORDERS_SUCCESS', payload: orders });
} catch (err) {
dispatch({ type: 'FETCH_ORDERS_FAIL', payload: err });
throw err;
}
}
}
store.dispatch(login('my-username', 'my-password'));
expect(store.getActions()).toContain([
'LOGIN_START',
'FETCH_ORDERS_SUCCESS'
]);
The assertion above will fail because FETCH_ORDERS_SUCCESS
will not yet exist in the stack of actions.
To solve this, one can use setTimeout
explicitly in each test:
store.dispatch(login('my-username', 'my-password'));
setTimeout(() => expect(store.getActions()).toContain([
'LOGIN_START',
'FETCH_ORDERS_SUCCESS'
]), 50);
However, this is not pretty and is error-prone. redux-mock-store-await-actions
makes this easier for you.
Supply the action types to await for.
import waitForActions from 'redux-mock-store-await-actions';
import configureStore from 'redux-mock-store';
import thunkMiddleware from 'redux-thunk';
const store = configureStore([thunkMiddleware])();
store.dispatch(login('my-username', 'my-password'));
await waitForActions(store, ['LOGIN_START', 'FETCH_ORDERS_SUCCESS']);
Supply the action objects to await for, matching a subset of the properties of the dispatched actions. It performs a deep comparison between property values of dispatched and expected actions to determine whether the expected actions are partially contained in the stack of dispatched actions.
import waitForActions from 'redux-mock-store-await-actions';
import configureStore from 'redux-mock-store';
import thunkMiddleware from 'redux-thunk';
const store = configureStore([thunkMiddleware])();
store.dispatch(login('my-username', 'my-password'));
// { type: 'LOGIN_START', payload: { username: 'my-username' } }
// matches
// { type: 'LOGIN_START', payload: { username: 'my-username', password } }
//
// { type: 'FETCH_ORDERS_SUCCESS', }
// matches
// { type: 'FETCH_ORDERS_SUCCESS', payload: orders }
await waitForActions(store, [
{
type: 'LOGIN_START',
payload: { username: 'my-username' },
},
{
type: 'FETCH_ORDERS_SUCCESS',
},
]);
Returns a Promise
which fulfills if all actions
are dispatched before the timeout expires. The Promise
has a .cancel()
function which, if called, will reject the Promise
.
The Promise
might be rejected:
TimeoutError
.cancel()
invocation, throwing CancelledError
MismatchError
NOTE: Subsequent calls to waitForActions
with the same actions should be preceded by a call to store.clearActions()
, otherwise the returned Promise
will resolve immediately.
Type: Object
The redux-mock-store
.
Type: Object
String
Array
Function
The actions to wait for. It can be either:
String
: an action type string.Object
: an action object.Array
of either
Type: Number
Default: 2000
The timeout given in milliseconds.
Type: Number
Default: 0
Specifies the time in milliseconds that every invocation to the action's matcher take place at since the last invocation. When set to zero, throttling is disabled.
When throttling is enabled, the matcher
will be called at most once per throttleWait
milliseconds receiving the array of actions dispatched until that time. If the matcher
does not resolve the Promise
until timeout
milliseconds have elapsed, the Promise
is rejected throwing TimeoutError
.
This feature is useful when one needs to wait for several actions or a burst of actions to be dispatched, effectively skip invocations to the action's matcher until the Redux store "settles" to avoid running complex action comparison logic in the meantime and improve performance.
Type: Function
Default: .matchers.order
Supplies custom behavior to specify how expected and dispatched actions should be compared. The function accepts two arguments: the array of expected actions and dispatched actions.
The matcher must either:
true
to indicate a match has occurred and fulfill the Promise
false
to indicate a match is yet to occur and the Promise
remains in pending stateMismatchError
to indicate a match will not occur anymore and reject the Promise
Two built-in matchers are already shipped and available under .matchers
property:
order
matcher performs a comparison between the specified order of expected actions against the order of arrival of dispatched actions. On the first mismatch detected, MismatchError
is thrown for early rejectioncontaining
matcher is a less strict matcher which checks whether expected actions are contained within dispatched actionsBoth matchers perform a partial deep comparison between dispatched and expected actions, as per Lodash's isMatch().
Example of a custom matcher implementation:
import waitForActions from 'redux-mock-store-await-actions';
import configureStore from 'redux-mock-store';
import thunkMiddleware from 'redux-thunk';
const store = configureStore([thunkMiddleware])();
const expectedActions = [
{ type: 'LOGIN_START', payload: { username: 'my-username' } },
{ type: 'FETCH_ORDERS_SUCCESS' }
];
store.dispatch(login('my-username', 'my-password'));
// Throws if LOGIN_FAIL is dispatched or
// Matches when LOGIN_START and FETCH_ORDERS_SUCCESS are dispatched
waitForActions(store, expectedActions, { matcher: (expectedActions, storeActions) => {
const hasLoginFail = storeActions.some((action) => action.type === 'LOGIN_FAIL');
if (hasLoginFail) {
throw new waitForActions.MismatchError();
}
const hasLoginStart = storeActions.some((action) => action.type === 'LOGIN_START' && action.payload.username === 'my-username');
const hasFetchOrdersSuccess = storeActions.some((action) => action.type === 'FETCH_ORDERS_SUCCESS');
return hasLoginStart && hasFetchOrdersSuccess;
}})
.then(() => {
// Expected actions dispatched
})
.catch((err) => {
// MismatchError
});
$ npm test
$ npm test -- --watch
during development
FAQs
Waits for specific actions to be dispatched or a timeout expires.
The npm package redux-mock-store-await-actions receives a total of 254 weekly downloads. As such, redux-mock-store-await-actions popularity was classified as not popular.
We found that redux-mock-store-await-actions demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 17 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Cloudflare has launched a setup wizard allowing users to easily create and manage a security.txt file for vulnerability disclosure on their websites.
Security News
The Socket Research team breaks down a malicious npm package targeting the legitimate DOMPurify library. It uses obfuscated code to hide that it is exfiltrating browser and crypto wallet data.
Security News
ENISA’s 2024 report highlights the EU’s top cybersecurity threats, including rising DDoS attacks, ransomware, supply chain vulnerabilities, and weaponized AI.