Skip to content

Commit

Permalink
Merge pull request #1574 from ral-facilities/feature/add-exact-filter…
Browse files Browse the repository at this point in the history
…-#1540

Feature/add exact filter #1540
  • Loading branch information
kaperoo authored Aug 17, 2023
2 parents e5ee1a6 + 94c08bc commit 230b50c
Show file tree
Hide file tree
Showing 11 changed files with 145 additions and 28 deletions.
4 changes: 4 additions & 0 deletions packages/datagateway-common/src/api/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ describe('generic api functions', () => {
filters: {
name: { value: 'test', type: 'include' },
title: { value: 'test', type: 'exclude' },
doi: { value: 'test', type: 'exact' },
startDate: {
startDate: '2021-08-05',
endDate: '2021-08-06',
Expand All @@ -276,6 +277,7 @@ describe('generic api functions', () => {
params.append('order', JSON.stringify('id asc'));
params.append('where', JSON.stringify({ name: { ilike: 'test' } }));
params.append('where', JSON.stringify({ title: { nilike: 'test' } }));
params.append('where', JSON.stringify({ doi: { eq: 'test' } }));
params.append(
'where',
JSON.stringify({ startDate: { gte: '2021-08-05 00:00:00' } })
Expand All @@ -296,6 +298,7 @@ describe('generic api functions', () => {
filters: {
name: { value: 'test', type: 'include' },
title: { value: 'test', type: 'exclude' },
doi: { value: 'test', type: 'exact' },
startDate: {
startDate: '2021-08-05',
endDate: '2021-08-06',
Expand All @@ -309,6 +312,7 @@ describe('generic api functions', () => {
params.append('order', JSON.stringify('name asc'));
params.append('where', JSON.stringify({ name: { ilike: 'test' } }));
params.append('where', JSON.stringify({ title: { nilike: 'test' } }));
params.append('where', JSON.stringify({ doi: { eq: 'test' } }));
params.append(
'where',
JSON.stringify({ startDate: { gte: '2021-08-05 00:00:00' } })
Expand Down
7 changes: 6 additions & 1 deletion packages/datagateway-common/src/api/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,16 @@ export const getApiParams = (
'where',
JSON.stringify({ [column]: { ilike: filter.value } })
);
} else {
} else if (filter.type === 'exclude') {
searchParams.append(
'where',
JSON.stringify({ [column]: { nilike: filter.value } })
);
} else {
searchParams.append(
'where',
JSON.stringify({ [column]: { eq: filter.value } })
);
}
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ exports[`Text filter component renders correctly 1`] = `
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="test-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="test-select-filter-type"
Expand Down Expand Up @@ -108,7 +108,7 @@ exports[`Text filter component usePrincipalExperimenterFilter hook returns a fun
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="Principal Investigator-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="Principal Investigator-select-filter-type"
Expand Down Expand Up @@ -181,7 +181,7 @@ exports[`Text filter component useTextFilter hook returns a function which can g
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="Name-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="Name-select-filter-type"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,35 @@ describe('Text filter component', () => {
});
});

it('calls the onChange method once when input is typed while exact filter type is selected and calls again by debounced function after timeout', async () => {
const onChange = jest.fn();

render(
<TextColumnFilter
value={{ value: 'test', type: 'exact' }}
label="test"
onChange={onChange}
/>
);

// We simulate a change in the input from 'test' to 'test-again'.
const textFilterInput = await screen.findByRole('textbox', {
name: 'Filter by test',
hidden: true,
});

await user.clear(textFilterInput);
await user.type(textFilterInput, 'test-again');

jest.advanceTimersByTime(DEBOUNCE_DELAY);

expect(onChange).toHaveBeenCalledTimes(1);
expect(onChange).toHaveBeenLastCalledWith({
value: 'test-again',
type: 'exact',
});
});

it('calls the onChange method once when include filter type is selected while there is input', async () => {
const onChange = jest.fn();

Expand All @@ -104,7 +133,7 @@ describe('Text filter component', () => {
// We simulate a change in the select from 'exclude' to 'include'.
await user.click(
await screen.findByRole('button', {
name: 'include or exclude',
name: 'include, exclude or exact',
hidden: true,
})
);
Expand All @@ -131,7 +160,7 @@ describe('Text filter component', () => {
// We simulate a change in the select from 'include' to 'exclude'.
await user.click(
await screen.findByRole('button', {
name: 'include or exclude',
name: 'include, exclude or exact',
hidden: true,
})
);
Expand All @@ -144,6 +173,33 @@ describe('Text filter component', () => {
});
});

it('calls the onChange method once when exact filter type is selected while there is input', async () => {
const onChange = jest.fn();

render(
<TextColumnFilter
value={{ value: 'test', type: 'include' }}
label="test"
onChange={onChange}
/>
);

// We simulate a change in the select from 'include' to 'exact'.
await user.click(
await screen.findByRole('button', {
name: 'include, exclude or exact',
hidden: true,
})
);
await user.click(await screen.findByText('Exact'));

expect(onChange).toHaveBeenCalledTimes(1);
expect(onChange).toHaveBeenLastCalledWith({
value: 'test',
type: 'exact',
});
});

it('calls the onChange method once when input is cleared and calls again by debounced function after timeout', async () => {
const onChange = jest.fn();

Expand Down Expand Up @@ -182,7 +238,7 @@ describe('Text filter component', () => {
// We simulate a change in the select from 'exclude' to 'include'.
await user.click(
await screen.findByRole('button', {
name: 'include or exclude',
name: 'include, exclude or exact',
hidden: true,
})
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const TextColumnFilter = (props: {
renderValue={() => ''}
onChange={(e) => handleSelectChange(e.target.value as string)}
SelectDisplayProps={{
'aria-label': `include or exclude`,
'aria-label': `include, exclude or exact`,
}}
variant="standard"
>
Expand All @@ -113,6 +113,13 @@ const TextColumnFilter = (props: {
>
Exclude
</MenuItem>
<MenuItem
key="exact"
id="select-filter-type-exact"
value="exact"
>
Exact
</MenuItem>
</Select>
</InputAdornment>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ exports[`Data column header component renders correctly with filter but no sort
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="Test-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="Test-select-filter-type"
Expand Down Expand Up @@ -187,7 +187,7 @@ exports[`Data column header component renders correctly with sort and filter 1`]
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="Test-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="Test-select-filter-type"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('Investigations Table', () => {

it('should disable the hover tool tip by pressing escape', () => {
// The hover tool tip has a enter delay of 500ms.
// eslint-disable-next-line cypress/no-unnecessary-waiting
// eslint-disable-next-line cypress/no-unnecessary-waiting, cypress/unsafe-to-chain-command
cy.get('[data-testid="investigation-table-title"]')
.first()
.trigger('mouseover', { force: true })
Expand Down Expand Up @@ -78,6 +78,7 @@ describe('Investigations Table', () => {
expect(width).to.equal(columnWidth);
});

// eslint-disable-next-line cypress/unsafe-to-chain-command
cy.get('.react-draggable')
.first()
.trigger('mousedown')
Expand All @@ -95,6 +96,7 @@ describe('Investigations Table', () => {
});

// table width should grow if a column grows too large
// eslint-disable-next-line cypress/unsafe-to-chain-command
cy.get('.react-draggable')
.first()
.trigger('mousedown')
Expand Down Expand Up @@ -172,14 +174,55 @@ describe('Investigations Table', () => {
});

describe('should be able to filter by', () => {
it('text', () => {
cy.get('[aria-label="Filter by Title"]').first().type('wide');
it('exclude', () => {
cy.get('input[aria-label="Filter by Name"]')
.parent()
.find('[aria-label="include, exclude or exact"]')
.click();

cy.get('#select-filter-type-exclude').click();

cy.get('[aria-label="Filter by Name"]').first().type('INVESTIGATION 1');

cy.get('[aria-rowcount="48"]').should('exist');
cy.get('[aria-rowindex="1"] [aria-colindex="4"]').contains('87');

// check that size is correct after filtering
cy.get('[aria-rowindex="1"] [aria-colindex="7"]').contains('3.38 GB');
});

it('include', () => {
cy.get('input[aria-label="Filter by Name"]')
.parent()
.find('[aria-label="include, exclude or exact"]')
.click();

cy.get('#select-filter-type-include').click();

cy.get('[aria-label="Filter by Name"]').first().type('INVESTIGATION 1');

cy.get('[aria-rowcount="11"]').should('exist');
cy.get('[aria-rowindex="1"] [aria-colindex="4"]').contains('70');

// check that size is correct after filtering
cy.get('[aria-rowindex="1"] [aria-colindex="7"]').contains('3.12 GB');
});

it('exact', () => {
cy.get('input[aria-label="Filter by Name"]')
.parent()
.find('[aria-label="include, exclude or exact"]')
.click();

cy.get('#select-filter-type-exact').click();

cy.get('[aria-label="Filter by Name"]').first().type('INVESTIGATION 1');

cy.get('[aria-rowcount="4"]').should('exist');
cy.get('[aria-rowindex="1"] [aria-colindex="4"]').contains('85');
cy.get('[aria-rowcount="1"]').should('exist');
cy.get('[aria-rowindex="1"] [aria-colindex="4"]').contains('70');

// check that size is correct after filtering
cy.get('[aria-rowindex="1"] [aria-colindex="7"]').contains('3.34 GB');
cy.get('[aria-rowindex="1"] [aria-colindex="7"]').contains('3.12 GB');
});

it('date between', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ exports[`Admin Download Status Table should render correctly 1`] = `
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="downloadStatus.id-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="downloadStatus.id-select-filter-type"
Expand Down Expand Up @@ -280,7 +280,7 @@ exports[`Admin Download Status Table should render correctly 1`] = `
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="downloadStatus.fullname-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="downloadStatus.fullname-select-filter-type"
Expand Down Expand Up @@ -403,7 +403,7 @@ exports[`Admin Download Status Table should render correctly 1`] = `
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="downloadStatus.username-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="downloadStatus.username-select-filter-type"
Expand Down Expand Up @@ -526,7 +526,7 @@ exports[`Admin Download Status Table should render correctly 1`] = `
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="downloadStatus.preparedId-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="downloadStatus.preparedId-select-filter-type"
Expand Down Expand Up @@ -649,7 +649,7 @@ exports[`Admin Download Status Table should render correctly 1`] = `
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="downloadStatus.transport-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="downloadStatus.transport-select-filter-type"
Expand Down Expand Up @@ -772,7 +772,7 @@ exports[`Admin Download Status Table should render correctly 1`] = `
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="downloadStatus.status-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="downloadStatus.status-select-filter-type"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ exports[`Download Status Table should render correctly 1`] = `
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="downloadStatus.filename-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="downloadStatus.filename-select-filter-type"
Expand Down Expand Up @@ -240,7 +240,7 @@ exports[`Download Status Table should render correctly 1`] = `
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="downloadStatus.transport-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="downloadStatus.transport-select-filter-type"
Expand Down Expand Up @@ -363,7 +363,7 @@ exports[`Download Status Table should render correctly 1`] = `
<div
aria-expanded="false"
aria-haspopup="listbox"
aria-label="include or exclude"
aria-label="include, exclude or exact"
aria-labelledby="downloadStatus.status-select-filter-type"
class="MuiSelect-select MuiSelect-standard MuiInputBase-input MuiInput-input css-1rxz5jq-MuiSelect-select-MuiInputBase-input-MuiInput-input"
id="downloadStatus.status-select-filter-type"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,9 @@ describe('Admin Download Status Table', () => {

// We simulate a change in the select from 'include' to 'exclude'.
// click on the select box
await user.click(screen.getAllByLabelText('include or exclude')[5]);
await user.click(
screen.getAllByLabelText('include, exclude or exact')[5]
);
// click on exclude option
await user.click(
within(await screen.findByRole('listbox')).getByText('Exclude')
Expand Down
Loading

0 comments on commit 230b50c

Please sign in to comment.