Skip to content

Commit 970d33b

Browse files
committed
feat(filters): Test DataView filters
1 parent 34ae301 commit 970d33b

File tree

8 files changed

+699
-0
lines changed

8 files changed

+699
-0
lines changed
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import React from 'react';
2+
import { useDataViewFilters } from '@patternfly/react-data-view/dist/dynamic/Hooks';
3+
import { DataViewFilters } from '@patternfly/react-data-view/dist/dynamic/DataViewFilters';
4+
import { DataViewTextFilter } from '@patternfly/react-data-view/dist/dynamic/DataViewTextFilter';
5+
import { DataViewToolbar } from '@patternfly/react-data-view/dist/esm/DataViewToolbar';
6+
import { FilterIcon } from '@patternfly/react-icons';
7+
8+
const filtersProps = {
9+
ouiaId: 'DataViewFilters',
10+
toggleIcon: <FilterIcon />,
11+
values: { name: '', branch: '' }
12+
};
13+
14+
interface RepositoryFilters {
15+
name: string,
16+
branch: string
17+
};
18+
19+
const DataViewToolbarWithState = (props: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
20+
const { filters, onSetFilters, clearAllFilters } = useDataViewFilters<RepositoryFilters>({ initialFilters: { name: '', branch: '' } });
21+
22+
return (
23+
<DataViewToolbar
24+
ouiaId='FiltersExampleHeader'
25+
clearAllFilters = {clearAllFilters}
26+
filters={
27+
<DataViewFilters {...filtersProps} onChange={(_e, values) => onSetFilters(values)} values={filters} {...props}>
28+
<DataViewTextFilter filterId="name" title='Name' placeholder='Filter by name' />
29+
<DataViewTextFilter filterId="branch" title='Branch' placeholder='Filter by branch' />
30+
</DataViewFilters>
31+
}
32+
/>
33+
);
34+
};
35+
36+
describe('DataViewFilters', () => {
37+
it('renders DataViewFilters with menu and filter items', () => {
38+
cy.mount(<DataViewToolbarWithState />);
39+
cy.get('[data-ouia-component-id="DataViewFilters"]').should('exist');
40+
cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
41+
42+
cy.contains('Name').should('exist');
43+
cy.contains('Branch').should('exist');
44+
});
45+
46+
it('can select a filter option', () => {
47+
cy.mount(<DataViewToolbarWithState />);
48+
cy.get('[data-ouia-component-id="DataViewFilters"]').should('contain.text', 'Name');
49+
cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
50+
cy.contains('Branch').click();
51+
52+
cy.get('[data-ouia-component-id="DataViewFilters"]').should('contain.text', 'Branch');
53+
});
54+
55+
it('responds to input and clears the filters', () => {
56+
cy.mount(<DataViewToolbarWithState />);
57+
cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
58+
cy.contains('Name').click();
59+
60+
cy.get('input[placeholder="Filter by name"]').type('Repository one');
61+
cy.get('.pf-v5-c-chip__text').should('have.length', 1);
62+
cy.get('input[placeholder="Filter by name"]').clear();
63+
cy.get('.pf-v5-c-chip__text').should('have.length', 0);
64+
});
65+
66+
it('displays chips for selected filters', () => {
67+
cy.mount(<DataViewToolbarWithState />);
68+
cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
69+
cy.contains('Name').click();
70+
cy.get('input[placeholder="Filter by name"]').type('Repository one');
71+
72+
cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
73+
cy.contains('Branch').click();
74+
cy.get('input[placeholder="Filter by branch"]').type('Main branch');
75+
76+
cy.get('.pf-v5-c-chip__text').should('have.length', 2);
77+
cy.get('.pf-v5-c-chip__text').eq(0).should('contain.text', 'Repository one');
78+
cy.get('.pf-v5-c-chip__text').eq(1).should('contain.text', 'Main branch');
79+
});
80+
81+
it('removes filters by clicking individual chips', () => {
82+
cy.mount(<DataViewToolbarWithState />);
83+
cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
84+
cy.contains('Name').click();
85+
cy.get('input[placeholder="Filter by name"]').type('Repository one');
86+
87+
cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
88+
cy.contains('Branch').click();
89+
cy.get('input[placeholder="Filter by branch"]').type('Main branch');
90+
91+
cy.get('[data-ouia-component-id="close"]').should('have.length', 2);
92+
93+
cy.get('[data-ouia-component-id="close"]').first().click();
94+
cy.get('[data-ouia-component-id="close"]').last().click();
95+
96+
cy.get('[data-ouia-component-id="close"]').should('have.length', 0);
97+
});
98+
99+
it('clears all filters using the clear-all button', () => {
100+
cy.mount(<DataViewToolbarWithState />);
101+
cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
102+
cy.contains('Name').click();
103+
cy.get('input[placeholder="Filter by name"]').type('Repository one');
104+
105+
cy.get('[data-ouia-component-id="DataViewFilters"] .pf-v5-c-menu-toggle').click();
106+
cy.contains('Branch').click();
107+
cy.get('input[placeholder="Filter by branch"]').type('Main branch');
108+
109+
cy.get('[data-ouia-component-id="FiltersExampleHeader-clear-all-filters"]').should('exist').click();
110+
});
111+
});
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import React, { useState } from 'react';
2+
import { DataViewTextFilter } from '@patternfly/react-data-view/dist/dynamic/DataViewTextFilter';
3+
import { DataViewToolbar } from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar';
4+
5+
const defaultProps = {
6+
filterId: 'name',
7+
title: 'Name',
8+
value: '',
9+
ouiaId: 'DataViewTextFilter',
10+
placeholder: 'Filter by name'
11+
};
12+
13+
const DataViewToolbarWithState = (props: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
14+
const [ value, setValue ] = useState('Repository one');
15+
16+
return (
17+
<DataViewToolbar clearAllFilters={() => setValue('')}>
18+
<DataViewTextFilter {...defaultProps} value={value} onChange={() => setValue('')} {...props} />
19+
</DataViewToolbar>
20+
);
21+
};
22+
23+
describe('DataViewTextFilter', () => {
24+
25+
it('renders DataViewTextFilter with correct initial values', () => {
26+
cy.mount(<DataViewToolbarWithState value="" />);
27+
cy.get('[data-ouia-component-id="DataViewTextFilter"]').should('exist');
28+
cy.get('[data-ouia-component-id="DataViewTextFilter-input"] input')
29+
.should('have.attr', 'placeholder', 'Filter by name')
30+
.and('have.value', '');
31+
});
32+
33+
it('accepts input when passed', () => {
34+
cy.mount(<DataViewToolbarWithState value="" />);
35+
cy.get('[data-ouia-component-id="DataViewTextFilter-input"] input')
36+
.type('Repository one')
37+
.should('have.value', 'Repository one');
38+
});
39+
40+
it('displays a chip when value is present and removes it on delete', () => {
41+
cy.mount(<DataViewToolbarWithState />);
42+
cy.get('[data-ouia-component-id="DataViewTextFilter-input"] input').should('have.value', 'Repository one');
43+
44+
cy.get('.pf-v5-c-chip__text').contains('Repository one');
45+
cy.get('.pf-m-chip-group button.pf-v5-c-button.pf-m-plain').click();
46+
47+
cy.get('.pf-v5-c-chip__text').should('not.exist');
48+
cy.get('[data-ouia-component-id="DataViewTextFilter-input"] input').should('have.value', '');
49+
});
50+
51+
it('clears input when the clear button is clicked', () => {
52+
cy.mount(<DataViewToolbarWithState />);
53+
cy.get('[data-ouia-component-id="DataViewTextFilter-input"] input').should('have.value', 'Repository one');
54+
55+
cy.get('[data-ouia-component-id="DataViewToolbar-clear-all-filters"]').click();
56+
57+
cy.get('[data-ouia-component-id="DataViewTextFilter-input"] input').should('have.value', '');
58+
});
59+
60+
it('hides or shows the toolbar item based on showToolbarItem prop', () => {
61+
cy.mount(
62+
<DataViewToolbar>
63+
<DataViewTextFilter {...defaultProps} showToolbarItem={false} />
64+
</DataViewToolbar>
65+
);
66+
cy.get('[data-ouia-component-id="DataViewTextFilter"]').should('not.exist');
67+
68+
cy.mount(
69+
<DataViewToolbar>
70+
<DataViewTextFilter {...defaultProps} showToolbarItem />
71+
</DataViewToolbar>
72+
);
73+
cy.get('[data-ouia-component-id="DataViewTextFilter"]').should('exist');
74+
});
75+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React from 'react';
2+
import { render } from '@testing-library/react';
3+
import DataViewFilters from './DataViewFilters';
4+
import DataViewToolbar from '../DataViewToolbar';
5+
import DataViewTextFilter from '../DataViewTextFilter';
6+
7+
describe('DataViewFilters component', () => {
8+
const mockOnChange = jest.fn();
9+
10+
it('should render correctly', () => {
11+
const { container } = render(<DataViewToolbar
12+
filters={
13+
<DataViewFilters onChange={mockOnChange} values={{}}>
14+
<DataViewTextFilter filterId="one" title="One" />
15+
<DataViewTextFilter filterId="two" title="Two" />
16+
</DataViewFilters>
17+
}
18+
/>);
19+
expect(container).toMatchSnapshot();
20+
});
21+
});
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`DataViewFilters component should render correctly 1`] = `
4+
<div>
5+
<div
6+
class="pf-v5-c-toolbar"
7+
data-ouia-component-id="DataViewToolbar"
8+
data-ouia-component-type="PF5/Toolbar"
9+
data-ouia-safe="true"
10+
id="pf-random-id-0"
11+
>
12+
<div
13+
class="pf-v5-c-toolbar__content"
14+
>
15+
<div
16+
class="pf-v5-c-toolbar__content-section"
17+
>
18+
<div
19+
class="pf-v5-c-toolbar__item pf-m-search-filter"
20+
>
21+
<div
22+
class="pf-v5-c-toolbar__group pf-m-toggle-group pf-m-show-on-xl"
23+
data-ouia-component-id="DataViewFilters"
24+
>
25+
<div
26+
class="pf-v5-c-toolbar__toggle"
27+
>
28+
<button
29+
aria-disabled="false"
30+
aria-haspopup="false"
31+
aria-label="Show Filters"
32+
class="pf-v5-c-button pf-m-plain"
33+
data-ouia-component-id="OUIA-Generated-Button-plain-1"
34+
data-ouia-component-type="PF5/Button"
35+
data-ouia-safe="true"
36+
type="button"
37+
>
38+
<svg
39+
aria-hidden="true"
40+
class="pf-v5-svg"
41+
fill="currentColor"
42+
height="1em"
43+
role="img"
44+
viewBox="0 0 512 512"
45+
width="1em"
46+
>
47+
<path
48+
d="M487.976 0H24.028C2.71 0-8.047 25.866 7.058 40.971L192 225.941V432c0 7.831 3.821 15.17 10.237 19.662l80 55.98C298.02 518.69 320 507.493 320 487.98V225.941l184.947-184.97C520.021 25.896 509.338 0 487.976 0z"
49+
/>
50+
</svg>
51+
</button>
52+
</div>
53+
<div
54+
class="pf-v5-c-toolbar__group pf-m-filter-group"
55+
>
56+
<div>
57+
<button
58+
aria-expanded="false"
59+
class="pf-v5-c-menu-toggle"
60+
data-ouia-component-id="OUIA-Generated-MenuToggle-1"
61+
data-ouia-component-type="PF5/MenuToggle"
62+
data-ouia-safe="true"
63+
type="button"
64+
>
65+
<span
66+
class="pf-v5-c-menu-toggle__icon"
67+
>
68+
<svg
69+
aria-hidden="true"
70+
class="pf-v5-svg"
71+
fill="currentColor"
72+
height="1em"
73+
role="img"
74+
viewBox="0 0 512 512"
75+
width="1em"
76+
>
77+
<path
78+
d="M487.976 0H24.028C2.71 0-8.047 25.866 7.058 40.971L192 225.941V432c0 7.831 3.821 15.17 10.237 19.662l80 55.98C298.02 518.69 320 507.493 320 487.98V225.941l184.947-184.97C520.021 25.896 509.338 0 487.976 0z"
79+
/>
80+
</svg>
81+
</span>
82+
<span
83+
class="pf-v5-c-menu-toggle__text"
84+
>
85+
One
86+
</span>
87+
<span
88+
class="pf-v5-c-menu-toggle__controls"
89+
>
90+
<span
91+
class="pf-v5-c-menu-toggle__toggle-icon"
92+
>
93+
<svg
94+
aria-hidden="true"
95+
class="pf-v5-svg"
96+
fill="currentColor"
97+
height="1em"
98+
role="img"
99+
viewBox="0 0 320 512"
100+
width="1em"
101+
>
102+
<path
103+
d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"
104+
/>
105+
</svg>
106+
</span>
107+
</span>
108+
</button>
109+
</div>
110+
<div
111+
class="pf-v5-c-toolbar__item"
112+
data-ouia-component-id="DataViewTextFilter"
113+
>
114+
<div
115+
class="pf-v5-c-text-input-group"
116+
data-ouia-component-id="DataViewTextFilter-input"
117+
>
118+
<div
119+
class="pf-v5-c-text-input-group__main pf-m-icon"
120+
>
121+
<span
122+
class="pf-v5-c-text-input-group__text"
123+
>
124+
<span
125+
class="pf-v5-c-text-input-group__icon"
126+
>
127+
<svg
128+
aria-hidden="true"
129+
class="pf-v5-svg"
130+
fill="currentColor"
131+
height="1em"
132+
role="img"
133+
viewBox="0 0 512 512"
134+
width="1em"
135+
>
136+
<path
137+
d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"
138+
/>
139+
</svg>
140+
</span>
141+
<input
142+
aria-label="One filter"
143+
class="pf-v5-c-text-input-group__text-input"
144+
id="one"
145+
placeholder="Filter by One"
146+
type="text"
147+
value=""
148+
/>
149+
</span>
150+
</div>
151+
</div>
152+
</div>
153+
</div>
154+
</div>
155+
</div>
156+
</div>
157+
</div>
158+
<div
159+
class="pf-v5-c-toolbar__content pf-m-hidden"
160+
hidden=""
161+
>
162+
<div
163+
class="pf-v5-c-toolbar__group"
164+
/>
165+
<div
166+
class="pf-v5-c-toolbar__item"
167+
>
168+
<button
169+
aria-disabled="false"
170+
class="pf-v5-c-button pf-m-link pf-m-inline"
171+
data-ouia-component-id="DataViewToolbar-clear-all-filters"
172+
data-ouia-component-type="PF5/Button"
173+
data-ouia-safe="true"
174+
type="button"
175+
>
176+
Clear filters
177+
</button>
178+
</div>
179+
</div>
180+
</div>
181+
</div>
182+
`;

0 commit comments

Comments
 (0)