-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New faceted search results component (#132)
* Bare initial code for new faceted search component * Add Cypress to this component * Copy cypress test from current faceted search result - WIP * Use fix version (1.2.1) from `random-words` module as the upgraded version (1.3.0) was erred with webpack loader error TODO: fix this later * Add CheckboxFacetGroup component * Removed unneeded test folder as we use Cypress for testing * Add CheckboxFacetGroup component * Improve CheckboxFacetGroup component * Add FilterSidebar component * Add MultiselectDropdownFacetGroup component * Add MultiselectDropdownFacetGroup to FacetGroups cypress tests * Add MultiselectDropdownFacetGroup to FilterSidebar component * Fix name and description of the facet groups Randomise species, cell types and organism parts * Add FilterList component without fetch loader but processing new response structure from backend * Add FacetedSearchContainer component - WIP (need to fix onChange propagation) * Fix some failing test in FacetedSearchContainer cypress test - 1 is still failing WIP * Fix FacetedSearchContainer - its test is passing now TODO: improve the test, clean the code * Fix CheckboxFacetGroup when we select multiply checkbox * Add missing fixtures * Fix queryParams prop type definition * Fix the checkboxes checked state in Checkbox facet group * Add html demo with real data for the new faceted search result * Fix species checkbox group behaviour WIP for the other groups * Fix multi select dropdown facet groups behaviour * Fix is marker gene behaviour * Clean the code * Fix deleting an already selected facet or all of the facets * Fix adding/deleting filter options that contains comma in their names * Fix cypress tests in CheckboxFacetGroup * Fix cypress tests in CheckboxFacetGroup and in MultiSelectDropdownFacetGroup * Fix cypress tests in FacetedSearchContainer.cy.js * Add header config to webpack configuration * Add code coverage for cypress tests * Update README.md * Optimising REST calls Not calling the endpoint of the currently modified facet group * Reorganising tests for facet groups * Apply code review findings for FacetedSearchContainer test * Apply code review findings for package.json * Apply code review findings * Apply code review findings for README * Apply code review findings for FilterList and convert it to stateless * Apply code review findings for CheckboxFacetGroup and convert it to stateless * Replace id with role * Fix the state modification in FacetedSearchController * Replace ids from the standard vocabulary for roles * Remove unneeded coveralls dependency * Update webpack version to ^5.73 * Clean and simplify map usage Co-authored-by: Alfonso Muñoz-Pomer Fuentes <[email protected]> * Fix the cleaned code in the previous commit :-) * Update Cypress to the latest version * Simplify more facet groups default properties * Generalise facet group initialization * Update the `scripts` section of package.json * Replaced double quotes to single one in the import section * Add back `webpack-cli` as a dev dependency and fix the README * Wait for response of the result list + add general interception for each component * Fix onChange property definition * Remove sorting from the demo page as we are not using it * Add ReactToolTip to properly show the tooltip on the page * Update cypress version Co-authored-by: Alfonso Muñoz-Pomer Fuentes <[email protected]> * Fix quotes Co-authored-by: Alfonso Muñoz-Pomer Fuentes <[email protected]> --------- Co-authored-by: Alfonso Muñoz-Pomer Fuentes <[email protected]>
- Loading branch information
1 parent
1ac1630
commit 0b98a0f
Showing
48 changed files
with
35,655 additions
and
7 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"presets": ["@babel/preset-react", "@babel/preset-env"], | ||
"plugins": [ "transform-class-properties", "istanbul" ] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
webpack.config.js | ||
serve.config.js | ||
coverage/ | ||
__mocks__/ | ||
lib/ | ||
dist/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "@ebi-gene-expression-group" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# IntelliJ IDEA project files | ||
.idea/ | ||
|
||
# https://github.com/github/gitignore/blob/master/Node.gitignore | ||
|
||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Bower dependency directory (https://bower.io/) | ||
bower_components | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (http://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules/ | ||
jspm_packages/ | ||
|
||
# Typescript v1 declaration files | ||
typings/ | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional eslint cache | ||
.eslintcache | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Output of 'npm pack' | ||
*.tgz | ||
|
||
# Yarn Integrity file | ||
.yarn-integrity | ||
|
||
# dotenv environment variables file | ||
.env | ||
|
||
# Build files | ||
dist/ | ||
lib/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Ignore everything | ||
* | ||
.* | ||
|
||
# But the build files... | ||
!lib/** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
# Faceted Search Results for Single Cell Expression Atlas | ||
|
||
[![Build Status](https://travis-ci.org/ebi-gene-expression-group/scxa-faceted-search-results.svg?branch=master)](https://travis-ci.org/ebi-gene-expression-group/scxa-faceted-search-results) [![Coverage Status](https://coveralls.io/repos/github/ebi-gene-expression-group/scxa-faceted-search-results/badge.svg?branch=master)](https://coveralls.io/github/ebi-gene-expression-group/scxa-faceted-search-results?branch=master) | ||
|
||
A lightweight and extensible component to list and filter lists of search results. It receives a URL (as a combination | ||
of `host` and `resource`) to async-fetch the results, and a React component class to visualise each element (e.g. a | ||
card). | ||
|
||
The facets are used to render a sidebar on the left as a set of filtering controls. | ||
Filter groups can be displayed either as searchable, multiselect dropdown lists or as checkboxes. | ||
|
||
Two more optional props, namely `noResultsMessageFormatter` and `resultsMessageFormatter`, return a string which is | ||
displayed when there are no results, and as a header on top of the search results, respectively. In many occasions it | ||
is useful to display such messages using information returned by the server; that’s the reason why both functions take | ||
the JSON payload as an argument, allowing for some customisation in that regard. For example, if in the case of no | ||
results the server returns a field `reason` you could have something like this: | ||
``` | ||
<ReactFacetedSearch | ||
... | ||
noResultsMessageFormatter={(data) => `Your search yielded no results: ${data.reason}`} | ||
``` | ||
|
||
# Requirements | ||
|
||
You should have at least Node 16 LTS with NPM 8 or later. | ||
You can check your current installed version executing this command. | ||
```shell | ||
npm --version | ||
8.5.6 | ||
``` | ||
|
||
## How to execute the unit tests with Cypress | ||
|
||
We are using the [Cypress framework](https://docs.cypress.io/guides/overview/why-cypress) for unit testing this package. | ||
You can execute the existing tests in the following way: | ||
1. Type `npx cypress open` in the terminal in the root folder of this package. | ||
2. In the appearing browser window you have to click on `Component Testing`, | ||
select a browser and click on `Start Component Testing in <browser name>`. | ||
3. In the appearing list just click on the test you would like to run and check the results on the screen. | ||
|
||
## Try out the component with a given example | ||
Just run [webpack-dev-server](https://github.com/webpack/webpack-dev-server): | ||
``` | ||
npx webpack serve --mode=development | ||
``` | ||
|
||
## How to run test with code coverage in the console | ||
|
||
Run tests with: | ||
|
||
```shell | ||
npx cypress run --component | ||
``` | ||
|
||
If you want to omit video recording: | ||
|
||
```shell | ||
npx cypress run --component --record false | ||
``` | ||
|
||
Find coverage reports at: `./coverage/lcov-report/index.html` | ||
|
||
|
||
## Add code coverage (in a nutshell) | ||
|
||
This is an abridged version of https://docs.cypress.io/guides/tooling/code-coverage. | ||
|
||
Add the following three packages: | ||
```bash | ||
npm install -D babel-plugin-transform-class-properties babel-plugin-istanbul @cypress/code-coverage | ||
``` | ||
|
||
Add the two plugins to your `.babelrc` file: | ||
```json | ||
{ | ||
"presets": ["@babel/preset-react", "@babel/preset-env"], | ||
"plugins": [ "transform-class-properties", "istanbul" ] | ||
} | ||
``` | ||
|
||
Add `@cypress/code-coverage` in your `cypress.config.js` file so it looks like this: | ||
```js | ||
const { defineConfig } = require(`cypress`) | ||
|
||
module.exports = defineConfig({ | ||
component: { | ||
setupNodeEvents(on, config) { | ||
require(`@cypress/code-coverage/task`)(on, config) | ||
// include any other plugin code... | ||
|
||
// It's IMPORTANT to return the config object | ||
// with any changed environment variables | ||
return config | ||
}, | ||
devServer: { | ||
framework: `react`, | ||
bundler: `webpack` | ||
} | ||
} | ||
}) | ||
``` | ||
|
||
Lastly, add the following import to `cypress/support/component.js`: | ||
```js | ||
import '@cypress/code-coverage/support' | ||
``` | ||
|
||
# Combining with the EBI Visual Framework | ||
React-Select allows you to style the `div` that encloses the `input` element, but not the `input` element itself. | ||
Therefore it’s convenient to add the snippet below to override the styling set by the | ||
[EBI Visual Framework](https://github.com/ebiwd/EBI-Framework) for `input` elements. | ||
``` | ||
.input-clear input, .input-clear input:focus { | ||
height: unset; | ||
box-shadow: none; | ||
margin: 0; | ||
} | ||
``` | ||
At the time of writing this applies to the most recent version (v1.3). Wrapping these styles within the appropriate | ||
`div` selector is sufficient. See | ||
https://github.com/ebi-gene-expression-group/scxa-faceted-search-results/blob/master/html/filter-list.html for a | ||
working example. | ||
|
||
# A note about building with Webpack | ||
The component uses `async`/`await` to fetch the JSON payload from the server. This requires to prefix the entry with | ||
`@babel/polyfill`. If you are already using an equivalent polyfill or | ||
[Runtime transform](http://babeljs.io/docs/plugins/transform-runtime/) you may skip this. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
const { defineConfig } = require(`cypress`) | ||
|
||
module.exports = defineConfig({ | ||
component: { | ||
setupNodeEvents(on, config) { | ||
require(`@cypress/code-coverage/task`)(on, config) | ||
// include any other plugin code... | ||
|
||
// It's IMPORTANT to return the config object | ||
// with any changed environment variables | ||
return config | ||
}, | ||
devServer: { | ||
framework: `react`, | ||
bundler: `webpack` | ||
} | ||
} | ||
}) |
104 changes: 104 additions & 0 deletions
104
packages/scxa-faceted-search-results-v5/cypress/component/CheckboxFacetGroup.cy.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import React from 'react' | ||
|
||
import CheckboxFacetGroup from '../../src/facetgroups/CheckboxFacetGroup' | ||
|
||
import { getFacets, getPropsForCheckBoxGroupWithTooltip, getPropsWithoutTooltip, getRandomInt } from './TestUtils' | ||
import vindicators from '../fixtures/vindicatorsResponse.json' | ||
|
||
const props = { | ||
name: `Vindicators`, | ||
description: `Show the vindicators`, | ||
facets: [], | ||
queryParams: [] | ||
} | ||
|
||
describe(`CheckboxFacetGroup`, () => { | ||
beforeEach(() => { | ||
while (props.facets.length === 0) { | ||
props.facets = vindicators.filter(() => Math.random() > 0.5) | ||
} | ||
props.facets = props.facets.map(e => ({ ...e, disabled: false })) | ||
}) | ||
|
||
it(`displays the expected tooltip if it exists`, () => { | ||
const props = { | ||
...getPropsForCheckBoxGroupWithTooltip(), | ||
facets: getFacets() | ||
} | ||
|
||
cy.mount(<CheckboxFacetGroup {...props }/>) | ||
cy.get(`div.padding-bottom-xlarge h4 sup span`) | ||
.should(`have.class`, `icon icon-generic`) | ||
.should(`have.attr`, `data-tip`).then((dataTip) => { | ||
expect(dataTip.toString() | ||
.replace(`<span>`, ``) | ||
.replace(`</span>`, ``) | ||
.replace(`<br>`, ` `)) | ||
.to.equal(props.description) | ||
}) | ||
}) | ||
|
||
it(`doesn't display tooltip if not present`, () => { | ||
const propsWithoutTooltip = { | ||
...getPropsWithoutTooltip(), | ||
facets: getFacets() | ||
} | ||
cy.mount(<CheckboxFacetGroup {...propsWithoutTooltip}/>) | ||
cy.get(`div.padding-bottom-xlarge h4`) | ||
.children() | ||
.should(`have.length`, 0) | ||
}) | ||
|
||
it(`renders the right number of checkboxes and the facet name`, () => { | ||
cy.mount(<CheckboxFacetGroup {...props} />) | ||
|
||
cy.get(`input`).should((inputs) => { | ||
expect(inputs.length).to.equal(props.facets.length) | ||
}) | ||
cy.get(`input[type="checkbox"]`).should((checkboxes) => { | ||
expect(checkboxes.length).to.equal(props.facets.length) | ||
}) | ||
cy.get(`h4`).should(`contains.text`, props.name) | ||
cy.get(`input`).should(`not.have.attr`, `disabled`) | ||
cy.get(`label`).should(`not.have.attr`, `color`) | ||
}) | ||
|
||
it(`displays disabled check boxes greyed out`, () => { | ||
props.facets = props.facets.map(e => ({ ...e, disabled: true })) | ||
cy.mount(<CheckboxFacetGroup {...props} />) | ||
|
||
cy.get(`input`).should(`have.attr`, `disabled`) | ||
cy.get(`label`) | ||
.should(`have.attr`, `style`) | ||
.should(`eq`, `color: lightgrey;`) | ||
}) | ||
|
||
it(`callback is called when a checkbox is checked/unchecked with the right arguments`, () => { | ||
const randomCheckboxIndex = getRandomInt(0, props.facets.length) | ||
const mockCallbackWrapper = { | ||
onChange: function (facetGroup, checkedFacets) { | ||
} | ||
} | ||
cy.spy(mockCallbackWrapper, `onChange`).as(`onChange`) | ||
|
||
cy.mount(<CheckboxFacetGroup {...props} onChange={mockCallbackWrapper.onChange} />) | ||
|
||
cy.get(`input[type="checkbox"]`).eq(randomCheckboxIndex).click() | ||
cy.get(`@onChange`) | ||
.should(`have.been.calledOnceWithExactly`, | ||
props.name, | ||
[props.facets[randomCheckboxIndex]], | ||
props.facets | ||
) | ||
|
||
cy.get(`input[type="checkbox"]`).eq(randomCheckboxIndex).click() | ||
cy.get(`@onChange`) | ||
.should(`have.been.callCount`, 2) | ||
.should(`have.been.calledWith`, | ||
props.name, [props.facets[randomCheckboxIndex]] | ||
) | ||
.should(`have.been.calledWith`, | ||
props.name, [], props.facets | ||
) | ||
}) | ||
}) |
Oops, something went wrong.