diff --git a/THIRD-PARTY-NOTICES b/THIRD-PARTY-NOTICES index 0ebbf2ae4..b8c50283e 100644 --- a/THIRD-PARTY-NOTICES +++ b/THIRD-PARTY-NOTICES @@ -487,7 +487,7 @@ CDN The following NPM package may be included in this product: - - @yext/search-core@2.4.0 + - @yext/search-core@2.5.1 This package contains the following license and notice below: diff --git a/package-lock.json b/package-lock.json index 95a36ccce..c9f6f6601 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,18 @@ { "name": "@yext/answers-search-ui", - "version": "1.16.5", + "version": "1.16.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@yext/answers-search-ui", - "version": "1.16.5", + "version": "1.16.6", "license": "BSD-3-Clause", "dependencies": { "@mapbox/mapbox-gl-language": "^0.10.1", "@yext/answers-storage": "^1.1.0", "@yext/rtf-converter": "^1.7.1", - "@yext/search-core": "^2.4.0", + "@yext/search-core": "^2.5.1", "bowser": "^2.11.0", "cross-fetch": "^3.1.5", "css-vars-ponyfill": "^2.4.3", @@ -3325,9 +3325,9 @@ } }, "node_modules/@yext/search-core": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@yext/search-core/-/search-core-2.4.0.tgz", - "integrity": "sha512-slPiKO3lENIB8aqr509ljjkaHJ9UJXnBu0iSv8CAdFsoZomdXTQExlbGBPHVZ6q0rEBahDR4PSMWlvFp9b7yAQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@yext/search-core/-/search-core-2.5.1.tgz", + "integrity": "sha512-Xdq5k1xuf1iueADcsoAGdtX5PV4NcZlMj03RYuDP9Jylm7rSSw+KDIUIh/lC7sFpzp3jKDW5jgH3NHz2dB3fZA==", "dependencies": { "@babel/runtime-corejs3": "^7.12.5", "cross-fetch": "^3.1.5" @@ -8962,9 +8962,9 @@ "integrity": "sha512-HtPrzGk8aBF9rLeQNuImcXci7YVqsMEKzVflEWaCJu25ehxyDNiZRWoSxqSFUBfma8LERqKo70t/TcaGjIsM9g==" }, "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, "engines": { "node": "*" @@ -10117,9 +10117,9 @@ } }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, "node_modules/http-signature": { @@ -20122,9 +20122,9 @@ } }, "node_modules/terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", "dev": true, "dependencies": { "commander": "^2.20.0", @@ -25256,9 +25256,9 @@ } }, "@yext/search-core": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@yext/search-core/-/search-core-2.4.0.tgz", - "integrity": "sha512-slPiKO3lENIB8aqr509ljjkaHJ9UJXnBu0iSv8CAdFsoZomdXTQExlbGBPHVZ6q0rEBahDR4PSMWlvFp9b7yAQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@yext/search-core/-/search-core-2.5.1.tgz", + "integrity": "sha512-Xdq5k1xuf1iueADcsoAGdtX5PV4NcZlMj03RYuDP9Jylm7rSSw+KDIUIh/lC7sFpzp3jKDW5jgH3NHz2dB3fZA==", "requires": { "@babel/runtime-corejs3": "^7.12.5", "cross-fetch": "^3.1.5" @@ -29711,9 +29711,9 @@ "integrity": "sha512-HtPrzGk8aBF9rLeQNuImcXci7YVqsMEKzVflEWaCJu25ehxyDNiZRWoSxqSFUBfma8LERqKo70t/TcaGjIsM9g==" }, "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true }, "get-intrinsic": { @@ -30629,9 +30629,9 @@ } }, "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, "http-signature": { @@ -38492,9 +38492,9 @@ } }, "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", "dev": true, "requires": { "commander": "^2.20.0", diff --git a/package.json b/package.json index d7771b444..0e9dd90c3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yext/answers-search-ui", - "version": "1.16.5", + "version": "1.16.6", "description": "Javascript Search Programming Interface", "main": "dist/answers-umd.js", "repository": { @@ -30,7 +30,7 @@ "@mapbox/mapbox-gl-language": "^0.10.1", "@yext/answers-storage": "^1.1.0", "@yext/rtf-converter": "^1.7.1", - "@yext/search-core": "^2.4.0", + "@yext/search-core": "^2.5.1", "bowser": "^2.11.0", "cross-fetch": "^3.1.5", "css-vars-ponyfill": "^2.4.3", diff --git a/src/ui/components/filters/filteroptionscomponent.js b/src/ui/components/filters/filteroptionscomponent.js index d60822061..241f9435c 100644 --- a/src/ui/components/filters/filteroptionscomponent.js +++ b/src/ui/components/filters/filteroptionscomponent.js @@ -448,21 +448,21 @@ export default class FilterOptionsComponent extends Component { if (!filter) { filterOption.classList.remove('hiddenSearch'); filterOption.classList.remove('displaySearch'); - labelEl.innerHTML = labelText; + labelEl.textContent = labelText; } else { const matchedSubstring = this._getMatchedSubstring( labelText.toLowerCase(), filter.toLowerCase()); if (matchedSubstring) { filterOption.classList.add('displaySearch'); filterOption.classList.remove('hiddenSearch'); - labelEl.innerHTML = new HighlightedValue({ + labelEl.textContent = new HighlightedValue({ value: labelText, matchedSubstrings: [matchedSubstring] }).get(); } else { filterOption.classList.add('hiddenSearch'); filterOption.classList.remove('displaySearch'); - labelEl.innerHTML = labelText; + labelEl.textContent = labelText; } } } diff --git a/src/ui/sass/modules/_SearchBar.scss b/src/ui/sass/modules/_SearchBar.scss index d3cf8879f..650d76045 100644 --- a/src/ui/sass/modules/_SearchBar.scss +++ b/src/ui/sass/modules/_SearchBar.scss @@ -280,6 +280,7 @@ $searchbar-button-text-color-active: var(--yxt-searchbar-button-text-color-base) &-buttonImage .Icon svg, .Icon-image { + display: block; width: 2em; height: 2em; } @@ -287,6 +288,10 @@ $searchbar-button-text-color-active: var(--yxt-searchbar-button-text-color-base) &-instructions { display: none; } + + &-CustomLoadingImage { + display: block; + } } // If custom icons are supplied, the SVGs simply alternate opacity diff --git a/src/ui/templates/icons/builtInIcon.hbs b/src/ui/templates/icons/builtInIcon.hbs index 0355d648e..00b0c3b82 100644 --- a/src/ui/templates/icons/builtInIcon.hbs +++ b/src/ui/templates/icons/builtInIcon.hbs @@ -1,3 +1,3 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/ui/templates/icons/icon.hbs b/src/ui/templates/icons/icon.hbs index 422af5e7f..c272170c1 100644 --- a/src/ui/templates/icons/icon.hbs +++ b/src/ui/templates/icons/icon.hbs @@ -1,7 +1,7 @@ - + diff --git a/src/ui/templates/icons/iconPartial.hbs b/src/ui/templates/icons/iconPartial.hbs index e9538d044..2e6020fdc 100644 --- a/src/ui/templates/icons/iconPartial.hbs +++ b/src/ui/templates/icons/iconPartial.hbs @@ -1,7 +1,7 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/ui/templates/icons/searchBarIcon.hbs b/src/ui/templates/icons/searchBarIcon.hbs index c15c187e5..617dcca42 100644 --- a/src/ui/templates/icons/searchBarIcon.hbs +++ b/src/ui/templates/icons/searchBarIcon.hbs @@ -1,41 +1,41 @@ {{#if showLoadingIndicator}} {{#if customLoadingIconUrl}} -
+ {{> icons/iconPartial iconUrl=customLoadingIconUrl}} -
+ {{else}} -
-
+ {{/if}} {{/if}} {{#if submitIcon}} -
+ {{> icons/builtInIcon iconName=submitIcon}} -
+ {{else if _config.customIconUrl}} -
+ {{> icons/iconPartial iconUrl=_config.customIconUrl}} -
+ {{else}} -
{{> icons/builtInIcon iconName='yext_animated_forward' classNames='yxt-SearchBar-MagnifyingGlass--static Icon--lg' complexContentsParams=forwardIconOpts.complexContentsParams }} -
-
{{> icons/builtInIcon iconName='yext_animated_reverse' classNames='yxt-SearchBar-Yext--static Icon--lg' complexContentsParams=forwardIconOpts.complexContentsParams }} -
+ {{/if}} diff --git a/src/ui/templates/icons/voiceSearchIcon.hbs b/src/ui/templates/icons/voiceSearchIcon.hbs index 8160ef592..132788adf 100644 --- a/src/ui/templates/icons/voiceSearchIcon.hbs +++ b/src/ui/templates/icons/voiceSearchIcon.hbs @@ -14,4 +14,4 @@ {{/if}} - \ No newline at end of file + diff --git a/tests/setup/enzymeadapter.js b/tests/setup/enzymeadapter.js index 289915808..d058cc6d7 100644 --- a/tests/setup/enzymeadapter.js +++ b/tests/setup/enzymeadapter.js @@ -110,7 +110,16 @@ export default class AnswersAdapter extends EnzymeAdapter { composed: args.composed, cancelable: args.cancelable }); - Object.assign(event, args); + + if (Array.isArray(...args)) { + for (const arg in args) { + if (arg && arg.target) { + Object.defineProperty(event, 'target', { value: arg.target }); + } + } + } else { + Object.defineProperty(event, 'target', { value: args[0].target }); + } node.instance.dispatchEvent(event); } diff --git a/tests/ui/components/filters/filteroptionscomponent.js b/tests/ui/components/filters/filteroptionscomponent.js index 44ea64699..feef18c2a 100644 --- a/tests/ui/components/filters/filteroptionscomponent.js +++ b/tests/ui/components/filters/filteroptionscomponent.js @@ -116,6 +116,48 @@ describe('filter options component', () => { expect(wrapper.find('.js-yxt-FilterOptions-showMore')).toHaveLength(1); }); + it('renders correct options based on the searchable input', () => { + const config = { + ...defaultConfig, + control: 'multioption', + searchable: true + }; + const component = COMPONENT_MANAGER.create('FilterOptions', config); + const wrapper = mount(component); + expect(options).toHaveLength(6); + const searchInputEl = wrapper.find('.js-yxt-FilterOptions-filter'); + expect(searchInputEl).toHaveLength(1); + + // empty input + searchInputEl.at(0).simulate('input', { target: { value: '' } }); + expect(wrapper.find('.js-yxt-FilterOptions-clearSearch').hasClass('js-hidden')).toBeTruthy(); + expect(wrapper.find('.js-yxt-FilterOptions-container') + .hasClass('yxt-FilterOptions-container--searching')).toBeFalsy(); + let filterOptionEls = wrapper.find('.js-yxt-FilterOptions-option'); + for (let index = 0; index < filterOptionEls.length; index++) { + const filterOptionEl = filterOptionEls.at(index); + + expect(filterOptionEl.hasClass('hiddenSearch')).toBeFalsy(); + expect(filterOptionEl.hasClass('displaySearch')).toBeFalsy(); + expect(filterOptionEl.find('.js-yxt-FilterOptions-optionLabel--name').text().trim()) + .toEqual(options[index].label); + } + + // non-empty input + searchInputEl.at(0).simulate('input', { target: { value: 'cir' } }); + expect(wrapper.find('.js-yxt-FilterOptions-clearSearch').hasClass('js-hidden')).toBeFalsy(); + expect(wrapper.find('.js-yxt-FilterOptions-container') + .hasClass('yxt-FilterOptions-container--searching')).toBeTruthy(); + filterOptionEls = wrapper.find('.js-yxt-FilterOptions-option'); + for (let index = 0; index < filterOptionEls.length; index++) { + const filterOptionEl = filterOptionEls.at(index); + expect(filterOptionEl.hasClass(index === 0 ? 'displaySearch' : 'hiddenSearch')).toBeTruthy(); + expect(filterOptionEl.hasClass(index === 0 ? 'hiddenSearch' : 'displaySearch')).toBeFalsy(); + expect(filterOptionEl.find('.js-yxt-FilterOptions-optionLabel--name').text().trim()) + .toEqual(index === 0 ? 'ciri' : options[index].label); + } + }); + it('renders correct number of multi options', () => { const config = { ...defaultConfig,