diff --git a/src/common/constants.js b/src/common/constants.js index 24017cacd..0ff2c67b1 100644 --- a/src/common/constants.js +++ b/src/common/constants.js @@ -82,7 +82,6 @@ export const GEN3 = 'gen3'; export const FENCES = [GEN3, DCF]; export const CAVATICA = 'cavatica'; -export const SERVICES = [...FENCES, CAVATICA]; export const GOOGLE = 'google'; export const FACEBOOK = 'facebook'; diff --git a/src/components/Login/utils.js b/src/components/Login/utils.js index 2f0eb617a..9fd689b6d 100644 --- a/src/components/Login/utils.js +++ b/src/components/Login/utils.js @@ -4,7 +4,6 @@ import isArrayLikeObject from 'lodash/isArrayLikeObject'; import toLower from 'lodash/toLower'; import { CAVATICA, FENCES } from 'common/constants'; -import { INTEGRATION_PREFIX } from 'common/constants'; import { getUser as getCavaticaUser } from 'services/cavatica'; import { getAccessToken } from 'services/fence'; import { createProfile, getProfile } from 'services/profiles'; @@ -106,6 +105,3 @@ export const fetchIntegrationTokens = ({ setIntegrationToken, api }) => { }); }); }; - -export const hasIntegrationTokenForFence = (fenceName) => - !!localStorage.getItem(`${INTEGRATION_PREFIX}${fenceName}`); diff --git a/src/components/UserProfile/Integration.js b/src/components/UserProfile/Integration.js index ab697b796..3a40b3e2d 100644 --- a/src/components/UserProfile/Integration.js +++ b/src/components/UserProfile/Integration.js @@ -3,7 +3,6 @@ import React from 'react'; import { connect as reduxConnect } from 'react-redux'; import { BookOutlined } from '@ant-design/icons'; import { notification } from 'antd'; -import { injectState } from 'freactal'; import get from 'lodash/get'; import PropTypes from 'prop-types'; import { compose, setPropTypes } from 'recompose'; @@ -63,7 +62,6 @@ const disconnect = async ({ fence, api, setConnecting, - effects, setError, removeFenceConnection, removeFenceStudies, @@ -71,7 +69,6 @@ const disconnect = async ({ setConnecting(true); try { await deleteFenceTokens(api, fence); - await effects.setIntegrationToken(fence, null); removeFenceConnection(fence); removeFenceStudies(fence); await trackFenceAction({ @@ -91,7 +88,6 @@ const connect = async ({ fence, api, setConnecting, - effects, setError, fetchFenceStudiesIfNeeded, addFenceConnection, @@ -100,7 +96,6 @@ const connect = async ({ try { await fenceConnect(api, fence); const token = await getAccessToken(api, fence); - effects.setIntegrationToken(fence, token); const details = convertTokenToUser(token); addFenceConnection(fence, details); fetchFenceStudiesIfNeeded(api, fence, computeAclsForConnection(details)); @@ -137,7 +132,6 @@ function Integration(props) { fence, logo, description, - effects, api, } = props; @@ -165,7 +159,6 @@ function Integration(props) { connectCbParams: { fence, api, - effects, addFenceConnection, fetchFenceStudiesIfNeeded, }, @@ -175,7 +168,6 @@ function Integration(props) { disConnectCbParams: { fence, api, - effects, removeFenceConnection, removeFenceStudies, }, @@ -197,15 +189,12 @@ const connector = reduxConnect(null, mapDispatchToProps); const Enhanced = compose( connector, - injectState, withApi, setPropTypes({ logo: PropTypes.node.isRequired, description: PropTypes.string.isRequired, connecting: PropTypes.bool, fence: PropTypes.string.isRequired, - state: PropTypes.object.isRequired, - effects: PropTypes.object.isRequired, api: PropTypes.func.isRequired, addFenceConnection: PropTypes.func, fetchFenceStudiesIfNeeded: PropTypes.func, diff --git a/src/stateProviders/provideLoggedInUser.js b/src/stateProviders/provideLoggedInUser.js index 428b7ea6f..24ecc1812 100644 --- a/src/stateProviders/provideLoggedInUser.js +++ b/src/stateProviders/provideLoggedInUser.js @@ -3,7 +3,7 @@ import { mergeIntoState, provideState } from 'freactal'; import jwtDecode from 'jwt-decode'; import get from 'lodash/get'; -import { EGO_JWT_KEY, SERVICES } from 'common/constants'; +import { CAVATICA, EGO_JWT_KEY } from 'common/constants'; import { INTEGRATION_PREFIX } from 'common/constants'; import ROUTES from 'common/routes'; import { handleJWT, isAdminToken, validateJWT } from 'components/Login/utils'; @@ -74,12 +74,10 @@ export default provideState({ }); // Get all integration keys from local storage - SERVICES.forEach((service) => { - const storedToken = localStorage.getItem(`integration_${service}`); - if (storedToken) { - state.integrationTokens[service] = storedToken; - } - }); + const storedToken = localStorage.getItem(`${INTEGRATION_PREFIX}${CAVATICA}`); + if (storedToken) { + state.integrationTokens[CAVATICA] = storedToken; + } setEgoTokenCookie(jwt); }; @@ -170,26 +168,20 @@ export default provideState({ return { ...state, loggedInUserToken: token, loginProvider: provider }; }, setIntegrationToken: (effects, service, token) => (state) => { - if (SERVICES.includes(service)) { - const tokenKey = `${INTEGRATION_PREFIX}${service}`; + if (CAVATICA === service) { + const tokenKey = `${INTEGRATION_PREFIX}${CAVATICA}`; if (token) { localStorage.setItem(tokenKey, token); - state.integrationTokens[service] = token; + state.integrationTokens[CAVATICA] = token; } else { localStorage.removeItem(tokenKey); - delete state.integrationTokens[service]; + delete state.integrationTokens[CAVATICA]; } } return { ...state, integrationTokens: { ...state.integrationTokens } }; }, - getIntegrationToken: (effects, service) => () => { - if (SERVICES.includes(service)) { - const tokenKey = `${INTEGRATION_PREFIX}${service}`; - return tokenKey ? localStorage.getItem(tokenKey) : null; - } - }, clearIntegrationTokens: () => (state) => { - SERVICES.forEach((service) => localStorage.removeItem(`${INTEGRATION_PREFIX}${service}`)); + localStorage.removeItem(`${INTEGRATION_PREFIX}${CAVATICA}`); return { ...state, integrationTokens: {} }; }, setIsLoadingUser: (isLoading) => (state) => ({ ...state, isLoadingUser: isLoading }), diff --git a/src/store/actionCreators/Test/fenceConnections.test.ts b/src/store/actionCreators/Test/fenceConnections.test.ts index 493a4125e..41679cbc3 100644 --- a/src/store/actionCreators/Test/fenceConnections.test.ts +++ b/src/store/actionCreators/Test/fenceConnections.test.ts @@ -2,10 +2,9 @@ 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 { DCF, GEN3 } from 'common/constants'; import { getFenceUser } from 'services/fence'; import { DispatchFenceConnections, FenceConnectionsActions } from 'store/fenceConnectionsTypes'; -import { makeFakeLocalStorage } from 'utils'; import { addFenceConnection, @@ -29,18 +28,11 @@ 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(); }); @@ -61,8 +53,11 @@ describe('Fence Connections actions', () => { }); it('should manage acls adequately', () => { + // @ts-ignore expect(concatAllFencesAcls(MOCK_FENCE_CONNECTIONS)).toEqual(['a', 'b', 'c', 'x', 'y', 'z']); + // @ts-ignore expect(computeAclsForConnection(MOCK_FENCE_CONNECTIONS[GEN3])).toEqual(['a', 'b', 'c']); + // @ts-ignore expect(computeAclsByFence(MOCK_FENCE_CONNECTIONS)).toEqual({ [GEN3]: ['a', 'b', 'c'], [DCF]: ['x', 'y', 'z'], @@ -75,6 +70,7 @@ describe('Fence Connections actions', () => { fenceName: GEN3, connection: MOCK_GEN3_CONNECTION, }; + // @ts-ignore expect(addFenceConnection(GEN3, MOCK_GEN3_CONNECTION)).toEqual(expectedAction); }); @@ -101,30 +97,11 @@ describe('Fence Connections actions', () => { 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', + ' 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: { @@ -152,18 +129,23 @@ describe('Fence Connections actions', () => { }); const expectedActions = [ { - type: FenceConnectionsActions.toggleIsFetchingAllFenceConnections, isLoading: true, + type: 'toggleIsFetchingAllFenceConnections', + }, + { + connection: MOCK_GEN3_CONNECTION, + fenceName: GEN3, + type: FenceConnectionsActions.addFenceConnection, }, { - type: FenceConnectionsActions.toggleIsFetchingAllFenceConnections, isLoading: false, + type: 'toggleIsFetchingAllFenceConnections', }, ]; const dispatch: DispatchFenceConnections = store.dispatch; - await dispatch(fetchAllFencesConnectionsIfNeeded(mockApi, FENCES)); + await dispatch(fetchAllFencesConnectionsIfNeeded(mockApi, [GEN3])); expect(store.getActions()).toEqual(expectedActions); }); diff --git a/src/store/actionCreators/Test/fenceStudies.test.ts b/src/store/actionCreators/Test/fenceStudies.test.ts index cde982306..02cab4218 100644 --- a/src/store/actionCreators/Test/fenceStudies.test.ts +++ b/src/store/actionCreators/Test/fenceStudies.test.ts @@ -2,10 +2,9 @@ import { AnyAction } from 'redux'; import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; -import { DCF, GEN3, INTEGRATION_PREFIX } from 'common/constants'; +import { DCF, GEN3 } from 'common/constants'; import { getAuthStudiesIdAndCount, getStudiesCountByNameAndAcl } from 'services/fenceStudies'; import { DispatchFenceStudies, FenceStudiesActions } from 'store/fenceStudiesTypes'; -import { makeFakeLocalStorage } from 'utils'; import { addFenceStudies, @@ -31,19 +30,12 @@ const mockStore = configureMockStore(middleware); jest.mock('services/fenceStudies'); describe('Fence Studies actions', () => { - beforeAll(() => { - Object.defineProperty(window, 'localStorage', { - value: makeFakeLocalStorage(), - }); - }); - beforeEach(() => { (getAuthStudiesIdAndCount as jest.Mock).mockReset(); (getStudiesCountByNameAndAcl as jest.Mock).mockReset(); }); afterEach(() => { - window.localStorage.clear(); jest.clearAllMocks(); }); @@ -117,12 +109,17 @@ describe('Fence Studies actions', () => { expect(store.getActions()).toEqual(expectedActions); }); - it('should not fetch fence studies if user has no integration token for particular fence', async () => { - localStorage.removeItem(`${INTEGRATION_PREFIX}${GEN3}`); + it('should fetch fence studies if user has already has connection for particular fence', async () => { + (getAuthStudiesIdAndCount as jest.Mock).mockImplementation(() => + Promise.resolve(MOCK_STUDIES_IDS_AND_COUNTS), + ); + (getStudiesCountByNameAndAcl as jest.Mock).mockImplementation(() => + Promise.resolve(MOCK_AUTH_STUDIES_FROM_GEN3), + ); const store = mockStore({ fenceStudies: { - fenceStudies: {}, + fenceStudies: MOCK_AUTH_STUDIES_WITH_2_FENCES, isFetchingAllFenceStudies: false, }, }); @@ -133,32 +130,4 @@ describe('Fence Studies actions', () => { expect(store.getActions()).toEqual(NO_ACTIONS); }); - - it( - 'should fetch fence studies if user has' + - ' 1) an integration token' + - ' 2) already has connection for particular fence', - async () => { - (getAuthStudiesIdAndCount as jest.Mock).mockImplementation(() => - Promise.resolve(MOCK_STUDIES_IDS_AND_COUNTS), - ); - (getStudiesCountByNameAndAcl as jest.Mock).mockImplementation(() => - Promise.resolve(MOCK_AUTH_STUDIES_FROM_GEN3), - ); - localStorage.setItem(`${INTEGRATION_PREFIX}${GEN3}`, 'token'); - - const store = mockStore({ - fenceStudies: { - fenceStudies: MOCK_AUTH_STUDIES_WITH_2_FENCES, - isFetchingAllFenceStudies: false, - }, - }); - - const dispatch: DispatchFenceStudies = store.dispatch; - - await dispatch(fetchFenceStudiesIfNeeded(mockApi, GEN3, { [GEN3]: ['phs'] })); - - expect(store.getActions()).toEqual(NO_ACTIONS); - }, - ); }); diff --git a/src/store/actionCreators/fenceConnections.ts b/src/store/actionCreators/fenceConnections.ts index 07e8228a1..8ced4945c 100644 --- a/src/store/actionCreators/fenceConnections.ts +++ b/src/store/actionCreators/fenceConnections.ts @@ -1,7 +1,6 @@ import isEmpty from 'lodash/isEmpty'; import { ThunkAction } from 'redux-thunk'; -import { hasIntegrationTokenForFence } from 'components/Login/utils'; import { getFenceUser } from 'services/fence'; import { Api } from '../apiTypes'; @@ -34,7 +33,7 @@ export const toggleIsFetchingAllFenceConnections = ( }); const shouldFetchConnections = (fenceName: FenceName, state: RootState): boolean => - hasIntegrationTokenForFence(fenceName) && isEmpty(selectFenceConnections(state)[fenceName]); + isEmpty(selectFenceConnections(state)[fenceName]); export const fetchFencesConnections = ( api: Api, diff --git a/src/store/actionCreators/fenceStudies.ts b/src/store/actionCreators/fenceStudies.ts index c2dc53746..25af50961 100644 --- a/src/store/actionCreators/fenceStudies.ts +++ b/src/store/actionCreators/fenceStudies.ts @@ -2,7 +2,6 @@ import flatMap from 'lodash/flatMap'; import isEmpty from 'lodash/isEmpty'; import { ThunkAction } from 'redux-thunk'; -import { hasIntegrationTokenForFence } from 'components/Login/utils'; import { getAuthStudiesIdAndCount, getStudiesCountByNameAndAcl } from 'services/fenceStudies'; import { Api } from '../apiTypes'; @@ -30,10 +29,7 @@ export const removeFenceStudies = (fenceName: FenceName): FenceStudiesActionType const shouldFetchFenceStudies = (fenceName: FenceName, state: RootState) => { const studiesForFence = selectFenceStudies(state)[fenceName]; - return ( - hasIntegrationTokenForFence(fenceName) && - (isEmpty(studiesForFence) || isEmpty(studiesForFence.authorizedStudies)) - ); + return isEmpty(studiesForFence) || isEmpty(studiesForFence.authorizedStudies); }; export const fetchFenceStudies = ( diff --git a/src/utils.js b/src/utils.js index a92e9379a..2a4bc3bb6 100644 --- a/src/utils.js +++ b/src/utils.js @@ -132,6 +132,18 @@ export const formatQuotientToExponentialOrElse = (num, denum, defaultValue = '') canQuotientBeComputed(num, denum) ? `${toExponentialNotation(num / denum)}` : defaultValue; //ref: https://nofluffweb.com/mock-local-storage-in-jest-tests +/* +* setup example with jest: +* beforeAll(() => { + Object.defineProperty(window, 'localStorage', { + value: makeFakeLocalStorage(), + }); + }); + + afterEach(() => { + window.localStorage.clear(); + }); +* */ export const makeFakeLocalStorage = () => { let store = {}; return {