Skip to content

Commit

Permalink
Test/area coordinates (#264)
Browse files Browse the repository at this point in the history
* refactor: Revrite hook to simplify and be able to test.

* test: AreaCoordinate hooks.

* refactor: Seperate mockedData into own file and collect tests in a seperate folder.

* refactor: Fix error and move test related files from hooks to tests.

* test: Test render and area select in AreaCoordinate component.
  • Loading branch information
mheggelund authored May 2, 2024
1 parent f37d910 commit 6c3a992
Show file tree
Hide file tree
Showing 5 changed files with 402 additions and 8 deletions.
9 changes: 7 additions & 2 deletions src/components/AreaCoordinates/AreaCoordinates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
ModelAreaTypeDto,
} from '../../api/generated';
import Img from '../../features/ModelView/image.png';
import { useFetchCases } from '../../hooks/useFetchCases';
import { useFetchModel } from '../../hooks/useFetchModel';
import { useFetchModelAreas } from '../../hooks/useFetchModelAreas';
import { useMutateAreaCoordinates } from '../../hooks/useMutateAreaCoordinates';
Expand Down Expand Up @@ -85,7 +86,11 @@ export const AreaCoordinates = ({
useState<AreaCoordinateType>();
const { modelId } = useParams();
const { data, isLoading } = useFetchModel(modelId);
const { activeAreaResultList } = useModelResults(activeArea.name);
const cases = useFetchCases();
const { activeAreaResultList } = useModelResults(
activeArea.name,
cases.data?.data,
);
const modelAreas = useFetchModelAreas();
const mutateAreaCoordinates = useMutateAreaCoordinates();

Expand Down Expand Up @@ -282,7 +287,7 @@ export const AreaCoordinates = ({
></Autocomplete>
</Styled.CoordinateGroup>

{activeArea.modelAreaTypeId !== '' && (
{activeArea.name !== '' && (
<Styled.CoordinateFields>
<Styled.CoordinateGroup>
<Typography variant="h6">Top Left Corner</Typography>
Expand Down
13 changes: 7 additions & 6 deletions src/components/AreaCoordinates/hooks/useModelResults.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useFetchCases } from '../../../hooks/useFetchCases';

export const useModelResults = (activeArea: string) => {
const cases = useFetchCases();
import { ComputeCaseDto } from '../../../api/generated';

export const useModelResults = (
activeArea: string,
cases: ComputeCaseDto[] | undefined,
) => {
const activeAreaResultList =
cases.data &&
cases.data.data
cases &&
cases
.filter((c) => c.modelArea !== null)
.filter((ca) => ca.modelArea.name === activeArea);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/* eslint-disable max-lines-per-function */
import { MsalProvider } from '@azure/msal-react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { cleanup, fireEvent, render, screen } from '@testing-library/react';
import { MsalReactTester } from 'msal-react-tester';
import { AreaCoordinates } from '../AreaCoordinates';

import { useFetchCases } from '../../../hooks/useFetchCases';
import { useFetchModel } from '../../../hooks/useFetchModel';
import { useFetchModelAreas } from '../../../hooks/useFetchModelAreas';
import { useModelResults } from '../hooks/useModelResults';

import {
mockAnalogueModelDetail,
mockedActiveComputeCase,
mockedComputeCase,
mockedModelAreaType,
} from './mockedData';

let msalTester: MsalReactTester;

beforeEach(() => {
// new instance of msal tester for each test
msalTester = new MsalReactTester();
// spy all required msal things
msalTester.spyMsal();
});

afterEach(() => {
cleanup();
msalTester.resetSpyMsal();
jest.clearAllMocks();
});

jest.mock('../../../hooks/useFetchCases');
jest.mock('../../../hooks/useFetchModel');
jest.mock('../../../hooks/useFetchModelAreas');
jest.mock('../hooks/useModelResults');

const Render = () => {
const testQueryClient = new QueryClient();

// @ts-ignore because of error
useFetchCases.mockReturnValue({
data: mockedComputeCase,
success: true,
isLoading: false,
isSuccess: true,
isError: false,
});

// @ts-ignore because of error
useFetchModel.mockReturnValue({
data: mockAnalogueModelDetail,
success: true,
isLoading: false,
isSuccess: true,
isError: false,
});

// @ts-ignore because of error
useFetchModelAreas.mockReturnValue({
data: mockedModelAreaType,
success: true,
isLoading: false,
isSuccess: true,
isError: false,
});

// @ts-ignore because of error
useModelResults.mockReturnValue(mockedActiveComputeCase);

return (
<MsalProvider instance={msalTester.client}>
<QueryClientProvider client={testQueryClient}>
<AreaCoordinates setSaveAlert={jest.fn()} />
</QueryClientProvider>
</MsalProvider>
);
};

test('renders Area Coordinates component after loading in an empty state', async () => {
render(<Render />);

const nameLable = screen.getByLabelText('Select area', {
selector: 'input',
});
expect(nameLable).toBeInTheDocument();
expect(nameLable).toHaveValue('');

expect(screen.queryByText('Top Left Corner')).not.toBeInTheDocument();
expect(screen.queryByText('Edit coordinates')).not.toBeInTheDocument();
});

test('Select area Autocomplete updates correct on model area select', async () => {
render(<Render />);

const nameLable = screen.getByLabelText('Select area', {
selector: 'input',
});

expect(nameLable).toHaveValue('');

fireEvent.change(nameLable, {
target: {
value: mockedModelAreaType[0].name,
},
});
fireEvent.keyDown(nameLable, { key: 'Enter', code: 'Enter' });
expect(nameLable).toHaveValue(mockedModelAreaType[0].name);

fireEvent.change(nameLable, {
target: {
value: mockedModelAreaType[1].name,
},
});
fireEvent.keyDown(nameLable, { key: 'Enter', code: 'Enter' });
expect(nameLable).toHaveValue(mockedModelAreaType[1].name);
});
122 changes: 122 additions & 0 deletions src/components/AreaCoordinates/tests/AreaCoordinates.hooks.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/* eslint-disable testing-library/render-result-naming-convention */
/* eslint-disable max-lines-per-function */
import { MsalProvider } from '@azure/msal-react';
import * as ReactQuery from '@tanstack/react-query';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { cleanup, renderHook, screen, waitFor } from '@testing-library/react';
import { MsalReactTester } from 'msal-react-tester';
import { useFetchCases } from '../../../hooks/useFetchCases';
import { useFetchModel } from '../../../hooks/useFetchModel';
import { useFetchModelAreas } from '../../../hooks/useFetchModelAreas';
import { AreaCoordinates } from '../AreaCoordinates';
import { useModelResults } from '../hooks/useModelResults';
import {
defaultArea,
mockAnalogueModelDetail,
mockedComputeCase,
mockedModelAreaType,
modelId,
} from './mockedData';

let msalTester: MsalReactTester;

function wrapper(props: { children: React.ReactNode }) {
const testQueryClient = new QueryClient();
return (
<MsalProvider instance={msalTester.client}>
<QueryClientProvider client={testQueryClient}>
{props.children}
<AreaCoordinates setSaveAlert={jest.fn()} />
</QueryClientProvider>
</MsalProvider>
);
}

const mockGetData = async (data: any) => {
const mock = jest.spyOn(ReactQuery, 'useQuery');

// @ts-ignore because of error
mock.mockImplementation(() => {
return data
? Promise.resolve({
data: data,
isLoading: false,
isSuccess: true,
isError: false,
})
: Promise.reject('error');
});

return mock;
};

beforeEach(() => {
// new instance of msal tester for each test
msalTester = new MsalReactTester();

// spy all required msal things
msalTester.spyMsal();
});

afterEach(() => {
cleanup();
msalTester.resetSpyMsal();
jest.clearAllMocks();
});

test('Calls fetchModel api with mock data', async () => {
const mock = await mockGetData(mockAnalogueModelDetail);

const { result } = renderHook(() => useFetchModel(modelId), { wrapper });

const res = await result.current;

await waitFor(() => expect(mock).toHaveBeenCalled());
await waitFor(() => expect(res.data).toBe(mockAnalogueModelDetail));
});

test('Calls fetchCases api with mock data', async () => {
const mock = await mockGetData(mockedComputeCase);

const { result } = renderHook(() => useFetchCases(), { wrapper });

const res = await result.current;

await waitFor(() => expect(mock).toHaveBeenCalled());
await waitFor(() => expect(res.data).toBe(mockedComputeCase));
});

test('Calls useModelResult hook with mock data', async () => {
const mock = await mockGetData(mockedComputeCase);

const { result } = renderHook(
() => useModelResults(defaultArea.name, [mockedComputeCase]),
{ wrapper },
);

const res = await result.current;

await waitFor(() => expect(mock).toHaveBeenCalled());
await waitFor(() => expect(res.activeAreaResultList).toHaveLength(1));
});

test('Calls useFetchModelAreas hook with mock data', async () => {
const mock = await mockGetData(mockedModelAreaType);

const { result } = renderHook(() => useFetchModelAreas(), { wrapper });

const res = await result.current;

await waitFor(() => expect(mock).toHaveBeenCalled());
await waitFor(() => expect(res.data).toBe(mockedModelAreaType));
});

test('renders AreaCoordinates component in loading state', async () => {
await mockGetData(mockAnalogueModelDetail);

const { result } = renderHook(() => useFetchModel(modelId), { wrapper });
await result.current;

const loading = screen.getByText('Loading.....');
expect(loading).toBeVisible();
});
Loading

0 comments on commit 6c3a992

Please sign in to comment.