baazjs
Version:
304 lines (243 loc) • 10.9 kB
JavaScript
jest.mock('../networkUtils');
import { PREFETCH_IMAGES } from '@magento/venia-ui/lib/constants/swMessageTypes';
import { THIRTY_DAYS, CATALOG_CACHE_NAME } from '../../defaults';
import {
isResizedCatalogImage,
findSameOrLargerImage,
createCatalogCacheHandler,
registerImagePreFetchHandler
} from '../imageCacheHandler';
import { __handlers__ } from '../messageHandler';
import { isFastNetwork } from '../networkUtils';
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();
});
});
describe('Testing findSameOrLargerImage', () => {
const mockMatchFn = jest.fn();
beforeAll(() => {
global.caches = {
open: function() {
return Promise.resolve({
keys: 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'
}
]);
},
match: mockMatchFn
});
}
};
});
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';
mockMatchFn.mockReturnValue(Promise.resolve({ url: expectedUrl }));
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';
mockMatchFn.mockReturnValue(Promise.resolve({ url: expectedUrl }));
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);
});
});
describe('Testing createCatalogCacheHandler', () => {
function CacheFirst(options = {}) {
this.cacheName = options.cacheName;
this.plugins = options.plugins;
}
function CacheableResponsePlugin(options = {}) {
this.statuses = options.statuses;
}
function ExpirationPlugin(options = {}) {
this.maxEntries = options.maxEntries;
this.maxAgeSeconds = options.maxAgeSeconds;
}
beforeAll(() => {
global.workbox = {
strategies: {
CacheFirst
},
cacheableResponse: {
Plugin: CacheableResponsePlugin
},
expiration: {
Plugin: ExpirationPlugin
}
};
});
test('createCatalogCacheHandler should return an instance of workbox.strategies.CacheFirst', () => {
expect(createCatalogCacheHandler()).toBeInstanceOf(CacheFirst);
});
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);
});
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]);
});
});
describe('Testing registerImagePreFetchHandler', () => {
function clearHandlersObject() {
Object.keys(__handlers__).forEach(messageType => {
delete __handlers__[messageType];
});
}
const mockMatchFn = jest.fn();
const mockPutFn = jest.fn();
const mockFetch = jest.fn();
beforeAll(() => {
global.fetch = mockFetch;
global.caches = {
open: function() {
return Promise.resolve({
put: mockPutFn
});
},
match: mockMatchFn
};
});
beforeEach(() => {
clearHandlersObject();
mockMatchFn.mockRestore();
mockPutFn.mockRestore();
mockFetch.mockRestore();
});
test('registerImagePreFetchHandler should create a handler for PREFETCH_IMAGES', () => {
expect(__handlers__).not.toHaveProperty(PREFETCH_IMAGES);
registerImagePreFetchHandler();
expect(__handlers__).toHaveProperty(PREFETCH_IMAGES);
});
test("PREFETCH_IMAGES's handler should not pre fetch if network is slow and send error status as reply", () => {
const mockPostmessage = jest.fn();
const event = { ports: [{ postMessage: mockPostmessage }] };
const payload = {
urls: []
};
isFastNetwork.mockReturnValue(false);
registerImagePreFetchHandler();
const returnValue = __handlers__[PREFETCH_IMAGES][0](payload, event);
expect(mockPostmessage).toHaveBeenCalledWith({
status: 'error',
message: `Slow Network detected. Not pre-fetching images. ${
payload.urls
}`
});
expect(returnValue).toBeNull();
});
test("If fast network, PREFETCH_IMAGES's handler should fetch images if not cached already and cache it for future use", async () => {
const sampleUrl = 'www.adobe.com';
const mockPostmessage = jest.fn();
const event = { ports: [{ postMessage: mockPostmessage }] };
const payload = {
urls: [sampleUrl]
};
const mockClone = jest.fn();
const mockRespose = {
clone: mockClone
};
const mockCloneReturnValue = {};
isFastNetwork.mockReturnValue(true);
mockMatchFn.mockReturnValue(Promise.resolve(null));
mockFetch.mockReturnValue(Promise.resolve(mockRespose));
mockClone.mockReturnValue(mockCloneReturnValue);
mockPutFn.mockReturnValue(Promise.resolve(true));
registerImagePreFetchHandler();
const handler = __handlers__[PREFETCH_IMAGES][0];
const returnValue = await handler(payload, event);
expect(mockPostmessage).toHaveBeenCalledWith({ status: 'done' });
expect(mockFetch).toHaveBeenCalledWith(sampleUrl);
expect(mockPutFn).toHaveBeenCalledWith(sampleUrl, mockCloneReturnValue);
expect(returnValue[0]).toBe(mockRespose);
});
test("If fast network, PERFETCH_IMAGES's handler should not fetch images if already cached", async () => {
const sampleUrl = 'www.adobe.com';
const mockPostmessage = jest.fn();
const event = { ports: [{ postMessage: mockPostmessage }] };
const payload = {
urls: [sampleUrl]
};
const mockRespose = {};
isFastNetwork.mockReturnValue(true);
mockMatchFn.mockReturnValue(Promise.resolve(mockRespose));
mockFetch.mockReturnValue(Promise.resolve(mockRespose));
mockPutFn.mockReturnValue(Promise.resolve(true));
registerImagePreFetchHandler();
const handler = __handlers__[PREFETCH_IMAGES][0];
const returnValue = await handler(payload, event);
expect(mockPostmessage).toHaveBeenCalledWith({ status: 'done' });
expect(mockFetch).not.toHaveBeenCalled();
expect(mockPutFn).not.toHaveBeenCalled();
expect(returnValue[0]).toBe(mockRespose);
});
});