ui-soxo-bootstrap-core 2.6.62-dev.4 → 2.6.63-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/lib/components/global-header/global-header.js +191 -151
- package/core/lib/components/index.js +13 -0
- package/core/lib/components/support-desk/components/{raise-ticket/raise-ticket.js → support-frame/support-frame.js} +42 -19
- package/core/lib/components/support-desk/support-desk.js +8 -8
- package/core/lib/components/support-desk/support-desk.scss +0 -72
- package/core/lib/components/support-desk/support-desk.utils.js +35 -315
- package/core/lib/components/support-desk/support-desk.utils.test.js +51 -308
- package/core/lib/elements/basic/table/column-filter/column-filter.js +299 -0
- package/core/lib/elements/basic/table/column-filter/column-filter.scss +48 -0
- package/core/lib/elements/basic/table/column-filter/column-filter.test.js +148 -0
- package/core/lib/elements/basic/table/readme.md +50 -1
- package/core/lib/elements/basic/table/table.js +59 -4
- package/core/lib/elements/basic/table/table.test.js +80 -0
- package/package.json +1 -1
- package/core/lib/components/support-desk/components/my-tickets/my-tickets.js +0 -343
- package/core/lib/components/support-desk/support-desk.dom.test.js +0 -20
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/* Excel style column filter of the table */
|
|
2
|
+
|
|
3
|
+
.column-filter-dropdown {
|
|
4
|
+
width: 240px;
|
|
5
|
+
padding: 8px;
|
|
6
|
+
|
|
7
|
+
.column-filter-search {
|
|
8
|
+
margin-bottom: 8px;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.column-filter-select-all {
|
|
12
|
+
width: 100%;
|
|
13
|
+
padding: 4px 0 6px;
|
|
14
|
+
border-bottom: 1px solid #f0f0f0;
|
|
15
|
+
font-weight: 600;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.column-filter-options {
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
max-height: 220px;
|
|
22
|
+
padding: 6px 0;
|
|
23
|
+
overflow-y: auto;
|
|
24
|
+
scrollbar-width: thin;
|
|
25
|
+
|
|
26
|
+
.ant-checkbox-wrapper {
|
|
27
|
+
margin: 0;
|
|
28
|
+
padding: 3px 0;
|
|
29
|
+
word-break: break-word;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.column-filter-actions {
|
|
34
|
+
display: flex;
|
|
35
|
+
justify-content: space-between;
|
|
36
|
+
gap: 8px;
|
|
37
|
+
padding-top: 8px;
|
|
38
|
+
border-top: 1px solid #f0f0f0;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.column-filter-icon {
|
|
43
|
+
color: #bfbfbf;
|
|
44
|
+
|
|
45
|
+
&--active {
|
|
46
|
+
color: #1677ff;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
getColumnFilterKey,
|
|
6
|
+
getColumnFilterValue,
|
|
7
|
+
isFilterableColumn,
|
|
8
|
+
applyColumnFilters,
|
|
9
|
+
hasColumnFilters,
|
|
10
|
+
getColumnValues,
|
|
11
|
+
withColumnFilters,
|
|
12
|
+
ColumnFilterDropdown,
|
|
13
|
+
} from './column-filter';
|
|
14
|
+
|
|
15
|
+
jest.mock('react-i18next', () => ({
|
|
16
|
+
useTranslation: () => ({ t: (text) => text }),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
// The core Button reads the theme from the global store, a plain button is enough here
|
|
20
|
+
jest.mock('../../button/button', () => ({ children, onClick, disabled }) => (
|
|
21
|
+
<button type="button" onClick={onClick} disabled={disabled}>
|
|
22
|
+
{children}
|
|
23
|
+
</button>
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
const genderColumn = { key: 'gender', title: 'Gender', render: (record) => <span>{record.gender}</span> };
|
|
27
|
+
|
|
28
|
+
const cityColumn = { key: 'city', title: 'City', dataIndex: ['address', 'city'] };
|
|
29
|
+
|
|
30
|
+
const statusColumn = { key: 'status', title: 'Status', render: () => <select />, exportDefinition: (record) => record.status };
|
|
31
|
+
|
|
32
|
+
const records = [
|
|
33
|
+
{ id: 1, gender: 'Male', address: { city: 'Calicut' }, status: 'Booked' },
|
|
34
|
+
{ id: 2, gender: 'Female', address: { city: 'Kochi' }, status: 'Arrived' },
|
|
35
|
+
{ id: 3, gender: 'Male', address: { city: 'Kochi' }, status: 'Booked' },
|
|
36
|
+
{ id: 4, gender: '', address: { city: 'Calicut' }, status: 'Arrived' },
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
describe('column filter helpers', () => {
|
|
40
|
+
it('reads the rendered text of the cell', () => {
|
|
41
|
+
expect(getColumnFilterValue(genderColumn, records[0])).toBe('Male');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('reads the dataIndex value, path arrays included', () => {
|
|
45
|
+
expect(getColumnFilterValue(cityColumn, records[1])).toBe('Kochi');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('falls back to the export value when the cell has no text', () => {
|
|
49
|
+
expect(getColumnFilterValue(statusColumn, records[1])).toBe('Arrived');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('keys the filter by key, else by dataIndex', () => {
|
|
53
|
+
expect(getColumnFilterKey({ dataIndex: ['address', 'city'] })).toBe('address.city');
|
|
54
|
+
expect(getColumnFilterKey({ key: 'gender', dataIndex: 'x' })).toBe('gender');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('leaves out columns marked filterable false or without a value', () => {
|
|
58
|
+
expect(isFilterableColumn(genderColumn)).toBe(true);
|
|
59
|
+
expect(isFilterableColumn({ ...genderColumn, filterable: false })).toBe(false);
|
|
60
|
+
expect(isFilterableColumn({ key: 'empty', title: 'Empty' })).toBe(false);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('keeps only the records matching every filtered column', () => {
|
|
64
|
+
const columns = [genderColumn, cityColumn];
|
|
65
|
+
|
|
66
|
+
expect(applyColumnFilters(records, columns, { gender: ['Male'] }).map((r) => r.id)).toEqual([1, 3]);
|
|
67
|
+
expect(applyColumnFilters(records, columns, { gender: ['Male'], city: ['Kochi'] }).map((r) => r.id)).toEqual([3]);
|
|
68
|
+
expect(applyColumnFilters(records, columns, {})).toBe(records);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('ignores the excepted column, to list its values from the other filters', () => {
|
|
72
|
+
const columns = [genderColumn, cityColumn];
|
|
73
|
+
|
|
74
|
+
expect(applyColumnFilters(records, columns, { gender: ['Male'], city: ['Kochi'] }, 'city').map((r) => r.id)).toEqual([1, 3]);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('tells whether any filter is applied', () => {
|
|
78
|
+
expect(hasColumnFilters({})).toBe(false);
|
|
79
|
+
expect(hasColumnFilters({ gender: undefined })).toBe(false);
|
|
80
|
+
expect(hasColumnFilters({ gender: ['Male'] })).toBe(true);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('lists distinct values sorted with blanks last', () => {
|
|
84
|
+
expect(getColumnValues(genderColumn, records)).toEqual(['Female', 'Male', '']);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('adds the filter dropdown only to filterable columns', () => {
|
|
88
|
+
const columns = withColumnFilters([{ key: '#', filterable: false, render: () => 1 }, genderColumn], records, { gender: ['Male'] }, jest.fn());
|
|
89
|
+
|
|
90
|
+
expect(columns[0].filterDropdown).toBeUndefined();
|
|
91
|
+
expect(columns[1].filterDropdown).toBeInstanceOf(Function);
|
|
92
|
+
expect(columns[1].filteredValue).toEqual(['Male']);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('ColumnFilterDropdown', () => {
|
|
97
|
+
function renderDropdown(props = {}) {
|
|
98
|
+
const onApply = jest.fn();
|
|
99
|
+
const close = jest.fn();
|
|
100
|
+
|
|
101
|
+
render(<ColumnFilterDropdown column={genderColumn} records={records} visible onApply={onApply} close={close} {...props} />);
|
|
102
|
+
|
|
103
|
+
return { onApply, close };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
it('lists every value ticked when the column has no filter, blanks labelled', () => {
|
|
107
|
+
renderDropdown();
|
|
108
|
+
|
|
109
|
+
['Female', 'Male', '(Blanks)'].forEach((label) => expect(screen.getByLabelText(label)).toBeChecked());
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('applies the picked values and closes', () => {
|
|
113
|
+
const { onApply, close } = renderDropdown();
|
|
114
|
+
|
|
115
|
+
fireEvent.click(screen.getByLabelText('Female'));
|
|
116
|
+
fireEvent.click(screen.getByText('OK'));
|
|
117
|
+
|
|
118
|
+
expect(onApply).toHaveBeenCalledWith(['Male', '']);
|
|
119
|
+
expect(close).toHaveBeenCalled();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('removes the filter when every value is selected', () => {
|
|
123
|
+
const { onApply } = renderDropdown({ applied: ['Male'] });
|
|
124
|
+
|
|
125
|
+
fireEvent.click(screen.getByLabelText('Select All'));
|
|
126
|
+
fireEvent.click(screen.getByText('OK'));
|
|
127
|
+
|
|
128
|
+
expect(onApply).toHaveBeenCalledWith(undefined);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('Clear All unticks everything and disables OK', () => {
|
|
132
|
+
renderDropdown();
|
|
133
|
+
|
|
134
|
+
fireEvent.click(screen.getByText('Clear All'));
|
|
135
|
+
|
|
136
|
+
expect(screen.getByLabelText('Male')).not.toBeChecked();
|
|
137
|
+
expect(screen.getByText('OK').closest('button')).toBeDisabled();
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('narrows the list with the search', () => {
|
|
141
|
+
renderDropdown();
|
|
142
|
+
|
|
143
|
+
fireEvent.change(screen.getByPlaceholderText('Search'), { target: { value: 'fem' } });
|
|
144
|
+
|
|
145
|
+
expect(screen.getByLabelText('Female')).toBeInTheDocument();
|
|
146
|
+
expect(screen.queryByLabelText('Male')).not.toBeInTheDocument();
|
|
147
|
+
});
|
|
148
|
+
});
|
|
@@ -6,4 +6,53 @@ Here is how we can simply add a table.
|
|
|
6
6
|
import Table from "./table";
|
|
7
7
|
|
|
8
8
|
<Table />;
|
|
9
|
-
```
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Column filters
|
|
12
|
+
|
|
13
|
+
`columnFilters` adds an Excel style filter to every column header: the distinct values of
|
|
14
|
+
the column with Search, Select All / Clear All and a "(Blanks)" option. Filters of several
|
|
15
|
+
columns work together, and the values listed for a column are the ones left by the other
|
|
16
|
+
filters.
|
|
17
|
+
|
|
18
|
+
The values are the text shown in the cell (the column `render`), the `exportDefinition`
|
|
19
|
+
when the cell is a component, else the `dataIndex` value. Leave a column out with
|
|
20
|
+
`filterable: false`, or pass the keys of the columns to filter:
|
|
21
|
+
|
|
22
|
+
```jsx
|
|
23
|
+
<TableComponent columns={columns} dataSource={rows} columnFilters={['gender', 'source']} />
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Filtered by the table
|
|
27
|
+
|
|
28
|
+
When the whole list is in `dataSource`, the table filters it:
|
|
29
|
+
|
|
30
|
+
```jsx
|
|
31
|
+
<TableComponent columns={columns} dataSource={rows} columnFilters />
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Filtered by the screen
|
|
35
|
+
|
|
36
|
+
With server side paging the screen keeps the filters and filters the data itself:
|
|
37
|
+
|
|
38
|
+
```jsx
|
|
39
|
+
import { TableComponent, applyColumnFilters, hasColumnFilters } from 'ui-soxo-bootstrap-core';
|
|
40
|
+
|
|
41
|
+
const [filters, setFilters] = useState({});
|
|
42
|
+
|
|
43
|
+
const rows = applyColumnFilters(records, columns, filters);
|
|
44
|
+
|
|
45
|
+
<TableComponent
|
|
46
|
+
columns={columns}
|
|
47
|
+
dataSource={rows}
|
|
48
|
+
columnFilters
|
|
49
|
+
filters={filters}
|
|
50
|
+
onFilterChange={(key, values) => setFilters({ ...filters, [key]: values })}
|
|
51
|
+
// Records the values are listed from, the dataSource when not given
|
|
52
|
+
filterRecords={records}
|
|
53
|
+
/>;
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`onFilterChange` gets the column key and the selected values, `undefined` when the filter
|
|
57
|
+
is removed (every value selected). `hasColumnFilters(filters)` tells whether any filter is
|
|
58
|
+
applied, ex: to load the whole range instead of one page.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React, { useContext, useEffect } from 'react';
|
|
1
|
+
import React, { useContext, useEffect, useState } from 'react';
|
|
2
2
|
import { Table } from 'antd';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import { GlobalContext } from '../../../Store';
|
|
5
|
+
import { withColumnFilters, applyColumnFilters, getColumnFilterKey } from './column-filter/column-filter';
|
|
5
6
|
|
|
6
7
|
import './table.scss';
|
|
7
8
|
|
|
@@ -12,9 +13,55 @@ import './table.scss';
|
|
|
12
13
|
* use it for long lists only. The header cells stay inside the same table as the rows
|
|
13
14
|
* (see table.scss), so the columns always line up with the header.
|
|
14
15
|
*/
|
|
15
|
-
const TableComponent = ({
|
|
16
|
+
const TableComponent = ({
|
|
17
|
+
columns,
|
|
18
|
+
dataSource,
|
|
19
|
+
loading,
|
|
20
|
+
fixed,
|
|
21
|
+
scroll,
|
|
22
|
+
summary,
|
|
23
|
+
pagination,
|
|
24
|
+
title,
|
|
25
|
+
onChange,
|
|
26
|
+
freezeHeader,
|
|
27
|
+
// Excel style filter - true for every column (a column is left out with `filterable: false`), or the keys of the columns to filter
|
|
28
|
+
columnFilters = false,
|
|
29
|
+
// Applied filters ({ [columnKey]: values }), when the screen filters the data itself (ex: server side paging)
|
|
30
|
+
filters,
|
|
31
|
+
// Called with the column key and the selected values (undefined when the filter is removed)
|
|
32
|
+
onFilterChange,
|
|
33
|
+
// Records the filter values are listed from, the dataSource when not given
|
|
34
|
+
filterRecords,
|
|
35
|
+
}) => {
|
|
16
36
|
const { state } = useContext(GlobalContext);
|
|
17
37
|
|
|
38
|
+
const [localFilters, setLocalFilters] = useState({});
|
|
39
|
+
|
|
40
|
+
// Controlled when the screen passes the filters, else the table filters its own dataSource
|
|
41
|
+
const isControlled = filters !== undefined;
|
|
42
|
+
|
|
43
|
+
const appliedFilters = isControlled ? filters || {} : localFilters;
|
|
44
|
+
|
|
45
|
+
const filterSource = filterRecords || dataSource || [];
|
|
46
|
+
|
|
47
|
+
// With a list of keys only those columns get the filter
|
|
48
|
+
const filterColumns = Array.isArray(columnFilters)
|
|
49
|
+
? columns.map((col) => (columnFilters.includes(getColumnFilterKey(col)) ? col : { ...col, filterable: false }))
|
|
50
|
+
: columns;
|
|
51
|
+
|
|
52
|
+
const filteredColumns = columnFilters
|
|
53
|
+
? withColumnFilters(filterColumns, filterSource, appliedFilters, (key, values) => {
|
|
54
|
+
if (!isControlled) setLocalFilters((current) => ({ ...current, [key]: values }));
|
|
55
|
+
|
|
56
|
+
if (onFilterChange) onFilterChange(key, values);
|
|
57
|
+
})
|
|
58
|
+
: columns;
|
|
59
|
+
|
|
60
|
+
// The opt out flag is only for the filter, it is not passed on to antd
|
|
61
|
+
const visibleColumns = filteredColumns.map(({ filterable, ...col }) => col);
|
|
62
|
+
|
|
63
|
+
const visibleData = columnFilters && !isControlled ? applyColumnFilters(dataSource, filterColumns, localFilters) : dataSource;
|
|
64
|
+
|
|
18
65
|
useEffect(() => {}, [state.theme.colors]);
|
|
19
66
|
|
|
20
67
|
// Header styling
|
|
@@ -57,7 +104,7 @@ const TableComponent = ({ columns, dataSource, loading, fixed, scroll, summary,
|
|
|
57
104
|
}));
|
|
58
105
|
|
|
59
106
|
// Apply fixed property to the columns you need
|
|
60
|
-
const updatedColumns =
|
|
107
|
+
const updatedColumns = visibleColumns.map((col) => ({
|
|
61
108
|
...col,
|
|
62
109
|
onHeaderCell: () => ({
|
|
63
110
|
style: headerStyle,
|
|
@@ -70,7 +117,7 @@ const TableComponent = ({ columns, dataSource, loading, fixed, scroll, summary,
|
|
|
70
117
|
title={title ? () => title : undefined}
|
|
71
118
|
scroll={scroll}
|
|
72
119
|
className={freezeHeader ? 'frozen-header-table' : undefined}
|
|
73
|
-
dataSource={
|
|
120
|
+
dataSource={visibleData}
|
|
74
121
|
loading={loading}
|
|
75
122
|
bordered
|
|
76
123
|
fixed={fixed}
|
|
@@ -97,6 +144,14 @@ TableComponent.propTypes = {
|
|
|
97
144
|
data: PropTypes.array.isRequired,
|
|
98
145
|
loading: PropTypes.bool,
|
|
99
146
|
freezeHeader: PropTypes.bool,
|
|
147
|
+
/** Excel style filter - true for every column (a column is left out with `filterable: false`), or the keys of the columns to filter */
|
|
148
|
+
columnFilters: PropTypes.oneOfType([PropTypes.bool, PropTypes.arrayOf(PropTypes.string)]),
|
|
149
|
+
/** Applied filters ({ [columnKey]: values }), pass it to filter the data in the screen */
|
|
150
|
+
filters: PropTypes.object,
|
|
151
|
+
/** Called with the column key and the selected values, undefined when the filter is removed */
|
|
152
|
+
onFilterChange: PropTypes.func,
|
|
153
|
+
/** Records the filter values are listed from, the dataSource when not given */
|
|
154
|
+
filterRecords: PropTypes.array,
|
|
100
155
|
};
|
|
101
156
|
|
|
102
157
|
TableComponent.defaultProps = {
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
|
|
4
|
+
import TableComponent from './table';
|
|
5
|
+
import { GlobalContext } from '../../../Store';
|
|
6
|
+
|
|
7
|
+
jest.mock('react-i18next', () => ({
|
|
8
|
+
useTranslation: () => ({ t: (text) => text }),
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
// The real store pulls in every module of the library, the table only reads the theme from it
|
|
12
|
+
jest.mock('../../../Store', () => ({ GlobalContext: require('react').createContext({}) }));
|
|
13
|
+
|
|
14
|
+
// The core Button reads the theme from the global store, a plain button is enough here
|
|
15
|
+
jest.mock('../button/button', () => ({ children, onClick, disabled }) => (
|
|
16
|
+
<button type="button" onClick={onClick} disabled={disabled}>
|
|
17
|
+
{children}
|
|
18
|
+
</button>
|
|
19
|
+
));
|
|
20
|
+
|
|
21
|
+
// antd Table watches the screen size, jsdom has no matchMedia
|
|
22
|
+
beforeAll(() => {
|
|
23
|
+
window.matchMedia =
|
|
24
|
+
window.matchMedia ||
|
|
25
|
+
(() => ({ matches: false, addListener: () => {}, removeListener: () => {}, addEventListener: () => {}, removeEventListener: () => {} }));
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const columns = [
|
|
29
|
+
{ key: 'name', title: 'Name', render: (record) => record.name },
|
|
30
|
+
{ key: 'gender', title: 'Gender', render: (record) => record.gender },
|
|
31
|
+
{ key: 'city', title: 'City', dataIndex: 'city' },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const rows = [
|
|
35
|
+
{ key: 1, name: 'Anu', gender: 'Female', city: 'Kochi' },
|
|
36
|
+
{ key: 2, name: 'Ravi', gender: 'Male', city: 'Calicut' },
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
function renderTable(props) {
|
|
40
|
+
return render(
|
|
41
|
+
<GlobalContext.Provider value={{ state: { theme: { colors: {} } } }}>
|
|
42
|
+
<TableComponent columns={columns} dataSource={rows} {...props} />
|
|
43
|
+
</GlobalContext.Provider>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
describe('TableComponent column filters', () => {
|
|
48
|
+
it('has no filter without columnFilters', () => {
|
|
49
|
+
const { container } = renderTable();
|
|
50
|
+
|
|
51
|
+
expect(container.querySelectorAll('.column-filter-icon')).toHaveLength(0);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('filters every column with columnFilters', () => {
|
|
55
|
+
const { container } = renderTable({ columnFilters: true });
|
|
56
|
+
|
|
57
|
+
expect(container.querySelectorAll('.column-filter-icon')).toHaveLength(3);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('filters only the listed columns', () => {
|
|
61
|
+
const { container } = renderTable({ columnFilters: ['gender'] });
|
|
62
|
+
|
|
63
|
+
expect(container.querySelectorAll('.column-filter-icon')).toHaveLength(1);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('filters its own rows with the applied filters', () => {
|
|
67
|
+
const { getByText, queryByText } = renderTable({ columnFilters: ['gender'], filters: undefined });
|
|
68
|
+
|
|
69
|
+
expect(getByText('Anu')).toBeTruthy();
|
|
70
|
+
expect(queryByText('Ravi')).toBeTruthy();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('shows the screen filters as active, leaving the rows to the screen', () => {
|
|
74
|
+
const { container, getByText } = renderTable({ columnFilters: ['gender'], filters: { gender: ['Male'] }, onFilterChange: jest.fn() });
|
|
75
|
+
|
|
76
|
+
expect(container.querySelectorAll('.column-filter-icon--active')).toHaveLength(1);
|
|
77
|
+
// Controlled: the screen filters the dataSource, the table shows what it gets
|
|
78
|
+
expect(getByText('Anu')).toBeTruthy();
|
|
79
|
+
});
|
|
80
|
+
});
|