Skip to content

Commit

Permalink
global: array of filters as input for query
Browse files Browse the repository at this point in the history
  • Loading branch information
topless committed Apr 1, 2020
1 parent db60103 commit fd43974
Show file tree
Hide file tree
Showing 3 changed files with 279 additions and 7 deletions.
235 changes: 235 additions & 0 deletions src/lib/state/selectors/query-array.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
/*
* This file is part of React-SearchKit.
* Copyright (C) 2018-2019 CERN.
*
* React-SearchKit is free software; you can redistribute it and/or modify it
* under the terms of the MIT License; see LICENSE file for more details.
*/

import { updateQueryFilters } from './query';

/**
* Same tests as query.test.js but query is an array of filters.
*/
describe('queries with first level filters.', () => {
test('query with `type: Publication` should be added when not in the state.', () => {
const state = [['file_type', 'pdf']];
const query = [['type', 'Publication']];

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([
['file_type', 'pdf'],
['type', 'Publication'],
]);
});

test('query with `type: Publication` should be added when another `type` is already in the state.', () => {
const state = [
['file_type', 'pdf'],
['type', 'Image'],
];
const query = [['type', 'Publication']];

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([
['file_type', 'pdf'],
['type', 'Image'],
['type', 'Publication'],
]);
});

test('query with `type: Image` should remove it from the state when it is already there.', () => {
const state = [
['file_type', 'pdf'],
['type', 'Image'],
['type', 'Publication'],
];
const query = [['type', 'Image']];

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([
['file_type', 'pdf'],
['type', 'Publication'],
]);
});
});

describe('queries with second level filters.', () => {
test('query with `subtype: Other` should be added when not in the state.', () => {
const state = [
['file_type', 'pdf'],
['type', 'Image'],
];
const query = [['type', 'Publication', ['subtype', 'Other']]];

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([
['file_type', 'pdf'],
['type', 'Image'],
['type', 'Publication', ['subtype', 'Other']],
]);
});

test('query with `type` should remove from the state any children query.', () => {
const state = [
['file_type', 'pdf'],
['type', 'Image'],
['type', 'Publication', ['subtype', 'Other']],
['type', 'Publication', ['subtype', 'Report']],
['type', 'Publication', ['subtype', 'Article']],
];
const query = [['type', 'Publication']];

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([
['file_type', 'pdf'],
['type', 'Image'],
]);
});

test('query with `subtype: Other` should remove any query with the parent `type: Publication`.', () => {
const state = [
['file_type', 'pdf'],
['type', 'Image'],
['type', 'Publication'],
];
const query = [['type', 'Publication', ['subtype', 'Other']]];

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([
['file_type', 'pdf'],
['type', 'Image'],
['type', 'Publication', ['subtype', 'Other']],
]);
});

test('query with `subtype: Other` should remove it from the state when it is already there.', () => {
const state = [
['file_type', 'pdf'],
['type', 'Image'],
['type', 'Publication', ['subtype', 'Other']],
];
const query = [['type', 'Publication', ['subtype', 'Other']]];

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([
['file_type', 'pdf'],
['type', 'Image'],
['type', 'Publication'],
]);
});
});

describe('queries with third level filters.', () => {
test('query with `subsubtype: Public reports` should be added when not in the state.', () => {
const state = [
['file_type', 'png'],
['file_type', 'pdf'],
['type', 'Image'],
];
const query = [['type', 'Publication', ['subtype', 'Report']]];

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([
['file_type', 'png'],
['file_type', 'pdf'],
['type', 'Image'],
['type', 'Publication', ['subtype', 'Report']],
]);
});

test('query with `subtype: Report` should remove from the state any child query with `subsubtype`', () => {
const state = [
['file_type', 'png'],
['file_type', 'pdf'],
['type', 'Image'],
[
'type',
'Publication',
['subtype', 'Report', ['subsubtype', 'Restricted']],
],
['type', 'Publication', ['subtype', 'Report', ['subsubtype', 'Public']]],
];
const query = [['type', 'Publication', ['subtype', 'Report']]];

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([
['file_type', 'png'],
['file_type', 'pdf'],
['type', 'Image'],
['type', 'Publication'],
]);
});

test('query with `type: Publication` should remove from the state any child query with `subtype` or `subsubtype`', () => {
const state = [
['file_type', 'png'],
['file_type', 'pdf'],
['type', 'Image'],
[
'type',
'Publication',
['subtype', 'Report', ['subsubtype', 'Restricted']],
],
];
const query = [['type', 'Publication']];

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([
['file_type', 'png'],
['file_type', 'pdf'],
['type', 'Image'],
]);
});

test('query with `subsubtype: Report` should remove it from the state when it is already there.', () => {
const state = [
['file_type', 'pdf'],
['type', 'Image'],
[
'type',
'Publication',
['subtype', 'Report', ['subsubtype', 'Public reports']],
],
];
const query = [
[
'type',
'Publication',
['subtype', 'Report', ['subsubtype', 'Public reports']],
],
];

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([
['file_type', 'pdf'],
['type', 'Image'],
['type', 'Publication', ['subtype', 'Report']],
]);
});
});

describe('user clears previous selections', () => {
const state = [
['type', 'Publication', ['subtype', 'Report', ['subsubtype', 'Public']]],
['file_type', 'pdf'],
];

test('`type` selections are removed when user unselects it', () => {
const query = [['type', 'Publication']];
const newState = updateQueryFilters(query, state);

expect(newState).toEqual([['file_type', 'pdf']]);
});
});
26 changes: 24 additions & 2 deletions src/lib/state/selectors/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@
*/

import Qs from 'qs';
import _forEach from 'lodash/forEach';
import _head from 'lodash/head';
import _isArray from 'lodash/isArray';
import _isEmpty from 'lodash/isEmpty';
import _pick from 'lodash/pick';

/**
* Return true if the first string starts and contains the second.
* @param {string} first a string
Expand Down Expand Up @@ -39,8 +43,7 @@ function removeLastChild(arr) {
return [];
}

export const updateQueryFilters = (queryFilter, stateFilters) => {
if (_isEmpty(queryFilter)) return;
function updateFilter(queryFilter, stateFilters) {
/**
* convert query and state to strings so they can be compared
*/
Expand Down Expand Up @@ -101,6 +104,25 @@ export const updateQueryFilters = (queryFilter, stateFilters) => {
* convert back to lists
*/
return filteredStrStates.map(strState => parse(strState));
}

export const updateQueryFilters = (queryFilter, stateFilters) => {
if (_isEmpty(queryFilter)) return;

/** If we have one filter as query = ['file_type', 'pdf'] */
if (!_isArray(_head(queryFilter))) {
return updateFilter(queryFilter, stateFilters);
}

/** If we have an array of filters as query we apply the filters one by one.
* e.g. query = [['file_type', 'pdf'], ['file_type', 'txt']]
*/
let tempStateFilters = stateFilters;
_forEach(
queryFilter,
filter => (tempStateFilters = updateFilter(filter, tempStateFilters))
);
return tempStateFilters;
};

export const updateQueryState = (oldState, newState, storeKeys) => {
Expand Down
25 changes: 20 additions & 5 deletions src/lib/state/selectors/query.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,17 @@ describe('queries with first level filters.', () => {

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([['file_type', 'pdf'], ['type', 'Publication']]);
expect(newState).toEqual([
['file_type', 'pdf'],
['type', 'Publication'],
]);
});

test('query with `type: Publication` should be added when another `type` is already in the state.', () => {
const state = [['file_type', 'pdf'], ['type', 'Image']];
const state = [
['file_type', 'pdf'],
['type', 'Image'],
];
const query = ['type', 'Publication'];

const newState = updateQueryFilters(query, state);
Expand All @@ -61,13 +67,19 @@ describe('queries with first level filters.', () => {

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([['file_type', 'pdf'], ['type', 'Publication']]);
expect(newState).toEqual([
['file_type', 'pdf'],
['type', 'Publication'],
]);
});
});

describe('queries with second level filters.', () => {
test('query with `subtype: Other` should be added when not in the state.', () => {
const state = [['file_type', 'pdf'], ['type', 'Image']];
const state = [
['file_type', 'pdf'],
['type', 'Image'],
];
const query = ['type', 'Publication', ['subtype', 'Other']];

const newState = updateQueryFilters(query, state);
Expand All @@ -91,7 +103,10 @@ describe('queries with second level filters.', () => {

const newState = updateQueryFilters(query, state);

expect(newState).toEqual([['file_type', 'pdf'], ['type', 'Image']]);
expect(newState).toEqual([
['file_type', 'pdf'],
['type', 'Image'],
]);
});

test('query with `subtype: Other` should remove any query with the parent `type: Publication`.', () => {
Expand Down

0 comments on commit fd43974

Please sign in to comment.