diff --git a/lib/server.js b/lib/server.js index b56adbe..72fb513 100644 --- a/lib/server.js +++ b/lib/server.js @@ -62,9 +62,9 @@ export default class AppManagerServer { return params; }; - _parseQuery = (query: string | QueryType) => (typeof query === 'object' ? query : qs.parse(query)); + _parseQuery = (query: string | QueryType = {}) => (typeof query === 'object' ? query : qs.parse(query)); - init = async (path: string, query: string | QueryType, ...getMarkupArgs: Array): Promise => { + init = async (path: string, query?: string | QueryType, ...getMarkupArgs: Array): Promise => { const currentAppName = this._getAppNameFromPath(path); if (!currentAppName) { @@ -87,7 +87,7 @@ export default class AppManagerServer { const fragmentName = appFragments[slotName]; const fragment = this._fragments[fragmentName]; - const markup = typeof fragment.getMarkup === 'function' ? await fragment.getMarkup(state, ...getMarkupArgs) : ''; + const markup = fragment && typeof fragment.getMarkup === 'function' ? await fragment.getMarkup(state, ...getMarkupArgs) : ''; return { slotName, markup }; }); diff --git a/package-lock.json b/package-lock.json index 3421552..728cacb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "app-manager", - "version": "0.19.2", + "version": "0.19.3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2734,6 +2734,15 @@ "type-detect": "4.0.3" } }, + "chai-as-promised": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "dev": true, + "requires": { + "check-error": "1.0.2" + } + }, "chalk": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", @@ -8001,7 +8010,7 @@ "lolex": "2.3.2", "nise": "1.2.2", "supports-color": "5.1.0", - "type-detect": "4.0.7" + "type-detect": "4.0.8" }, "dependencies": { "lodash.get": { @@ -8020,9 +8029,9 @@ } }, "type-detect": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.7.tgz", - "integrity": "sha512-4Rh17pAMVdMWzktddFhISRnUnFIStObtUMNGzDwlA6w/77bmGv3aBbRdCmQR6IjzfkTo9otnW+2K/cDRhKSxDA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true } } diff --git a/package.json b/package.json index e0c925c..41894f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "app-manager", - "version": "0.19.3", + "version": "0.19.4", "description": "Script for managing the lifecycles of multiple apps on a single page", "main": "es5/index.js", "scripts": { @@ -35,10 +35,10 @@ "homepage": "https://github.com/tomruttle/app-manager#readme", "nyc": { "check-coverage": true, - "lines": 70, - "statements": 70, + "lines": 80, + "statements": 80, "functions": 100, - "branches": 64, + "branches": 70, "include": [ "lib/**" ], @@ -59,6 +59,7 @@ "babel-preset-flow": "^6.23.0", "babel-register": "^6.26.0", "chai": "^4.1.2", + "chai-as-promised": "^7.1.1", "env-test": "^1.0.0", "eslint": "^4.16.0", "eslint-config-airbnb-base": "^12.1.0", diff --git a/test/server.test.js b/test/server.test.js new file mode 100644 index 0000000..9e81dec --- /dev/null +++ b/test/server.test.js @@ -0,0 +1,94 @@ +// @flow + +import chai, { expect } from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import sinon from 'sinon'; + +import AppManagerServer from '../lib/server'; + +chai.use(chaiAsPromised); + +describe('Server', () => { + function getConfig() { + return { + apps: { + app_a: { + name: 'app_a', + fragments: ['fragment_a'], + appPath: '/app-a', + }, + app_b: { + name: 'app_b', + fragments: ['fragment_b'], + appPath: '/app-b/:param1?', + }, + }, + fragments: { + fragment_a: { + name: 'fragment_a', + managed: true, + slots: ['app'], + loadScript: () => { throw new Error('Should not be called.'); }, + getMarkup: sinon.stub().returns(Promise.resolve('fragment_a')), + }, + fragment_b: { + name: 'fragment_b', + managed: true, + slots: ['app'], + loadScript: () => { throw new Error('Should not be called.'); }, + getMarkup: sinon.stub().returns(Promise.resolve('fragment_b')), + }, + }, + slots: { + app: { name: 'app', querySelector: null }, + other: { name: 'other', querySelector: null }, + }, + }; + } + + describe('init', () => { + it('rejects if path does not match any apps', () => { + const appManagerServer = new AppManagerServer(getConfig()); + expect(appManagerServer.init('/app-c')).be.rejectedWith('server.invalid_appPath'); + }); + + it('returns the async return value of getMarkup for the correct app in the correct slot', async () => { + const config = getConfig(); + const appManagerServer = new AppManagerServer(config); + const appMarkup = await appManagerServer.init('/app-a'); + + expect(appMarkup).to.deep.equals({ app: 'fragment_a', other: '' }); + + const getMarkupStubB = config.fragments.fragment_b.getMarkup; + expect(getMarkupStubB.called).to.be.false; + + const getMarkupStubA = config.fragments.fragment_a.getMarkup; + expect(getMarkupStubA.calledOnce).to.be.true; + + const args = getMarkupStubA.args[0]; + expect(args).to.be.an('array').with.length(1); + expect(args[0].app.name).to.equals('app_a'); + }); + + it('can handle params, query params, and additional arguments', async () => { + const config = getConfig(); + const appManagerServer = new AppManagerServer(config); + const appMarkup = await appManagerServer.init('/app-b/test', 'query=success', 'additional data'); + + expect(appMarkup).to.deep.equals({ app: 'fragment_b', other: '' }); + + const getMarkupStubA = config.fragments.fragment_a.getMarkup; + expect(getMarkupStubA.called).to.be.false; + + const getMarkupStubB = config.fragments.fragment_b.getMarkup; + expect(getMarkupStubB.calledOnce).to.be.true; + + const args = getMarkupStubB.args[0]; + expect(args).to.be.an('array').with.length(2); + expect(args[0].app.name).to.equals('app_b'); + expect(args[0].params).to.deep.equals({ param1: 'test' }); + expect(args[0].query).to.deep.equals({ query: 'success' }); + expect(args[1]).to.equals('additional data'); + }); + }); +});