Skip to content

Commit

Permalink
(HP-2023) Better version of GdprCallback
Browse files Browse the repository at this point in the history
  • Loading branch information
NikoHelle committed Oct 16, 2023
1 parent d1a807d commit 3b2b93c
Show file tree
Hide file tree
Showing 3 changed files with 230 additions and 12 deletions.
48 changes: 36 additions & 12 deletions src/gdprApi/GdprAuthorizationCodeManagerCallback.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useCallback } from 'react';
import React, { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useHistory } from 'react-router';

Check warning on line 3 in src/gdprApi/GdprAuthorizationCodeManagerCallback.tsx

View workflow job for this annotation

GitHub Actions / lint-and-test

'useHistory' is defined but never used

import styles from './gdprAuthorizationCodeManagerCallback.module.css';
import useAuthCodeQueues, {
Expand All @@ -8,27 +9,50 @@ import useAuthCodeQueues, {
} from './useAuthCodeQueues';
import { getStoredQueueData } from '../common/actionQueue/actionQueueStorage';
import { useErrorPageRedirect } from '../profile/hooks/useErrorPageRedirect';
import { QueueState } from '../common/actionQueue/useActionQueue';
import { QueueController } from '../common/actionQueue/actionQueue';
import { didFailedActionRedirect } from './actions/utils';

function GdprAuthorizationCodeManagerCallback(): React.ReactElement {
const redirectToErrorPage = useErrorPageRedirect();
const { t } = useTranslation();
const storedData = getStoredQueueData(authCodeQueuesStorageKey) || {};

const onError = useCallback(() => {
redirectToErrorPage({
message: t('notification.defaultErrorText'),
});
}, [redirectToErrorPage, t]);
//const history = useHistory();
const storedData = useMemo(
() => getStoredQueueData(authCodeQueuesStorageKey) || {},
[]
);
const onError = useCallback(
(controller: QueueController, state: QueueState) => {

Check warning on line 25 in src/gdprApi/GdprAuthorizationCodeManagerCallback.tsx

View workflow job for this annotation

GitHub Actions / lint-and-test

'state' is defined but never used
const failedAction = controller.getFailed();
if (!failedAction || !didFailedActionRedirect(failedAction)) {
console.log('action does not redirect', failedAction);

Check warning on line 28 in src/gdprApi/GdprAuthorizationCodeManagerCallback.tsx

View workflow job for this annotation

GitHub Actions / lint-and-test

Unexpected console statement
// if storedData.startP....
//history.push(`/?error=${failedAction ? failedAction.type : 'unknown'}`);
// else
redirectToErrorPage({
message: t('notification.defaultErrorText'),
});
} else {
console.log('action redirects', failedAction);

Check warning on line 36 in src/gdprApi/GdprAuthorizationCodeManagerCallback.tsx

View workflow job for this annotation

GitHub Actions / lint-and-test

Unexpected console statement
}
},
[redirectToErrorPage, t]
);
const authCodeQueueProps = ({
...storedData,
onError,
} as unknown) as AuthCodeQueuesProps;
const downloadProfileQueue = useAuthCodeQueues(authCodeQueueProps);
const { shouldHandleCallback, resume } = useAuthCodeQueues(
authCodeQueueProps
);
React.useEffect(() => {
if (downloadProfileQueue.shouldHandleCallback()) {
downloadProfileQueue.resume();
if (shouldHandleCallback()) {
window.requestAnimationFrame(() => {
resume();
});
}
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<div className={styles['wrapper']}>
Expand Down
187 changes: 187 additions & 0 deletions src/gdprApi/__tests__/GdprAuthorizationCodeManagerCallback.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
import React from 'react';
import { act, waitFor } from '@testing-library/react';

import {
createQueueFromProps,
Action,
} from '../../common/actionQueue/actionQueue';
import { storeQueue } from '../../common/actionQueue/actionQueueStorage';
import mockWindowLocation from '../../common/test/mockWindowLocation';
import {
renderComponentWithMocksAndContexts,
cleanComponentMocks,
} from '../../common/test/testingLibraryTools';
import config from '../../config';
import GdprAuthorizationCodeManagerCallback from '../GdprAuthorizationCodeManagerCallback';
import {
ActionMockData,
setMockActionData,
isActionTriggered,
} from '../actions/__mocks__/mock.util';
import { getScenarioWhereNextPhaseIsResumeCallback } from '../actions/__mocks__/queueScenarios';
import { getQueue } from '../actions/queues';
import {
AuthCodeQueuesProps,
authCodeQueuesStorageKey,
} from '../useAuthCodeQueues';
import { tunnistamoAuthCodeParserAction } from '../actions/authCodeParser';
import { tunnistamoAuthCodeCallbackUrlAction } from '../actions/authCodeCallbackUrlDetector';
import { loadKeycloakConfigAction } from '../actions/loadKeycloakConfig';
import { getMockCallArgs } from '../../common/test/jestMockHelper';

const mockHistoryTracker = jest.fn();

jest.mock('react-router', () => ({
...jest.requireActual('react-router'),
useHistory: () => ({
push: mockHistoryTracker,
replace: mockHistoryTracker,
}),
}));

jest.mock('../actions/queues');

describe('<GdprAuthorizationCodeManagerCallback /> ', () => {
const mockedWindowControls = mockWindowLocation();

const onCompleted = jest.fn();
const onError = jest.fn();

const downloadQueueProps: AuthCodeQueuesProps = {
queueName: 'downloadProfile',
startPagePath: config.downloadPath,
onCompleted,
onError,
};

// store the queue actions from actual GdprAuthorizationCodeManagerCallbackQueue with new props
const setStoredState = (overrideQueueProps: Partial<Action>[]) => {
const queue = getQueue(downloadQueueProps).map(queueProps => {
const overrides =
overrideQueueProps.find(op => op.type === queueProps.type) || {};
return {
...queueProps,
...overrides,
};
});
storeQueue(authCodeQueuesStorageKey, createQueueFromProps(queue));
};

// set mocked responses and stored data
const initQueue = (props: ActionMockData[]) => {
const storedProps: Partial<Action>[] = [];
props.forEach(data => {
setMockActionData(data);
if (data.store) {
storedProps.push({
type: data.type,
complete: true, //!data.storeAsActive
errorMessage: data.rejectValue ? String(data.rejectValue) : undefined,
result: data.resolveValue,
active: !!data.storeAsActive,
});
}
});
if (storedProps.length) {
setStoredState(storedProps);
}
};

const initTests = async () =>
renderComponentWithMocksAndContexts(
jest.fn(),
<GdprAuthorizationCodeManagerCallback />
);

afterEach(() => {
mockedWindowControls.reset();
cleanComponentMocks();
jest.clearAllMocks();
});

beforeEach(() => {
mockedWindowControls.setPath(config.gdprCallbackPath);
});

it(`Queue is resumed - if possible`, async () => {
initQueue(getScenarioWhereNextPhaseIsResumeCallback());
await act(async () => {
await initTests();
await waitFor(() => {
expect(
isActionTriggered(tunnistamoAuthCodeParserAction.type)
).toBeTruthy();
});
});
});
it(`Queue is not resumed when next action is not resumable. (Should redirect!)`, async () => {
initQueue(
getScenarioWhereNextPhaseIsResumeCallback({
overrides: [
{
type: tunnistamoAuthCodeCallbackUrlAction.type,
store: true,
},
{
type: tunnistamoAuthCodeParserAction.type,
store: true,
},
],
})
);
await act(async () => {
await initTests();
await waitFor(() => {
expect(isActionTriggered(loadKeycloakConfigAction.type)).toBeFalsy();
});
});
});
it(`If queue fails and failed action will redirect, redirection in not made again.`, async () => {
initQueue(
getScenarioWhereNextPhaseIsResumeCallback({
overrides: [
{
type: tunnistamoAuthCodeParserAction.type,
resolveValue: undefined,
runOriginal: true,
},
],
})
);
await act(async () => {
await initTests();
await waitFor(() => {
expect(
isActionTriggered(tunnistamoAuthCodeParserAction.type)
).toBeTruthy();
});
const lastCall = getMockCallArgs(mockHistoryTracker, 0)[0] as string;
expect(
lastCall.includes(`/?error=${tunnistamoAuthCodeParserAction.type}`)
).toBeTruthy();
});
});
it(`If queue fails and failed action will not redirect, redirect to start page.`, async () => {
initQueue(
getScenarioWhereNextPhaseIsResumeCallback({
overrides: [
{
type: loadKeycloakConfigAction.type,
resolveValue: undefined,
rejectValue: new Error('UPS'),
autoTrigger: true,
runOriginal: false,
},
],
})
);
await act(async () => {
await initTests();
await waitFor(() => {
expect(isActionTriggered(loadKeycloakConfigAction.type)).toBeTruthy();
});
const lastCall = getMockCallArgs(mockHistoryTracker, 0)[0] as string;
expect(lastCall.includes('/error?message=')).toBeTruthy();
});
});
});
7 changes: 7 additions & 0 deletions src/gdprApi/actions/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,3 +330,10 @@ export function useInternalRedirect(
}, [controller, history]);
return funcs;
}

export function didFailedActionRedirect(action: Action) {
return (
getData(action, 'redirectsOnError') === true ||
getInternalRequestPathFromError(action) !== undefined
);
}

0 comments on commit 3b2b93c

Please sign in to comment.