Skip to content

Commit

Permalink
v1.8.4
Browse files Browse the repository at this point in the history
## Fixes
- Fixed a bug that prevented Facets in the URL from being applied on page load. (#1429)
  • Loading branch information
tmeyer2115 committed Jun 10, 2021
2 parents 49b6d0f + a78d4a1 commit 8362481
Show file tree
Hide file tree
Showing 9 changed files with 256 additions and 17 deletions.
2 changes: 1 addition & 1 deletion THIRD-PARTY-NOTICES
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The following NPM packages may be included in this product:

- @yext/answers-search-ui@1.8.3
- @yext/answers-search-ui@1.8.4
- @yext/answers-storage@1.1.0

These packages each contain the following license and notice below:
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@yext/answers-search-ui",
"version": "1.8.3",
"version": "1.8.4",
"description": "Javascript Answers Programming Interface",
"main": "dist/answers-umd.js",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion src/core/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ export default class Core {
* Persists the current `facetFilters` state into the URL.
*/
_persistFacets () {
const persistedFacets = this.filterRegistry.createFacetsFromFilterNodes();
const persistedFacets = this.filterRegistry.getFacets();
this.storage.setWithPersist(StorageKeys.PERSISTED_FACETS, persistedFacets);
}

Expand Down
21 changes: 15 additions & 6 deletions src/core/filters/filterregistry.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,10 @@ export default class FilterRegistry {

/**
* Combines the active facet FilterNodes into a single Facet
*
* @returns {Facet}
*/
createFacetsFromFilterNodes () {
_createFacetsFromFilterNodes () {
const getFilters = fn => fn.getChildren().length
? fn.getChildren().flatMap(getFilters)
: fn.getFilter();
Expand All @@ -183,16 +184,24 @@ export default class FilterRegistry {
}

/**
* Gets the facet filters as an array of Filters to send to the answers-core.
* Returns the current Facets state.
*
* @returns {Facet[]} from answers-core
* @returns {Facet}
*/
getFacetsPayload () {
getFacets () {
const hasFacetFilterNodes = this.storage.has(StorageKeys.FACET_FILTER_NODES);
const facets = hasFacetFilterNodes
? this.createFacetsFromFilterNodes()
return hasFacetFilterNodes
? this._createFacetsFromFilterNodes()
: this.storage.get(StorageKeys.PERSISTED_FACETS) || {};
}

/**
* Gets the facet filters as an array of Filters to send to the answers-core.
*
* @returns {Facet[]} from answers-core
*/
getFacetsPayload () {
const facets = this.getFacets();
const coreFacets = Object.entries(facets).map(([fieldId, filterArray]) => {
return {
fieldId: fieldId,
Expand Down
17 changes: 12 additions & 5 deletions tests/acceptance/acceptancesuites/facetsonload.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import {
setupServer,
shutdownServer,
FACETS_PAGE
FACETS_ON_LOAD_PAGE
} from '../server';
import FacetsPage from '../pageobjects/facetspage';
import { RequestLogger } from 'testcafe';
import {
browserBackButton,
browserRefreshPage,
browserForwardButton,
registerIE11NoCacheHook
} from '../utils';
import { getMostRecentQueryParamsFromLogger } from '../requestUtils';

fixture`Facets page`
.before(setupServer)
.after(shutdownServer)
.page`${FACETS_PAGE}`;
.page`${FACETS_ON_LOAD_PAGE}`;

test('Facets work with back/forward navigation and page refresh', async t => {
const logger = RequestLogger({
Expand All @@ -42,7 +43,6 @@ test('Facets work with back/forward navigation and page refresh', async t => {
let options;
options = await filterBox.getFilterOptions('Employee Department');
await options.toggleOption('Client Delivery');
await filterBox.applyFilters();
currentFacets = await getFacetsFromRequest();
const state1 = {
c_puppyPreference: [],
Expand All @@ -55,7 +55,6 @@ test('Facets work with back/forward navigation and page refresh', async t => {

options = await filterBox.getFilterOptions('Employee Department');
await options.toggleOption('Technology');
await filterBox.applyFilters();
currentFacets = await getFacetsFromRequest();
const state2 = {
c_employeeDepartment: [
Expand All @@ -68,7 +67,6 @@ test('Facets work with back/forward navigation and page refresh', async t => {

options = await filterBox.getFilterOptions('Puppy Preference');
await options.toggleOption('Frodo');
await filterBox.applyFilters();
currentFacets = await getFacetsFromRequest();
const state3 = {
c_puppyPreference: [{ c_puppyPreference: { $eq: 'Frodo' } }],
Expand All @@ -87,6 +85,11 @@ test('Facets work with back/forward navigation and page refresh', async t => {
await t.expect(currentFacets).eql(state3);
logger.clear();

await browserRefreshPage();
currentFacets = await getFacetsFromRequest();
await t.expect(currentFacets).eql(state3);
logger.clear();

await browserBackButton();
currentFacets = await getFacetsFromRequest();
await t.expect(currentFacets).eql(state2);
Expand All @@ -99,4 +102,8 @@ test('Facets work with back/forward navigation and page refresh', async t => {
await browserBackButton();
currentFacets = await getFacetsFromRequest();
await t.expect(currentFacets).eql({});

await browserForwardButton();
currentFacets = await getFacetsFromRequest();
await t.expect(currentFacets).eql(state1);
});
193 changes: 193 additions & 0 deletions tests/acceptance/fixtures/html/facetsonload.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
<html>

<head>
<meta charset="utf-8" />

<script src="http://localhost:9999/dist/answerstemplates.compiled.min.js"></script>
<script src="http://localhost:9999/dist/answers.js"></script>
<link rel="stylesheet" type="text/css" href="http://localhost:9999/dist/answers.css">
<style>
.bottom {
display: flex;
}

.left {
max-width: 300px;
}
</style>
</head>

<body>
<div class="answers-container">
<div class="search-bar-container"></div>
<div class="navigation-container"></div>
<div class="bottom">
<div class="left">
<div class="filter-search-container"></div>
<div class="sort-options-container"></div>
<div class="filterbox-container"></div>
<div class="facets-container"></div>
</div>
<div class="right">
<div class="pagination-container"></div>
<div class="results-container"></div>
</div>
</div>
</div>

<script>
ANSWERS.init({
apiKey: '2d8c550071a64ea23e263118a2b0680b',
experienceKey: 'slanswers',
businessId: '3350634',
experienceVersion: 'PRODUCTION',
templateBundle: TemplateBundle.default,
search: {
verticalKey: 'people',
},
onReady: function () {
this.addComponent('SearchBar', {
container: '.search-bar-container',
clearButton: true,
promptForLocation: true,
verticalKey: 'people',
allowEmptySearch: true
});

this.addComponent('Navigation', {
container: '.navigation-container',
verticalPages: [
{
label: 'Home',
url: './universal',
isFirst: true
},
{
label: 'Facets',
url: './facets',
isActive: true
},
{
label: 'Vertical',
url: './vertical',
}
],
});

this.addComponent('SortOptions', {
container: '.sort-options-container',
options: [
{
type: 'FIELD',
field: 'c_popularity',
direction: 'DESC',
label: 'Popularity'
},
{
type: "ENTITY_DISTANCE",
label: 'Recently Released'
},
{
type: 'RELEVANCE',
label: 'Price - Low to High'
},
{
type: 'RELEVANCE',
label: 'Price - High to Low'
}
],
verticalKey: 'people'
});

ANSWERS.addComponent('FilterBox', {
container: '.filterbox-container',
filters: [
{
type: "FilterOptions",
label: "DISTANCE",
optionType: "RADIUS_FILTER",
control: "singleoption",
options: [
{
"label": "5 miles",
"value": 8046.72,
},
{
"label": "10 miles",
"value": 16093.4,
},
{
"label": "25 miles",
"value": 40233.6,
},
{
"label": "1000 miles",
"value": 1.609e+6,
},
]
},
{
type: 'FilterOptions',
optionType: 'STATIC_FILTER',
label: 'STATIC FILTERS',
control: 'multioption',
options: [
{
label: 'Bot2',
field: 'c_awards',
value: 'Bot2'
},
{
label: 'Marty',
field: 'c_puppyPreference',
value: 'Marty',
},
{
label: 'Frodo',
field: 'c_puppyPreference',
value: 'Frodo',
}
]
}
],
verticalKey: 'people',
searchOnChange: true,
expand: false
});

this.addComponent('VerticalResults', {
container: '.results-container',
appliedFilters: {
removable: true
}
});

this.addComponent('Facets', {
container: '.facets-container',
verticalKey: 'people',
expand: false,
searchOnChange: true
});

this.addComponent('FilterSearch', {
container: '.filter-search-container',
verticalKey: 'people',
title: 'filtersearch',
searchParameters: {
fields: [{
fieldId: 'builtin.location',
entityTypeId: 'ce_person',
sectioned: false,
}]
}
});

this.addComponent('Pagination', {
container:'.pagination-container',
});
}
})
</script>
</body>

</html>
1 change: 1 addition & 0 deletions tests/acceptance/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ export async function shutdownServer (ctx) {
export const UNIVERSAL_PAGE = 'http://localhost:9999/tests/acceptance/fixtures/html/universal';
export const VERTICAL_PAGE = 'http://localhost:9999/tests/acceptance/fixtures/html/vertical';
export const FACETS_PAGE = 'http://localhost:9999/tests/acceptance/fixtures/html/facets';
export const FACETS_ON_LOAD_PAGE = 'http://localhost:9999/tests/acceptance/fixtures/html/facetsonload';
export const FILTERBOX_PAGE = 'http://localhost:9999/tests/acceptance/fixtures/html/filterbox';
export const UNIVERSAL_INITIAL_SEARCH_PAGE = 'http://localhost:9999/tests/acceptance/fixtures/html/universalinitialsearch';
33 changes: 31 additions & 2 deletions tests/core/filters/filterregistry.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,15 +284,44 @@ describe('FilterRegistry', () => {
});
});

it('createFacetsFromFilterNodes', () => {
it('_createFacetsFromFilterNodes', () => {
registry.setFacetFilterNodes(['random_field', 'another_field'], [node1, node2]);
const expectedFacets = {
another_field: [],
c_1: [{ c_1: { $eq: '1' } }],
c_2: [{ c_2: { $eq: '2' } }],
random_field: []
};
expect(registry.createFacetsFromFilterNodes()).toEqual(expectedFacets);
expect(registry._createFacetsFromFilterNodes()).toEqual(expectedFacets);
});

it('getFacets defaults to the current state of PERSISTED_FACETS if no filter nodes exist', () => {
const persistedFacets = {
c_employeeDepartment: [
{
c_employeeDepartment: {
$eq: 'International Dang Sales'
}
}
]
};
registry.storage.set(StorageKeys.PERSISTED_FACETS, persistedFacets);
expect(registry.getFacets()).toEqual(persistedFacets);
});

it('getFacets uses FACET_FILTER_NODES if they exist', () => {
registry.setFacetFilterNodes(['random_field', 'another_field'], [node1, node2]);
const persistedFacets = {
c_employeeDepartment: [
{
c_employeeDepartment: {
$eq: 'International Dang Sales'
}
}
]
};
registry.storage.set(StorageKeys.PERSISTED_FACETS, persistedFacets);
expect(registry.getFacets()).toEqual(registry._createFacetsFromFilterNodes());
});

it('transforms static filters with multiple matchers into combined filters', () => {
Expand Down

0 comments on commit 8362481

Please sign in to comment.