diff --git a/package-lock.json b/package-lock.json index 67634d44..fdf1c1e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-storefront", - "version": "7.6.0", + "version": "7.9.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -4562,7 +4562,7 @@ }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "resolved": "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" }, "babel-plugin-transform-define": { @@ -4611,7 +4611,7 @@ }, "babel-plugin-transform-object-rest-spread": { "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "resolved": "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", "requires": { "babel-plugin-syntax-object-rest-spread": "^6.8.0", @@ -5838,7 +5838,7 @@ "dependencies": { "bytes": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "resolved": "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true }, @@ -6090,7 +6090,7 @@ }, "globby": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "resolved": "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz", "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", "requires": { "array-union": "^1.0.1", @@ -6126,7 +6126,7 @@ }, "slash": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "resolved": "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz", "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" } } @@ -10636,7 +10636,7 @@ }, "is-regexp": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "resolved": "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz", "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" }, "is-relative": { @@ -13309,7 +13309,7 @@ "dependencies": { "source-map": { "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "resolved": "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } diff --git a/package.json b/package.json index 0fd83ba2..1f031f41 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-storefront", - "version": "7.9.1", + "version": "7.9.2", "description": "Build and deploy e-commerce progressive web apps (PWAs) in record time.", "module": "./index.js", "license": "Apache-2.0", diff --git a/src/ForwardThumbnail.js b/src/ForwardThumbnail.js index 5aeef9cb..442016ae 100644 --- a/src/ForwardThumbnail.js +++ b/src/ForwardThumbnail.js @@ -25,11 +25,18 @@ export default function ForwardThumbnail({ children }) { const context = useContext(PWAContext) const srcRef = useRef(null) - useEffect(() => { - srcRef.current = ref.current.querySelector('img').getAttribute('src') - }, [children]) + const setSrcRef = useCallback(() => { + if (ref.current.querySelector('img')) { + srcRef.current = ref.current.querySelector('img').getAttribute('src') + } + }, []) + + useEffect(setSrcRef, [children]) const handleClick = useCallback(() => { + if (!srcRef.current) { + setSrcRef() + } context.thumbnail.current = { src: srcRef.current } }, []) diff --git a/src/plp/SearchResultsProvider.js b/src/plp/SearchResultsProvider.js index 65af5239..bd805a5a 100644 --- a/src/plp/SearchResultsProvider.js +++ b/src/plp/SearchResultsProvider.js @@ -25,31 +25,43 @@ import replaceState from '../router/replaceState' */ export default function SearchResultsProvider({ store, updateStore, children }) { useEffect(() => { - setState({ - pageData: { - ...store.pageData, - appliedFilters: store.pageData.filters, - }, - }) - }, []) - - const setState = state => { - store = { ...store, ...state } - updateStore(store) - } + if (store.reloading) { + async function refresh() { + const query = getQueryForState() + const apiUrl = getURLForState(query) + + // Don't show page for user + delete query.page + replaceState(null, null, getURLForState(query)) + + const { + pageData: { products, total }, + } = await fetch(`/api${apiUrl}`).then(res => res.json()) + updateStore(store => ({ + reloading: false, + pageData: { + ...store.pageData, + total, + products: + store.pageData.page === 0 ? products : store.pageData.products.concat(products), + }, + })) + } + refresh() + } + }, [store]) /** * Fetches the next page of results */ const fetchMore = () => { - setState({ + updateStore(store => ({ + reloading: true, pageData: { ...store.pageData, page: store.pageData.page + 1, }, - }) - - return refresh() + })) } /** @@ -86,38 +98,33 @@ export default function SearchResultsProvider({ store, updateStore, children }) * @param {Boolean} submit If true, fetches new results from the server */ const setFilters = (filters, submit) => { - const { appliedFilters } = store.pageData const filtersChanged = JSON.stringify(filters.map(v => v.toLowerCase()).sort()) !== - JSON.stringify(appliedFilters.map(v => v.toLowerCase()).sort()) + JSON.stringify(store.pageData.filters.map(v => v.toLowerCase()).sort()) - setState({ + updateStore(store => ({ + reloading: Boolean(submit), pageData: { ...store.pageData, filters, - filtersChanged, + filtersChanged: submit ? false : filtersChanged, + page: submit ? 0 : store.pageData.page, }, - }) - - if (submit) { - applyFilters() - } + })) } /** * Applies the selected filters, resets the page to 0 and fetches new results from the server. */ const applyFilters = () => { - setState({ + updateStore(store => ({ + reloading: true, pageData: { ...store.pageData, filtersChanged: false, - appliedFilters: [...store.pageData.filters], page: 0, }, - }) - - refresh() + })) } /** @@ -162,45 +169,15 @@ export default function SearchResultsProvider({ store, updateStore, children }) return pathname + qs.stringify(query, { addQueryPrefix: true }) + hash } - /** - * Fetches new results from the server - * @param {Object} options - */ - const refresh = async () => { - const query = getQueryForState() - const apiUrl = getURLForState(query) - - // Don't show page for user - delete query.page - replaceState(null, null, getURLForState(query)) - - if (store.pageData.page === 0) { - setState({ reloading: true }) - } - - const { - pageData: { products }, - } = await fetch(`/api${apiUrl}`).then(res => res.json()) - - setState({ - reloading: false, - pageData: { - ...store.pageData, - products: store.pageData.page === 0 ? products : store.pageData.products.concat(products), - }, - }) - } - const setSort = option => { - setState({ + updateStore(store => ({ + reloading: true, pageData: { ...store.pageData, sort: option.code, page: 0, }, - }) - - refresh() + })) } return ( diff --git a/src/plp/useSearchResultsStore.js b/src/plp/useSearchResultsStore.js index 2585341d..bac60212 100644 --- a/src/plp/useSearchResultsStore.js +++ b/src/plp/useSearchResultsStore.js @@ -13,7 +13,6 @@ export default function useSearchResultsStore(lazyProps) { filters: [], sort: 'rating', sortSaved: 'rating', - appliedFilters: [], sortOptions: [], filtersChanged: false, }), diff --git a/test/ForwardThumbnail.test.js b/test/ForwardThumbnail.test.js index c1233238..e3566a33 100644 --- a/test/ForwardThumbnail.test.js +++ b/test/ForwardThumbnail.test.js @@ -30,6 +30,24 @@ describe('ForwardThumbnail', () => { expect(wrapper.find('#test2').prop('src')).toBe('test2') }) + it('should render when no img selector in children', () => { + const Test = () => { + thumbnail = useRef(null) + + return ( + + +
test1
+
+
+ ) + } + + wrapper = mount() + + expect(wrapper.find('#test1').text()).toBe('test1') + }) + it('should set context thumbnail onClick', async () => { wrapper = mount() diff --git a/test/plp/SearchResultsProvider.test.js b/test/plp/SearchResultsProvider.test.js index 6120cf87..e5fb3263 100644 --- a/test/plp/SearchResultsProvider.test.js +++ b/test/plp/SearchResultsProvider.test.js @@ -9,9 +9,9 @@ describe('SearchResultsProvider', () => { pageData: { test: 'test', page: 0, - appliedFilters: [], filters: ['blue'], products: [{ id: 'first' }], + total: 50, }, } let wrapper, context, getStore @@ -81,7 +81,7 @@ describe('SearchResultsProvider', () => { it('toggleFilter - toggle existing filter', async () => { const facet = { code: 'blue' } - initialStore.pageData.appliedFilters = ['blue'] + initialStore.pageData.filters = ['blue'] wrapper = mount() @@ -92,8 +92,6 @@ describe('SearchResultsProvider', () => { expect(getStore.pageData.filters).toStrictEqual([]) expect(getStore.pageData.filtersChanged).toBe(true) - - initialStore.pageData.appliedFilters = [] }) it('toggleFilter - with submit', async () => { @@ -113,9 +111,7 @@ describe('SearchResultsProvider', () => { await wrapper.update() }) - expect(getStore.pageData.appliedFilters).toStrictEqual( - initialStore.pageData.filters.concat(facet.code), - ) + expect(getStore.pageData.filters).toStrictEqual(['blue', 'red']) expect(getStore.pageData.filtersChanged).toBe(false) expect(fetch).toHaveBeenCalled() }) @@ -132,7 +128,6 @@ describe('SearchResultsProvider', () => { }) it('clearFilters - with submit', async () => { - initialStore.pageData.appliedFilters = ['blue'] fetchMock.mockResponseOnce( JSON.stringify({ pageData: { @@ -148,10 +143,7 @@ describe('SearchResultsProvider', () => { }) expect(getStore.pageData.filters).toStrictEqual([]) - expect(getStore.pageData.appliedFilters).toStrictEqual([]) expect(fetch).toHaveBeenCalled() - - initialStore.pageData.appliedFilters = [] }) it('refresh - should always remove "more" query param if sees it', async () => { @@ -182,6 +174,7 @@ describe('SearchResultsProvider', () => { JSON.stringify({ pageData: { products: [], + total: 0, }, }), ) @@ -194,7 +187,7 @@ describe('SearchResultsProvider', () => { expect(getStore.pageData.filtersChanged).toBe(false) expect(getStore.pageData.page).toBe(0) - expect(getStore.pageData.appliedFilters).toStrictEqual(initialStore.pageData.filters) + expect(getStore.pageData.total).toBe(0) expect(fetch).toHaveBeenCalled() })