Skip to content

Commit

Permalink
Merge pull request #298 from namecheap/addTestsForFragmentHooks
Browse files Browse the repository at this point in the history
chore: added tests for fragment hooks
  • Loading branch information
ifree92 authored May 25, 2021
2 parents 011361a + 843ba2a commit f59f896
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 1 deletion.
2 changes: 1 addition & 1 deletion ilc/server/tailor/fragment-hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const parseLinkHeader = require('tailorx/lib/parse-link-header');

const { appIdToNameAndSlot } = require('../../common/utils');

function insertStart(stream, attributes, headers, index) {
function insertStart(stream, attributes, headers) {
const bundleVersionOverrides = _.pick(attributes, ['wrapperPropsOverride']);

if (headers.link) {
Expand Down
175 changes: 175 additions & 0 deletions ilc/server/tailor/fragment-hooks.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
const chai = require('chai');
const {getFragmentAttributes} = require('../../tests/helpers');
const {insertStart, insertEnd} = require('./fragment-hooks');
const {PassThrough} = require('stream');

describe('fragment-hooks', () => {
describe('insertEnd', () => {
it('should not write to stream', () => {
const mockStream = new PassThrough();
const fragmentAttrs = getFragmentAttributes();
const headers = {};

insertEnd(mockStream, fragmentAttrs, headers);

chai.expect(mockStream.readableLength).to.be.equal(0);
});
});

describe('insertStart', () => {
it('should write a script tag with wrapper overrides', () => {
const mockStream = new PassThrough();
const fragmentAttrs = getFragmentAttributes({
wrapperPropsOverride: {
param1: 'value1',
param2: 'value2',
}
});
const headers = {};

insertStart(mockStream, fragmentAttrs, headers);

const streamData = mockStream.read();

chai.expect(streamData).to.be.instanceOf(Buffer);
chai.expect(streamData.toString()).to.be.equal('<script type="spa-config-override">{"wrapperPropsOverride":{"param1":"value1","param2":"value2"}}</script>');
});


it('should write async fragment code warning comments for ref stylesheet ', () => {
const mockStream = new PassThrough();
const fragmentAttrs = getFragmentAttributes({async: true});
const headers = {
link: '<https://domain.com/app.css>; rel="stylesheet"',
};

insertStart(mockStream, fragmentAttrs, headers);

const streamData = mockStream.read();

chai.expect(streamData).to.be.instanceOf(Buffer);
chai.expect(streamData.toString()).to.be.equal(
'<!-- Async fragments are not fully implemented yet: https://domain.com/app.css -->' +
'<script type="spa-config-override">{"cssBundle":"https://domain.com/app.css"}</script>'
);

});

it('should inject style link override function and script config override tag', () => {
const mockStream = new PassThrough();
const fragmentAttrs = getFragmentAttributes({id: 'autogenerated_identifier'});
const headers = {
link: '<https://domain.com/app.css>; rel="stylesheet"',
};

insertStart(mockStream, fragmentAttrs, headers);

const streamData = mockStream.read();

chai.expect(streamData).to.be.instanceOf(Buffer);
chai.expect(streamData.toString()).to.be.equal(
'<script>(function(url, id){const link = document.head.querySelector(\'link[data-fragment-id="\' + id + \'"]\');if (link && link.href !== url) {link.href = url;}})("https://domain.com/app.css", "autogenerated_identifier");</script>' +
'<script type="spa-config-override">{"cssBundle":"https://domain.com/app.css"}</script>'
);
});

it('shouldn\'t inject style link override function if attribute.id hasn\'t been provided', () => {
const mockStream = new PassThrough();
const fragmentAttrs = getFragmentAttributes({id: ''});
const headers = {
link: '<https://domain.com/app.css>; rel="stylesheet"',
};

insertStart(mockStream, fragmentAttrs, headers);

const streamData = mockStream.read();

chai.expect(streamData).to.be.instanceOf(Buffer);
chai.expect(streamData.toString()).to.be.equal(
'<script type="spa-config-override">{"cssBundle":"https://domain.com/app.css"}</script>'
);
});

it('should inject overrides with spaBundle', () => {
const mockStream = new PassThrough();
const fragmentAttrs = getFragmentAttributes({id: 'autogenerated_identifier'});
const headers = {
link: '<https://domain.com/single_spa.js>; rel="fragment-script"; as="script"; crossorigin="anonymous"',
};

insertStart(mockStream, fragmentAttrs, headers);

const streamData = mockStream.read();
chai.expect(streamData).to.be.instanceOf(Buffer);
chai.expect(streamData.toString()).to.be.equal('<script type="spa-config-override">{"spaBundle":"https://domain.com/single_spa.js","appName":"autogenerated_identifier"}</script>');
});

it('should correct map appName for overrides', () => {
const mockStream = new PassThrough();
const fragmentAttrs = getFragmentAttributes({
id: 'autogenerated_identifier',
wrapperConf: {
appId: 'wrapper__at__body',
name: '@portal/wrapper',
src: 'https://wrapper.com/fragment',
timeout: 2000
},
});

const headers = {
link: '<https://domain.com/single_spa.js>; rel="fragment-script"; as="script"; crossorigin="anonymous"',
};

insertStart(mockStream, fragmentAttrs, headers);

const streamData = mockStream.read();
chai.expect(streamData).to.be.instanceOf(Buffer);
chai.expect(streamData.toString()).to.be.equal('<script type="spa-config-override">{"spaBundle":"https://domain.com/single_spa.js","appName":"@portal/wrapper"}</script>');
});

it('should forward fragment dependency through overrides', () => {
const mockStream = new PassThrough();
const fragmentAttrs = getFragmentAttributes({id: 'autogenerated_identifier'});
const headers = {
link: '<https://domain.com/single_spa.js>; rel="fragment-dependency"; name="dep_name"',
};

insertStart(mockStream, fragmentAttrs, headers);

const streamData = mockStream.read();

chai.expect(streamData).to.be.instanceOf(Buffer);
chai.expect(streamData.toString()).to.be.equal('<script type="spa-config-override">{"dependencies":{"dep_name":"https://domain.com/single_spa.js"}}</script>');
});

it('should forward a few fragment dependencies through overrides', () => {
const mockStream = new PassThrough();
const fragmentAttrs = getFragmentAttributes({id: 'autogenerated_identifier'});
const headers = {
link: '<https://domain.com/single_spa.js>; rel="fragment-dependency"; name="dep_name", <https://domain2.com/single_spa2.js>; rel="fragment-dependency"; name="dep_name2"',
};

insertStart(mockStream, fragmentAttrs, headers);

const streamData = mockStream.read();

chai.expect(streamData).to.be.instanceOf(Buffer);
chai.expect(streamData.toString()).to.be.equal('<script type="spa-config-override">{"dependencies":{"dep_name":"https://domain.com/single_spa.js","dep_name2":"https://domain2.com/single_spa2.js"}}</script>');
});

it('shouldn\'t forward fragment dependency uri if its name hasn\'t been provided', () => {
const mockStream = new PassThrough();
const fragmentAttrs = getFragmentAttributes({id: 'autogenerated_identifier'});
const headers = {
link: '<https://domain.com/single_spa.js>; rel="fragment-script"; as="script"; crossorigin="anonymous", <https://domain.com/single_spa.js>; rel="fragment-dependency";',
};

insertStart(mockStream, fragmentAttrs, headers);

const streamData = mockStream.read();

chai.expect(streamData).to.be.instanceOf(Buffer);
chai.expect(streamData.toString()).to.be.equal('<script type="spa-config-override">{"spaBundle":"https://domain.com/single_spa.js","appName":"autogenerated_identifier"}</script>');
})
});
});
24 changes: 24 additions & 0 deletions ilc/tests/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,34 @@ function setupMockServersForApps() {
});
}

/**
* Returns mock attributes for tests
* @param overrideAttributes override default attributes
* @returns {{async: boolean, public: boolean, ignoreInvalidSsl: boolean, appProps: {}, wrapperConf: null, id: string, returnHeaders: boolean, url: string, timeout: number, primary: boolean, forwardQuerystring: boolean}}
*/
function getFragmentAttributes(overrideAttributes = {}) {
const defaultAttributes = {
id: 'microfrontend__at__slot',
appProps: {},
wrapperConf: null,
url: 'https://domain.com/',
async: false,
primary: false,
public: false,
timeout: 1000,
returnHeaders: false,
forwardQuerystring: false,
ignoreInvalidSsl: false,
}

return {...defaultAttributes, ...overrideAttributes};
}

module.exports = {
getRegistryMock,
getRouterProps,
getFragmentResponses,
getPluginManagerMock,
setupMockServersForApps,
getFragmentAttributes,
}

0 comments on commit f59f896

Please sign in to comment.