Skip to content

Commit

Permalink
refactor: kids-first#3346 add redux tests
Browse files Browse the repository at this point in the history
  • Loading branch information
evans-g-crsj committed Jul 14, 2021
1 parent bcb86f3 commit 0237956
Show file tree
Hide file tree
Showing 10 changed files with 655 additions and 46 deletions.
75 changes: 41 additions & 34 deletions src/services/fenceStudies.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import keys from 'lodash/keys';

import { graphql } from 'services/arranger';

export const getAuthStudiesIdAndCount = async (api, fence, userAcl) =>
graphql(api)({
export const getAuthStudiesIdAndCount = async (api, fence, userAcl) => {
const response = await graphql(api)({
query: `
query AuthorizedStudyIdsAndCount($sqon: JSON) {
file {
Expand All @@ -26,34 +26,39 @@ export const getAuthStudiesIdAndCount = async (api, fence, userAcl) =>
],
},
},
}).then(
({
data: {
file: {
aggregations: {
participants__study__external_id: { buckets },
},
});

const {
data: {
file: {
aggregations: {
participants__study__external_id: { buckets },
},
},
}) =>
buckets.reduce((obj, { key, doc_count }) => {
obj[key] = { authorizedFiles: doc_count };
return obj;
}, {}),
},
} = response;

return buckets.reduce(
(obj, { key, doc_count }) => ({ ...obj, [key]: { authorizedFiles: doc_count } }),
{},
);
};

export const getStudiesCountByNameAndAcl = async (api, studies, userAcl) => {
const studyIds = keys(studies);

const sqons = studyIds.reduce((obj, studyId) => {
obj[`${studyId}_sqon`] = {
op: 'in',
content: { field: 'participants.study.external_id', value: [studyId] },
};
return obj;
}, {});
const sqons = studyIds.reduce(
(obj, studyId) => ({
...obj,
[`${studyId}_sqon`]: {
op: 'in',
content: { field: 'participants.study.external_id', value: [studyId] },
},
}),
{},
);

return graphql(api)({
const response = await graphql(api)({
query: `
query StudyCountByNamesAndAcl(${studyIds.map(
(studyId) => `$${studyId}_sqon: JSON`,
Expand Down Expand Up @@ -83,17 +88,19 @@ export const getStudiesCountByNameAndAcl = async (api, studies, userAcl) => {
}
`,
variables: sqons,
}).then(({ data: { file } }) =>
studyIds.map((id) => {
let study = {};
const agg = file[id];
study['acl'] = agg['acl']['buckets'].map((b) => b.key).filter((a) => userAcl.includes(a));
study['studyShortName'] = agg['participants__study__short_name']['buckets'][0]['key'];
study['totalFiles'] = agg['participants__study__short_name']['buckets'][0]['doc_count'];
study['id'] = id;
study['authorizedFiles'] = studies[id]['authorizedFiles'];
});

return study;
}),
);
const {
data: { file },
} = response;
return studyIds.map((id) => {
const agg = file[id];
return {
acl: agg['acl']['buckets'].map((b) => b.key).filter((a) => userAcl.includes(a)),
studyShortName: agg['participants__study__short_name']['buckets'][0]['key'],
totalFiles: agg['participants__study__short_name']['buckets'][0]['doc_count'],
id,
authorizedFiles: studies[id]['authorizedFiles'],
};
});
};
170 changes: 170 additions & 0 deletions src/store/actionCreators/Test/fenceConnections.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import { AnyAction } from 'redux';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

import { DCF, FENCES, GEN3, INTEGRATION_PREFIX } from 'common/constants';
import { getFenceUser } from 'services/fence';
import { DispatchFenceConnections, FenceConnectionsActions } from 'store/fenceConnectionsTypes';
import { makeFakeLocalStorage } from 'utils';

import {
addFenceConnection,
computeAclsByFence,
computeAclsForConnection,
concatAllFencesAcls,
fetchAllFencesConnectionsIfNeeded,
fetchFencesConnections,
fetchFencesConnectionsIfNeeded,
removeFenceConnection,
toggleIsFetchingAllFenceConnections,
} from '../fenceConnections';

import { MOCK_FENCE_CONNECTIONS, MOCK_GEN3_CONNECTION, mockApi } from './mockDataFence';

const NO_ACTIONS: AnyAction[] = [];

const middleware = [thunk];
const mockStore = configureMockStore(middleware);

jest.mock('services/fence');

describe('Fence Connections actions', () => {
beforeAll(() => {
Object.defineProperty(window, 'localStorage', {
value: makeFakeLocalStorage(),
});
});

beforeEach(() => {
(getFenceUser as jest.Mock).mockReset();
});

afterEach(() => {
window.localStorage.clear();
jest.clearAllMocks();
});

it('should create an action to toggle all fence connections', () => {
const expectedAction = {
type: FenceConnectionsActions.toggleIsFetchingAllFenceConnections,
isLoading: true,
};
expect(toggleIsFetchingAllFenceConnections(true)).toEqual(expectedAction);
});

it('should create an action when removing a fence connection', () => {
const expectedAction = {
type: FenceConnectionsActions.removeFenceConnection,
fenceName: DCF,
};
expect(removeFenceConnection(DCF)).toEqual(expectedAction);
});

it('should manage acls adequately', () => {
expect(concatAllFencesAcls(MOCK_FENCE_CONNECTIONS)).toEqual(['a', 'b', 'c', 'x', 'y', 'z']);
expect(computeAclsForConnection(MOCK_FENCE_CONNECTIONS[GEN3])).toEqual(['a', 'b', 'c']);
expect(computeAclsByFence(MOCK_FENCE_CONNECTIONS)).toEqual({
[GEN3]: ['a', 'b', 'c'],
[DCF]: ['x', 'y', 'z'],
});
});

it('should create an action to add a fence connection', () => {
const expectedAction = {
type: FenceConnectionsActions.addFenceConnection,
fenceName: GEN3,
connection: MOCK_GEN3_CONNECTION,
};
expect(addFenceConnection(GEN3, MOCK_GEN3_CONNECTION)).toEqual(expectedAction);
});

it('should fetch fence connections when user is adequately connected to a data repository', async () => {
(getFenceUser as jest.Mock).mockImplementation(() => Promise.resolve(MOCK_GEN3_CONNECTION));
const store = mockStore({
fenceConnections: {
fenceConnections: {},
isFetchingAllFenceConnections: false,
},
});

const dispatch: DispatchFenceConnections = store.dispatch;

await dispatch(fetchFencesConnections(mockApi, GEN3));

const expectedActions = [
{
type: FenceConnectionsActions.addFenceConnection,
fenceName: GEN3,
connection: MOCK_GEN3_CONNECTION,
},
];
expect(store.getActions()).toEqual(expectedActions);
});

it('should not fetch fence connections if user has no integration token for particular fence', async () => {
localStorage.removeItem(`${INTEGRATION_PREFIX}${GEN3}`);

const store = mockStore({
fenceConnections: {
fenceConnections: {},
isFetchingAllFenceConnections: false,
},
});

const dispatch: DispatchFenceConnections = store.dispatch;

await dispatch(fetchFencesConnectionsIfNeeded(mockApi, GEN3));

expect(store.getActions()).toEqual(NO_ACTIONS);
});

it(
'should not fetch fence connections if user has' +
' 1) an integration token' +
' 2) already has connection for particular fence',
async () => {
(getFenceUser as jest.Mock).mockImplementation(() => Promise.resolve(MOCK_GEN3_CONNECTION));
localStorage.setItem(`${INTEGRATION_PREFIX}${GEN3}`, 'token');

const store = mockStore({
fenceConnections: {
fenceConnections: { [GEN3]: MOCK_GEN3_CONNECTION },
isFetchingAllFenceConnections: false,
},
});

const dispatch: DispatchFenceConnections = store.dispatch;

await dispatch(fetchFencesConnectionsIfNeeded(mockApi, GEN3));

expect(store.getActions()).toEqual(NO_ACTIONS);
},
);

it('should activate a loader when one wants to fetch fence connections', async () => {
(getFenceUser as jest.Mock).mockImplementation(() => Promise.resolve(MOCK_GEN3_CONNECTION));

const store = mockStore({
fenceConnections: {
fenceConnections: {},
isFetchingAllFenceConnections: false,
},
});
const expectedActions = [
{
type: FenceConnectionsActions.toggleIsFetchingAllFenceConnections,
isLoading: true,
},
{
type: FenceConnectionsActions.toggleIsFetchingAllFenceConnections,
isLoading: false,
},
];

const dispatch: DispatchFenceConnections = store.dispatch;

await dispatch(fetchAllFencesConnectionsIfNeeded(mockApi, FENCES));

expect(store.getActions()).toEqual(expectedActions);
});
});
Loading

0 comments on commit 0237956

Please sign in to comment.