Skip to content

Commit

Permalink
fix(targets): disable delete button on non-custom targets (#502)
Browse files Browse the repository at this point in the history
* disable delete button on non-custom targets

* fixed test

* rename symbol

* cleanup
  • Loading branch information
maxcao13 authored Sep 6, 2022
1 parent e871759 commit b355296
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 17 deletions.
5 changes: 3 additions & 2 deletions src/app/TargetSelect/TargetSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { CreateTargetModal } from './CreateTargetModal';
import _ from 'lodash';
import { NotificationCategory } from '@app/Shared/Services/NotificationChannel.service';

export const CUSTOM_TARGETS_REALM = "Custom Targets";
export interface TargetSelectProps {
}

Expand All @@ -62,7 +63,7 @@ export const TargetSelect: React.FunctionComponent<TargetSelectProps> = (props)
const [isLoading, setLoading] = React.useState(false);
const [isModalOpen, setModalOpen] = React.useState(false);
const addSubscription = useSubscriptions();

const setCachedTargetSelection = React.useCallback((target) => {
localStorage.setItem(TARGET_KEY, JSON.stringify(target));
}, [localStorage]);
Expand Down Expand Up @@ -226,7 +227,7 @@ export const TargetSelect: React.FunctionComponent<TargetSelectProps> = (props)
/>
<Button
aria-label="Delete target"
isDisabled={isLoading || (selected == NO_TARGET)}
isDisabled={isLoading || (selected == NO_TARGET) || (selected.annotations?.cryostat['REALM'] !== CUSTOM_TARGETS_REALM)}
onClick={deleteTarget}
variant="control"
icon={<TrashIcon />}
Expand Down
7 changes: 4 additions & 3 deletions src/test/Rules/__snapshots__/CreateRule.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -905,15 +905,16 @@ exports[`<CreateRule/> renders correctly 1`] = `
</span>
</button>
<button
aria-disabled={false}
aria-disabled={true}
aria-label="Delete target"
className="pf-c-button pf-m-control"
className="pf-c-button pf-m-control pf-m-disabled"
data-ouia-component-id="OUIA-Generated-Button-control-2"
data-ouia-component-type="PF4/Button"
data-ouia-safe={true}
disabled={false}
disabled={true}
onClick={[Function]}
role={null}
tabIndex={null}
type="button"
>
<span
Expand Down
53 changes: 41 additions & 12 deletions src/test/Targets/TargetSelect.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,39 +37,47 @@
*/
import * as React from 'react';
import renderer from 'react-test-renderer'
import { render, screen, within } from '@testing-library/react';
import { cleanup, render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';

import { of } from 'rxjs';
import { createMemoryHistory } from 'history';

import { TargetSelect } from '@app/TargetSelect/TargetSelect';
import { CUSTOM_TARGETS_REALM, TargetSelect } from '@app/TargetSelect/TargetSelect';
import { defaultServices, ServiceContext } from '@app/Shared/Services/Services';
import userEvent from '@testing-library/user-event';
import { NotificationMessage } from '@app/Shared/Services/NotificationChannel.service';
import { Target } from '@app/Shared/Services/Target.service';

const mockFooConnectUrl = 'service:jmx:rmi://someFooUrl';
const mockBarConnectUrl = 'service:jmx:rmi://someBarUrl';
const mockBazConnectUrl = 'service:jmx:rmi://someBazUrl';
const mockFooTarget = { connectUrl: mockFooConnectUrl, alias: 'fooTarget' };
const mockBarTarget = { connectUrl: mockBarConnectUrl, alias: 'barTarget' }
const mockBazTarget = { connectUrl: mockBazConnectUrl, alias: 'bazTarget' }

const mockHistoryPush = jest.fn();
// Test fails if new Map([['REALM', 'Custom Targets']]) is used, most likely since 'cryostat' Map is not being utilized
const cryostatAnnotation = new Map();
cryostatAnnotation['REALM'] = CUSTOM_TARGETS_REALM;
const mockFooTarget: Target = {
connectUrl: mockFooConnectUrl,
alias: 'fooTarget',
annotations: {
cryostat: cryostatAnnotation,
platform : new Map()
}
};
const mockBarTarget: Target = { ...mockFooTarget, connectUrl: mockBarConnectUrl, alias: 'barTarget' }
const mockBazTarget: Target = { connectUrl: mockBazConnectUrl, alias: 'bazTarget' }

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useRouteMatch: () => ({ url: '/baseUrl' }),
useHistory: () => ({
push: mockHistoryPush,
}),
}));

jest.spyOn(defaultServices.target, 'target')
.mockReturnValue(of(mockFooTarget))
.mockReturnValueOnce(of())
.mockReturnValueOnce(of())
.mockReturnValueOnce(of(mockFooTarget))
.mockReturnValueOnce(of(mockFooTarget))
.mockReturnValueOnce(of(mockFooTarget))
.mockReturnValueOnce(of(mockBazTarget)) // does nothing when trying to delete non-custom targets

jest.spyOn(defaultServices.targets, 'targets')
.mockReturnValue(of([mockFooTarget, mockBarTarget]))
Expand All @@ -90,6 +98,9 @@ jest.spyOn(defaultServices.targets, 'queryForTargets')
jest.spyOn(defaultServices.notificationChannel, 'messages')
.mockReturnValue(of())


afterEach(cleanup);

describe('<TargetSelect />', () => {
it('renders correctly', () => {
const tree = renderer.create(
Expand Down Expand Up @@ -154,20 +165,38 @@ describe('<TargetSelect />', () => {
expect(createTargetRequestSpy).toBeCalledWith(mockBazTarget);
});

it('deletes target when delete button clicked', () => {
it('deletes target when delete button clicked', async () => {
render(
<ServiceContext.Provider value={defaultServices}>
<TargetSelect />
</ServiceContext.Provider>
);

const deleteButton = screen.getByLabelText('Delete target');
await waitFor(() => expect(deleteButton).not.toBeDisabled());

userEvent.click(deleteButton);

const deleteTargetRequestSpy = jest.spyOn(defaultServices.api, 'deleteTarget');
expect(deleteTargetRequestSpy).toBeCalledTimes(1);
expect(deleteTargetRequestSpy).toBeCalledWith(mockFooTarget);
});

it('does nothing when trying to delete non-custom targets', () => {
render(
<ServiceContext.Provider value={defaultServices}>
<TargetSelect />
</ServiceContext.Provider>
);
const deleteButton = screen.getByLabelText('Delete target');
userEvent.click(deleteButton);

const deleteTargetRequestSpy = jest.spyOn(defaultServices.api, 'deleteTarget');

expect(deleteTargetRequestSpy).toBeCalledTimes(0);
expect(deleteButton).toBeDisabled();
});

it('refreshes targets when button clicked', () => {
render(
<ServiceContext.Provider value={defaultServices}>
Expand Down

0 comments on commit b355296

Please sign in to comment.