Skip to content

Commit

Permalink
Merge branch 'develop' into jimbo/magento-routes
Browse files Browse the repository at this point in the history
  • Loading branch information
dpatil-magento authored Nov 13, 2019
2 parents e1c7551 + 0f91cd4 commit 79b9b33
Show file tree
Hide file tree
Showing 9 changed files with 901 additions and 3 deletions.
7 changes: 6 additions & 1 deletion packages/pwa-buildpack/lib/Utilities/graphQL.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
const fetch = require('node-fetch');
const graphQLQueries = require('../queries');
const { Agent: HTTPSAgent } = require('https');

// To be used with `node-fetch` in order to allow self-signed certificates.
const fetchAgent = new HTTPSAgent({ rejectUnauthorized: false });

const fetchQuery = query => {
return fetch(
Expand All @@ -10,7 +14,8 @@ const fetchQuery = query => {
'Content-Type': 'application/json',
'Accept-Encoding': 'gzip'
},
body: JSON.stringify({ query })
body: JSON.stringify({ query }),
agent: fetchAgent
}
)
.then(result => result.json())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
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(options = {}) {
this.statuses = options.statuses;
}

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);
});

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]);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
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();

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).toBe('/');
});

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 () => {
/**
* 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.
*/
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);

/**
* 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.
*/
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();

/**
* Restoring prototype function definitions
*/
global.Response.prototype.text = originalText;
global.Response.prototype.clone = originalClone;
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import {
isResizedCatalogImage,
findSameOrLargerImage
} 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();
});
});

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);
});
});
Loading

0 comments on commit 79b9b33

Please sign in to comment.