From 2c9117cee0ff780313a203a89014e3121a876f15 Mon Sep 17 00:00:00 2001 From: "O.Bilenko" Date: Fri, 5 Apr 2019 12:48:17 +0200 Subject: [PATCH 01/11] PWA-1809 Add coupon + product to cart QR code does not add the product to the cart --- libraries/commerce/cart/constants/index.js | 1 + libraries/commerce/cart/streams/index.js | 24 +++++++ libraries/commerce/cart/streams/index.spec.js | 32 ++++++++- .../commerce/cart/subscriptions/index.js | 70 ++++++++++++++++++- .../commerce/cart/subscriptions/index.spec.js | 15 ++-- libraries/commerce/checkout/index.js | 3 + .../commerce/scanner/actions/handleQrCode.js | 14 +++- libraries/commerce/scanner/helpers/index.js | 6 +- .../commerce/scanner/helpers/index.spec.js | 4 +- 9 files changed, 153 insertions(+), 16 deletions(-) diff --git a/libraries/commerce/cart/constants/index.js b/libraries/commerce/cart/constants/index.js index f6fa3d4264..c5bdd749f3 100644 --- a/libraries/commerce/cart/constants/index.js +++ b/libraries/commerce/cart/constants/index.js @@ -1,4 +1,5 @@ export const CART_PATH = '/cart'; +export const DEEPLINK_CART_ADD_PRODUCT_PATTERN = '/cart_add_product/:productId/:couponId'; export const DEEPLINK_CART_ADD_COUPON_PATTERN = '/cart_add_coupon/:couponId'; export const CART_ITEM_TYPE_COUPON = 'coupon'; diff --git a/libraries/commerce/cart/streams/index.js b/libraries/commerce/cart/streams/index.js index a194cea129..4cc72fba9b 100644 --- a/libraries/commerce/cart/streams/index.js +++ b/libraries/commerce/cart/streams/index.js @@ -5,6 +5,7 @@ import { routeDidEnter$, routeWillLeave$, routeDidLeave$, + navigate$, } from '@shopgate/pwa-common/streams/router'; import { getCurrentPathname } from '@shopgate/pwa-common/selectors/router'; import { @@ -33,6 +34,8 @@ import { DELETE_COUPONS_FROM_CART, ERROR_DELETE_COUPONS_FROM_CART, SUCCESS_DELETE_COUPONS_FROM_CART, + + DEEPLINK_CART_ADD_PRODUCT_PATTERN, } from '../constants'; /** @@ -183,3 +186,24 @@ export const cartUpdateFailed$ = main$.filter(({ action }) => ( action.type === ERROR_ADD_COUPONS_TO_CART || action.type === ERROR_DELETE_COUPONS_FROM_CART )); + +/** + * Gets triggered when /cart_add_product/123/COUPON route is navigated + * @type {Observable} + */ +export const routeAddProductNavigate$ = navigate$ + .filter(({ action: { params: { pathname = '' } = {} } }) => ( + pathname.includes(DEEPLINK_CART_ADD_PRODUCT_PATTERN.split('/')[1]) + )) + .map((params) => { + const [, , productId, couponCode] = params.action.params.pathname.split('/'); + return { + ...params, + action: { + ...params.action, + productId: decodeURIComponent(productId), + couponCode: decodeURIComponent(couponCode), + }, + }; + }); + diff --git a/libraries/commerce/cart/streams/index.spec.js b/libraries/commerce/cart/streams/index.spec.js index ff8dc357bb..4dd3c00a3f 100644 --- a/libraries/commerce/cart/streams/index.spec.js +++ b/libraries/commerce/cart/streams/index.spec.js @@ -1,10 +1,14 @@ import { createMockStore } from '@shopgate/pwa-common/store'; import { ACTION_PUSH, ACTION_POP, ACTION_REPLACE } from '@virtuous/conductor'; import { CART_PATH } from '@shopgate/pwa-common-commerce/cart/constants'; -import { routeWillEnter } from '@shopgate/pwa-common/action-creators/router'; +import { routeWillEnter, navigate } from '@shopgate/pwa-common/action-creators/router'; import receiveCart from '@shopgate/pwa-common-commerce/cart/action-creators/receiveCart'; import { getCurrentPathname } from '@shopgate/pwa-common/selectors/router'; -import { routeWithCouponWillEnter$, cartUpdatedWhileVisible$ } from './index'; +import { + routeWithCouponWillEnter$, + cartUpdatedWhileVisible$, + routeAddProductNavigate$, +} from './index'; jest.mock('@shopgate/pwa-common/selectors/router', () => ({ getCurrentPathname: jest.fn() })); @@ -85,4 +89,28 @@ describe('Cart streams', () => { expect(subscriber).toHaveBeenCalled(); }); }); + + describe('routeAddProductNavigate$', () => { + let subscriber; + beforeEach(() => { + subscriber = jest.fn(); + routeAddProductNavigate$.subscribe(subscriber); + }); + + it('should not emit when navigate does not map pattern', () => { + dispatch(navigate({ pathname: '/some_path' })); + expect(subscriber).not.toHaveBeenCalled(); + }); + + it('should emit and map event correctly', () => { + dispatch(navigate({ pathname: '/cart_add_product/345%2F34%23/TEST-CODE' })); + expect(subscriber).toHaveBeenCalledTimes(1); + expect(subscriber).toHaveBeenCalledWith(expect.objectContaining({ + action: expect.objectContaining({ + productId: '345/34#', + couponCode: 'TEST-CODE', + }), + })); + }); + }); }); diff --git a/libraries/commerce/cart/subscriptions/index.js b/libraries/commerce/cart/subscriptions/index.js index 380f6cc88f..844b069a37 100644 --- a/libraries/commerce/cart/subscriptions/index.js +++ b/libraries/commerce/cart/subscriptions/index.js @@ -1,4 +1,6 @@ import 'rxjs/add/operator/debounceTime'; +import 'rxjs/add/observable/of'; +import { Observable } from 'rxjs/Observable'; import event from '@shopgate/pwa-core/classes/Event'; import pipelineDependencies from '@shopgate/pwa-core/classes/PipelineDependencies'; import { redirects } from '@shopgate/pwa-common/collections'; @@ -8,8 +10,12 @@ import showModal from '@shopgate/pwa-common/actions/modal/showModal'; import fetchRegisterUrl from '@shopgate/pwa-common/actions/user/fetchRegisterUrl'; import { LoadingProvider } from '@shopgate/pwa-common/providers'; import { MODAL_PIPELINE_ERROR } from '@shopgate/pwa-common/constants/ModalTypes'; +import { getProductById, getProductRoute, hasProductVariety } from '@shopgate/pwa-common-commerce/product'; +import { historyReplace, historyPop } from '@shopgate/pwa-common/actions/router'; +import { checkoutSucceeded$ } from '@shopgate/pwa-common-commerce/checkout'; import * as pipelines from '../constants/Pipelines'; import addCouponsToCart from '../actions/addCouponsToCart'; +import addProductsToCart from '../actions/addProductsToCart'; import fetchCart from '../actions/fetchCart'; import { cartDidEnter$, @@ -25,10 +31,15 @@ import { routeWithCouponWillEnter$, remoteCartDidUpdate$, cartUpdateFailed$, + routeAddProductNavigate$, } from '../streams'; import setCartProductPendingCount from '../action-creators/setCartProductPendingCount'; -import { CART_PATH, DEEPLINK_CART_ADD_COUPON_PATTERN } from '../constants'; -import { checkoutSucceeded$ } from '../../checkout/streams'; +import { + CART_PATH, + DEEPLINK_CART_ADD_COUPON_PATTERN, + DEEPLINK_CART_ADD_PRODUCT_PATTERN, + CART_ITEM_TYPE_PRODUCT, +} from '../constants'; /** * Cart subscriptions. @@ -76,6 +87,8 @@ export default function cart(subscribe) { return null; }); + // This will be handled in 2 deferred subscriptions + redirects.set(DEEPLINK_CART_ADD_PRODUCT_PATTERN, () => null); }); /** @@ -92,9 +105,11 @@ export default function cart(subscribe) { // Push (deeplink) with coupon concurrent to get cart on app start pipelineDependencies.set(pipelines.SHOPGATE_CART_ADD_COUPONS, [ + pipelines.SHOPGATE_CART_ADD_PRODUCTS, pipelines.SHOPGATE_CART_GET_CART, ]); pipelineDependencies.set(pipelines.SHOPGATE_CART_DELETE_COUPONS, [ + pipelines.SHOPGATE_CART_ADD_PRODUCTS, pipelines.SHOPGATE_CART_GET_CART, ]); @@ -167,4 +182,55 @@ export default function cart(subscribe) { dispatch(addCouponsToCart([coupon])); } }); + + /** + * Deeplink to add product to cart, eg /cart_add_product/123 + */ + subscribe(routeAddProductNavigate$, ({ dispatch, action, getState }) => { + // NO product or variety + if (!getProductById(getState(), action) + || hasProductVariety(getState(), action)) { + // Redirect to item page to select options/variant + dispatch(historyReplace({ + pathname: getProductRoute(action.productId), + })); + } else { + dispatch(addProductsToCart([{ + productId: action.productId, + quantity: 1, + }])); + dispatch(historyPop()); + } + }); + + /** + * Deffer coupon adding to a cart, until we have at least 1 product + */ + const addCouponDeferred$ = routeAddProductNavigate$ + // Only if coupon is given + .filter(({ action: { couponCode = '' } }) => !!couponCode) + .withLatestFrom(cartReceived$) + .switchMap( + ([navigate, cartReceived]) => { + if (cartReceived.action.cart.cartItems.find(i => i.type === CART_ITEM_TYPE_PRODUCT)) { + // We have items in cart, add coupon immediately + return Observable.of(navigate); + } + // Wait until first product in cart to add a coupon + return cartReceived$.filter(cartReceivedNext => ( + cartReceivedNext.action.cart.cartItems.find(i => i.type === CART_ITEM_TYPE_PRODUCT) + )).first(); + }, + ([navigate]) => navigate + ); + + /** + * Deeplink to add product and coupon to cart, eg /cart_add_product/123/COUPON + */ + subscribe(addCouponDeferred$, async ({ dispatch, action }) => { + const { couponCode } = action; + if (couponCode) { + dispatch(addCouponsToCart([couponCode])); + } + }); } diff --git a/libraries/commerce/cart/subscriptions/index.spec.js b/libraries/commerce/cart/subscriptions/index.spec.js index fb0758993e..9e5472255d 100644 --- a/libraries/commerce/cart/subscriptions/index.spec.js +++ b/libraries/commerce/cart/subscriptions/index.spec.js @@ -1,7 +1,10 @@ import { redirects } from '@shopgate/pwa-common/collections'; import { appWillStart$ } from '@shopgate/pwa-common/streams/app'; import addCouponsToCart from '../actions/addCouponsToCart'; -import { DEEPLINK_CART_ADD_COUPON_PATTERN } from '../constants'; +import { + DEEPLINK_CART_ADD_COUPON_PATTERN, + DEEPLINK_CART_ADD_PRODUCT_PATTERN, +} from '../constants'; import { routeWithCouponWillEnter$ } from '../streams'; import subscription from './index'; @@ -34,11 +37,11 @@ describe('Cart subscriptions', () => { it('should setup a redirect handler for cart_add_coupon deeplinks', () => { callback(); - expect(redirectsSetSpy).toHaveBeenCalledTimes(1); - expect(redirectsSetSpy).toHaveBeenCalledWith( - DEEPLINK_CART_ADD_COUPON_PATTERN, - expect.any(Function) - ); + expect(redirectsSetSpy).toHaveBeenCalledTimes(2); + expect(redirectsSetSpy.mock.calls).toEqual([ + [DEEPLINK_CART_ADD_COUPON_PATTERN, expect.any(Function)], + [DEEPLINK_CART_ADD_PRODUCT_PATTERN, expect.any(Function)], + ]); }); it('should dispatch the addCouponsToCart action when a cart_add_coupon deeplink was opened', () => { diff --git a/libraries/commerce/checkout/index.js b/libraries/commerce/checkout/index.js index 8d17a511b0..928c4c99fe 100644 --- a/libraries/commerce/checkout/index.js +++ b/libraries/commerce/checkout/index.js @@ -7,3 +7,6 @@ export * from './constants/Pipelines'; // SELECTORS export * from './selectors'; + +// STREAMS +export * from './streams'; diff --git a/libraries/commerce/scanner/actions/handleQrCode.js b/libraries/commerce/scanner/actions/handleQrCode.js index 1de8e4bcc2..3b3427ae1a 100644 --- a/libraries/commerce/scanner/actions/handleQrCode.js +++ b/libraries/commerce/scanner/actions/handleQrCode.js @@ -55,10 +55,22 @@ export default ({ scope, format, payload }) => async (dispatch, getState) => { dispatch(historyPop()); break; case QR_CODE_TYPE_PRODUCT: - case QR_CODE_TYPE_PRODUCT_WITH_COUPON: // Force to fetch missing products await dispatch(fetchProductsById([data.productId])); + // Check from a store + if (!getProductById(getState(), data)) { + notFound(); + } else { + dispatch(successHandleScanner(scope, format, payload)); + dispatch(historyReplace({ + pathname: link, + })); + } + break; + case QR_CODE_TYPE_PRODUCT_WITH_COUPON: + await dispatch(fetchProductsById([data.productId])); + // Check from a store if (!getProductById(getState(), data)) { notFound(); diff --git a/libraries/commerce/scanner/helpers/index.js b/libraries/commerce/scanner/helpers/index.js index b20897b6a7..314a857641 100644 --- a/libraries/commerce/scanner/helpers/index.js +++ b/libraries/commerce/scanner/helpers/index.js @@ -31,12 +31,12 @@ const typeParsers = { [QR_CODE_TYPE_PRODUCT_WITH_COUPON]: (url) => { const [,,, paramTwo, paramThree] = url.pathname.split('/'); - const decodedParamTwo = decodeURIComponent(decodeURIComponent(paramTwo)); + const decodedParamTwo = decodeURIComponent(paramTwo); return { - link: `${getProductRoute(decodedParamTwo)}?coupon=${paramThree}`, + link: `/cart_add_product/${decodedParamTwo}/${paramThree}`, data: { - productId: decodedParamTwo, + productId: decodeURIComponent(decodedParamTwo), couponCode: paramThree, }, }; diff --git a/libraries/commerce/scanner/helpers/index.spec.js b/libraries/commerce/scanner/helpers/index.spec.js index 070680b0fb..b21c681e1e 100644 --- a/libraries/commerce/scanner/helpers/index.spec.js +++ b/libraries/commerce/scanner/helpers/index.spec.js @@ -54,10 +54,10 @@ describe('scanner helpers', () => { }); }); - it('should parse a PDP link with coupon', () => { + it('should parse add product with coupon link', () => { const result = parse2dsQrCode(`http://${QR_CODE_HOST_2DS}/9/30186/345%252F34%2523/TEST-CODE?s=26`); expect(result).toEqual({ - link: `${getProductRoute('345/34#')}?coupon=TEST-CODE`, + link: '/cart_add_product/345%2F34%23/TEST-CODE', type: QR_CODE_TYPE_PRODUCT_WITH_COUPON, data: { productId: '345/34#', couponCode: 'TEST-CODE' }, }); From 651501d5e9c1ebac0b9c687e08f6522f62cb35ca Mon Sep 17 00:00:00 2001 From: "O.Bilenko" Date: Wed, 3 Apr 2019 13:39:47 +0200 Subject: [PATCH 02/11] PWA-1792 Social media app deeplinks not working on pwa --- .../common/subscriptions/helpers/handleLinks.js | 11 +++++++++++ libraries/common/subscriptions/router.js | 6 ++++++ libraries/common/subscriptions/router.spec.js | 15 +++++++++++++++ themes/theme-gmd/widgets/Html/connector.js | 2 +- themes/theme-gmd/widgets/Html/index.jsx | 14 ++++++++++++-- themes/theme-ios11/widgets/Html/connector.js | 2 +- themes/theme-ios11/widgets/Html/index.jsx | 12 +++++++++++- 7 files changed, 57 insertions(+), 5 deletions(-) diff --git a/libraries/common/subscriptions/helpers/handleLinks.js b/libraries/common/subscriptions/helpers/handleLinks.js index 94cc65dbd1..666ddcb063 100644 --- a/libraries/common/subscriptions/helpers/handleLinks.js +++ b/libraries/common/subscriptions/helpers/handleLinks.js @@ -2,6 +2,7 @@ import { router, ACTION_REPLACE } from '@virtuous/conductor'; import flushTab from '@shopgate/pwa-core/commands/flushTab'; import openPage from '@shopgate/pwa-core/commands/openPage'; import showTab from '@shopgate/pwa-core/commands/showTab'; +import { openPageExtern } from '@shopgate/pwa-core'; import { logger } from '@shopgate/pwa-core/helpers'; import appConfig from '@shopgate/pwa-common/helpers/config'; import { getCurrentRoute } from '@shopgate/pwa-common/selectors/router'; @@ -198,6 +199,16 @@ export const openExternalLink = (location, historyAction, state) => { handleAppRedirect(historyAction, state); }; +/** + * Opens external url with openPageExternal command. + * @param {string} location The location to open. + */ +export const openExternalUrl = (location) => { + openPageExtern({ + src: location, + }); +}; + /** * Opens an legacy link in the old system in the given targetTab. * @param {Object} options Options of the link. diff --git a/libraries/common/subscriptions/router.js b/libraries/common/subscriptions/router.js index 59d4c328d0..29746fadac 100644 --- a/libraries/common/subscriptions/router.js +++ b/libraries/common/subscriptions/router.js @@ -124,6 +124,12 @@ export default function routerSubscriptions(subscribe) { // If there is one of the known protocols in the url. if (location && handler.hasKnownProtocols(location)) { if (handler.isExternalLink(location)) { + const { target } = routeState || {}; + if (target === '_blank') { + // Deeplinks to social apps: fb, whatsapp, etc. Treat as native links + handler.openExternalUrl(location); + return; + } handler.openExternalLink(location, historyAction, state); } else if (handler.isNativeLink(location)) { handler.openNativeLink(location); diff --git a/libraries/common/subscriptions/router.spec.js b/libraries/common/subscriptions/router.spec.js index 85b292e3e1..76189f1990 100644 --- a/libraries/common/subscriptions/router.spec.js +++ b/libraries/common/subscriptions/router.spec.js @@ -86,6 +86,7 @@ describe('Router subscriptions', () => { describe('navigate$', () => { const openExternalLinkSpy = jest.spyOn(handler, 'openExternalLink'); + const openExternalUrlSpy = jest.spyOn(handler, 'openExternalUrl'); const openNativeLinkSpy = jest.spyOn(handler, 'openNativeLink'); const openLegacySpy = jest.spyOn(handler, 'openLegacy'); const openLegacyLinkSpy = jest.spyOn(handler, 'openLegacyLink'); @@ -352,6 +353,20 @@ describe('Router subscriptions', () => { ); }); + it('should handle external urls with target=_blank as expected', async () => { + const params = { + action: ACTION_PUSH, + pathname: 'https://m.me/facebookID', + state: { + target: '_blank', + }, + }; + + await callback(createCallbackPayload({ params })); + expect(openExternalUrlSpy).toBeCalledTimes(1); + expect(openExternalUrlSpy).toHaveBeenCalledWith(params.pathname); + }); + it('should handle native links like expected', async () => { /** * Replace the implementation of handler.openNative link temporarily. It reassigns diff --git a/themes/theme-gmd/widgets/Html/connector.js b/themes/theme-gmd/widgets/Html/connector.js index a6d4d7f674..d4696b0717 100644 --- a/themes/theme-gmd/widgets/Html/connector.js +++ b/themes/theme-gmd/widgets/Html/connector.js @@ -7,7 +7,7 @@ import { historyPush } from '@shopgate/pwa-common/actions/router'; * @return {Object} The extended component props. */ const mapDispatchToProps = dispatch => ({ - navigate: pathname => dispatch(historyPush({ pathname })), + navigate: params => dispatch(historyPush(params)), }); export default connect(null, mapDispatchToProps, null, { pure: () => true }); diff --git a/themes/theme-gmd/widgets/Html/index.jsx b/themes/theme-gmd/widgets/Html/index.jsx index 46cadd6ab8..7edae5a069 100644 --- a/themes/theme-gmd/widgets/Html/index.jsx +++ b/themes/theme-gmd/widgets/Html/index.jsx @@ -99,9 +99,19 @@ class Html extends Component { handleTap = (e) => { const aTag = e.target.closest('a'); - if (aTag && aTag.attributes.href) { + const { + attributes: { + href: { value: href = '' } = {}, + target: { value: target = '' } = {}, + } = {}, + } = aTag; + + if (href) { e.preventDefault(); - this.props.navigate(aTag.attributes.href.value); + this.props.navigate({ + pathname: href, + ...target && { state: { target } }, + }); } }; diff --git a/themes/theme-ios11/widgets/Html/connector.js b/themes/theme-ios11/widgets/Html/connector.js index a6d4d7f674..d4696b0717 100644 --- a/themes/theme-ios11/widgets/Html/connector.js +++ b/themes/theme-ios11/widgets/Html/connector.js @@ -7,7 +7,7 @@ import { historyPush } from '@shopgate/pwa-common/actions/router'; * @return {Object} The extended component props. */ const mapDispatchToProps = dispatch => ({ - navigate: pathname => dispatch(historyPush({ pathname })), + navigate: params => dispatch(historyPush(params)), }); export default connect(null, mapDispatchToProps, null, { pure: () => true }); diff --git a/themes/theme-ios11/widgets/Html/index.jsx b/themes/theme-ios11/widgets/Html/index.jsx index 46cadd6ab8..785e4b4181 100644 --- a/themes/theme-ios11/widgets/Html/index.jsx +++ b/themes/theme-ios11/widgets/Html/index.jsx @@ -99,9 +99,19 @@ class Html extends Component { handleTap = (e) => { const aTag = e.target.closest('a'); + const { + attributes: { + href: { value: href = '' } = {}, + target: { value: target = '' } = {}, + } = {}, + } = aTag; + if (aTag && aTag.attributes.href) { e.preventDefault(); - this.props.navigate(aTag.attributes.href.value); + this.props.navigate({ + pathname: href, + ...target && { state: { target } }, + }); } }; From 900470361b8f587b6dcb8ea8293492348bf43f6d Mon Sep 17 00:00:00 2001 From: "O.Bilenko" Date: Thu, 4 Apr 2019 08:50:17 +0200 Subject: [PATCH 03/11] PWA-1792 Social media app deeplinks not working on pwa --- .../subscriptions/helpers/handleLinks.js | 22 +++++++++--------- .../subscriptions/helpers/handleLinks.spec.js | 23 ++++++++++++++++++- libraries/common/subscriptions/router.js | 8 +------ libraries/common/subscriptions/router.spec.js | 10 +++++--- 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/libraries/common/subscriptions/helpers/handleLinks.js b/libraries/common/subscriptions/helpers/handleLinks.js index 666ddcb063..9648eed074 100644 --- a/libraries/common/subscriptions/helpers/handleLinks.js +++ b/libraries/common/subscriptions/helpers/handleLinks.js @@ -176,8 +176,18 @@ export const handleAppRedirect = (historyAction, state) => { * @param {string} location The location to open. * @param {string} historyAction The history action which was used to open the link. * @param {Object} state The application state. + * @param {Object} locationState state params for location */ -export const openExternalLink = (location, historyAction, state) => { +export const openExternalLink = (location, historyAction, state, locationState = {}) => { + const { target } = locationState; + if (target === '_blank') { + // Deeplinks to social apps: fb, whatsapp, etc. Treat as native links + openPageExtern({ + src: location, + }); + return; + } + showTab({ targetTab: 'in_app_browser', animation: 'slideInFromBottom', @@ -199,16 +209,6 @@ export const openExternalLink = (location, historyAction, state) => { handleAppRedirect(historyAction, state); }; -/** - * Opens external url with openPageExternal command. - * @param {string} location The location to open. - */ -export const openExternalUrl = (location) => { - openPageExtern({ - src: location, - }); -}; - /** * Opens an legacy link in the old system in the given targetTab. * @param {Object} options Options of the link. diff --git a/libraries/common/subscriptions/helpers/handleLinks.spec.js b/libraries/common/subscriptions/helpers/handleLinks.spec.js index 46cae2de44..d6d8a862c1 100644 --- a/libraries/common/subscriptions/helpers/handleLinks.spec.js +++ b/libraries/common/subscriptions/helpers/handleLinks.spec.js @@ -1,4 +1,10 @@ -import { isShopLink, sanitizeLink } from './handleLinks'; +import { openPageExtern, openPage } from '@shopgate/pwa-core'; +import { isShopLink, sanitizeLink, openExternalLink } from './handleLinks'; + +jest.mock('@shopgate/pwa-core', () => ({ + openPageExtern: jest.fn(), + openPage: jest.fn(), +})); jest.mock('@shopgate/pwa-common/helpers/config', () => ({ shopCNAME: 'm.example.com', @@ -61,5 +67,20 @@ describe('handleLinks helpers', () => { } ); }); + + describe('openExternalLink', () => { + it('should call openPageExtern', () => { + const location = 'http://m.me/shopgate'; + openExternalLink( + location, + 'ACTION', + {}, + { target: '_blank' } + ); + expect(openPageExtern).toBeCalledTimes(1); + expect(openPageExtern).toBeCalledWith({ src: location }); + expect(openPage).not.toBeCalled(); + }); + }); }); diff --git a/libraries/common/subscriptions/router.js b/libraries/common/subscriptions/router.js index 29746fadac..975ec58f2d 100644 --- a/libraries/common/subscriptions/router.js +++ b/libraries/common/subscriptions/router.js @@ -124,13 +124,7 @@ export default function routerSubscriptions(subscribe) { // If there is one of the known protocols in the url. if (location && handler.hasKnownProtocols(location)) { if (handler.isExternalLink(location)) { - const { target } = routeState || {}; - if (target === '_blank') { - // Deeplinks to social apps: fb, whatsapp, etc. Treat as native links - handler.openExternalUrl(location); - return; - } - handler.openExternalLink(location, historyAction, state); + handler.openExternalLink(location, historyAction, state, routeState); } else if (handler.isNativeLink(location)) { handler.openNativeLink(location); } diff --git a/libraries/common/subscriptions/router.spec.js b/libraries/common/subscriptions/router.spec.js index 76189f1990..eb5b662485 100644 --- a/libraries/common/subscriptions/router.spec.js +++ b/libraries/common/subscriptions/router.spec.js @@ -86,7 +86,6 @@ describe('Router subscriptions', () => { describe('navigate$', () => { const openExternalLinkSpy = jest.spyOn(handler, 'openExternalLink'); - const openExternalUrlSpy = jest.spyOn(handler, 'openExternalUrl'); const openNativeLinkSpy = jest.spyOn(handler, 'openNativeLink'); const openLegacySpy = jest.spyOn(handler, 'openLegacy'); const openLegacyLinkSpy = jest.spyOn(handler, 'openLegacyLink'); @@ -363,8 +362,13 @@ describe('Router subscriptions', () => { }; await callback(createCallbackPayload({ params })); - expect(openExternalUrlSpy).toBeCalledTimes(1); - expect(openExternalUrlSpy).toHaveBeenCalledWith(params.pathname); + expect(openExternalLinkSpy).toBeCalledTimes(1); + expect(openExternalLinkSpy).toHaveBeenCalledWith( + params.pathname, + params.action, + mockedRouterState, + params.state + ); }); it('should handle native links like expected', async () => { From 5f471c0b9013980146b0967b87590acc5f5a7e9b Mon Sep 17 00:00:00 2001 From: "O.Bilenko" Date: Thu, 4 Apr 2019 09:02:22 +0200 Subject: [PATCH 04/11] PWA-1792 Social media app deeplinks not working on pwa --- libraries/common/subscriptions/router.spec.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/common/subscriptions/router.spec.js b/libraries/common/subscriptions/router.spec.js index eb5b662485..6c9a5bef8c 100644 --- a/libraries/common/subscriptions/router.spec.js +++ b/libraries/common/subscriptions/router.spec.js @@ -348,7 +348,8 @@ describe('Router subscriptions', () => { expect(openExternalLinkSpy).toHaveBeenCalledWith( params.pathname, params.action, - mockedRouterState + mockedRouterState, + undefined ); }); From b8e36d8862382cecc47666ca6949e7b155ad2217 Mon Sep 17 00:00:00 2001 From: shopgate-deployer Date: Fri, 5 Apr 2019 12:08:17 +0000 Subject: [PATCH 05/11] Released 6.3.2-rc.1 --- .../extension-config.json | 2 +- .../frontend/package.json | 12 ++++----- .../extension-config.json | 2 +- .../frontend/package.json | 10 +++---- .../extension-config.json | 2 +- .../frontend/package.json | 12 ++++----- lerna.json | 2 +- libraries/commerce/package.json | 10 +++---- libraries/common/package.json | 8 +++--- libraries/core/package.json | 2 +- libraries/tracking-core/package.json | 6 ++--- libraries/tracking/package.json | 12 ++++----- libraries/ui-ios/package.json | 4 +-- libraries/ui-material/package.json | 4 +-- libraries/ui-shared/package.json | 10 +++---- libraries/webcheckout/package.json | 6 ++--- themes/theme-gmd/extension-config.json | 2 +- themes/theme-gmd/package.json | 24 ++++++++--------- themes/theme-ios11/extension-config.json | 2 +- themes/theme-ios11/package.json | 26 +++++++++---------- utils/benchmark/package.json | 2 +- utils/e2e/package.json | 2 +- utils/eslint-config/package.json | 2 +- utils/unit-tests/package.json | 4 +-- 24 files changed, 84 insertions(+), 84 deletions(-) diff --git a/extensions/@shopgate-product-reviews/extension-config.json b/extensions/@shopgate-product-reviews/extension-config.json index dd8e715196..4802a066b5 100644 --- a/extensions/@shopgate-product-reviews/extension-config.json +++ b/extensions/@shopgate-product-reviews/extension-config.json @@ -1,5 +1,5 @@ { - "version": "6.3.1", + "version": "6.3.2-rc.1", "id": "@shopgate/product-reviews", "components": [ { diff --git a/extensions/@shopgate-product-reviews/frontend/package.json b/extensions/@shopgate-product-reviews/frontend/package.json index 28ce56ba35..a298d557d2 100644 --- a/extensions/@shopgate-product-reviews/frontend/package.json +++ b/extensions/@shopgate-product-reviews/frontend/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/product-reviews", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Shopgate Connect Product Reviews extension.", "license": "Apache-2.0", "scripts": { @@ -19,11 +19,11 @@ } }, "devDependencies": { - "@shopgate/eslint-config": "6.3.1", - "@shopgate/pwa-common": "6.3.1", - "@shopgate/pwa-common-commerce": "6.3.1", - "@shopgate/pwa-core": "6.3.1", - "@shopgate/pwa-unit-test": "6.3.1", + "@shopgate/eslint-config": "6.3.2-rc.1", + "@shopgate/pwa-common": "6.3.2-rc.1", + "@shopgate/pwa-common-commerce": "6.3.2-rc.1", + "@shopgate/pwa-core": "6.3.2-rc.1", + "@shopgate/pwa-unit-test": "6.3.2-rc.1", "@shopgate/react-hammerjs": "0.5.3", "babel-plugin-react-transform": "^3.0.0", "coveralls": "^3.0.0", diff --git a/extensions/@shopgate-tracking-ga-native/extension-config.json b/extensions/@shopgate-tracking-ga-native/extension-config.json index 96956d7232..99eccecf8b 100644 --- a/extensions/@shopgate-tracking-ga-native/extension-config.json +++ b/extensions/@shopgate-tracking-ga-native/extension-config.json @@ -1,5 +1,5 @@ { - "version": "6.3.1", + "version": "6.3.2-rc.1", "id": "@shopgate/tracking-ga-native", "components": [ { diff --git a/extensions/@shopgate-tracking-ga-native/frontend/package.json b/extensions/@shopgate-tracking-ga-native/frontend/package.json index 81c4f682a3..8b2f9f7f4f 100644 --- a/extensions/@shopgate-tracking-ga-native/frontend/package.json +++ b/extensions/@shopgate-tracking-ga-native/frontend/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/tracking-ga-native", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Shopgate Connect Google Analytics native tracker extension.", "main": "frontend/index.js", "repository": "shopgate/tracking-ga-native", @@ -23,12 +23,12 @@ } }, "dependencies": { - "@shopgate/tracking-core": "6.3.1" + "@shopgate/tracking-core": "6.3.2-rc.1" }, "devDependencies": { - "@shopgate/eslint-config": "6.3.1", - "@shopgate/pwa-common": "6.3.1", - "@shopgate/pwa-core": "6.3.1", + "@shopgate/eslint-config": "6.3.2-rc.1", + "@shopgate/pwa-common": "6.3.2-rc.1", + "@shopgate/pwa-core": "6.3.2-rc.1", "@shopgate/react-hammerjs": "0.5.3", "babel-core": "^6.26.3", "babel-plugin-transform-class-properties": "^6.24.1", diff --git a/extensions/@shopgate-user-privacy/extension-config.json b/extensions/@shopgate-user-privacy/extension-config.json index 716295f555..6a77e9ce14 100644 --- a/extensions/@shopgate-user-privacy/extension-config.json +++ b/extensions/@shopgate-user-privacy/extension-config.json @@ -1,5 +1,5 @@ { - "version": "6.3.1", + "version": "6.3.2-rc.1", "id": "@shopgate/user-privacy", "configuration": { "isActive": { diff --git a/extensions/@shopgate-user-privacy/frontend/package.json b/extensions/@shopgate-user-privacy/frontend/package.json index 7c383051c2..4f191ffb78 100644 --- a/extensions/@shopgate-user-privacy/frontend/package.json +++ b/extensions/@shopgate-user-privacy/frontend/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/user-privacy", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Shopgate Connect User Privacy Extension", "license": "Apache 2.0", "repository": { @@ -11,11 +11,11 @@ "lint": "eslint --ignore-path ../.gitignore --ext .js --ext .jsx ." }, "devDependencies": { - "@shopgate/eslint-config": "6.3.1", - "@shopgate/pwa-common": "6.3.1", - "@shopgate/pwa-common-commerce": "6.3.1", - "@shopgate/pwa-core": "6.3.1", - "@shopgate/pwa-ui-shared": "6.3.1", + "@shopgate/eslint-config": "6.3.2-rc.1", + "@shopgate/pwa-common": "6.3.2-rc.1", + "@shopgate/pwa-common-commerce": "6.3.2-rc.1", + "@shopgate/pwa-core": "6.3.2-rc.1", + "@shopgate/pwa-ui-shared": "6.3.2-rc.1", "eslint": "^4.17.0", "prop-types": "^15.6.0", "react": "~16.3.2", diff --git a/lerna.json b/lerna.json index 07887d2240..fd6d89a3b0 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "lerna": "2.9.0", - "version": "6.3.1", + "version": "6.3.2-rc.1", "packages": [ "extensions/@shopgate-product-reviews/frontend", "extensions/@shopgate-tracking-ga-native/frontend", diff --git a/libraries/commerce/package.json b/libraries/commerce/package.json index b518619f7d..e260d53db1 100644 --- a/libraries/commerce/package.json +++ b/libraries/commerce/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-common-commerce", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Commerce library for the Shopgate Connect PWA.", "license": "Apache-2.0", "author": "Shopgate ", @@ -19,10 +19,10 @@ "reselect": "^3.0.1" }, "devDependencies": { - "@shopgate/pwa-common": "6.3.1", - "@shopgate/pwa-core": "6.3.1", - "@shopgate/pwa-unit-test": "6.3.1", - "@shopgate/tracking-core": "6.3.1", + "@shopgate/pwa-common": "6.3.2-rc.1", + "@shopgate/pwa-core": "6.3.2-rc.1", + "@shopgate/pwa-unit-test": "6.3.2-rc.1", + "@shopgate/tracking-core": "6.3.2-rc.1", "lodash": "^4.17.4", "react": "~16.6.0", "react-dom": "~16.6.0", diff --git a/libraries/common/package.json b/libraries/common/package.json index c389885b0d..217e1f2f87 100644 --- a/libraries/common/package.json +++ b/libraries/common/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-common", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Common library for the Shopgate Connect PWA.", "license": "Apache-2.0", "author": "Shopgate ", @@ -16,7 +16,7 @@ ], "dependencies": { "@sentry/browser": "^4.6.3", - "@shopgate/pwa-benchmark": "6.3.1", + "@shopgate/pwa-benchmark": "6.3.2-rc.1", "@virtuous/conductor": "~2.1.1", "@virtuous/react-conductor": "~2.1.1", "@virtuous/redux-persister": "1.1.0-beta.7", @@ -44,9 +44,9 @@ "url-search-params": "^0.10.0" }, "devDependencies": { - "@shopgate/eslint-config": "6.3.1", + "@shopgate/eslint-config": "6.3.2-rc.1", "@shopgate/pwa-benchmark": "6.0.0", - "@shopgate/pwa-core": "6.3.1", + "@shopgate/pwa-core": "6.3.2-rc.1", "lodash": "^4.17.4", "prop-types": "^15.6.0", "react": "~16.6.0", diff --git a/libraries/core/package.json b/libraries/core/package.json index e48aad9cf5..c50d9412da 100644 --- a/libraries/core/package.json +++ b/libraries/core/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-core", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Core library for the Shopgate Connect PWA.", "author": "Support ", "license": "Apache-2.0", diff --git a/libraries/tracking-core/package.json b/libraries/tracking-core/package.json index 1575bc1e41..048e65ea3b 100644 --- a/libraries/tracking-core/package.json +++ b/libraries/tracking-core/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/tracking-core", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Tracking core library for the Shopgate Connect PWA.", "author": "Shopgate ", "license": "Apache-2.0", @@ -16,8 +16,8 @@ "connect" ], "devDependencies": { - "@shopgate/eslint-config": "6.3.1", - "@shopgate/pwa-core": "6.3.1", + "@shopgate/eslint-config": "6.3.2-rc.1", + "@shopgate/pwa-core": "6.3.2-rc.1", "chai": "^3.5.0", "jest": "^23.5.0", "jsdom": "9.8.3", diff --git a/libraries/tracking/package.json b/libraries/tracking/package.json index 70a830e145..f81e81561b 100644 --- a/libraries/tracking/package.json +++ b/libraries/tracking/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-tracking", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Tracking library for the Shopgate Connect PWA.", "license": "Apache-2.0", "author": "Shopgate ", @@ -15,11 +15,11 @@ "connect" ], "devDependencies": { - "@shopgate/eslint-config": "6.3.1", - "@shopgate/pwa-common": "6.3.1", - "@shopgate/pwa-common-commerce": "6.3.1", - "@shopgate/pwa-core": "6.3.1", - "@shopgate/tracking-core": "6.3.1", + "@shopgate/eslint-config": "6.3.2-rc.1", + "@shopgate/pwa-common": "6.3.2-rc.1", + "@shopgate/pwa-common-commerce": "6.3.2-rc.1", + "@shopgate/pwa-core": "6.3.2-rc.1", + "@shopgate/tracking-core": "6.3.2-rc.1", "reselect": "^3.0.1", "rxjs": "^5.4.3" } diff --git a/libraries/ui-ios/package.json b/libraries/ui-ios/package.json index 223d989cf1..394e02e3f1 100644 --- a/libraries/ui-ios/package.json +++ b/libraries/ui-ios/package.json @@ -1,11 +1,11 @@ { "name": "@shopgate/pwa-ui-ios", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Shopgate's iOS UI components.", "main": "index.js", "license": "Apache-2.0", "devDependencies": { - "@shopgate/pwa-common": "6.3.1", + "@shopgate/pwa-common": "6.3.2-rc.1", "react": "~16.6.0" }, "peerDependencies": { diff --git a/libraries/ui-material/package.json b/libraries/ui-material/package.json index 5350075cd5..3de840b2e5 100644 --- a/libraries/ui-material/package.json +++ b/libraries/ui-material/package.json @@ -1,11 +1,11 @@ { "name": "@shopgate/pwa-ui-material", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Shopgate's material design UI components.", "main": "index.js", "license": "Apache-2.0", "devDependencies": { - "@shopgate/pwa-common": "6.3.1", + "@shopgate/pwa-common": "6.3.2-rc.1", "react": "~16.6.0" }, "dependencies": { diff --git a/libraries/ui-shared/package.json b/libraries/ui-shared/package.json index 0e948402fd..adbeb27c32 100644 --- a/libraries/ui-shared/package.json +++ b/libraries/ui-shared/package.json @@ -1,16 +1,16 @@ { "name": "@shopgate/pwa-ui-shared", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Shopgate's shared UI components.", "main": "index.js", "license": "Apache-2.0", "dependencies": { - "@shopgate/pwa-ui-ios": "6.3.1", - "@shopgate/pwa-ui-material": "6.3.1" + "@shopgate/pwa-ui-ios": "6.3.2-rc.1", + "@shopgate/pwa-ui-material": "6.3.2-rc.1" }, "devDependencies": { - "@shopgate/pwa-common": "6.3.1", - "@shopgate/pwa-common-commerce": "6.3.1", + "@shopgate/pwa-common": "6.3.2-rc.1", + "@shopgate/pwa-common-commerce": "6.3.2-rc.1", "react": "~16.6.0" }, "peerDependencies": { diff --git a/libraries/webcheckout/package.json b/libraries/webcheckout/package.json index d9d3f1de68..5feca00fdd 100644 --- a/libraries/webcheckout/package.json +++ b/libraries/webcheckout/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-webcheckout-shopify", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Webcheckout Shopify library for the Shopgate Connect PWA.", "license": "Apache-2.0", "author": "Shopgate ", @@ -17,8 +17,8 @@ "connect" ], "devDependencies": { - "@shopgate/pwa-common": "6.3.1", - "@shopgate/pwa-core": "6.3.1", + "@shopgate/pwa-common": "6.3.2-rc.1", + "@shopgate/pwa-core": "6.3.2-rc.1", "react": "~16.6.0" } } diff --git a/themes/theme-gmd/extension-config.json b/themes/theme-gmd/extension-config.json index a2bfa129c9..843845a0f4 100644 --- a/themes/theme-gmd/extension-config.json +++ b/themes/theme-gmd/extension-config.json @@ -1,5 +1,5 @@ { - "version": "6.3.1", + "version": "6.3.2-rc.1", "id": "@shopgate/theme-gmd", "configuration": { "appId": { diff --git a/themes/theme-gmd/package.json b/themes/theme-gmd/package.json index 60516a11f8..f3221e2437 100644 --- a/themes/theme-gmd/package.json +++ b/themes/theme-gmd/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/theme-gmd", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Google Material Design theme for the Shopgate Connect PWA.", "repository": "shopgate/theme-gmd", "bugs": "https://github.com/shopgate/theme-gmd/issues", @@ -16,14 +16,14 @@ "e2e:user": "cypress open -P ./e2e/extensions/user" }, "dependencies": { - "@shopgate/pwa-common": "6.3.1", - "@shopgate/pwa-common-commerce": "6.3.1", - "@shopgate/pwa-core": "6.3.1", - "@shopgate/pwa-tracking": "6.3.1", - "@shopgate/pwa-ui-material": "6.3.1", - "@shopgate/pwa-ui-shared": "6.3.1", - "@shopgate/pwa-webcheckout-shopify": "6.3.1", - "@shopgate/tracking-core": "6.3.1", + "@shopgate/pwa-common": "6.3.2-rc.1", + "@shopgate/pwa-common-commerce": "6.3.2-rc.1", + "@shopgate/pwa-core": "6.3.2-rc.1", + "@shopgate/pwa-tracking": "6.3.2-rc.1", + "@shopgate/pwa-ui-material": "6.3.2-rc.1", + "@shopgate/pwa-ui-shared": "6.3.2-rc.1", + "@shopgate/pwa-webcheckout-shopify": "6.3.2-rc.1", + "@shopgate/tracking-core": "6.3.2-rc.1", "@virtuous/conductor": "~2.1.1", "@virtuous/react-conductor": "~2.1.1", "babel-core": "^6.26.3", @@ -64,9 +64,9 @@ "smoothscroll-polyfill": "^0.4.3" }, "devDependencies": { - "@shopgate/eslint-config": "6.3.1", - "@shopgate/pwa-e2e-test": "6.3.1", - "@shopgate/pwa-unit-test": "6.3.1", + "@shopgate/eslint-config": "6.3.2-rc.1", + "@shopgate/pwa-e2e-test": "6.3.2-rc.1", + "@shopgate/pwa-unit-test": "6.3.2-rc.1", "coveralls": "^3.0.0", "eslint": "^4.17.0", "eslint-import-resolver-babel-module": "4.0.0", diff --git a/themes/theme-ios11/extension-config.json b/themes/theme-ios11/extension-config.json index a9a07e695d..50031ee272 100644 --- a/themes/theme-ios11/extension-config.json +++ b/themes/theme-ios11/extension-config.json @@ -1,5 +1,5 @@ { - "version": "6.3.1", + "version": "6.3.2-rc.1", "id": "@shopgate/theme-ios11", "configuration": { "appId": { diff --git a/themes/theme-ios11/package.json b/themes/theme-ios11/package.json index 92142301fa..4e10646cf7 100644 --- a/themes/theme-ios11/package.json +++ b/themes/theme-ios11/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/theme-ios11", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "iOS11 theme for the Shopgate Connect PWA.", "repository": "shopgate/theme-ios11", "bugs": "https://github.com/shopgate/theme-ios11/issues", @@ -15,15 +15,15 @@ "e2e:checkout": "cypress open -P ./e2e/extensions/checkout" }, "dependencies": { - "@shopgate/pwa-common": "6.3.1", - "@shopgate/pwa-common-commerce": "6.3.1", - "@shopgate/pwa-core": "6.3.1", - "@shopgate/pwa-tracking": "6.3.1", - "@shopgate/pwa-ui-ios": "6.3.1", - "@shopgate/pwa-ui-material": "6.3.1", - "@shopgate/pwa-ui-shared": "6.3.1", - "@shopgate/pwa-webcheckout-shopify": "6.3.1", - "@shopgate/tracking-core": "6.3.1", + "@shopgate/pwa-common": "6.3.2-rc.1", + "@shopgate/pwa-common-commerce": "6.3.2-rc.1", + "@shopgate/pwa-core": "6.3.2-rc.1", + "@shopgate/pwa-tracking": "6.3.2-rc.1", + "@shopgate/pwa-ui-ios": "6.3.2-rc.1", + "@shopgate/pwa-ui-material": "6.3.2-rc.1", + "@shopgate/pwa-ui-shared": "6.3.2-rc.1", + "@shopgate/pwa-webcheckout-shopify": "6.3.2-rc.1", + "@shopgate/tracking-core": "6.3.2-rc.1", "@virtuous/conductor": "~2.1.1", "@virtuous/react-conductor": "~2.1.1", "babel-core": "^6.26.3", @@ -65,9 +65,9 @@ "smoothscroll-polyfill": "^0.4.3" }, "devDependencies": { - "@shopgate/eslint-config": "6.3.1", - "@shopgate/pwa-e2e-test": "6.3.1", - "@shopgate/pwa-unit-test": "6.3.1", + "@shopgate/eslint-config": "6.3.2-rc.1", + "@shopgate/pwa-e2e-test": "6.3.2-rc.1", + "@shopgate/pwa-unit-test": "6.3.2-rc.1", "coveralls": "^3.0.0", "eslint": "^4.17.0", "eslint-import-resolver-babel-module": "4.0.0", diff --git a/utils/benchmark/package.json b/utils/benchmark/package.json index 3724fe801a..0766d69a17 100644 --- a/utils/benchmark/package.json +++ b/utils/benchmark/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-benchmark", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Benchmark suite for PWA", "author": "Rene Eichhorn", "main": "index.js", diff --git a/utils/e2e/package.json b/utils/e2e/package.json index 0f21feddc9..a605d7a0c1 100644 --- a/utils/e2e/package.json +++ b/utils/e2e/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-e2e-test", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "E2E test setup for the Shopgate Connect PWA.", "author": "Shopgate ", "license": "Apache-2.0" diff --git a/utils/eslint-config/package.json b/utils/eslint-config/package.json index 8619c9c7cb..ce1f0c43ac 100644 --- a/utils/eslint-config/package.json +++ b/utils/eslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/eslint-config", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Eslint configuration for the Shopgate Connect projects.", "author": "Shopgate ", "license": "Apache-2.0", diff --git a/utils/unit-tests/package.json b/utils/unit-tests/package.json index b7d0764fe6..f902e94ee4 100644 --- a/utils/unit-tests/package.json +++ b/utils/unit-tests/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-unit-test", - "version": "6.3.1", + "version": "6.3.2-rc.1", "description": "Unit test setup for the Shopgate Connect PWA.", "author": "Shopgate ", "license": "Apache-2.0", @@ -14,7 +14,7 @@ "react-tap-event-plugin": "^3.0.2" }, "devDependencies": { - "@shopgate/eslint-config": "6.3.1", + "@shopgate/eslint-config": "6.3.2-rc.1", "jest": "^23.5.0", "react": "~16.6.0", "react-dom": "~16.6.0" From 5e2c0596c319b65a0764c09df90f5ea8a73cd7be Mon Sep 17 00:00:00 2001 From: shopgate-deployer Date: Fri, 5 Apr 2019 12:17:34 +0000 Subject: [PATCH 06/11] Released 6.3.2 --- .../extension-config.json | 2 +- .../frontend/package.json | 12 ++++----- .../extension-config.json | 2 +- .../frontend/package.json | 10 +++---- .../extension-config.json | 2 +- .../frontend/package.json | 12 ++++----- lerna.json | 2 +- libraries/commerce/package.json | 10 +++---- libraries/common/package.json | 8 +++--- libraries/core/package.json | 2 +- libraries/tracking-core/package.json | 6 ++--- libraries/tracking/package.json | 12 ++++----- libraries/ui-ios/package.json | 4 +-- libraries/ui-material/package.json | 4 +-- libraries/ui-shared/package.json | 10 +++---- libraries/webcheckout/package.json | 6 ++--- themes/theme-gmd/extension-config.json | 2 +- themes/theme-gmd/package.json | 24 ++++++++--------- themes/theme-ios11/extension-config.json | 2 +- themes/theme-ios11/package.json | 26 +++++++++---------- utils/benchmark/package.json | 2 +- utils/e2e/package.json | 2 +- utils/eslint-config/package.json | 2 +- utils/unit-tests/package.json | 4 +-- 24 files changed, 84 insertions(+), 84 deletions(-) diff --git a/extensions/@shopgate-product-reviews/extension-config.json b/extensions/@shopgate-product-reviews/extension-config.json index 4802a066b5..3cfcc66eed 100644 --- a/extensions/@shopgate-product-reviews/extension-config.json +++ b/extensions/@shopgate-product-reviews/extension-config.json @@ -1,5 +1,5 @@ { - "version": "6.3.2-rc.1", + "version": "6.3.2", "id": "@shopgate/product-reviews", "components": [ { diff --git a/extensions/@shopgate-product-reviews/frontend/package.json b/extensions/@shopgate-product-reviews/frontend/package.json index a298d557d2..d2f69de369 100644 --- a/extensions/@shopgate-product-reviews/frontend/package.json +++ b/extensions/@shopgate-product-reviews/frontend/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/product-reviews", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Shopgate Connect Product Reviews extension.", "license": "Apache-2.0", "scripts": { @@ -19,11 +19,11 @@ } }, "devDependencies": { - "@shopgate/eslint-config": "6.3.2-rc.1", - "@shopgate/pwa-common": "6.3.2-rc.1", - "@shopgate/pwa-common-commerce": "6.3.2-rc.1", - "@shopgate/pwa-core": "6.3.2-rc.1", - "@shopgate/pwa-unit-test": "6.3.2-rc.1", + "@shopgate/eslint-config": "6.3.2", + "@shopgate/pwa-common": "6.3.2", + "@shopgate/pwa-common-commerce": "6.3.2", + "@shopgate/pwa-core": "6.3.2", + "@shopgate/pwa-unit-test": "6.3.2", "@shopgate/react-hammerjs": "0.5.3", "babel-plugin-react-transform": "^3.0.0", "coveralls": "^3.0.0", diff --git a/extensions/@shopgate-tracking-ga-native/extension-config.json b/extensions/@shopgate-tracking-ga-native/extension-config.json index 99eccecf8b..0054e14377 100644 --- a/extensions/@shopgate-tracking-ga-native/extension-config.json +++ b/extensions/@shopgate-tracking-ga-native/extension-config.json @@ -1,5 +1,5 @@ { - "version": "6.3.2-rc.1", + "version": "6.3.2", "id": "@shopgate/tracking-ga-native", "components": [ { diff --git a/extensions/@shopgate-tracking-ga-native/frontend/package.json b/extensions/@shopgate-tracking-ga-native/frontend/package.json index 8b2f9f7f4f..605f6d2b85 100644 --- a/extensions/@shopgate-tracking-ga-native/frontend/package.json +++ b/extensions/@shopgate-tracking-ga-native/frontend/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/tracking-ga-native", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Shopgate Connect Google Analytics native tracker extension.", "main": "frontend/index.js", "repository": "shopgate/tracking-ga-native", @@ -23,12 +23,12 @@ } }, "dependencies": { - "@shopgate/tracking-core": "6.3.2-rc.1" + "@shopgate/tracking-core": "6.3.2" }, "devDependencies": { - "@shopgate/eslint-config": "6.3.2-rc.1", - "@shopgate/pwa-common": "6.3.2-rc.1", - "@shopgate/pwa-core": "6.3.2-rc.1", + "@shopgate/eslint-config": "6.3.2", + "@shopgate/pwa-common": "6.3.2", + "@shopgate/pwa-core": "6.3.2", "@shopgate/react-hammerjs": "0.5.3", "babel-core": "^6.26.3", "babel-plugin-transform-class-properties": "^6.24.1", diff --git a/extensions/@shopgate-user-privacy/extension-config.json b/extensions/@shopgate-user-privacy/extension-config.json index 6a77e9ce14..ae73a6b734 100644 --- a/extensions/@shopgate-user-privacy/extension-config.json +++ b/extensions/@shopgate-user-privacy/extension-config.json @@ -1,5 +1,5 @@ { - "version": "6.3.2-rc.1", + "version": "6.3.2", "id": "@shopgate/user-privacy", "configuration": { "isActive": { diff --git a/extensions/@shopgate-user-privacy/frontend/package.json b/extensions/@shopgate-user-privacy/frontend/package.json index 4f191ffb78..71dad4de7a 100644 --- a/extensions/@shopgate-user-privacy/frontend/package.json +++ b/extensions/@shopgate-user-privacy/frontend/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/user-privacy", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Shopgate Connect User Privacy Extension", "license": "Apache 2.0", "repository": { @@ -11,11 +11,11 @@ "lint": "eslint --ignore-path ../.gitignore --ext .js --ext .jsx ." }, "devDependencies": { - "@shopgate/eslint-config": "6.3.2-rc.1", - "@shopgate/pwa-common": "6.3.2-rc.1", - "@shopgate/pwa-common-commerce": "6.3.2-rc.1", - "@shopgate/pwa-core": "6.3.2-rc.1", - "@shopgate/pwa-ui-shared": "6.3.2-rc.1", + "@shopgate/eslint-config": "6.3.2", + "@shopgate/pwa-common": "6.3.2", + "@shopgate/pwa-common-commerce": "6.3.2", + "@shopgate/pwa-core": "6.3.2", + "@shopgate/pwa-ui-shared": "6.3.2", "eslint": "^4.17.0", "prop-types": "^15.6.0", "react": "~16.3.2", diff --git a/lerna.json b/lerna.json index fd6d89a3b0..a5b7aaab37 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "lerna": "2.9.0", - "version": "6.3.2-rc.1", + "version": "6.3.2", "packages": [ "extensions/@shopgate-product-reviews/frontend", "extensions/@shopgate-tracking-ga-native/frontend", diff --git a/libraries/commerce/package.json b/libraries/commerce/package.json index e260d53db1..7a88294c57 100644 --- a/libraries/commerce/package.json +++ b/libraries/commerce/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-common-commerce", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Commerce library for the Shopgate Connect PWA.", "license": "Apache-2.0", "author": "Shopgate ", @@ -19,10 +19,10 @@ "reselect": "^3.0.1" }, "devDependencies": { - "@shopgate/pwa-common": "6.3.2-rc.1", - "@shopgate/pwa-core": "6.3.2-rc.1", - "@shopgate/pwa-unit-test": "6.3.2-rc.1", - "@shopgate/tracking-core": "6.3.2-rc.1", + "@shopgate/pwa-common": "6.3.2", + "@shopgate/pwa-core": "6.3.2", + "@shopgate/pwa-unit-test": "6.3.2", + "@shopgate/tracking-core": "6.3.2", "lodash": "^4.17.4", "react": "~16.6.0", "react-dom": "~16.6.0", diff --git a/libraries/common/package.json b/libraries/common/package.json index 217e1f2f87..4ab7ccb79e 100644 --- a/libraries/common/package.json +++ b/libraries/common/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-common", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Common library for the Shopgate Connect PWA.", "license": "Apache-2.0", "author": "Shopgate ", @@ -16,7 +16,7 @@ ], "dependencies": { "@sentry/browser": "^4.6.3", - "@shopgate/pwa-benchmark": "6.3.2-rc.1", + "@shopgate/pwa-benchmark": "6.3.2", "@virtuous/conductor": "~2.1.1", "@virtuous/react-conductor": "~2.1.1", "@virtuous/redux-persister": "1.1.0-beta.7", @@ -44,9 +44,9 @@ "url-search-params": "^0.10.0" }, "devDependencies": { - "@shopgate/eslint-config": "6.3.2-rc.1", + "@shopgate/eslint-config": "6.3.2", "@shopgate/pwa-benchmark": "6.0.0", - "@shopgate/pwa-core": "6.3.2-rc.1", + "@shopgate/pwa-core": "6.3.2", "lodash": "^4.17.4", "prop-types": "^15.6.0", "react": "~16.6.0", diff --git a/libraries/core/package.json b/libraries/core/package.json index c50d9412da..c630b4b753 100644 --- a/libraries/core/package.json +++ b/libraries/core/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-core", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Core library for the Shopgate Connect PWA.", "author": "Support ", "license": "Apache-2.0", diff --git a/libraries/tracking-core/package.json b/libraries/tracking-core/package.json index 048e65ea3b..1d12425e14 100644 --- a/libraries/tracking-core/package.json +++ b/libraries/tracking-core/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/tracking-core", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Tracking core library for the Shopgate Connect PWA.", "author": "Shopgate ", "license": "Apache-2.0", @@ -16,8 +16,8 @@ "connect" ], "devDependencies": { - "@shopgate/eslint-config": "6.3.2-rc.1", - "@shopgate/pwa-core": "6.3.2-rc.1", + "@shopgate/eslint-config": "6.3.2", + "@shopgate/pwa-core": "6.3.2", "chai": "^3.5.0", "jest": "^23.5.0", "jsdom": "9.8.3", diff --git a/libraries/tracking/package.json b/libraries/tracking/package.json index f81e81561b..a5ea451a07 100644 --- a/libraries/tracking/package.json +++ b/libraries/tracking/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-tracking", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Tracking library for the Shopgate Connect PWA.", "license": "Apache-2.0", "author": "Shopgate ", @@ -15,11 +15,11 @@ "connect" ], "devDependencies": { - "@shopgate/eslint-config": "6.3.2-rc.1", - "@shopgate/pwa-common": "6.3.2-rc.1", - "@shopgate/pwa-common-commerce": "6.3.2-rc.1", - "@shopgate/pwa-core": "6.3.2-rc.1", - "@shopgate/tracking-core": "6.3.2-rc.1", + "@shopgate/eslint-config": "6.3.2", + "@shopgate/pwa-common": "6.3.2", + "@shopgate/pwa-common-commerce": "6.3.2", + "@shopgate/pwa-core": "6.3.2", + "@shopgate/tracking-core": "6.3.2", "reselect": "^3.0.1", "rxjs": "^5.4.3" } diff --git a/libraries/ui-ios/package.json b/libraries/ui-ios/package.json index 394e02e3f1..b6a8dbc593 100644 --- a/libraries/ui-ios/package.json +++ b/libraries/ui-ios/package.json @@ -1,11 +1,11 @@ { "name": "@shopgate/pwa-ui-ios", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Shopgate's iOS UI components.", "main": "index.js", "license": "Apache-2.0", "devDependencies": { - "@shopgate/pwa-common": "6.3.2-rc.1", + "@shopgate/pwa-common": "6.3.2", "react": "~16.6.0" }, "peerDependencies": { diff --git a/libraries/ui-material/package.json b/libraries/ui-material/package.json index 3de840b2e5..9193a14e61 100644 --- a/libraries/ui-material/package.json +++ b/libraries/ui-material/package.json @@ -1,11 +1,11 @@ { "name": "@shopgate/pwa-ui-material", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Shopgate's material design UI components.", "main": "index.js", "license": "Apache-2.0", "devDependencies": { - "@shopgate/pwa-common": "6.3.2-rc.1", + "@shopgate/pwa-common": "6.3.2", "react": "~16.6.0" }, "dependencies": { diff --git a/libraries/ui-shared/package.json b/libraries/ui-shared/package.json index adbeb27c32..f8a4a7c91f 100644 --- a/libraries/ui-shared/package.json +++ b/libraries/ui-shared/package.json @@ -1,16 +1,16 @@ { "name": "@shopgate/pwa-ui-shared", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Shopgate's shared UI components.", "main": "index.js", "license": "Apache-2.0", "dependencies": { - "@shopgate/pwa-ui-ios": "6.3.2-rc.1", - "@shopgate/pwa-ui-material": "6.3.2-rc.1" + "@shopgate/pwa-ui-ios": "6.3.2", + "@shopgate/pwa-ui-material": "6.3.2" }, "devDependencies": { - "@shopgate/pwa-common": "6.3.2-rc.1", - "@shopgate/pwa-common-commerce": "6.3.2-rc.1", + "@shopgate/pwa-common": "6.3.2", + "@shopgate/pwa-common-commerce": "6.3.2", "react": "~16.6.0" }, "peerDependencies": { diff --git a/libraries/webcheckout/package.json b/libraries/webcheckout/package.json index 5feca00fdd..7981d7b04f 100644 --- a/libraries/webcheckout/package.json +++ b/libraries/webcheckout/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-webcheckout-shopify", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Webcheckout Shopify library for the Shopgate Connect PWA.", "license": "Apache-2.0", "author": "Shopgate ", @@ -17,8 +17,8 @@ "connect" ], "devDependencies": { - "@shopgate/pwa-common": "6.3.2-rc.1", - "@shopgate/pwa-core": "6.3.2-rc.1", + "@shopgate/pwa-common": "6.3.2", + "@shopgate/pwa-core": "6.3.2", "react": "~16.6.0" } } diff --git a/themes/theme-gmd/extension-config.json b/themes/theme-gmd/extension-config.json index 843845a0f4..e26419943e 100644 --- a/themes/theme-gmd/extension-config.json +++ b/themes/theme-gmd/extension-config.json @@ -1,5 +1,5 @@ { - "version": "6.3.2-rc.1", + "version": "6.3.2", "id": "@shopgate/theme-gmd", "configuration": { "appId": { diff --git a/themes/theme-gmd/package.json b/themes/theme-gmd/package.json index f3221e2437..c1ca65bf4e 100644 --- a/themes/theme-gmd/package.json +++ b/themes/theme-gmd/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/theme-gmd", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Google Material Design theme for the Shopgate Connect PWA.", "repository": "shopgate/theme-gmd", "bugs": "https://github.com/shopgate/theme-gmd/issues", @@ -16,14 +16,14 @@ "e2e:user": "cypress open -P ./e2e/extensions/user" }, "dependencies": { - "@shopgate/pwa-common": "6.3.2-rc.1", - "@shopgate/pwa-common-commerce": "6.3.2-rc.1", - "@shopgate/pwa-core": "6.3.2-rc.1", - "@shopgate/pwa-tracking": "6.3.2-rc.1", - "@shopgate/pwa-ui-material": "6.3.2-rc.1", - "@shopgate/pwa-ui-shared": "6.3.2-rc.1", - "@shopgate/pwa-webcheckout-shopify": "6.3.2-rc.1", - "@shopgate/tracking-core": "6.3.2-rc.1", + "@shopgate/pwa-common": "6.3.2", + "@shopgate/pwa-common-commerce": "6.3.2", + "@shopgate/pwa-core": "6.3.2", + "@shopgate/pwa-tracking": "6.3.2", + "@shopgate/pwa-ui-material": "6.3.2", + "@shopgate/pwa-ui-shared": "6.3.2", + "@shopgate/pwa-webcheckout-shopify": "6.3.2", + "@shopgate/tracking-core": "6.3.2", "@virtuous/conductor": "~2.1.1", "@virtuous/react-conductor": "~2.1.1", "babel-core": "^6.26.3", @@ -64,9 +64,9 @@ "smoothscroll-polyfill": "^0.4.3" }, "devDependencies": { - "@shopgate/eslint-config": "6.3.2-rc.1", - "@shopgate/pwa-e2e-test": "6.3.2-rc.1", - "@shopgate/pwa-unit-test": "6.3.2-rc.1", + "@shopgate/eslint-config": "6.3.2", + "@shopgate/pwa-e2e-test": "6.3.2", + "@shopgate/pwa-unit-test": "6.3.2", "coveralls": "^3.0.0", "eslint": "^4.17.0", "eslint-import-resolver-babel-module": "4.0.0", diff --git a/themes/theme-ios11/extension-config.json b/themes/theme-ios11/extension-config.json index 50031ee272..4a98389776 100644 --- a/themes/theme-ios11/extension-config.json +++ b/themes/theme-ios11/extension-config.json @@ -1,5 +1,5 @@ { - "version": "6.3.2-rc.1", + "version": "6.3.2", "id": "@shopgate/theme-ios11", "configuration": { "appId": { diff --git a/themes/theme-ios11/package.json b/themes/theme-ios11/package.json index 4e10646cf7..0e4e754c04 100644 --- a/themes/theme-ios11/package.json +++ b/themes/theme-ios11/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/theme-ios11", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "iOS11 theme for the Shopgate Connect PWA.", "repository": "shopgate/theme-ios11", "bugs": "https://github.com/shopgate/theme-ios11/issues", @@ -15,15 +15,15 @@ "e2e:checkout": "cypress open -P ./e2e/extensions/checkout" }, "dependencies": { - "@shopgate/pwa-common": "6.3.2-rc.1", - "@shopgate/pwa-common-commerce": "6.3.2-rc.1", - "@shopgate/pwa-core": "6.3.2-rc.1", - "@shopgate/pwa-tracking": "6.3.2-rc.1", - "@shopgate/pwa-ui-ios": "6.3.2-rc.1", - "@shopgate/pwa-ui-material": "6.3.2-rc.1", - "@shopgate/pwa-ui-shared": "6.3.2-rc.1", - "@shopgate/pwa-webcheckout-shopify": "6.3.2-rc.1", - "@shopgate/tracking-core": "6.3.2-rc.1", + "@shopgate/pwa-common": "6.3.2", + "@shopgate/pwa-common-commerce": "6.3.2", + "@shopgate/pwa-core": "6.3.2", + "@shopgate/pwa-tracking": "6.3.2", + "@shopgate/pwa-ui-ios": "6.3.2", + "@shopgate/pwa-ui-material": "6.3.2", + "@shopgate/pwa-ui-shared": "6.3.2", + "@shopgate/pwa-webcheckout-shopify": "6.3.2", + "@shopgate/tracking-core": "6.3.2", "@virtuous/conductor": "~2.1.1", "@virtuous/react-conductor": "~2.1.1", "babel-core": "^6.26.3", @@ -65,9 +65,9 @@ "smoothscroll-polyfill": "^0.4.3" }, "devDependencies": { - "@shopgate/eslint-config": "6.3.2-rc.1", - "@shopgate/pwa-e2e-test": "6.3.2-rc.1", - "@shopgate/pwa-unit-test": "6.3.2-rc.1", + "@shopgate/eslint-config": "6.3.2", + "@shopgate/pwa-e2e-test": "6.3.2", + "@shopgate/pwa-unit-test": "6.3.2", "coveralls": "^3.0.0", "eslint": "^4.17.0", "eslint-import-resolver-babel-module": "4.0.0", diff --git a/utils/benchmark/package.json b/utils/benchmark/package.json index 0766d69a17..88ce52e8d3 100644 --- a/utils/benchmark/package.json +++ b/utils/benchmark/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-benchmark", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Benchmark suite for PWA", "author": "Rene Eichhorn", "main": "index.js", diff --git a/utils/e2e/package.json b/utils/e2e/package.json index a605d7a0c1..1a6af2f4ae 100644 --- a/utils/e2e/package.json +++ b/utils/e2e/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-e2e-test", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "E2E test setup for the Shopgate Connect PWA.", "author": "Shopgate ", "license": "Apache-2.0" diff --git a/utils/eslint-config/package.json b/utils/eslint-config/package.json index ce1f0c43ac..a57b93881e 100644 --- a/utils/eslint-config/package.json +++ b/utils/eslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/eslint-config", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Eslint configuration for the Shopgate Connect projects.", "author": "Shopgate ", "license": "Apache-2.0", diff --git a/utils/unit-tests/package.json b/utils/unit-tests/package.json index f902e94ee4..47f39eb3a9 100644 --- a/utils/unit-tests/package.json +++ b/utils/unit-tests/package.json @@ -1,6 +1,6 @@ { "name": "@shopgate/pwa-unit-test", - "version": "6.3.2-rc.1", + "version": "6.3.2", "description": "Unit test setup for the Shopgate Connect PWA.", "author": "Shopgate ", "license": "Apache-2.0", @@ -14,7 +14,7 @@ "react-tap-event-plugin": "^3.0.2" }, "devDependencies": { - "@shopgate/eslint-config": "6.3.2-rc.1", + "@shopgate/eslint-config": "6.3.2", "jest": "^23.5.0", "react": "~16.6.0", "react-dom": "~16.6.0" From 91541d2095039e1cc23c096df2e35c4e6cc3cdb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frithjof=20Klo=CC=88s?= Date: Fri, 5 Apr 2019 16:00:07 +0200 Subject: [PATCH 07/11] PWA-1827 Introduced handled payload formats to the ScannerEventListener --- libraries/commerce/scanner/constants/index.js | 13 ++ libraries/commerce/scanner/streams/index.js | 7 +- .../commerce/scanner/streams/index.spec.js | 6 +- .../commerce/scanner/subscriptions/index.js | 6 +- .../scanner/subscriptions/index.spec.js | 35 +++++- libraries/core/classes/Scanner/index.js | 17 ++- libraries/core/classes/Scanner/index.spec.js | 10 ++ .../core/classes/ScannerEventHandler/index.js | 7 ++ .../classes/ScannerEventHandler/index.spec.js | 27 ++++ .../classes/ScannerEventListener/index.js | 43 +++++-- .../ScannerEventListener/index.spec.js | 115 ++++++++++++------ libraries/core/constants/Scanner.js | 13 -- libraries/tracking/helpers/index.js | 6 +- 13 files changed, 216 insertions(+), 89 deletions(-) diff --git a/libraries/commerce/scanner/constants/index.js b/libraries/commerce/scanner/constants/index.js index 662029992c..a84eaef605 100644 --- a/libraries/commerce/scanner/constants/index.js +++ b/libraries/commerce/scanner/constants/index.js @@ -16,3 +16,16 @@ export const QR_CODE_TYPE_SEARCH = 'b'; export const QR_CODE_TYPE_PAGE = '1'; export const QR_CODE_HOST_2DS = '2d.is'; + +export const SCANNER_FORMATS_BARCODE = [ + 'UPC_E', + 'CODE_39', + 'EAN_13', + 'EAN_8', + 'CODE_93', + 'CODE_128', + 'PDF_417', + 'ITF', +]; + +export const SCANNER_FORMATS_QR_CODE = ['QR_CODE']; diff --git a/libraries/commerce/scanner/streams/index.js b/libraries/commerce/scanner/streams/index.js index c836b891a9..52aa3dcd77 100644 --- a/libraries/commerce/scanner/streams/index.js +++ b/libraries/commerce/scanner/streams/index.js @@ -1,15 +1,12 @@ import { main$ } from '@shopgate/pwa-common/streams/main'; import { routeDidEnter$ } from '@shopgate/pwa-common/streams/router'; -import { - SCANNER_FORMATS_BARCODE, - SCANNER_FORMATS_QR_CODE, -} from '@shopgate/pwa-core/constants/Scanner'; - import { SCANNER_STARTED, SCANNER_CANCELLED, SCANNER_FINISHED, SCANNER_PATH, + SCANNER_FORMATS_BARCODE, + SCANNER_FORMATS_QR_CODE, } from '../constants'; /** @type {Observable} */ diff --git a/libraries/commerce/scanner/streams/index.spec.js b/libraries/commerce/scanner/streams/index.spec.js index 295253d5b9..c13de23d78 100644 --- a/libraries/commerce/scanner/streams/index.spec.js +++ b/libraries/commerce/scanner/streams/index.spec.js @@ -1,9 +1,5 @@ /* eslint-disable extra-rules/no-single-line-objects */ import { mainSubject } from '@shopgate/pwa-common/store/middelwares/streams'; -import { - SCANNER_FORMATS_BARCODE, - SCANNER_FORMATS_QR_CODE, -} from '@shopgate/pwa-core/constants/Scanner'; import { ROUTE_DID_ENTER } from '@shopgate/pwa-common/constants/ActionTypes'; import { scannerDidEnter$, @@ -18,6 +14,8 @@ import { SCANNER_FINISHED, SCANNER_STARTED, SCANNER_PATH, + SCANNER_FORMATS_BARCODE, + SCANNER_FORMATS_QR_CODE, } from '../constants'; describe('scanner streams', () => { diff --git a/libraries/commerce/scanner/subscriptions/index.js b/libraries/commerce/scanner/subscriptions/index.js index 12edb2fb26..a8a0862c6a 100644 --- a/libraries/commerce/scanner/subscriptions/index.js +++ b/libraries/commerce/scanner/subscriptions/index.js @@ -5,11 +5,15 @@ import { appDidStart$ } from '@shopgate/pwa-common/streams'; import scannerFinished from '../action-creators/scannerFinished'; import handleBarCode from '../actions/handleBarCode'; import handleQrCode from '../actions/handleQrCode'; +import { SCANNER_FORMATS_BARCODE, SCANNER_FORMATS_QR_CODE } from '../constants'; import { scannerFinishedBarCode$, scannerFinishedQrCode$, } from '../streams'; +// Scanner payload formats which are handled by the subscriptions. +export const handledFormats = [...SCANNER_FORMATS_BARCODE, ...SCANNER_FORMATS_QR_CODE]; + /** * Scanner subscriptions. * @param {Function} subscribe The subscribe function. @@ -17,7 +21,7 @@ import { export default (subscribe) => { // Register global listener to convert to stream subscribe(appDidStart$, ({ dispatch }) => { - Scanner.addListener(new ScannerEventListener('Scanner listener') + Scanner.addListener(new ScannerEventListener('Scanner listener', null, null, handledFormats) .setHandler(({ scope, payload: { format, code: payload } = {} }) => { dispatch(scannerFinished(scope, format, payload)); })); diff --git a/libraries/commerce/scanner/subscriptions/index.spec.js b/libraries/commerce/scanner/subscriptions/index.spec.js index 92efa3e7ea..30396d7d82 100644 --- a/libraries/commerce/scanner/subscriptions/index.spec.js +++ b/libraries/commerce/scanner/subscriptions/index.spec.js @@ -6,7 +6,7 @@ import { appDidStart$ } from '@shopgate/pwa-common/streams'; import scannerFinished from '../action-creators/scannerFinished'; import handleBarCode from '../actions/handleBarCode'; import handleQrCode from '../actions/handleQrCode'; -import subscriptions from './index'; +import subscriptions, { handledFormats } from './index'; jest.mock('@shopgate/pwa-core/classes/Scanner', () => ({ addListener: jest.fn(), @@ -22,11 +22,14 @@ describe('scanner subscriptions', () => { const subscribe = jest.fn(); const dispatch = jest.fn(); - // Event from scanner - const mockedEvent = new ScannerEvent( + /** + * @param {string} [format='EAN_13'] The event format. + * @returns {ScannerEvent} + */ + const createMockedEvent = (format = 'EAN_13') => new ScannerEvent( SCANNER_SCOPE_DEFAULT, SCANNER_TYPE_BARCODE, - { format: 'EAN_13', code: '0000000000000' } + { format, code: '0000000000000' } ); let appDidStartStream$; @@ -61,17 +64,37 @@ describe('scanner subscriptions', () => { expect(appDidStartCallback).toBeInstanceOf(Function); }); - it('should dispatch mapped ScannerEvent action', () => { + it('should dispatch mapped ScannerEvent action', async () => { appDidStartCallback({ dispatch }); expect(Scanner.addListener).toHaveBeenCalledTimes(1); const [[listenerActual]] = Scanner.addListener.mock.calls; expect(listenerActual.handler).toBeInstanceOf(Function); - listenerActual.handler(mockedEvent); + await listenerActual.notify(createMockedEvent()); // Expect event to be mapped to stream expect(scannerFinished).toBeCalledWith(SCANNER_SCOPE_DEFAULT, 'EAN_13', '0000000000000'); }); + + it('should dispatch mapped ScannerEvent action for every supported format', async () => { + appDidStartCallback({ dispatch }); + const [[listenerActual]] = Scanner.addListener.mock.calls; + + const events = handledFormats + .map(format => listenerActual.handler(createMockedEvent(format))); + + await Promise.all(events); + + expect(scannerFinished).toHaveBeenCalledTimes(handledFormats.length); + }); + + it('should not dispatch mapped ScannerEvent action for an unsupported format', async () => { + appDidStartCallback({ dispatch }); + const [[listenerActual]] = Scanner.addListener.mock.calls; + await listenerActual.notify(createMockedEvent('unknown')); + + expect(scannerFinished).not.toHaveBeenCalled(); + }); }); describe('scanFinishedBarCode subscription', () => { diff --git a/libraries/core/classes/Scanner/index.js b/libraries/core/classes/Scanner/index.js index 7dd49c7d19..a17d14d846 100644 --- a/libraries/core/classes/Scanner/index.js +++ b/libraries/core/classes/Scanner/index.js @@ -266,21 +266,28 @@ export class Scanner { * @param {ScannerEventPayload} payload The payload of the scanner event for the scanned result. */ handleScan = async (payload) => { + const event = new ScannerEvent( + this.scope, + this.type, + payload + ); + + if (!this.eventHandler.hasListenersForEvent(event)) { + return; + } + if (this.handling) { logger.warn('Scan result ignored in handling stage', payload); return; } + this.handling = true; this.stop(); try { // Ignore return values from handlers. - await this.eventHandler.notifyAllListeners(new ScannerEvent( - this.scope, - this.type, - payload - )); + await this.eventHandler.notifyAllListeners(event); // Notify the close handler that the Scanner is done doing his work. if (this.closeHandler) { diff --git a/libraries/core/classes/Scanner/index.spec.js b/libraries/core/classes/Scanner/index.spec.js index 2262ca3c7c..dfcd95c5e6 100644 --- a/libraries/core/classes/Scanner/index.spec.js +++ b/libraries/core/classes/Scanner/index.spec.js @@ -407,14 +407,17 @@ describe('Scanner', () => { code: 'code', }; const closeHandlerMock = jest.fn(); + let hasListenersForEventMock; beforeEach(async () => { await scannerInstance.open(scope, type, closeHandlerMock); + hasListenersForEventMock = jest.spyOn(scannerInstance.eventHandler, 'hasListenersForEvent').mockReturnValue(true); }); it('should forward a ScannerEvent to the event handler', async () => { let result = null; const mockedNotifyAllListeners = jest.fn((e) => { result = e; }); + scannerInstance.eventHandler.notifyAllListeners = mockedNotifyAllListeners; await scannerInstance.handleScan(payload); @@ -441,6 +444,13 @@ describe('Scanner', () => { expect(scannerInstance.start).toBeCalledTimes(1); }); + it('should not run when no suitable event listener was registered', async () => { + hasListenersForEventMock.mockReturnValueOnce(false); + const result = await scannerInstance.handleScan(payload); + expect(result).toBeUndefined(); + expect(scannerInstance.handling).toBeFalsy(); + }); + it('should not be running after a successful scan if not restarted', async () => { const stopSpy = jest.spyOn(scannerInstance, 'stop'); await scannerInstance.handleScan(payload); diff --git a/libraries/core/classes/ScannerEventHandler/index.js b/libraries/core/classes/ScannerEventHandler/index.js index 9f19f65153..31fb808945 100644 --- a/libraries/core/classes/ScannerEventHandler/index.js +++ b/libraries/core/classes/ScannerEventHandler/index.js @@ -22,6 +22,13 @@ export default class ScannerEventHandler { */ detach = eventListener => this.eventListeners.delete(eventListener); + /** + * @param {ScannerEvent} event The event which has been emitted by the scanner. + * @returns {boolean} + */ + hasListenersForEvent = event => + Array.from(this.eventListeners).some(listener => listener.canHandleEvent(event)); + /** * @param {ScannerEvent} event The event which has been emitted by the scanner. * @returns {Promise} diff --git a/libraries/core/classes/ScannerEventHandler/index.spec.js b/libraries/core/classes/ScannerEventHandler/index.spec.js index d952e0d541..dc28a81059 100644 --- a/libraries/core/classes/ScannerEventHandler/index.spec.js +++ b/libraries/core/classes/ScannerEventHandler/index.spec.js @@ -2,6 +2,7 @@ import ScannerEventHandler from './index'; import ScannerEventListener from '../ScannerEventListener'; import ScannerEvent from '../ScannerEvent'; +jest.mock('@shopgate/pwa-core/classes/AppCommand'); // Prevent console output of the logger jest.mock('../../helpers', () => ({ logger: { @@ -80,6 +81,32 @@ describe('ScannerEventHandler', () => { }); }); + describe('hasListenersForEvent(format)', () => { + it('should return true when listeners are registered for a passed format', () => { + const format = 'format'; + const otherFormat = 'otherFormat'; + eventHandler.attach(new ScannerEventListener(null, 'scope', 'type', [format]) + .setHandler(() => { })); + eventHandler.attach(new ScannerEventListener(null, null, null, [otherFormat]) + .setHandler(() => { })); + + const event = new ScannerEvent('scope', 'type', { format }); + const result = eventHandler.hasListenersForEvent(event); + expect(result).toBe(true); + }); + + it('should return false when no listeners are registered for a passed format', () => { + const format = 'format'; + const otherFormat = 'otherFormat'; + eventHandler.attach(new ScannerEventListener(null, 'scope', 'type', [format]) + .setHandler(() => { })); + + const event = new ScannerEvent('scope', 'type', { format: otherFormat }); + const result = eventHandler.hasListenersForEvent(event); + expect(result).toBe(false); + }); + }); + describe('notifyAllListeners(event)', () => { const mockPayload = { format: 'format', diff --git a/libraries/core/classes/ScannerEventListener/index.js b/libraries/core/classes/ScannerEventListener/index.js index 7f29376efb..db261a96b7 100644 --- a/libraries/core/classes/ScannerEventListener/index.js +++ b/libraries/core/classes/ScannerEventListener/index.js @@ -9,11 +9,13 @@ class ScannerEventListener { * @param {string|null} name A name for the listener object to refer to. * @param {string|null} scope The scanner scope to listen for. * @param {string|null} type THe type of scanner events to listen for. + * @param {Array} formats The formats which can be processed by the listener. */ - constructor(name = null, scope = null, type = null) { + constructor(name = null, scope = null, type = null, formats = []) { this.name = name || 'unnamed'; this.scope = scope || null; this.type = type || null; + this.formats = formats || []; this.handler = null; } @@ -39,6 +41,34 @@ class ScannerEventListener { return this; } + /** + * Checks if the event fits to the handler. + * @param {ScannerEvent} event The scanner event which was emitted. + * @returns {boolean} + */ + canHandleEvent = (event) => { + if (!this.handler) { + logger.warn(`No event handler defined for eventListener "${this.name}"`); + return false; + } + + if (this.type && this.type !== event.getType()) { + return false; + } + + if (this.scope && this.scope !== event.getScope()) { + return false; + } + + const { format } = event.getPayload() || {}; + + if (this.formats.length && !this.formats.includes(format)) { + return false; + } + + return true; + }; + /** * Attach the current event listener to the app scanner. */ @@ -51,16 +81,7 @@ class ScannerEventListener { * @param {ScannerEvent} event The scanner event which was emitted. */ notify = async (event) => { - if (!this.handler) { - logger.warn(`No event handler defined for eventListener "${this.name}"`); - return; - } - - // Skip handling if the events scope or type don't fit to the handler - if (this.type && this.type !== event.type) { - return; - } - if (this.scope && this.scope !== event.scope) { + if (!this.canHandleEvent(event)) { return; } diff --git a/libraries/core/classes/ScannerEventListener/index.spec.js b/libraries/core/classes/ScannerEventListener/index.spec.js index 4f332d5403..1c5c136f82 100644 --- a/libraries/core/classes/ScannerEventListener/index.spec.js +++ b/libraries/core/classes/ScannerEventListener/index.spec.js @@ -3,6 +3,7 @@ import ScannerEvent from '../ScannerEvent'; import AppScanner from '../Scanner'; import { logger } from '../../helpers'; +jest.mock('@shopgate/pwa-core/classes/AppCommand'); jest.mock('../../helpers', () => ({ logger: { error: jest.fn(), @@ -96,74 +97,103 @@ describe('ScannerEventListener', () => { }); }); - describe('notify(event)', () => { + describe('canHandleEvent(event)', () => { const mockPayload = { format: 'format', code: 'code', }; - it('should print a warning if no handlers are attached', async () => { + it('should return false and print a warning if no handlers are attached', () => { const l = new ScannerEventListener(); - await l.notify(null); - + const result = l.canHandleEvent(null); + expect(result).toBe(false); expect(logger.warn).toBeCalledTimes(1); }); - it('should print a warning if the custom handler returns a value', async () => { - const customHandler = jest.fn(() => 'Some return-value'); - const l = new ScannerEventListener(name).setHandler(customHandler); - await l.notify(new ScannerEvent('scope', 'type', mockPayload)); - - expect(logger.warn).toBeCalledTimes(1); - }); - - it('should call the handler on every event for "global" listeners', async () => { - const customHandler = jest.fn(); + it('should return true on every event for "global" listeners', () => { const listenScope = null; const listenType = null; const differentScope = 'different-scope'; const differentType = 'different-type'; - const l = new ScannerEventListener(name, listenScope, listenType).setHandler(customHandler); - await l.notify(new ScannerEvent(differentScope, differentType, mockPayload)); + const l = new ScannerEventListener(name, listenScope, listenType).setHandler(() => {}); + const result = l.canHandleEvent(new ScannerEvent(differentScope, differentType, mockPayload)); - expect(customHandler).toBeCalled(); + expect(result).toBe(true); }); - it('should forward the event to the handler', async () => { - const customHandler = jest.fn(); - const listenScope = null; - const listenType = null; + it('should return the correct values for specific event scopes only', () => { + const listenScope = 'interesting-scope'; const differentScope = 'different-scope'; + const anyType = 'any-type'; + const l = new ScannerEventListener(name, listenScope).setHandler(() => {}); + const result = [ + l.canHandleEvent(new ScannerEvent(listenScope, anyType, mockPayload)), + l.canHandleEvent(new ScannerEvent(differentScope, anyType, mockPayload)), + ]; + + expect(result).toEqual([true, false]); + }); + + it('should return the correct values for specific event types only', () => { + const listenType = 'interesting-type'; const differentType = 'different-type'; - const l = new ScannerEventListener(name, listenScope, listenType).setHandler(customHandler); - const e = new ScannerEvent(differentScope, differentType, mockPayload); - await l.notify(e); + const anyScope = 'any-scope'; + const l = new ScannerEventListener(name, null, listenType).setHandler(() => {}); + const result = [ + l.canHandleEvent(new ScannerEvent(anyScope, listenType, mockPayload)), + l.canHandleEvent(new ScannerEvent(anyScope, differentType, mockPayload)), + ]; - expect(customHandler).toBeCalledWith(e); + expect(result).toEqual([true, false]); }); - it('should call the handler for specific event scopes only', async () => { - const customHandler = jest.fn(); + it('should return the correct values for specific event scope/type combinations only', () => { const listenScope = 'interesting-scope'; + const listenType = 'interesting-type'; const differentScope = 'different-scope'; - const anyType = 'any-type'; - const l = new ScannerEventListener(name, listenScope).setHandler(customHandler); - await l.notify(new ScannerEvent(listenScope, anyType, mockPayload)); - await l.notify(new ScannerEvent(differentScope, anyType, mockPayload)); + const differentType = 'different-type'; + const l = new ScannerEventListener(name, listenScope, listenType).setHandler(() => {}); + const result = [ + l.canHandleEvent(new ScannerEvent(listenScope, listenType, mockPayload)), + l.canHandleEvent(new ScannerEvent(listenScope, differentType, mockPayload)), + l.canHandleEvent(new ScannerEvent(differentScope, listenType, mockPayload)), + l.canHandleEvent(new ScannerEvent(differentScope, differentType, mockPayload)), + ]; - expect(customHandler).toBeCalledTimes(1); + expect(result).toEqual([true, false, false, false]); }); - it('should call the handler for specific event types only', async () => { - const customHandler = jest.fn(); + it('should return the correct values for specific payload format combinations only ', () => { + const listenScope = 'interesting-scope'; const listenType = 'interesting-type'; - const differentType = 'different-type'; - const anyScope = 'any-scope'; - const l = new ScannerEventListener(name, null, listenType).setHandler(customHandler); - await l.notify(new ScannerEvent(anyScope, listenType, mockPayload)); - await l.notify(new ScannerEvent(anyScope, differentType, mockPayload)); + const listenFormats = ['format']; + const l = new ScannerEventListener(name, listenScope, listenType, listenFormats) + .setHandler(() => { }); - expect(customHandler).toBeCalledTimes(1); + const result = [ + l.canHandleEvent(new ScannerEvent(listenScope, listenType, mockPayload)), + l.canHandleEvent(new ScannerEvent(listenScope, listenType, { + ...mockPayload, + format: 'otherFormat', + })), + ]; + + expect(result).toEqual([true, false]); + }); + }); + + describe('notify(event)', () => { + const mockPayload = { + format: 'format', + code: 'code', + }; + + it('should print a warning if the custom handler returns a value', async () => { + const customHandler = jest.fn(() => 'Some return-value'); + const l = new ScannerEventListener(name).setHandler(customHandler); + await l.notify(new ScannerEvent('scope', 'type', mockPayload)); + + expect(logger.warn).toBeCalledTimes(1); }); it('should call the handler for specific event scope/type combinations only', async () => { @@ -179,6 +209,11 @@ describe('ScannerEventListener', () => { await l.notify(new ScannerEvent(differentScope, differentType, mockPayload)); expect(customHandler).toBeCalledTimes(1); + const [[event]] = customHandler.mock.calls; + expect(event).toBeInstanceOf(ScannerEvent); + expect(event.getScope()).toBe(listenScope); + expect(event.getType()).toBe(listenType); + expect(event.getPayload()).toEqual(mockPayload); }); it('should forward the handler error to the caller', async () => { diff --git a/libraries/core/constants/Scanner.js b/libraries/core/constants/Scanner.js index 4df6121071..ac3c833ade 100644 --- a/libraries/core/constants/Scanner.js +++ b/libraries/core/constants/Scanner.js @@ -58,17 +58,4 @@ export const SCANNER_TYPE_IMAGE = 'imageCapturing'; */ export const SCANNER_SCOPE_DEFAULT = 'default'; -export const SCANNER_FORMATS_BARCODE = [ - 'UPC_E', - 'CODE_39', - 'EAN_13', - 'EAN_8', - 'CODE_93', - 'CODE_128', - 'PDF_417', - 'ITF', -]; - -export const SCANNER_FORMATS_QR_CODE = ['QR_CODE']; - export const SCANNER_MIN_APP_LIB_VERSION = '21.0'; diff --git a/libraries/tracking/helpers/index.js b/libraries/tracking/helpers/index.js index bd20b5282b..31d687c929 100644 --- a/libraries/tracking/helpers/index.js +++ b/libraries/tracking/helpers/index.js @@ -1,10 +1,6 @@ import get from 'lodash/get'; import find from 'lodash/find'; import { logger } from '@shopgate/pwa-core/helpers'; -import { - SCANNER_FORMATS_BARCODE, - SCANNER_FORMATS_QR_CODE, -} from '@shopgate/pwa-core/constants/Scanner'; import { QR_CODE_TYPE_HOMEPAGE, QR_CODE_TYPE_PRODUCT, @@ -13,6 +9,8 @@ import { QR_CODE_TYPE_CATEGORY, QR_CODE_TYPE_SEARCH, QR_CODE_TYPE_PAGE, + SCANNER_FORMATS_BARCODE, + SCANNER_FORMATS_QR_CODE, } from '@shopgate/pwa-common-commerce/scanner/constants'; import { parse2dsQrCode } from '@shopgate/pwa-common-commerce/scanner/helpers'; import core from '@shopgate/tracking-core/core/Core'; From 2a15e19d90cb6406d0cd6857ae1cfdf2c844543f Mon Sep 17 00:00:00 2001 From: "O.Bilenko" Date: Fri, 5 Apr 2019 16:29:46 +0200 Subject: [PATCH 08/11] PWA-1809 Decode, encode product id and coupon --- libraries/commerce/scanner/helpers/index.js | 9 +++++---- libraries/commerce/scanner/helpers/index.spec.js | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libraries/commerce/scanner/helpers/index.js b/libraries/commerce/scanner/helpers/index.js index 314a857641..c6affd14ea 100644 --- a/libraries/commerce/scanner/helpers/index.js +++ b/libraries/commerce/scanner/helpers/index.js @@ -31,13 +31,14 @@ const typeParsers = { [QR_CODE_TYPE_PRODUCT_WITH_COUPON]: (url) => { const [,,, paramTwo, paramThree] = url.pathname.split('/'); - const decodedParamTwo = decodeURIComponent(paramTwo); + const decodedParamTwo = decodeURIComponent(decodeURIComponent(paramTwo)); + const decodedParamThree = decodeURIComponent(decodeURIComponent(paramThree)); return { - link: `/cart_add_product/${decodedParamTwo}/${paramThree}`, + link: `/cart_add_product/${encodeURIComponent(decodedParamTwo)}/${encodeURIComponent(decodedParamThree)}`, data: { - productId: decodeURIComponent(decodedParamTwo), - couponCode: paramThree, + productId: decodedParamTwo, + couponCode: decodedParamThree, }, }; }, diff --git a/libraries/commerce/scanner/helpers/index.spec.js b/libraries/commerce/scanner/helpers/index.spec.js index b21c681e1e..4fef405bba 100644 --- a/libraries/commerce/scanner/helpers/index.spec.js +++ b/libraries/commerce/scanner/helpers/index.spec.js @@ -55,11 +55,11 @@ describe('scanner helpers', () => { }); it('should parse add product with coupon link', () => { - const result = parse2dsQrCode(`http://${QR_CODE_HOST_2DS}/9/30186/345%252F34%2523/TEST-CODE?s=26`); + const result = parse2dsQrCode(`http://${QR_CODE_HOST_2DS}/9/30186/345%252F34%2523/TEST%252FCODE%2523?s=26`); expect(result).toEqual({ - link: '/cart_add_product/345%2F34%23/TEST-CODE', + link: '/cart_add_product/345%2F34%23/TEST%2FCODE%23', type: QR_CODE_TYPE_PRODUCT_WITH_COUPON, - data: { productId: '345/34#', couponCode: 'TEST-CODE' }, + data: { productId: '345/34#', couponCode: 'TEST/CODE#' }, }); }); From d52a94bbd1b574b73db437ba3600b98ce5de84b1 Mon Sep 17 00:00:00 2001 From: "O.Bilenko" Date: Mon, 8 Apr 2019 09:04:51 +0200 Subject: [PATCH 09/11] PWA-1827 Log not handled scanner event --- libraries/core/classes/Scanner/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/core/classes/Scanner/index.js b/libraries/core/classes/Scanner/index.js index a17d14d846..bb155fa0d0 100644 --- a/libraries/core/classes/Scanner/index.js +++ b/libraries/core/classes/Scanner/index.js @@ -273,6 +273,7 @@ export class Scanner { ); if (!this.eventHandler.hasListenersForEvent(event)) { + logger.warn('No scanner listeners', payload); return; } From ae64ac0550bbf962a06b1394f428f9fed5442933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frithjof=20Klo=CC=88s?= Date: Mon, 8 Apr 2019 13:27:20 +0200 Subject: [PATCH 10/11] Bugfix for wrong scanner tracking --- libraries/tracking/helpers/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/tracking/helpers/index.js b/libraries/tracking/helpers/index.js index 31d687c929..c676a514d3 100644 --- a/libraries/tracking/helpers/index.js +++ b/libraries/tracking/helpers/index.js @@ -252,7 +252,7 @@ export const buildScannerUtmUrl = ({ const { location } = scannerRoute; - const newPath = new URL(`scanner://${location}`); + const newPath = new URL(location, 'http://scanner.com'); const utms = { utm_source: source, From a095d94946470348fbfd7bca1b56af59383da086 Mon Sep 17 00:00:00 2001 From: "O.Bilenko" Date: Tue, 9 Apr 2019 16:50:27 +0200 Subject: [PATCH 11/11] PWA-1849 Engage Cart: Keep shipping costs selector --- libraries/commerce/cart/selectors/index.js | 17 ++++++++++++++++- .../components/ShippingCosts/connector.js | 4 ++-- .../components/ShippingCosts/connector.js | 4 ++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/libraries/commerce/cart/selectors/index.js b/libraries/commerce/cart/selectors/index.js index a974f084a1..ecad71fd49 100644 --- a/libraries/commerce/cart/selectors/index.js +++ b/libraries/commerce/cart/selectors/index.js @@ -167,11 +167,26 @@ export const getGrandTotal = createSelector( * Selects the shipping costs. * @returns {Object} */ -export const getShippingCosts = createSelector( +export const getShippingCost = createSelector( getTotals, totals => totals.find(total => total.type === CART_TOTALS_TYPE_SHIPPING) || null ); +/** + * Selects the summed up shipping costs of the cart. + * @returns {number} + */ +export const getShippingCosts = createSelector( + getShippingCost, + (shippingCost) => { + if (!shippingCost) { + return null; + } + const { amount = 0 } = shippingCost; + return amount; + } +); + /** * Selects the tax value of the cart. * @returns {Object} diff --git a/themes/theme-gmd/pages/Cart/components/PaymentBar/components/Content/components/ShippingCosts/connector.js b/themes/theme-gmd/pages/Cart/components/PaymentBar/components/Content/components/ShippingCosts/connector.js index b1b14321fe..f7e81bfc08 100644 --- a/themes/theme-gmd/pages/Cart/components/PaymentBar/components/Content/components/ShippingCosts/connector.js +++ b/themes/theme-gmd/pages/Cart/components/PaymentBar/components/Content/components/ShippingCosts/connector.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux'; -import { getShippingCosts } from '@shopgate/pwa-common-commerce/cart/selectors'; +import { getShippingCost } from '@shopgate/pwa-common-commerce/cart/selectors'; /** * Maps the contents of the state to the component props. @@ -7,7 +7,7 @@ import { getShippingCosts } from '@shopgate/pwa-common-commerce/cart/selectors'; * @return {Object} The extended component props. */ const mapStateToProps = state => ({ - shippingCost: getShippingCosts(state), + shippingCost: getShippingCost(state), }); export default connect(mapStateToProps); diff --git a/themes/theme-ios11/pages/Cart/components/PaymentBar/components/Content/components/ShippingCosts/connector.js b/themes/theme-ios11/pages/Cart/components/PaymentBar/components/Content/components/ShippingCosts/connector.js index b1b14321fe..f7e81bfc08 100644 --- a/themes/theme-ios11/pages/Cart/components/PaymentBar/components/Content/components/ShippingCosts/connector.js +++ b/themes/theme-ios11/pages/Cart/components/PaymentBar/components/Content/components/ShippingCosts/connector.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux'; -import { getShippingCosts } from '@shopgate/pwa-common-commerce/cart/selectors'; +import { getShippingCost } from '@shopgate/pwa-common-commerce/cart/selectors'; /** * Maps the contents of the state to the component props. @@ -7,7 +7,7 @@ import { getShippingCosts } from '@shopgate/pwa-common-commerce/cart/selectors'; * @return {Object} The extended component props. */ const mapStateToProps = state => ({ - shippingCost: getShippingCosts(state), + shippingCost: getShippingCost(state), }); export default connect(mapStateToProps);