Reputation: 1892
I implemented my own way to handle access/refresh token. Basically when accessToken
is expired, it awaits the dispatch of another action and, if it is successful, it dispatch again itself. The code below explains it better:
export const refresh = () => async (dispatch) => {
dispatch({
type: REFRESH_USER_FETCHING,
});
try {
const user = await api.refresh();
dispatch({
type: REFRESH_USER_SUCCESS,
payload: user,
});
return history.push("/");
} catch (err) {
const { code } = err;
if (code !== "ACCESS_TOKEN_EXPIRED") {
dispatch({
type: REFRESH_USER_ERROR,
payload: err,
});
const pathsToRedirect = ["/signup"];
const {
location: { pathname },
} = history;
const path = pathsToRedirect.includes(pathname) ? pathname : "/login";
return history.push(path);
}
try {
await dispatch(refreshToken());
return dispatch(refresh());
} catch (subErr) {
dispatch({
type: REFRESH_USER_ERROR,
payload: err,
});
return history.push("/login");
}
}
};
export const refreshToken = () => async (dispatch) => {
dispatch({
type: REFRESH_TOKEN_FETCHING,
});
try {
await api.refreshToken();
dispatch({
type: REFRESH_TOKEN_SUCCESS,
});
} catch (err) {
dispatch({
type: REFRESH_TOKEN_ERROR,
payload: err,
});
}
};
the issue is that I am finding it really difficult to test with Jest. In fact, I have implemented this test:
import configureMockStore from "redux-mock-store";
import thunk from "redux-thunk";
import * as actionCreators from "./actionCreators";
import * as actions from "./actions";
import api from "../../api";
jest.mock("../../api");
const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
describe("authentication actionCreators", () => {
it("runs refresh, both token expired, should match the whole flow", async () => {
api.refresh.mockRejectedValue({
code: "ACCESS_TOKEN_EXPIRED",
message: "jwt expired",
});
api.refreshToken.mockRejectedValue({
code: "REFRESH_TOKEN_EXPIRED",
message: "jwt expired",
});
const expectedActions = [
{ type: actions.REFRESH_USER_FETCHING },
{ type: actions.REFRESH_TOKEN_FETCHING },
{ type: actions.REFRESH_TOKEN_ERROR },
{ type: actions.REFRESH_USER_ERROR },
];
const store = mockStore({ auth: {} });
await store.dispatch(actionCreators.refresh());
expect(store.getActions()).toEqual(expectedActions);
});
});
but instead of completing, the test runs indefenitely. This issue is not happening when I am testing it manually, so I think there is something missing in Jest, so my question is: is there a way to test this recursive behaviour?
Thanks
Upvotes: 0
Views: 402
Reputation: 7735
The problem is await you use with dispatch, dispatch returns an action, not a Promise, use Promise.resolve
instead.
Upvotes: 1