Skip to content
This repository has been archived by the owner on May 3, 2024. It is now read-only.

feat(fastifycdn): migrate holocron cdn to fastify #882

Merged
merged 8 commits into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions __mocks__/node-fetch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2022 American Express Travel Related Services Company, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,either express
* or implied. See the License for the specific language governing permissions and limitations
* under the License.
*/

const fetch = jest.createMockFromModule('node-fetch');
fetch.mockReturnJsonOnce = (obj) => {
if (obj instanceof Error) {
return fetch.mockImplementationOnce(() => Promise.reject(obj));
}

return fetch.mockImplementationOnce(() => Promise.resolve({ body: JSON.stringify(obj) }));
};

fetch.mockReturnFileOnce = (body) => {
if (body instanceof Error) {
return fetch.mockImplementationOnce(() => Promise.reject(body));
}

return fetch.mockImplementationOnce(() => Promise.resolve({ body, statusCode: 200 }));
};
module.exports = fetch;
128 changes: 3 additions & 125 deletions __tests__/server/devHolocronCDN.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@
*/
/* eslint-disable global-require */

import path from 'path';
import fs from 'fs';
import findUp from 'find-up';
import '../../src/server/devHolocronCDN';

jest.mock('cors', () => jest.fn(() => (req, res, next) => next()));
jest.mock('@americanexpress/one-app-dev-cdn', () => jest.fn(() => (req, res, next) => next()));
jest.mock('../../src/server/utils/devCdnFactory', () => jest.fn(() => (req, res, next) => next()));
jest.spyOn(fs, 'existsSync').mockImplementation(() => true);

describe('devHolocronCDN', () => {
Expand All @@ -36,16 +34,14 @@ describe('devHolocronCDN', () => {
});

describe('setup', () => {
let cors;
let oneAppDevCdn;

beforeEach(() => {
jest.resetModules();
});

async function load() {
cors = require('cors');
oneAppDevCdn = require('@americanexpress/one-app-dev-cdn');
oneAppDevCdn = require('../../src/server/utils/devCdnFactory');

const devHolocronCDN = require('../../src/server/devHolocronCDN').default;

Expand All @@ -54,127 +50,9 @@ describe('devHolocronCDN', () => {
return fastify;
}

it('should add cors to the app', async () => {
await load();
expect(cors).toHaveBeenCalled();
});

it('should add @americanexpress/one-app-dev-cdn to the static route', async () => {
it('should add one-app-dev-cdn to the static route', async () => {
await load();
expect(oneAppDevCdn).toHaveBeenCalled();
});

it('should give @americanexpress/one-app-dev-cdn the path to the static directory', async () => {
expect.assertions(1);
const moduleMapUrl = 'https://example.com/module-map.json';
process.argv = [
'',
'',
'--module-map-url',
moduleMapUrl,
];

await load();

return findUp('package.json')
.then((filepath) => {
expect(oneAppDevCdn).toHaveBeenCalledWith({
localDevPublicPath: path.join(path.dirname(filepath), 'static'),
remoteModuleMapUrl: moduleMapUrl,
useLocalModules: true,
});
});
});

it('does not require useLocalModules when no static module-map', async () => {
expect.assertions(1);
fs.existsSync.mockImplementationOnce(() => false);
const moduleMapUrl = 'https://example.com/module-map.json';
process.argv = [
'',
'',
'--module-map-url',
moduleMapUrl,
];

await load();

return findUp('package.json')
.then((filepath) => {
expect(oneAppDevCdn).toHaveBeenCalledWith({
localDevPublicPath: path.join(path.dirname(filepath), 'static'),
remoteModuleMapUrl: moduleMapUrl,
useLocalModules: false,
});
});
});
});

describe('routing', () => {
let corsMiddleware;
let oneAppDevCdnMiddleware;
let devHolocronCDN;
let cors;
let oneAppDevCdn;

beforeEach(() => {
jest.resetModules();
});

async function load() {
cors = require('cors');
oneAppDevCdn = require('@americanexpress/one-app-dev-cdn');
corsMiddleware = jest.fn((req, res, next) => next());
cors.mockReturnValue(corsMiddleware);
oneAppDevCdnMiddleware = jest.fn((req, res, next) => next());
oneAppDevCdn.mockReturnValue(oneAppDevCdnMiddleware);
devHolocronCDN = require('../../src/server/devHolocronCDN').default;

return devHolocronCDN();
}

it('should hit the cors middleware first', async () => {
expect.assertions(3);
const instance = await load();

corsMiddleware.mockImplementationOnce((req, res) => res.sendStatus(204));

const response = await instance.inject({
method: 'GET',
url: '/static/anything.json',
});

expect(corsMiddleware).toHaveBeenCalledTimes(1);
expect(oneAppDevCdnMiddleware).not.toHaveBeenCalled();
expect(response.statusCode).toBe(204);
});

it('should hit the one-app-dev-cdn middleware after cors', async () => {
expect.assertions(2);

const instance = await load();

await instance.inject({
method: 'GET',
url: '/static/anything.json',
});

expect(corsMiddleware).toHaveBeenCalledTimes(1);
expect(oneAppDevCdnMiddleware).toHaveBeenCalledTimes(1);
});

it('should miss the one-app-dev-cdn middleware if not a static route', async () => {
expect.assertions(2);

const instance = await load();

await instance.inject({
method: 'GET',
url: '/not-static.json',
});

expect(corsMiddleware).toHaveBeenCalledTimes(1);
expect(oneAppDevCdnMiddleware).not.toHaveBeenCalled();
});
});
});
39 changes: 39 additions & 0 deletions __tests__/server/utils/__snapshots__/devCdnFactory.spec.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`one-app-dev-cdn module-map.json extends the remote map with the local map 1`] = `"{"key":"not-used-in-development","modules":{"module-b":{"node":{"url":"http://localhost:3001/static/cdn/module-b/1.0.0/module-b.node.js","integrity":"123"},"browser":{"url":"http://localhost:3001/static/cdn/module-b/1.0.0/module-b.browser.js","integrity":"234"},"legacyBrowser":{"url":"http://localhost:3001/static/cdn/module-b/1.0.0/module-b.legacy.browser.js","integrity":"345"}},"module-a":{"node":{"url":"https://example.com/module-a/1.0.0/module-a.node.js","integrity":"123"},"browser":{"url":"https://example.com/module-a/1.0.0/module-a.browser.js","integrity":"234"},"legacyBrowser":{"url":"https://example.com/module-a/1.0.0/module-a.legacy.browser.js","integrity":"345"}}}}"`;

exports[`one-app-dev-cdn module-map.json extends the remote map with the local map and uses host instead of localhost 1`] = `"{"key":"not-used-in-development","modules":{"module-b":{"node":{"url":"http://localhost:80/static/cdn/module-b/1.0.0/module-b.node.js","integrity":"123"},"browser":{"url":"http://localhost:80/static/cdn/module-b/1.0.0/module-b.browser.js","integrity":"234"},"legacyBrowser":{"url":"http://localhost:80/static/cdn/module-b/1.0.0/module-b.legacy.browser.js","integrity":"345"}},"module-a":{"node":{"url":"https://example.com/module-a/1.0.0/module-a.node.js","integrity":"123"},"browser":{"url":"https://example.com/module-a/1.0.0/module-a.browser.js","integrity":"234"},"legacyBrowser":{"url":"https://example.com/module-a/1.0.0/module-a.legacy.browser.js","integrity":"345"}}}}"`;

exports[`one-app-dev-cdn module-map.json uses the local map overriding the cdn url placeholder with the one-app-dev-cdn url 1`] = `
{
"key": "not-used-in-development",
"modules": {
"module-a": {
"browser": {
"integrity": "234",
"url": "http://localhost:3001/module-a/1.0.0/module-a.browser.js",
},
"legacyBrowser": {
"integrity": "345",
"url": "http://localhost:3001/module-a/1.0.0/module-a.legacy.browser.js",
},
"node": {
"integrity": "123",
"url": "http://localhost:3001/module-a/1.0.0/module-a.node.js",
},
},
},
}
`;

exports[`one-app-dev-cdn modules gets remote modules: module map response 1`] = `"{"key":"not-used-in-development","modules":{"module-b":{"node":{"url":"http://localhost:3001/static/cdn/module-b/1.0.0/module-b.node.js","integrity":"123"},"browser":{"url":"http://localhost:3001/static/cdn/module-b/1.0.0/module-b.browser.js","integrity":"234"},"legacyBrowser":{"url":"http://localhost:3001/static/cdn/module-b/1.0.0/module-b.legacy.browser.js","integrity":"345"}}}}"`;

exports[`one-app-dev-cdn modules returns a 404 if a request for something not known as a module from the module map comes in: module map response 1`] = `"{"key":"not-used-in-development","modules":{"module-b":{"node":{"url":"http://localhost:3001/static/cdn/module-b/1.0.0/module-b.node.js","integrity":"123"},"browser":{"url":"http://localhost:3001/static/cdn/module-b/1.0.0/module-b.browser.js","integrity":"234"},"legacyBrowser":{"url":"http://localhost:3001/static/cdn/module-b/1.0.0/module-b.legacy.browser.js","integrity":"345"}}}}"`;

exports[`one-app-dev-cdn modules returns a 500 if a request to proxy a module from the module map fails: module map response 1`] = `"{"key":"not-used-in-development","modules":{"module-b":{"node":{"url":"http://localhost:3001/static/cdn/module-b/1.0.0/module-b.node.js","integrity":"123"},"browser":{"url":"http://localhost:3001/static/cdn/module-b/1.0.0/module-b.browser.js","integrity":"234"},"legacyBrowser":{"url":"http://localhost:3001/static/cdn/module-b/1.0.0/module-b.legacy.browser.js","integrity":"345"}}}}"`;

exports[`one-app-dev-cdn usage should throw if appPort is not given 1`] = `"appPort is a required param"`;

exports[`one-app-dev-cdn usage should throw if localDevPublicPath is not given 1`] = `"localDevPublicPath is a required param"`;

exports[`one-app-dev-cdn usage should throw if neither remoteModuleMapUrl nor useLocalModules is given 1`] = `"remoteModuleMapUrl is a required param when useLocalModules is not true"`;
Loading