From a0ca9fdb42fe60cc64a100abfccca5696bdef21f Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Tue, 29 Oct 2019 13:28:07 -0500 Subject: [PATCH 01/17] Added tests for setupWorkbox.js --- .../__tests__/setupWorkbox.spec.js | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 packages/venia-concept/src/ServiceWorker/__tests__/setupWorkbox.spec.js diff --git a/packages/venia-concept/src/ServiceWorker/__tests__/setupWorkbox.spec.js b/packages/venia-concept/src/ServiceWorker/__tests__/setupWorkbox.spec.js new file mode 100644 index 0000000000..7999d2c131 --- /dev/null +++ b/packages/venia-concept/src/ServiceWorker/__tests__/setupWorkbox.spec.js @@ -0,0 +1,68 @@ +import setupWorkbox from '../setupWorkbox'; + +beforeEach(() => { + global.workbox = { + core: { + skipWaiting: () => {}, + clientsClaim: () => {} + }, + precaching: { + precacheAndRoute: () => {} + } + }; + global.importScripts = () => {}; +}); + +test('importScripts should be called to fetch workbox-sw.js file', () => { + const importScripts = jest.spyOn(global, 'importScripts'); + + setupWorkbox(); + + expect(importScripts).toHaveBeenCalledWith( + expect.stringContaining('workbox-sw.js') + ); +}); + +test('skipWaiting should be called on workbox.core object', () => { + const skipWaiting = jest.spyOn(global.workbox.core, 'skipWaiting'); + + setupWorkbox(); + + expect(skipWaiting).toHaveBeenCalled(); +}); + +test('clientsClaim should be called on workbox.core object', () => { + const clientsClaim = jest.spyOn(global.workbox.core, 'clientsClaim'); + + setupWorkbox(); + + expect(clientsClaim).toHaveBeenCalled(); +}); + +test('precacheAndRoute should be called with self.__precacheManifest is a truthy value', () => { + const precacheAndRoute = jest.spyOn( + global.workbox.precaching, + 'precacheAndRoute' + ); + + const testObj = {}; + + self.__precacheManifest = testObj; + + setupWorkbox(); + + expect(precacheAndRoute).toHaveBeenCalledWith(testObj); +}); + +test('precacheAndRoute should be called with [] if self.__precacheManifest is a falsey value', () => { + const precacheAndRoute = jest.spyOn( + global.workbox.precaching, + 'precacheAndRoute' + ); + + self.__precacheManifest = null; + + setupWorkbox(); + + expect(precacheAndRoute).toHaveBeenCalledWith([]); +}); From dda04068993db9276acee2ab8ff0b261245db322 Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Tue, 29 Oct 2019 15:52:19 -0500 Subject: [PATCH 02/17] Added tests for registerRoutes.js --- .../__tests__/registerRoutes.spec.js | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 packages/venia-concept/src/ServiceWorker/__tests__/registerRoutes.spec.js diff --git a/packages/venia-concept/src/ServiceWorker/__tests__/registerRoutes.spec.js b/packages/venia-concept/src/ServiceWorker/__tests__/registerRoutes.spec.js new file mode 100644 index 0000000000..d4450d5ee0 --- /dev/null +++ b/packages/venia-concept/src/ServiceWorker/__tests__/registerRoutes.spec.js @@ -0,0 +1,105 @@ +import { THIRTY_DAYS, MAX_NUM_OF_IMAGES_TO_CACHE } from '../defaults'; +import registerRoutes from '../registerRoutes'; + +function StaleWhileRevalidate(options = {}) { + this.cacheName = options.cacheName; + this.plugins = options.plugins; +} + +function CacheFirst(options = {}) { + this.cacheName = options.cacheName; + this.plugins = options.plugins; +} + +function cacheableResponsePlugin() {} + +function expirationPlugin(options = {}) { + this.maxEntries = options.maxEntries; + this.maxAgeSeconds = options.maxAgeSeconds; +} + +beforeAll(() => { + global.workbox = { + strategies: { + StaleWhileRevalidate, + CacheFirst + }, + cacheableResponse: { + Plugin: cacheableResponsePlugin + }, + expiration: { + Plugin: expirationPlugin + }, + routing: { + registerRoute: function() {} + } + }; +}); + +test("A total of 5 routes need to be registered using workbox's registerRoute API", () => { + const registerRoute = jest.spyOn(global.workbox.routing, 'registerRoute'); + + registerRoutes(); + + expect(registerRoute).toHaveBeenCalledTimes(5); + + registerRoute.mockClear(); +}); + +test('There should be a route for robots.txt, favicon.ico and manifest.json with StaleWhileRevalidate strategy', () => { + const registerRoute = jest.spyOn(global.workbox.routing, 'registerRoute'); + + registerRoutes(); + + const [registrationCall] = registerRoute.mock.calls.filter( + call => + call[0].toString() === + new RegExp('(robots.txt|favicon.ico|manifest.json)').toString() + ); + + expect(registrationCall[1]).toBeInstanceOf(StaleWhileRevalidate); + + registerRoute.mockClear(); +}); + +test('There should be a route for all image types with CacheFirst strategy', () => { + const registerRoute = jest.spyOn(global.workbox.routing, 'registerRoute'); + + registerRoutes(); + + const [registrationCall] = registerRoute.mock.calls.filter( + call => + call[0].toString() === + new RegExp(/\.(?:png|gif|jpg|jpeg|svg)$/).toString() + ); + + expect(registrationCall[1]).toBeInstanceOf(CacheFirst); + expect(registrationCall[1].cacheName).toBe('images'); + expect(registrationCall[1].plugins[0]).toBeInstanceOf(expirationPlugin); + expect(registrationCall[1].plugins[0].maxEntries).toBe( + MAX_NUM_OF_IMAGES_TO_CACHE + ); + expect(registrationCall[1].plugins[0].maxAgeSeconds).toBe(THIRTY_DAYS); + + registerRoute.mockClear(); +}); + +test('There should be a route for all js files with CacheFirst strategy', () => { + const registerRoute = jest.spyOn(global.workbox.routing, 'registerRoute'); + + registerRoutes(); + + const [registrationCall] = registerRoute.mock.calls.filter( + call => call[0].toString() === new RegExp(/\.js$/).toString() + ); + + expect(registrationCall[1]).toBeInstanceOf(CacheFirst); + + console.log(registerRoute.mock.calls); + + console.log('\n\n\n\n'); + + console.log(registerRoute.mock.calls.reverse()[0]); + + registerRoute.mockClear(); +}); From 2a06bbc25745a97e476f9745528d31d6286a0661 Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Tue, 29 Oct 2019 15:53:19 -0500 Subject: [PATCH 03/17] Minor change. --- .../src/ServiceWorker/__tests__/registerRoutes.spec.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/venia-concept/src/ServiceWorker/__tests__/registerRoutes.spec.js b/packages/venia-concept/src/ServiceWorker/__tests__/registerRoutes.spec.js index d4450d5ee0..9b84743caf 100644 --- a/packages/venia-concept/src/ServiceWorker/__tests__/registerRoutes.spec.js +++ b/packages/venia-concept/src/ServiceWorker/__tests__/registerRoutes.spec.js @@ -95,11 +95,5 @@ test('There should be a route for all js files with CacheFirst strategy', () => expect(registrationCall[1]).toBeInstanceOf(CacheFirst); - console.log(registerRoute.mock.calls); - - console.log('\n\n\n\n'); - - console.log(registerRoute.mock.calls.reverse()[0]); - registerRoute.mockClear(); }); From 016453c9dc9031b84f66aa0668db2e4b8f15be75 Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Wed, 30 Oct 2019 15:23:08 -0500 Subject: [PATCH 04/17] Added tests for HTML route checking. --- .../__tests__/registerRoutes.spec.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/packages/venia-concept/src/ServiceWorker/__tests__/registerRoutes.spec.js b/packages/venia-concept/src/ServiceWorker/__tests__/registerRoutes.spec.js index 9b84743caf..1e991e110c 100644 --- a/packages/venia-concept/src/ServiceWorker/__tests__/registerRoutes.spec.js +++ b/packages/venia-concept/src/ServiceWorker/__tests__/registerRoutes.spec.js @@ -1,4 +1,5 @@ import { THIRTY_DAYS, MAX_NUM_OF_IMAGES_TO_CACHE } from '../defaults'; +import { cacheHTMLPlugin } from '../Utilities/htmlHandler'; import registerRoutes from '../registerRoutes'; function StaleWhileRevalidate(options = {}) { @@ -97,3 +98,26 @@ test('There should be a route for all js files with CacheFirst strategy', () => registerRoute.mockClear(); }); + +test('There should be a route for all HTML routes with StaleWhileRevalidate strategy', () => { + const registerRoute = jest.spyOn(global.workbox.routing, 'registerRoute'); + + registerRoutes(); + + /** + * This is a crude way to find the route by searching for + * isHTMLRoute function in the .toString() output, but I am + * out of options at this point. + * + * Obviously there might be a better way to do it just that I + * am not aware of it at this point. Feel free to change it. + */ + const [registrationCall] = registerRoute.mock.calls.filter(call => + call[0].toString().includes('isHTMLRoute') + ); + + expect(registrationCall[1]).toBeInstanceOf(StaleWhileRevalidate); + expect(registrationCall[1].plugins).toEqual([cacheHTMLPlugin]); + + registerRoute.mockClear(); +}); From e243176ebbef7daaa719ea49fc4cda40c06b9b49 Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Wed, 30 Oct 2019 15:59:50 -0500 Subject: [PATCH 05/17] Added tests for isResizedCatalogImage in imageCacheHandler.js --- .../__tests__/imageCacheHandler.spec.js | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 packages/venia-concept/src/ServiceWorker/Utilities/__tests__/imageCacheHandler.spec.js diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/imageCacheHandler.spec.js b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/imageCacheHandler.spec.js new file mode 100644 index 0000000000..ff13b9d770 --- /dev/null +++ b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/imageCacheHandler.spec.js @@ -0,0 +1,44 @@ +import { isResizedCatalogImage } from '../imageCacheHandler'; + +describe('Testing isResizedCatalogImage', () => { + const validCatalogImageURL = + 'https://develop.pwa-venia.com/media/catalog/product/cache/6ff2031bbe5bd4726a5a91896c8bef9e/v/d/vd07-pe_main_2.jpg?auto=webp&format=pjpg&width=640&height=800'; + + const catalogImageURLWithInvalidWidth = + 'https://develop.pwa-venia.com/media/catalog/product/cache/6ff2031bbe5bd4726a5a91896c8bef9e/v/d/vd07-pe_main_2.jpg?auto=webp&format=pjpg&width=640px&height=800px'; + + const invalidCatalogImageURL = + 'https://develop.pwa-venia.com/product/cache/6ff2031bbe5bd4726a5a91896c8bef9e/v/d/vd07-pe_main_2.jpg?auto=webp&format=pjpg&width=640&height=800'; + + test('isResizedCatalogImage should return boolean', () => { + expect( + typeof isResizedCatalogImage({ url: new URL(validCatalogImageURL) }) + ).toBe('boolean'); + }); + + test('isResizedCatalogImage should return true if the url provided is a valid catalog image url', () => { + expect( + isResizedCatalogImage({ url: new URL(validCatalogImageURL) }) + ).toBeTruthy(); + }); + + test('isResizedCatalogImage should return false if /media/catalog is missing in the URL', () => { + expect( + isResizedCatalogImage({ + url: new URL(invalidCatalogImageURL) + }) + ).toBeFalsy(); + }); + + test('isResizedCatalogImage should return false if width search param is not valid in the URL', () => { + expect( + isResizedCatalogImage({ + url: new URL(catalogImageURLWithInvalidWidth) + }) + ).toBeFalsy(); + }); + + test('isResizedCatalogImage should throw error if url is missing in the function params', () => { + expect(() => isResizedCatalogImage()).toThrowError(); + }); +}); From 842aeed3129f0fcd03888dee447c0db7729cdcf5 Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Tue, 5 Nov 2019 15:29:09 -0600 Subject: [PATCH 06/17] Added tests for findSameOrLargerImage of imageCacheHandler.js --- .../__tests__/imageCacheHandler.spec.js | 71 ++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/imageCacheHandler.spec.js b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/imageCacheHandler.spec.js index ff13b9d770..eac3c6d01d 100644 --- a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/imageCacheHandler.spec.js +++ b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/imageCacheHandler.spec.js @@ -1,4 +1,7 @@ -import { isResizedCatalogImage } from '../imageCacheHandler'; +import { + isResizedCatalogImage, + findSameOrLargerImage +} from '../imageCacheHandler'; describe('Testing isResizedCatalogImage', () => { const validCatalogImageURL = @@ -42,3 +45,69 @@ describe('Testing isResizedCatalogImage', () => { expect(() => isResizedCatalogImage()).toThrowError(); }); }); + +/** + * @jest-environment jest-environment-jsdom-fourteen + */ +describe('Testing findSameOrLargerImage', () => { + beforeAll(() => { + global.caches = { + open: function() { + return Promise.resolve({ + matchAll: function() { + return Promise.resolve([ + { + url: + 'https://develop.pwa-venia.com/media/catalog/v/s/vsk12-la_main_3.jpg?auto=webp&format=pjpg&width=160&height=200' + }, + { + url: + 'https://develop.pwa-venia.com/media/catalog/v/s/vsk12-la_main_3.jpg?auto=webp&format=pjpg&width=320&height=400' + }, + { + url: + 'https://develop.pwa-venia.com/media/catalog/v/s/vsk12-la_main_3.jpg?auto=webp&format=pjpg&width=1600&height=2000' + } + ]); + } + }); + } + }; + }); + + test('Should return response from cache for same URL if available', async () => { + const expectedUrl = + 'https://develop.pwa-venia.com/media/catalog/v/s/vsk12-la_main_3.jpg?auto=webp&format=pjpg&width=1600&height=2000'; + + const returnedResponse = await findSameOrLargerImage( + new URL(expectedUrl) + ); + + expect(returnedResponse.url).toBe(expectedUrl); + }); + + test('Should return the closest high resolution image response from cache for a given width', async () => { + const requestedUrl = + 'https://develop.pwa-venia.com/media/catalog/v/s/vsk12-la_main_3.jpg?auto=webp&format=pjpg&width=800&height=1000'; + + const expectedUrl = + 'https://develop.pwa-venia.com/media/catalog/v/s/vsk12-la_main_3.jpg?auto=webp&format=pjpg&width=1600&height=2000'; + + const returnedResponse = await findSameOrLargerImage( + new URL(requestedUrl) + ); + + expect(returnedResponse.url).toBe(expectedUrl); + }); + + test('Should return undefined if no closest high resolution image response is available in cache', async () => { + const requestedUrl = + 'https://develop.pwa-venia.com/media/catalog/v/s/vsk12-la_main_3.jpg?auto=webp&format=pjpg&width=2400&height=3000'; + + const returnedResponse = await findSameOrLargerImage( + new URL(requestedUrl) + ); + + expect(returnedResponse).toBe(undefined); + }); +}); From 5717d4b3fee4ba104a05d56ab023e55e620172e6 Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Tue, 5 Nov 2019 15:29:56 -0600 Subject: [PATCH 07/17] Minor change. --- .../Utilities/__tests__/imageCacheHandler.spec.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/imageCacheHandler.spec.js b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/imageCacheHandler.spec.js index eac3c6d01d..875a860fbc 100644 --- a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/imageCacheHandler.spec.js +++ b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/imageCacheHandler.spec.js @@ -46,9 +46,6 @@ describe('Testing isResizedCatalogImage', () => { }); }); -/** - * @jest-environment jest-environment-jsdom-fourteen - */ describe('Testing findSameOrLargerImage', () => { beforeAll(() => { global.caches = { From dda774093269b9442583354144339dd5b7d71cd4 Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Tue, 5 Nov 2019 16:02:05 -0600 Subject: [PATCH 08/17] Added tests for createCatalogCacheHandler --- .../__tests__/catalogCacheHandler.spec.js | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 packages/venia-concept/src/ServiceWorker/Utilities/__tests__/catalogCacheHandler.spec.js diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/catalogCacheHandler.spec.js b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/catalogCacheHandler.spec.js new file mode 100644 index 0000000000..cf69e20494 --- /dev/null +++ b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/catalogCacheHandler.spec.js @@ -0,0 +1,46 @@ +import { THIRTY_DAYS, CATALOG_CACHE_NAME } from '../../defaults'; +import { createCatalogCacheHandler } from '../catalogCacheHandler'; + +function StaleWhileRevalidate(options = {}) { + this.cacheName = options.cacheName; + this.plugins = options.plugins; +} + +function CacheableResponsePlugin() {} + +function ExpirationPlugin(options = {}) { + this.maxEntries = options.maxEntries; + this.maxAgeSeconds = options.maxAgeSeconds; +} + +beforeAll(() => { + global.workbox = { + strategies: { + StaleWhileRevalidate + }, + cacheableResponse: { + Plugin: CacheableResponsePlugin + }, + expiration: { + Plugin: ExpirationPlugin + } + }; +}); + +test('createCatalogCacheHandler should return an instance of workbox.strategies.StaleWhileRevalidate', () => { + expect(createCatalogCacheHandler()).toBeInstanceOf(StaleWhileRevalidate); +}); + +test('createCatalogCacheHandler should generate handler with cacheName set to the value of CATALOG_CACHE_NAME', () => { + expect(createCatalogCacheHandler().cacheName).toBe(CATALOG_CACHE_NAME); +}); + +test('createCatalogCacheHandler should generate handler with the exipiration plugin', () => { + const handler = createCatalogCacheHandler(); + const [expirationPlugin] = handler.plugins.filter( + plugin => plugin instanceof ExpirationPlugin + ); + + expect(expirationPlugin.maxEntries).toBe(60); + expect(expirationPlugin.maxAgeSeconds).toBe(THIRTY_DAYS); +}); From bac3e48e2b70e8827653630fcb08b09059b91277 Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Wed, 6 Nov 2019 10:02:46 -0600 Subject: [PATCH 09/17] Another test for catalogCacheHandler.js --- .../Utilities/__tests__/catalogCacheHandler.spec.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/catalogCacheHandler.spec.js b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/catalogCacheHandler.spec.js index cf69e20494..bb9304b466 100644 --- a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/catalogCacheHandler.spec.js +++ b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/catalogCacheHandler.spec.js @@ -6,7 +6,9 @@ function StaleWhileRevalidate(options = {}) { this.plugins = options.plugins; } -function CacheableResponsePlugin() {} +function CacheableResponsePlugin(options = {}) { + this.statuses = options.statuses; +} function ExpirationPlugin(options = {}) { this.maxEntries = options.maxEntries; @@ -44,3 +46,12 @@ test('createCatalogCacheHandler should generate handler with the exipiration plu expect(expirationPlugin.maxEntries).toBe(60); expect(expirationPlugin.maxAgeSeconds).toBe(THIRTY_DAYS); }); + +test('createCatalogCacheHandler should use the cacheable response plugin for statuses 0 and 200', () => { + const handler = createCatalogCacheHandler(); + const [cacheableResponsePlugin] = handler.plugins.filter( + plugin => plugin instanceof CacheableResponsePlugin + ); + + expect(cacheableResponsePlugin.statuses).toEqual([0, 200]); +}); From 07e27455c938429af5a8c2801c126b848e87ce3a Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Wed, 6 Nov 2019 12:40:13 -0600 Subject: [PATCH 10/17] Added tests for htmlHandler.js --- .../Utilities/__tests__/htmlHandler.spec.js | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 packages/venia-concept/src/ServiceWorker/Utilities/__tests__/htmlHandler.spec.js diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/htmlHandler.spec.js b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/htmlHandler.spec.js new file mode 100644 index 0000000000..1b50b2cd8b --- /dev/null +++ b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/htmlHandler.spec.js @@ -0,0 +1,55 @@ +jest.mock('../messageHandler'); + +import { cacheHTMLPlugin } from '../htmlHandler'; + +const matchFn = jest.fn(); + +beforeAll(() => { + global.caches = { + match: matchFn + }; + global.Request = function(url, { method, headers } = {}) { + this.url = url; + this.method = method; + this.headers = headers; + }; + global.Response = function() {}; +}); + +test('cacheHTMLPlugin should have cacheKeyWillBeUsed, requestWillFetch, fetchDidSucceed async functions implemented', () => { + matchFn.mockReturnValue(Promise.resolve(null)); + + expect(cacheHTMLPlugin).toHaveProperty('cacheKeyWillBeUsed'); + expect(cacheHTMLPlugin).toHaveProperty('requestWillFetch'); + expect(cacheHTMLPlugin).toHaveProperty('fetchDidSucceed'); + + expect(cacheHTMLPlugin.cacheKeyWillBeUsed).toBeInstanceOf(Function); + expect(cacheHTMLPlugin.requestWillFetch).toBeInstanceOf(Function); + expect(cacheHTMLPlugin.fetchDidSucceed).toBeInstanceOf(Function); + + expect(cacheHTMLPlugin.cacheKeyWillBeUsed()).toBeInstanceOf(Promise); + expect( + cacheHTMLPlugin.requestWillFetch({ + request: new Request('https://develop.pwa-venia.com/') + }) + ).toBeInstanceOf(Promise); + expect( + cacheHTMLPlugin.fetchDidSucceed({ + request: new Request('https://develop.pwa-venia.com/'), + response: new Response() + }) + ).toBeInstanceOf(Promise); +}); + +test('cacheKeyWillBeUsed function should return a promise that resolves to /', async () => { + const response = await cacheHTMLPlugin.cacheKeyWillBeUsed(); + + expect(response).toBe('/'); +}); + +test('requestWillFetch should return a new Request with url set to /', async () => { + const request = new Request('https://develop.pwa-venia.com/'); + const response = await cacheHTMLPlugin.requestWillFetch({ request }); + + expect(response.url).not.toBe(request.url); +}); From 8daefa649699fbe6f8a09b88badf2dbd2b124d41 Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Wed, 6 Nov 2019 13:43:48 -0600 Subject: [PATCH 11/17] Added tests for fetchDidSucceed function of cacheHTMLPlugin. --- .../Utilities/__tests__/htmlHandler.spec.js | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/htmlHandler.spec.js b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/htmlHandler.spec.js index 1b50b2cd8b..b6ba227f64 100644 --- a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/htmlHandler.spec.js +++ b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/htmlHandler.spec.js @@ -1,6 +1,9 @@ jest.mock('../messageHandler'); +import { HTML_UPDATE_AVAILABLE } from '@magento/venia-ui/lib/constants/swMessageTypes'; + import { cacheHTMLPlugin } from '../htmlHandler'; +import { sendMessageToWindow } from '../messageHandler'; const matchFn = jest.fn(); @@ -16,6 +19,10 @@ beforeAll(() => { global.Response = function() {}; }); +beforeEach(() => { + sendMessageToWindow.mockClear(); +}); + test('cacheHTMLPlugin should have cacheKeyWillBeUsed, requestWillFetch, fetchDidSucceed async functions implemented', () => { matchFn.mockReturnValue(Promise.resolve(null)); @@ -53,3 +60,82 @@ test('requestWillFetch should return a new Request with url set to /', async () expect(response.url).not.toBe(request.url); }); + +test('fetchDidSucceed should return the same response object given to it in params', async () => { + const request = new Request('https://develop.pwa-venia.com/'); + const response = new Response(); + + const returnedResponse = await cacheHTMLPlugin.fetchDidSucceed({ + request, + response + }); + + expect(returnedResponse).toBe(response); +}); + +test('fetchDidSucceed should not call sendMessageToWindow if the cache does not have a response for the url', async () => { + const request = new Request('https://develop.pwa-venia.com/'); + const response = new Response(); + + await cacheHTMLPlugin.fetchDidSucceed({ + request, + response + }); + + expect(sendMessageToWindow).not.toHaveBeenCalled(); +}); + +test('fetchDidSucceed should call sendMessageToWindow if the response is different from what is in the cache', async () => { + /** + * Mocking Request to return different value when .text is called. + */ + global.Response.prototype.text = function() { + return Promise.resolve( + `Hey I am random text ${Math.random() + .toString() + .slice(2)}` + ); + }; + global.Response.prototype.clone = function() { + return new Response(); + }; + + /** + * Mocking cache to have a response for 'https://develop.pwa-venia.com/' + */ + matchFn.mockReturnValue(Promise.resolve(new Response())); + + const url = 'https://develop.pwa-venia.com/'; + const request = new Request(url); + const response = new Response(); + + await cacheHTMLPlugin.fetchDidSucceed({ request, response }); + + expect(sendMessageToWindow).toHaveBeenCalledTimes(1); + expect(sendMessageToWindow).toHaveBeenCalledWith(HTML_UPDATE_AVAILABLE); +}); + +test('fetchDidSucceed should not call sendMessageToWindow if the response if same as that in the cache', async () => { + /** + * Mocking Request to return same value when .text is called. + */ + global.Response.prototype.text = function() { + return Promise.resolve('Hey I am same text'); + }; + global.Response.prototype.clone = function() { + return new Response(); + }; + + /** + * Mocking cache to have a response for 'https://develop.pwa-venia.com/' + */ + matchFn.mockReturnValue(Promise.resolve(new Response())); + + const url = 'https://develop.pwa-venia.com/'; + const request = new Request(url); + const response = new Response(); + + await cacheHTMLPlugin.fetchDidSucceed({ request, response }); + + expect(sendMessageToWindow).not.toHaveBeenCalled(); +}); From f84f0b4ac7e43a0d2583096320cd287982e6e9e1 Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Wed, 6 Nov 2019 15:26:58 -0600 Subject: [PATCH 12/17] Added tests for routeHandler.js --- .../Utilities/__tests__/routeHandler.spec.js | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 packages/venia-concept/src/ServiceWorker/Utilities/__tests__/routeHandler.spec.js diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/routeHandler.spec.js b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/routeHandler.spec.js new file mode 100644 index 0000000000..0a07ed8ec9 --- /dev/null +++ b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/routeHandler.spec.js @@ -0,0 +1,34 @@ +import { isHTMLRoute, isHomeRoute } from '../routeHandler'; + +const homePageUrl = 'https://develop.pwa-venia.com/'; +const urlWithHTML = 'https://develop.pwa-venia.com/isodora-skirt.html'; +const nonHTMLRoute = + 'https://magento-venia-concept-7bnnn.local.pwadev:9914/media/'; + +test('isHomeRoute should return boolean', () => { + expect(typeof isHomeRoute(new URL(homePageUrl))).toBe('boolean'); +}); + +test("isHomeRoute should return true if route's pathname is /", () => { + expect(isHomeRoute(new URL(homePageUrl))).toBeTruthy(); +}); + +test("isHomeRoute should return false if route's pathname is not /", () => { + expect(isHomeRoute(new URL(urlWithHTML))).toBeFalsy(); +}); + +test('isHTMLRoute should return boolean', () => { + expect(typeof isHTMLRoute(new URL(urlWithHTML))).toBe('boolean'); +}); + +test("isHTMLRoute should return true if route's pathname has .html", () => { + expect(isHTMLRoute(new URL(urlWithHTML))).toBeTruthy(); +}); + +test("isHTMLRoute should return false if route's pathname does not have .html", () => { + expect(isHTMLRoute(new URL(nonHTMLRoute))).toBeFalsy(); +}); + +test('isHTMLRoute should return true for home route', () => { + expect(isHTMLRoute(new URL(homePageUrl))).toBeTruthy(); +}); From a18f183fab1c87e3675a089df52e912ff18213e1 Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Wed, 6 Nov 2019 15:58:03 -0600 Subject: [PATCH 13/17] Added named export __handlers__ for testing purposes. --- .../src/ServiceWorker/Utilities/messageHandler.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js b/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js index bfcaa09d07..cbdf34ac52 100644 --- a/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js +++ b/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js @@ -9,6 +9,11 @@ */ const handlers = {}; +/** + * Exporting for testing purposes + */ +export const __handlers__ = handlers; + /** * * registerMessageHandler is a Util that registers a From 174bed4d67095019e5f758b033afe2d0dda1a588 Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Wed, 6 Nov 2019 15:58:19 -0600 Subject: [PATCH 14/17] Added tests for registerMessageHandler --- .../__tests__/messageHandler.spec.js | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 packages/venia-concept/src/ServiceWorker/Utilities/__tests__/messageHandler.spec.js diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/messageHandler.spec.js b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/messageHandler.spec.js new file mode 100644 index 0000000000..370e002161 --- /dev/null +++ b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/messageHandler.spec.js @@ -0,0 +1,61 @@ +import { __handlers__, registerMessageHandler } from '../messageHandler'; + +describe('Testing registerMessageHandler', () => { + const messageType = 'HELLO_WORLD'; + const handler = () => {}; + + function clearHandlersObject() { + Object.keys(__handlers__).forEach(messageType => { + delete __handlers__[messageType]; + }); + } + + afterEach(() => { + clearHandlersObject(); + }); + + test('registerMessageHandler should return function', () => { + expect(registerMessageHandler(messageType, handler)).toBeInstanceOf( + Function + ); + }); + + test('registerMessageHandler should add a message handler for a given type in the handlers object', () => { + registerMessageHandler(messageType, handler); + + expect(__handlers__).toHaveProperty(messageType); + expect(__handlers__[messageType]).toBeInstanceOf(Array); + expect(__handlers__[messageType]).toHaveLength(1); + expect(__handlers__[messageType]).toContain(handler); + }); + + test('registerMessageHandler should return function which when called should un-register handler', () => { + const unregisterHelloWorld = registerMessageHandler( + messageType, + handler + ); + + unregisterHelloWorld(); + + expect(__handlers__[messageType]).not.toContain(handler); + }); + + test("registerMessageHandler's return function should only unregister the function it registered", () => { + const unregisterHelloWorld = registerMessageHandler( + messageType, + handler + ); + + const anotherHandler = () => {}; + + registerMessageHandler(messageType, anotherHandler); + + expect(__handlers__[messageType]).toContain(handler); + expect(__handlers__[messageType]).toContain(anotherHandler); + + unregisterHelloWorld(); + + expect(__handlers__[messageType]).not.toContain(handler); + expect(__handlers__[messageType]).toContain(anotherHandler); + }); +}); From 2fc1475633a37da5b3d1238b3b62b3a13fb73a2a Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Thu, 7 Nov 2019 14:44:03 -0600 Subject: [PATCH 15/17] Added more tests for messageHandler.js --- .../__tests__/messageHandler.spec.js | 284 +++++++++++++++++- .../ServiceWorker/Utilities/messageHandler.js | 8 +- 2 files changed, 279 insertions(+), 13 deletions(-) diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/messageHandler.spec.js b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/messageHandler.spec.js index 370e002161..82f1d96703 100644 --- a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/messageHandler.spec.js +++ b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/messageHandler.spec.js @@ -1,19 +1,27 @@ -import { __handlers__, registerMessageHandler } from '../messageHandler'; +import { + __handlers__, + registerMessageHandler, + unRegisterMessageHandler, + handleMessageFromClient, + sendMessageToClient, + sendMessageToWindow +} from '../messageHandler'; -describe('Testing registerMessageHandler', () => { - const messageType = 'HELLO_WORLD'; - const handler = () => {}; +const messageType = 'HELLO_WORLD'; - function clearHandlersObject() { - Object.keys(__handlers__).forEach(messageType => { - delete __handlers__[messageType]; - }); - } +const handler = () => {}; - afterEach(() => { - clearHandlersObject(); +function clearHandlersObject() { + Object.keys(__handlers__).forEach(messageType => { + delete __handlers__[messageType]; }); +} + +afterEach(() => { + clearHandlersObject(); +}); +describe('Testing registerMessageHandler', () => { test('registerMessageHandler should return function', () => { expect(registerMessageHandler(messageType, handler)).toBeInstanceOf( Function @@ -59,3 +67,257 @@ describe('Testing registerMessageHandler', () => { expect(__handlers__[messageType]).toContain(anotherHandler); }); }); + +describe('Testing unRegisterMessageHandler', () => { + test('unRegisterMessageHandler should remove a handler for a given type', () => { + const anotherHandler = () => {}; + __handlers__[messageType] = [handler, anotherHandler]; + + unRegisterMessageHandler(messageType, handler); + + expect(__handlers__[messageType]).not.toContain(handler); + expect(__handlers__[messageType]).toContain(anotherHandler); + }); + + test('unRegisterMessageHandler should not modify the handlers object if the given handler is not part of it', () => { + const anotherHandler = () => {}; + __handlers__[messageType] = [handler]; + + const handlersBefore = __handlers__[messageType]; + + unRegisterMessageHandler(messageType, anotherHandler); + + expect(__handlers__[messageType]).toEqual(handlersBefore); + }); + + test('unRegisterMessageHandler should not modify __handlers__ if the given messageType is not registered', () => { + const anotherHandler = () => {}; + __handlers__[messageType] = [handler]; + + const handlersBefore = { ...__handlers__ }; + + unRegisterMessageHandler('TEST', anotherHandler); + + expect(__handlers__).toEqual(handlersBefore); + }); +}); + +describe('Testing handleMessageFromClient', () => { + test('handleMessageFromClient should call all registered handlers for a given messageType', () => { + const payload = {}; + const event = {}; + const handler1 = jest.fn(); + const handler2 = jest.fn(); + + registerMessageHandler(messageType, handler1); + registerMessageHandler(messageType, handler2); + + handleMessageFromClient(messageType, payload, event); + + expect(handler1).toHaveBeenCalledWith(payload, event); + expect(handler2).toHaveBeenCalledWith(payload, event); + }); + + test('handleMessageFromClient should call all registered handlers in the same order of registration (First in First called)', () => { + const payload = {}; + const event = {}; + const log = []; + const handler1 = () => { + log.push('handler1 called'); + }; + const handler2 = () => { + log.push('handler2 called'); + }; + + registerMessageHandler(messageType, handler1); + registerMessageHandler(messageType, handler2); + + handleMessageFromClient(messageType, payload, event); + + expect(log).toEqual(['handler1 called', 'handler2 called']); + }); +}); + +describe('Testing sendMessageToClient', () => { + function Port() { + this.onmessage = null; + } + + beforeEach(() => { + global.MessageChannel = function MessageChannel() { + this.port1 = new Port(); + this.port2 = new Port(); + + this.port1.postMessage = event => { + this.port2.onmessage && this.port2.onmessage(event); + }; + + this.port2.postMessage = event => { + this.port1.onmessage && this.port1.onmessage(event); + }; + }; + }); + + test('sendMessageToClient should return a Promise', () => { + expect( + sendMessageToClient({ postMessage: () => {} }, messageType, {}) + ).toBeInstanceOf(Promise); + }); + + test('sendMessageToClient should reject if the client does not have postMessage function defined', async () => { + await expect( + sendMessageToClient({ type: 'worker' }, messageType, {}) + ).rejects.toBe('Unable to send message to worker'); + }); + + test('sendMessageToClient should call the postMessage function on client with type, payload and a port to reply back', () => { + const port2 = new Port(); + global.MessageChannel = function MessageChannel() { + this.port1 = new Port(); + this.port2 = port2; + }; + const postMessage = jest.fn(); + const client = { postMessage }; + const payload = {}; + + sendMessageToClient(client, messageType, payload); + + expect(postMessage).toHaveBeenCalledWith( + { type: messageType, payload }, + [port2] + ); + }); + + test('sendMessageToClient should register onmessage handler on port1 of the channel to listen for replies from client', async () => { + const replyMessage = 'MESSAGE_RECEIVED'; + const postMessage = jest.fn(); + const client = { postMessage }; + + const reply = sendMessageToClient(client, messageType, {}); + + const [portToReplyToClient] = postMessage.mock.calls[0][1]; + + portToReplyToClient.postMessage({ data: replyMessage }); + + await expect(reply).resolves.toBe(replyMessage); + }); + + test('sendMessageToClient should resolve promise with data sent back by the client in the reply', async () => { + const replyData = { + messageType: 'MESSAGE_RECEIVED', + payload: {} + }; + const postMessage = jest.fn(); + const client = { postMessage }; + + const reply = sendMessageToClient(client, messageType, {}); + + const [portToReplyToClient] = postMessage.mock.calls[0][1]; + + portToReplyToClient.postMessage({ data: replyData }); + + await expect(reply).resolves.toBe(replyData); + }); + + test('sendMessageToClient should reject promise with error sent back from the client', async () => { + const replyData = { + error: 'Unable to read message!!!' + }; + const postMessage = jest.fn(); + const client = { postMessage }; + + const reply = sendMessageToClient(client, messageType, {}); + + const [portToReplyToClient] = postMessage.mock.calls[0][1]; + + portToReplyToClient.postMessage({ data: replyData }); + + await expect(reply).rejects.toBe(replyData.error); + }); +}); + +describe('Testing sendMessageToWindow', () => { + const windowPostMessage = jest.fn(); + const workerPostMessage = jest.fn(); + + function Port() { + this.onmessage = null; + } + + beforeEach(() => { + global.MessageChannel = function MessageChannel() { + this.port1 = new Port(); + this.port2 = new Port(); + + this.port1.postMessage = event => { + this.port2.onmessage && this.port2.onmessage(event); + }; + + this.port2.postMessage = event => { + this.port1.onmessage && this.port1.onmessage(event); + }; + }; + global.clients = { + matchAll: () => + Promise.resolve([ + { + type: 'window', + postMessage: windowPostMessage + }, + { + type: 'worker', + postMessage: workerPostMessage + } + ]) + }; + }); + + afterEach(() => { + windowPostMessage.mockClear(); + workerPostMessage.mockClear(); + }); + + test('sendMessageToWindow should return a Promise', () => { + expect(sendMessageToWindow(messageType, {})).toBeInstanceOf(Promise); + }); + + test('sendMessageToWindow should reject if the window client does not have postMessage function defined', async () => { + global.clients = { + matchAll: () => + Promise.resolve([ + { + type: 'window' + }, + { + type: 'worker', + postMessage: workerPostMessage + } + ]) + }; + + await expect(sendMessageToWindow(messageType, {})).rejects.toBe( + 'Unable to send message to window' + ); + }); + + test('sendMessageToWindow should call the postMessage function on window with type, payload and a port to reply back', () => { + const port2 = new Port(); + global.MessageChannel = function MessageChannel() { + this.port1 = new Port(); + this.port2 = port2; + }; + const payload = {}; + + sendMessageToWindow(messageType, payload); + + return new Promise(resolve => { + setTimeout(() => { + expect(windowPostMessage).toHaveBeenCalledWith( + { type: messageType, payload }, + [port2] + ); + resolve(); + }, 0); + }); + }); +}); diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js b/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js index cbdf34ac52..cda0e4d822 100644 --- a/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js +++ b/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js @@ -101,7 +101,7 @@ export const sendMessageToClient = (client, type, payload) => * channel.port1 is the port for the channel creator to use * to send a message to the receiver. * - * channel.port2 is the port for the message received to use + * channel.port2 is the port for the message receiver to use * to communicate to the channel creator. */ @@ -114,7 +114,11 @@ export const sendMessageToClient = (client, type, payload) => } }; - client.postMessage({ type, payload }, [channel.port2]); + if (client && client.postMessage) { + client.postMessage({ type, payload }, [channel.port2]); + } else { + reject(`Unable to send message to ${client.type}`); + } }); /** From 9a76a90263c55a9ba4f72a40b461557995555beb Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Tue, 12 Nov 2019 11:50:48 -0600 Subject: [PATCH 16/17] PR Changes. --- .../Utilities/__tests__/htmlHandler.spec.js | 30 +++++++++++++++---- .../ServiceWorker/Utilities/messageHandler.js | 2 +- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/htmlHandler.spec.js b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/htmlHandler.spec.js index b6ba227f64..3e5b504fef 100644 --- a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/htmlHandler.spec.js +++ b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/htmlHandler.spec.js @@ -19,10 +19,6 @@ beforeAll(() => { global.Response = function() {}; }); -beforeEach(() => { - sendMessageToWindow.mockClear(); -}); - test('cacheHTMLPlugin should have cacheKeyWillBeUsed, requestWillFetch, fetchDidSucceed async functions implemented', () => { matchFn.mockReturnValue(Promise.resolve(null)); @@ -58,7 +54,7 @@ test('requestWillFetch should return a new Request with url set to /', async () const request = new Request('https://develop.pwa-venia.com/'); const response = await cacheHTMLPlugin.requestWillFetch({ request }); - expect(response.url).not.toBe(request.url); + expect(response.url).toBe('/'); }); test('fetchDidSucceed should return the same response object given to it in params', async () => { @@ -86,6 +82,12 @@ test('fetchDidSucceed should not call sendMessageToWindow if the cache does not }); test('fetchDidSucceed should call sendMessageToWindow if the response is different from what is in the cache', async () => { + /** + * Collecting functions on prototype to restore after tests are done. + */ + const originalText = global.Response.prototype.text; + const originalClone = global.Response.prototype.clone; + /** * Mocking Request to return different value when .text is called. */ @@ -113,9 +115,21 @@ test('fetchDidSucceed should call sendMessageToWindow if the response is differe expect(sendMessageToWindow).toHaveBeenCalledTimes(1); expect(sendMessageToWindow).toHaveBeenCalledWith(HTML_UPDATE_AVAILABLE); + + /** + * Restoring prototype function definitions + */ + global.Response.prototype.text = originalText; + global.Response.prototype.clone = originalClone; }); test('fetchDidSucceed should not call sendMessageToWindow if the response if same as that in the cache', async () => { + /** + * Collecting functions on prototype to restore after tests are done. + */ + const originalText = global.Response.prototype.text; + const originalClone = global.Response.prototype.clone; + /** * Mocking Request to return same value when .text is called. */ @@ -138,4 +152,10 @@ test('fetchDidSucceed should not call sendMessageToWindow if the response if sam await cacheHTMLPlugin.fetchDidSucceed({ request, response }); expect(sendMessageToWindow).not.toHaveBeenCalled(); + + /** + * Restoring prototype function definitions + */ + global.Response.prototype.text = originalText; + global.Response.prototype.clone = originalClone; }); diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js b/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js index cda0e4d822..49e54a61dc 100644 --- a/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js +++ b/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js @@ -117,7 +117,7 @@ export const sendMessageToClient = (client, type, payload) => if (client && client.postMessage) { client.postMessage({ type, payload }, [channel.port2]); } else { - reject(`Unable to send message to ${client.type}`); + reject(`Unable to send message to ${client}`); } }); From 724e0854f986e852576b661801c81f5269de6adf Mon Sep 17 00:00:00 2001 From: Revanth Kumar Date: Tue, 12 Nov 2019 12:08:38 -0600 Subject: [PATCH 17/17] Minor. --- .../Utilities/__tests__/messageHandler.spec.js | 6 ++++++ .../src/ServiceWorker/Utilities/messageHandler.js | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/messageHandler.spec.js b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/messageHandler.spec.js index 82f1d96703..e28d8c5272 100644 --- a/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/messageHandler.spec.js +++ b/packages/venia-concept/src/ServiceWorker/Utilities/__tests__/messageHandler.spec.js @@ -170,6 +170,12 @@ describe('Testing sendMessageToClient', () => { ).rejects.toBe('Unable to send message to worker'); }); + test('sendMessageToClient should reject if the client is not defined', async () => { + await expect(sendMessageToClient(null, messageType, {})).rejects.toBe( + 'Unable to send message to client' + ); + }); + test('sendMessageToClient should call the postMessage function on client with type, payload and a port to reply back', () => { const port2 = new Port(); global.MessageChannel = function MessageChannel() { diff --git a/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js b/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js index 49e54a61dc..681d64a325 100644 --- a/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js +++ b/packages/venia-concept/src/ServiceWorker/Utilities/messageHandler.js @@ -117,7 +117,9 @@ export const sendMessageToClient = (client, type, payload) => if (client && client.postMessage) { client.postMessage({ type, payload }, [channel.port2]); } else { - reject(`Unable to send message to ${client}`); + reject( + `Unable to send message to ${client ? client.type : 'client'}` + ); } });