Skip to content

Commit

Permalink
test(filter): add test for DurationFilter
Browse files Browse the repository at this point in the history
  • Loading branch information
tthvo committed Sep 13, 2022
1 parent f3022ec commit 72569c7
Show file tree
Hide file tree
Showing 3 changed files with 271 additions and 7 deletions.
20 changes: 13 additions & 7 deletions src/app/Recordings/Filters/DurationFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ export const DurationFilter: React.FunctionComponent<DurationFilterProps> = (pro
const isContinuous = React.useMemo(() => props.durations && props.durations.includes("continuous"),
[props.durations]);

const handleContinousCheckBoxChange = React.useCallback((checked, envt) => {
props.onContinuousDurationSelect(checked);
}, [props.onContinuousDurationSelect]);

const handleEnterKey = React.useCallback((e) => {
if (e.key && e.key !== 'Enter') {
return;
}
props.onDurationInput(duration)
}, [props.onDurationInput, duration]);

return (
<Flex>
<FlexItem>
Expand All @@ -60,20 +71,15 @@ export const DurationFilter: React.FunctionComponent<DurationFilterProps> = (pro
aria-label="duration filter"
onChange={(e) => setDuration(Number(e))}
min="0"
onKeyDown={(e) => {
if (e.key && e.key !== 'Enter') {
return;
}
props.onDurationInput(duration);
}}
onKeyDown={handleEnterKey}
/>
</FlexItem>
<FlexItem>
<Checkbox
label="Continuous"
id="continuous-checkbox"
isChecked={isContinuous}
onChange={props.onContinuousDurationSelect}
onChange={handleContinousCheckBoxChange}
/>
</FlexItem>
</Flex>
Expand Down
201 changes: 201 additions & 0 deletions src/test/Recordings/Filters/DurationFilter.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
* Copyright The Cryostat Authors
*
* The Universal Permissive License (UPL), Version 1.0
*
* Subject to the condition set forth below, permission is hereby granted to any
* person obtaining a copy of this software, associated documentation and/or data
* (collectively the "Software"), free of charge and under any and all copyright
* rights in the Software, and any and all patent rights owned or freely
* licensable by each licensor hereunder covering either (i) the unmodified
* Software as contributed to or provided by such licensor, or (ii) the Larger
* Works (as defined below), to deal in both
*
* (a) the Software, and
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
* one is included with the Software (each a "Larger Work" to which the Software
* is contributed by such licensors),
*
* without restriction, including without limitation the rights to copy, create
* derivative works of, display, perform, and distribute the Software and make,
* use, sell, offer for sale, import, export, have made, and have sold the
* Software and the Larger Work(s), and to sublicense the foregoing rights on
* either these or other terms.
*
* This license is subject to the following condition:
* The above copyright notice and either this complete permission notice or at
* a minimum a reference to the UPL must be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

import { DurationFilter } from '@app/Recordings/Filters/DurationFilter';
import { ActiveRecording, RecordingState } from '@app/Shared/Services/Api.service';
import { cleanup, render, screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import renderer, { act } from 'react-test-renderer';

const mockRecordingLabels = {
someLabel: 'someValue',
};
const mockRecording: ActiveRecording = {
name: 'someRecording',
downloadUrl: 'http://downloadUrl',
reportUrl: 'http://reportUrl',
metadata: { labels: mockRecordingLabels },
startTime: 1234567890,
id: 0,
state: RecordingState.RUNNING,
duration: 30,
continuous: false,
toDisk: false,
maxSize: 0,
maxAge: 0,
};

const onDurationInput = jest.fn((durationInput) => { /**Do nothing. Used for checking renders */});
const onContinuousSelect = jest.fn((continuous) => { /**Do nothing. Used for checking renders */});

describe("<DurationFilter />", () => {
let emptyFilteredDuration: string[];
let filteredDurationsWithCont: string[];
let filteredDurationsWithoutCont: string[];

beforeEach(() => {
emptyFilteredDuration = [];
filteredDurationsWithCont = [ `${mockRecording.duration}`, "continuous" ];
filteredDurationsWithoutCont = [ `${mockRecording.duration}` ]
});

afterEach(cleanup);

it('renders correctly', async () => {
let tree;
await act(async () => {
tree = renderer.create(
<DurationFilter durations={emptyFilteredDuration} onContinuousDurationSelect={onContinuousSelect} onDurationInput={onDurationInput}/>
);
});
expect(tree.toJSON()).toMatchSnapshot();
});

it ('should check continous box if continous is in filter', () => {
render(
<DurationFilter durations={filteredDurationsWithCont} onContinuousDurationSelect={onContinuousSelect} onDurationInput={onDurationInput}/>
);

const checkBox = screen.getByRole('checkbox', { name: "Continuous" });
expect(checkBox).toBeInTheDocument();
expect(checkBox).toBeVisible();
expect(checkBox).toHaveAttribute("checked");
});

it ('should not check continous box if continous is in filter', () => {
render(
<DurationFilter durations={filteredDurationsWithoutCont} onContinuousDurationSelect={onContinuousSelect} onDurationInput={onDurationInput}/>
);

const checkBox = screen.getByRole('checkbox', { name: "Continuous" });
expect(checkBox).toBeInTheDocument();
expect(checkBox).toBeVisible();
expect(checkBox).not.toHaveAttribute("checked");
});

it ('should select continous when clicking unchecked continuous box', () => {
const submitContinous = jest.fn((continous) => {
filteredDurationsWithoutCont.push("continuous");
});

render(
<DurationFilter durations={filteredDurationsWithoutCont} onContinuousDurationSelect={submitContinous} onDurationInput={onDurationInput}/>
);

const checkBox = screen.getByRole('checkbox', { name: "Continuous" });
expect(checkBox).toBeInTheDocument();
expect(checkBox).toBeVisible();
expect(checkBox).not.toHaveAttribute("checked");

userEvent.click(checkBox);

expect(submitContinous).toHaveBeenCalledTimes(1);
expect(submitContinous).toHaveBeenCalledWith(true);

expect(filteredDurationsWithoutCont).toStrictEqual([`${mockRecording.duration}`, "continuous"]);
});

it ('should unselect continous when clicking checked continuous box', () => {
const submitContinous = jest.fn((continous) => {
filteredDurationsWithCont = filteredDurationsWithCont.filter((v) => v !== "continuous");
});

render(
<DurationFilter durations={filteredDurationsWithCont} onContinuousDurationSelect={submitContinous} onDurationInput={onDurationInput}/>
);

const checkBox = screen.getByRole('checkbox', { name: "Continuous" });
expect(checkBox).toBeInTheDocument();
expect(checkBox).toBeVisible();
expect(checkBox).toHaveAttribute("checked");

userEvent.click(checkBox);

expect(submitContinous).toHaveBeenCalledTimes(1);
expect(submitContinous).toHaveBeenCalledWith(false);
expect(filteredDurationsWithCont).toStrictEqual([`${mockRecording.duration}`]);
});

it ('should select a duration when pressing Enter', async () => {
const submitDuration = jest.fn((duration) => {
emptyFilteredDuration.push(duration);
});

render(
<DurationFilter durations={emptyFilteredDuration} onContinuousDurationSelect={onContinuousSelect} onDurationInput={submitDuration}/>
);

const durationInput = screen.getByLabelText("duration filter");
expect(durationInput).toBeInTheDocument();
expect(durationInput).toBeVisible();

userEvent.clear(durationInput);
userEvent.type(durationInput, "50");

// Press enter
userEvent.type(durationInput, "{enter}");

expect(submitDuration).toHaveBeenCalledTimes(1);
expect(submitDuration).toHaveBeenCalledWith(Number("50"));
expect(emptyFilteredDuration).toStrictEqual([50]);
});

it ('should not select a duration when pressing other keys', async () => {
const submitDuration = jest.fn((duration) => {
emptyFilteredDuration.push(duration);
});

render(
<DurationFilter durations={emptyFilteredDuration} onContinuousDurationSelect={onContinuousSelect} onDurationInput={submitDuration}/>
);

const durationInput = screen.getByLabelText("duration filter");
expect(durationInput).toBeInTheDocument();
expect(durationInput).toBeVisible();

userEvent.clear(durationInput);
userEvent.type(durationInput, "50");

// Press shift
userEvent.type(durationInput, "{shift}");

expect(submitDuration).toHaveBeenCalledTimes(0);
expect(emptyFilteredDuration).toStrictEqual([]);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<DurationFilter /> renders correctly 1`] = `
<div
className="pf-l-flex"
>
<div
className=""
>
<input
aria-invalid={false}
aria-label="duration filter"
className="pf-c-form-control"
data-ouia-component-id="OUIA-Generated-TextInputBase-1"
data-ouia-component-type="PF4/TextInput"
data-ouia-safe={true}
disabled={false}
id="duration-input"
min="0"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
readOnly={false}
required={false}
type="number"
value={30}
/>
</div>
<div
className=""
>
<div
className="pf-c-check"
>
<input
aria-invalid={false}
checked={false}
className="pf-c-check__input"
data-ouia-component-id="OUIA-Generated-Checkbox-1"
data-ouia-component-type="PF4/Checkbox"
data-ouia-safe={true}
disabled={false}
id="continuous-checkbox"
onChange={[Function]}
type="checkbox"
/>
<label
className="pf-c-check__label"
htmlFor="continuous-checkbox"
>
Continuous
</label>
</div>
</div>
</div>
`;

0 comments on commit 72569c7

Please sign in to comment.