Skip to content

Commit

Permalink
Task 711 - Hooked up feature flag api with UI (#302)
Browse files Browse the repository at this point in the history

---------

Co-authored-by: Scott Alexander <[email protected]>
Co-authored-by: Rio Knightley <[email protected]>
  • Loading branch information
3 people authored Feb 22, 2024
1 parent 0c8fdae commit d763338
Show file tree
Hide file tree
Showing 20 changed files with 341 additions and 228 deletions.
6 changes: 3 additions & 3 deletions app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import './styles/App.scss';
import PatientDetailsProvider from './providers/patientProvider/PatientProvider';
import SessionProvider from './providers/sessionProvider/SessionProvider';
import AppRouter from './router/AppRouter';
import FeatureFlagsProvider from './providers/featureFlagsProvider/FeatureFlagsProvider';
import ConfigProvider from './providers/configProvider/ConfigProvider';

function App() {
return (
<FeatureFlagsProvider>
<ConfigProvider>
<SessionProvider>
<PatientDetailsProvider>
<AppRouter />
</PatientDetailsProvider>
</SessionProvider>
</FeatureFlagsProvider>
</ConfigProvider>
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { routes } from '../../../types/generic/routes';
import { LG_RECORD_STAGE } from '../../../types/blocks/lloydGeorgeStages';
import usePatient from '../../../helpers/hooks/usePatient';

jest.mock('../../../helpers/hooks/useFeatureFlags');
jest.mock('../../../helpers/hooks/useConfig');
jest.mock('../deletionConfirmationStage/DeletionConfirmationStage', () => () => (
<div>Deletion complete</div>
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import useBaseAPIUrl from '../../../helpers/hooks/useBaseAPIUrl';
import usePatient from '../../../helpers/hooks/usePatient';
import { errorToParams } from '../../../helpers/utils/errorToParams';
import { isMock } from '../../../helpers/utils/isLocal';
import useFeatureFlags from '../../../helpers/hooks/useFeatureFlags';
import useConfig from '../../../helpers/hooks/useConfig';

export type Props = {
docType: DOCUMENT_TYPE;
Expand Down Expand Up @@ -51,7 +51,7 @@ function DeleteDocumentsStage({
const baseUrl = useBaseAPIUrl();
const baseHeaders = useBaseAPIHeaders();
const navigate = useNavigate();
const featureFlags = useFeatureFlags();
const config = useConfig();
const nhsNumber: string = patientDetails?.nhsNumber ?? '';
const formattedNhsNumber = formatNhsNumber(nhsNumber);

Expand Down Expand Up @@ -91,7 +91,7 @@ function DeleteDocumentsStage({
}
} catch (e) {
const error = e as AxiosError;
if (isMock(error) && !!featureFlags.mockLocal.recordUploaded) {
if (isMock(error) && !!config.mockLocal.recordUploaded) {
onSuccess();
} else {
if (error.response?.status === 403) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import userEvent from '@testing-library/user-event';
import usePatient from '../../../helpers/hooks/usePatient';
import { LinkProps } from 'react-router-dom';
import { routes } from '../../../types/generic/routes';
import useConfig from '../../../helpers/hooks/useConfig';
import { defaultFeatureFlags } from '../../../helpers/requests/getFeatureFlags';

jest.mock('../../../helpers/hooks/useFeatureFlags');
jest.mock('../../../helpers/hooks/useConfig');
const mockedUseNavigate = jest.fn();
const mockedAxios = axios as jest.Mocked<typeof axios>;
const mockedUsePatient = usePatient as jest.Mock;
const mockUseConfig = useConfig as jest.Mock;
const mockPdf = buildLgSearchResult();
const mockPatient = buildPatientDetails();
const mockSetStage = jest.fn();
Expand All @@ -32,6 +35,7 @@ describe('LloydGeorgeDownloadAllStage', () => {
beforeEach(() => {
process.env.REACT_APP_ENVIRONMENT = 'jest';
mockedUsePatient.mockReturnValue(mockPatient);
mockUseConfig.mockReturnValue({ featureFlags: defaultFeatureFlags, mockLocal: {} });
});
afterEach(() => {
jest.clearAllMocks();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { useNavigate, Link } from 'react-router-dom';
import { errorToParams } from '../../../helpers/utils/errorToParams';
import { AxiosError } from 'axios/index';
import { isMock } from '../../../helpers/utils/isLocal';
import useFeatureFlags from '../../../helpers/hooks/useFeatureFlags';
import useConfig from '../../../helpers/hooks/useConfig';

const FakeProgress = require('fake-progress');

Expand Down Expand Up @@ -56,7 +56,7 @@ function LloydGeorgeDownloadAllStage({
const linkRef = useRef<HTMLAnchorElement | null>(null);
const mounted = useRef(false);
const navigate = useNavigate();
const featureFlags = useFeatureFlags();
const { mockLocal } = useConfig();
const patientDetails = usePatient();
const nhsNumber = patientDetails?.nhsNumber ?? '';
const [delayTimer, setDelayTimer] = useState<NodeJS.Timeout>();
Expand Down Expand Up @@ -89,7 +89,7 @@ function LloydGeorgeDownloadAllStage({

useEffect(() => {
const onFail = (error: AxiosError) => {
if (isMock(error) && !!featureFlags.mockLocal.recordUploaded) {
if (isMock(error) && !!mockLocal.recordUploaded) {
if (typeof window !== 'undefined') {
const { protocol, host } = window.location;
setLinkAttributes({
Expand Down Expand Up @@ -149,7 +149,7 @@ function LloydGeorgeDownloadAllStage({
progressTimer,
deleteAfterDownload,
navigate,
featureFlags,
mockLocal,
]);

return inProgress ? (
Expand Down
15 changes: 6 additions & 9 deletions app/src/components/blocks/testPanel/TestPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
import React from 'react';
import 'react-toggle/style.css';
import { isLocal } from '../../../helpers/utils/isLocal';
import {
LocalFlags,
useFeatureFlagsContext,
} from '../../../providers/featureFlagsProvider/FeatureFlagsProvider';
import { LocalFlags, useConfigContext } from '../../../providers/configProvider/ConfigProvider';
import { REPOSITORY_ROLE } from '../../../types/generic/authRole';
import TestToggle, { ToggleProps } from './TestToggle';

function TestPanel() {
const [featureFlags, setFeatureFlags] = useFeatureFlagsContext();
const { isBsol, recordUploaded, userRole } = featureFlags.mockLocal;
const [config, setConfig] = useConfigContext();
const { isBsol, recordUploaded, userRole } = config.mockLocal;

const updateLocalFlag = (key: keyof LocalFlags, value: boolean | REPOSITORY_ROLE) => {
setFeatureFlags({
...featureFlags,
setConfig({
mockLocal: {
...featureFlags.mockLocal,
...config.mockLocal,
[key]: value,
},
featureFlags: config.featureFlags,
});
};

Expand Down
45 changes: 45 additions & 0 deletions app/src/helpers/hooks/useConfig.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { render, screen } from '@testing-library/react';
import useConfig from './useConfig';
import ConfigProvider, { GlobalConfig } from '../../providers/configProvider/ConfigProvider';
import { defaultFeatureFlags } from '../requests/getFeatureFlags';

describe('useConfig', () => {
beforeEach(() => {
sessionStorage.setItem('FeatureFlags', '');
process.env.REACT_APP_ENVIRONMENT = 'jest';
});
afterEach(() => {
jest.clearAllMocks();
});

it('returns true when feature flag in context', () => {
const config: GlobalConfig = {
featureFlags: { ...defaultFeatureFlags, testFeature1: true },
mockLocal: {},
};
renderHook(config);
expect(screen.getByText(`FLAG: true`)).toBeInTheDocument();
});

it('returns false when there is no feature flag in context', () => {
const config: GlobalConfig = {
featureFlags: { ...defaultFeatureFlags, testFeature1: false },
mockLocal: {},
};
renderHook(config);
expect(screen.getByText(`FLAG: false`)).toBeInTheDocument();
});
});

const TestApp = () => {
const config = useConfig();
return <div>{`FLAG: ${!!config.featureFlags.testFeature1}`.normalize()}</div>;
};

const renderHook = (config?: GlobalConfig) => {
return render(
<ConfigProvider configOverride={config}>
<TestApp />
</ConfigProvider>,
);
};
8 changes: 8 additions & 0 deletions app/src/helpers/hooks/useConfig.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { useConfigContext } from '../../providers/configProvider/ConfigProvider';

function useConfig() {
const [config] = useConfigContext();
return config;
}

export default useConfig;
40 changes: 0 additions & 40 deletions app/src/helpers/hooks/useFeatureFlags.test.tsx

This file was deleted.

8 changes: 0 additions & 8 deletions app/src/helpers/hooks/useFeatureFlags.tsx

This file was deleted.

36 changes: 36 additions & 0 deletions app/src/helpers/requests/getFeatureFlags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { AuthHeaders } from '../../types/blocks/authHeaders';
import { endpoints } from '../../types/generic/endpoints';

import axios from 'axios';
import { FeatureFlags } from '../../types/generic/featureFlags';

type Args = {
baseUrl: string;
baseHeaders: AuthHeaders;
};

type GetFeatureFlagsResponse = {
data: FeatureFlags;
};

export const defaultFeatureFlags = {
testFeature1: false,
testFeature2: false,
testFeature3: false,
};

const getFeatureFlags = async ({ baseUrl, baseHeaders }: Args) => {
const gatewayUrl = baseUrl + endpoints.FEATURE_FLAGS;
try {
const { data }: GetFeatureFlagsResponse = await axios.get(gatewayUrl, {
headers: {
...baseHeaders,
},
});
return data;
} catch (e) {
return defaultFeatureFlags;
}
};

export default getFeatureFlags;
Loading

0 comments on commit d763338

Please sign in to comment.