Skip to content

Commit

Permalink
Increase UI Test Coverage (#360)
Browse files Browse the repository at this point in the history
* Fix unit test axios import and update tests to disable retries.

* Update all tests to disable retries.

* Remove unnecessary notification bar condition.

* Add tests for more filter coverage. Update tests to ensure filters available before selecting.

* Remove jest max workers config.

* Add new build.

* Fix unit test console error.

* Remove unnecessary try catch blocks on home api calls. Add unit tests for additional home api coverage.

* Remove duplicate server status code. Add unit tests for apps section.

* Remove unnecessary table row check. Update unit tests to better mock state props.

* Update jest config max workers back to 1.
  • Loading branch information
jbouder committed Jun 28, 2024
1 parent 0602d92 commit 9335283
Show file tree
Hide file tree
Showing 21 changed files with 488 additions and 274 deletions.
20 changes: 10 additions & 10 deletions jhub_apps/static/js/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion ui/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const config: JestConfigWithTsJest = {
'!src/App.tsx',
'!src/main.tsx',
'!src/store.ts',
'!src/utils/axios.ts',
'!src/utils/*axios.ts',
'!**/*.d.ts',
'!**/types.ts',
'!**/index.ts',
Expand Down
8 changes: 7 additions & 1 deletion ui/src/components/app-card/app-card.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import { RecoilRoot } from 'recoil';
import AppCard from './app-card';

describe('AppCard', () => {
const queryClient = new QueryClient();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});
const mock = new MockAdapter(axios);

beforeAll(() => {
Expand Down
8 changes: 7 additions & 1 deletion ui/src/components/app-form/app-form.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ describe('AppForm', () => {
value: jest.fn(),
});

const queryClient = new QueryClient();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});
const mock = new MockAdapter(axios);
beforeAll(() => {
mock.reset();
Expand Down
35 changes: 31 additions & 4 deletions ui/src/components/app-sharing/app-sharing.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import { AppSharing } from '..';
import { currentUser as defaultUser } from '../../store';

describe('AppSharing', () => {
const queryClient = new QueryClient();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});
beforeEach(() => {
queryClient.clear();
});
Expand Down Expand Up @@ -113,6 +119,8 @@ describe('AppSharing', () => {
});

test('Adds permissions to table', async () => {
const setUserPermissionMock = jest.fn();
const setGroupPermissionMock = jest.fn();
const { baseElement, getByText } = render(
<RecoilRoot initializeState={({ set }) => set(defaultUser, currentUser)}>
<QueryClientProvider client={queryClient}>
Expand All @@ -123,8 +131,8 @@ describe('AppSharing', () => {
}}
isPublic={false}
setIsPublic={jest.fn()}
setCurrentUserPermissions={jest.fn()}
setCurrentGroupPermissions={jest.fn()}
setCurrentUserPermissions={setUserPermissionMock}
setCurrentGroupPermissions={setGroupPermissionMock}
/>
</QueryClientProvider>
</RecoilRoot>,
Expand All @@ -140,13 +148,32 @@ describe('AppSharing', () => {
});
const listbox = baseElement.querySelector('.MuiAutocomplete-listbox');
await act(async () => {
listbox?.querySelector('li')?.click();
const listItems = listbox?.querySelectorAll('li');
listItems?.forEach((item) => {
item.click();
});
});
const button = getByText('Share');
await act(async () => {
button.click();
});
}

expect(setUserPermissionMock).toHaveBeenCalledWith(expect.any(Function));
const userMockUpdater = setUserPermissionMock.mock.calls[0][0];
expect(userMockUpdater(['existing_user_permission'])).toEqual([
'user1',
'user2',
'user3',
]);

expect(setGroupPermissionMock).toHaveBeenCalledWith(expect.any(Function));
const groupMockUpdater = setGroupPermissionMock.mock.calls[0][0];
expect(groupMockUpdater(['existing_user_permission'])).toEqual([
'group1',
'group2',
'superadmin',
]);
});

test('removes existing permission', async () => {
Expand Down
105 changes: 53 additions & 52 deletions ui/src/components/app-sharing/app-sharing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,60 +276,61 @@ export const AppSharing = ({
<TableContainer>
<Table aria-label="Individuals and Groups" size="small">
<TableBody>
{(rowsPerPage > 0
? currentItems.slice(
page * rowsPerPage,
page * rowsPerPage + rowsPerPage,
)
: currentItems
).map((item) => (
<TableRow
key={item.name}
sx={{
'&:last-child td, &:last-child th': { border: 0 },
}}
>
<TableCell
component="td"
scope="row"
sx={{ fontSize: '16px' }}
{currentItems
.slice(
page * rowsPerPage,
page * rowsPerPage + rowsPerPage,
)
.map((item) => (
<TableRow
key={item.name}
sx={{
'&:last-child td, &:last-child th': {
border: 0,
},
}}
>
{item.name}{' '}
{item.type === 'group' ? (
<span style={{ fontWeight: 600 }}>
{' '}
(Group)
</span>
) : (
<></>
)}
</TableCell>
<TableCell align="right">
<Button
variant="text"
color="error"
size="small"
sx={{ fontWeight: '600', fontSize: '14px' }}
onClick={() => {
setCurrentItems((prev) =>
prev.filter((i) => i.name !== item.name),
);
if (item.type === 'group') {
setCurrentGroupPermissions((prev) =>
prev.filter((i) => i !== item.name),
);
} else {
setCurrentUserPermissions((prev) =>
prev.filter((i) => i !== item.name),
);
}
}}
<TableCell
component="td"
scope="row"
sx={{ fontSize: '16px' }}
>
Remove
</Button>
</TableCell>
</TableRow>
))}
{item.name}{' '}
{item.type === 'group' ? (
<span style={{ fontWeight: 600 }}>
{' '}
(Group)
</span>
) : (
<></>
)}
</TableCell>
<TableCell align="right">
<Button
variant="text"
color="error"
size="small"
sx={{ fontWeight: '600', fontSize: '14px' }}
onClick={() => {
setCurrentItems((prev) =>
prev.filter((i) => i.name !== item.name),
);
if (item.type === 'group') {
setCurrentGroupPermissions((prev) =>
prev.filter((i) => i !== item.name),
);
} else {
setCurrentUserPermissions((prev) =>
prev.filter((i) => i !== item.name),
);
}
}}
>
Remove
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
<TableFooter>
<TableRow>
Expand Down
8 changes: 7 additions & 1 deletion ui/src/components/navigation/navigation.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ import { Navigation } from '..';
import { currentUser as defaultUser } from '../../store';
import { theme } from '../../theme/theme';
describe('Navigation', () => {
const queryClient = new QueryClient();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});
const mock = new MockAdapter(axios);
beforeAll(() => {
mock.reset();
Expand Down
10 changes: 3 additions & 7 deletions ui/src/components/notification-bar/notification-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,9 @@ export const NotificationBar = ({
}: NotificationBarProps): React.ReactElement => {
return (
<div className="alert-wrapper">
{message ? (
<Alert id="alert-notification" severity={severity} onClose={onClose}>
{message}
</Alert>
) : (
<></>
)}
<Alert id="alert-notification" severity={severity} onClose={onClose}>
{message}
</Alert>
</div>
);
};
Expand Down
5 changes: 4 additions & 1 deletion ui/src/components/status-chip/status-chip.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { apps } from '@src/data/api';
import '@testing-library/jest-dom';
import { render, waitFor } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import { RecoilRoot } from 'recoil';
import { StatusChip } from '..';

Expand Down Expand Up @@ -82,7 +83,9 @@ describe('StatusChip', () => {
'.MuiIconButton-root',
) as HTMLButtonElement;
if (stopButton) {
stopButton.click();
act(() => {
stopButton.click();
});
}
waitFor(() => {
const stopModal = baseElement.querySelector('.MuiDialog-root');
Expand Down
8 changes: 7 additions & 1 deletion ui/src/pages/create-app/create-app.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import { RecoilRoot } from 'recoil';
import { CreateApp } from './create-app';

describe('CreateApp', () => {
const queryClient = new QueryClient();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});
const mock = new MockAdapter(axios);
beforeAll(() => {
mock.reset();
Expand Down
8 changes: 7 additions & 1 deletion ui/src/pages/edit-app/edit-app.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import { RecoilRoot } from 'recoil';
import { EditApp } from './edit-app';

describe('EditApp', () => {
const queryClient = new QueryClient();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});
const mock = new MockAdapter(axios);
beforeAll(() => {
mock.reset();
Expand Down
Loading

0 comments on commit 9335283

Please sign in to comment.