diff --git a/config.js b/config.js index 3e905b6..3c273f2 100644 --- a/config.js +++ b/config.js @@ -15,89 +15,198 @@ System.config({ }, map: { - "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.1.4", - "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.1.2", - "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.1.5", - "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1", - "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.1.1", - "aurelia-polyfills": "npm:aurelia-polyfills@1.0.0-beta.1.0.6", - "aurelia-router": "npm:aurelia-router@1.0.0-beta.1.1.0", - "aurelia-templating": "npm:aurelia-templating@1.0.0-beta.1.1.2", - "babel": "npm:babel-core@5.8.35", - "babel-runtime": "npm:babel-runtime@5.8.35", - "core-js": "npm:core-js@2.0.3", + "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3", + "aurelia-event-aggregator": "npm:aurelia-event-aggregator@1.0.0-beta.1.2.1", + "aurelia-framework": "npm:aurelia-framework@1.0.0-beta.1.2.5", + "aurelia-history": "npm:aurelia-history@1.0.0-beta.1.2.1", + "aurelia-history-browser": "npm:aurelia-history-browser@1.0.0-beta.1.2.1", + "aurelia-loader-default": "npm:aurelia-loader-default@1.0.0-beta.1.2.2", + "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1", + "aurelia-logging-console": "npm:aurelia-logging-console@1.0.0-beta.1.2.2", + "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1", + "aurelia-pal": "github:aurelia/pal@1.0.0-beta.1.2.2", + "aurelia-pal-browser": "github:aurelia/pal-browser@1.0.0-beta.2.0.1", + "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2", + "aurelia-polyfills": "npm:aurelia-polyfills@1.0.0-beta.1.1.6", + "aurelia-router": "npm:aurelia-router@1.0.0-beta.1.2.4", + "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1", + "aurelia-templating-binding": "npm:aurelia-templating-binding@1.0.0-beta.1.2.4", + "aurelia-templating-resources": "npm:aurelia-templating-resources@1.0.0-beta.1.2.6", + "aurelia-templating-router": "npm:aurelia-templating-router@1.0.0-beta.1.2.1", + "aurelia-testing": "npm:aurelia-testing@0.2.2", + "babel": "npm:babel-core@5.8.38", + "babel-runtime": "npm:babel-runtime@5.8.38", + "core-js": "npm:core-js@2.4.0", + "github:aurelia/pal-browser@1.0.0-beta.2.0.1": { + "aurelia-pal": "github:aurelia/pal@1.0.0-beta.1.2.2" + }, + "github:aurelia/templating@1.0.0-beta.2.0.1": { + "aurelia-binding": "npm:aurelia-binding@1.0.0-beta.1.3.6", + "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3", + "aurelia-loader": "npm:aurelia-loader@1.0.0-beta.1.2.0", + "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1", + "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1", + "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2", + "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2", + "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.2.1" + }, "github:jspm/nodelibs-assert@0.1.0": { - "assert": "npm:assert@1.3.0" + "assert": "npm:assert@1.4.1" + }, + "github:jspm/nodelibs-buffer@0.1.0": { + "buffer": "npm:buffer@3.6.0" }, "github:jspm/nodelibs-path@0.1.0": { "path-browserify": "npm:path-browserify@0.0.0" }, "github:jspm/nodelibs-process@0.1.2": { - "process": "npm:process@0.11.2" + "process": "npm:process@0.11.3" }, "github:jspm/nodelibs-util@0.1.0": { "util": "npm:util@0.10.3" }, - "npm:assert@1.3.0": { + "npm:assert@1.4.1": { + "assert": "github:jspm/nodelibs-assert@0.1.0", + "buffer": "github:jspm/nodelibs-buffer@0.1.0", + "process": "github:jspm/nodelibs-process@0.1.2", "util": "npm:util@0.10.3" }, - "npm:aurelia-binding@1.0.0-beta.1.2.1": { - "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.1.5", - "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1", - "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.1.1" - }, - "npm:aurelia-dependency-injection@1.0.0-beta.1.1.4": { - "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.1.2", - "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.1.5", - "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1" - }, - "npm:aurelia-event-aggregator@1.0.0-beta.1.1.0": { - "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.1.2" - }, - "npm:aurelia-loader@1.0.0-beta.1.1.1": { - "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.1.5", - "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.1.1" - }, - "npm:aurelia-metadata@1.0.0-beta.1.1.5": { - "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1" - }, - "npm:aurelia-polyfills@1.0.0-beta.1.0.6": { - "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1" - }, - "npm:aurelia-route-recognizer@1.0.0-beta.1.1.0": { - "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.1.1", - "core-js": "npm:core-js@2.0.3" - }, - "npm:aurelia-router@1.0.0-beta.1.1.0": { - "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.1.4", - "aurelia-event-aggregator": "npm:aurelia-event-aggregator@1.0.0-beta.1.1.0", - "aurelia-history": "npm:aurelia-history@1.0.0-beta.1.1.1", - "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.1.2", - "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.1.1", - "aurelia-route-recognizer": "npm:aurelia-route-recognizer@1.0.0-beta.1.1.0", - "core-js": "npm:core-js@2.0.3" - }, - "npm:aurelia-task-queue@1.0.0-beta.1.1.1": { - "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1" - }, - "npm:aurelia-templating@1.0.0-beta.1.1.2": { - "aurelia-binding": "npm:aurelia-binding@1.0.0-beta.1.2.1", - "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.1.4", - "aurelia-loader": "npm:aurelia-loader@1.0.0-beta.1.1.1", - "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.1.2", - "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.1.5", - "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.1.1", - "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.1.1", - "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.1.1" - }, - "npm:babel-runtime@5.8.35": { + "npm:aurelia-binding@1.0.0-beta.1.3.6": { + "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1", + "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1", + "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2", + "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.2.1" + }, + "npm:aurelia-bootstrapper@1.0.0-beta.1.2.1": { + "aurelia-event-aggregator": "npm:aurelia-event-aggregator@1.0.0-beta.1.2.1", + "aurelia-framework": "npm:aurelia-framework@1.0.0-beta.1.2.5", + "aurelia-history": "npm:aurelia-history@1.0.0-beta.1.2.1", + "aurelia-history-browser": "npm:aurelia-history-browser@1.0.0-beta.1.2.1", + "aurelia-loader-default": "npm:aurelia-loader-default@1.0.0-beta.1.2.2", + "aurelia-logging-console": "npm:aurelia-logging-console@1.0.0-beta.1.2.2", + "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2", + "aurelia-pal-browser": "npm:aurelia-pal-browser@1.0.0-beta.2.0.1", + "aurelia-polyfills": "npm:aurelia-polyfills@1.0.0-beta.1.1.6", + "aurelia-router": "npm:aurelia-router@1.0.0-beta.1.2.4", + "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1", + "aurelia-templating-binding": "npm:aurelia-templating-binding@1.0.0-beta.1.2.4", + "aurelia-templating-resources": "npm:aurelia-templating-resources@1.0.0-beta.1.2.6", + "aurelia-templating-router": "npm:aurelia-templating-router@1.0.0-beta.1.2.1" + }, + "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3": { + "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1", + "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1", + "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2" + }, + "npm:aurelia-event-aggregator@1.0.0-beta.1.2.1": { + "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1" + }, + "npm:aurelia-framework@1.0.0-beta.1.2.5": { + "aurelia-binding": "npm:aurelia-binding@1.0.0-beta.1.3.6", + "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3", + "aurelia-loader": "npm:aurelia-loader@1.0.0-beta.1.2.0", + "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1", + "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1", + "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2", + "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2", + "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.2.1", + "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1" + }, + "npm:aurelia-history-browser@1.0.0-beta.1.2.1": { + "aurelia-history": "npm:aurelia-history@1.0.0-beta.1.2.1", + "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2" + }, + "npm:aurelia-loader-default@1.0.0-beta.1.2.2": { + "aurelia-loader": "npm:aurelia-loader@1.0.0-beta.1.2.0", + "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1", + "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2" + }, + "npm:aurelia-loader@1.0.0-beta.1.2.0": { + "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1", + "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2" + }, + "npm:aurelia-logging-console@1.0.0-beta.1.2.2": { + "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1" + }, + "npm:aurelia-metadata@1.0.0-beta.1.2.1": { + "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2" + }, + "npm:aurelia-pal-browser@1.0.0-beta.2.0.1": { + "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2" + }, + "npm:aurelia-polyfills@1.0.0-beta.1.1.6": { + "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2" + }, + "npm:aurelia-route-recognizer@1.0.0-beta.1.2.1": { + "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2" + }, + "npm:aurelia-router@1.0.0-beta.1.2.4": { + "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3", + "aurelia-event-aggregator": "npm:aurelia-event-aggregator@1.0.0-beta.1.2.1", + "aurelia-history": "npm:aurelia-history@1.0.0-beta.1.2.1", + "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1", + "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2", + "aurelia-route-recognizer": "npm:aurelia-route-recognizer@1.0.0-beta.1.2.1" + }, + "npm:aurelia-task-queue@1.0.0-beta.1.2.1": { + "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2" + }, + "npm:aurelia-templating-binding@1.0.0-beta.1.2.4": { + "aurelia-binding": "npm:aurelia-binding@1.0.0-beta.1.3.6", + "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1", + "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1" + }, + "npm:aurelia-templating-resources@1.0.0-beta.1.2.6": { + "aurelia-binding": "npm:aurelia-binding@1.0.0-beta.1.3.6", + "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3", + "aurelia-loader": "npm:aurelia-loader@1.0.0-beta.1.2.0", + "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1", + "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1", + "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2", + "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2", + "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.2.1", + "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1" + }, + "npm:aurelia-templating-router@1.0.0-beta.1.2.1": { + "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3", + "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1", + "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1", + "aurelia-pal": "npm:aurelia-pal@1.0.0-beta.1.2.2", + "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2", + "aurelia-router": "npm:aurelia-router@1.0.0-beta.1.2.4", + "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1" + }, + "github:aurelia/templating@1.0.0-beta.2.0.1": { + "aurelia-binding": "npm:aurelia-binding@1.0.0-beta.1.3.6", + "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.0.0-beta.1.2.3", + "aurelia-loader": "npm:aurelia-loader@1.0.0-beta.1.2.0", + "aurelia-logging": "npm:aurelia-logging@1.0.0-beta.1.2.1", + "aurelia-metadata": "npm:aurelia-metadata@1.0.0-beta.1.2.1", + "aurelia-pal": "github:aurelia/pal@1.0.0-beta.1.2.2", + "aurelia-path": "npm:aurelia-path@1.0.0-beta.1.2.2", + "aurelia-task-queue": "npm:aurelia-task-queue@1.0.0-beta.1.2.1" + }, + "npm:aurelia-testing@0.2.2": { + "aurelia-bootstrapper": "npm:aurelia-bootstrapper@1.0.0-beta.1.2.1", + "aurelia-framework": "npm:aurelia-framework@1.0.0-beta.1.2.5", + "aurelia-templating": "github:aurelia/templating@1.0.0-beta.2.0.1" + }, + "npm:babel-runtime@5.8.38": { + "process": "github:jspm/nodelibs-process@0.1.2" + }, + "npm:buffer@3.6.0": { + "base64-js": "npm:base64-js@0.0.8", + "child_process": "github:jspm/nodelibs-child_process@0.1.0", + "fs": "github:jspm/nodelibs-fs@0.1.2", + "ieee754": "npm:ieee754@1.1.6", + "isarray": "npm:isarray@1.0.0", "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:core-js@2.0.3": { + "npm:core-js@2.4.0": { "fs": "github:jspm/nodelibs-fs@0.1.2", "path": "github:jspm/nodelibs-path@0.1.0", "process": "github:jspm/nodelibs-process@0.1.2", - "systemjs-json": "github:systemjs/plugin-json@0.1.0" + "systemjs-json": "github:systemjs/plugin-json@0.1.2" }, "npm:inherits@2.0.1": { "util": "github:jspm/nodelibs-util@0.1.0" @@ -105,7 +214,7 @@ System.config({ "npm:path-browserify@0.0.0": { "process": "github:jspm/nodelibs-process@0.1.2" }, - "npm:process@0.11.2": { + "npm:process@0.11.3": { "assert": "github:jspm/nodelibs-assert@0.1.0" }, "npm:util@0.10.3": { diff --git a/karma.conf.js b/karma.conf.js index db3d86d..d87b30a 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -15,12 +15,12 @@ module.exports = function(config) { jspm: { // Edit this to your needs loadFiles: ['test/setup.js', 'test/**/*.js'], - serveFiles: ['src/**/*.js'], + serveFiles: ['src/**/*.js'] }, // list of files / patterns to load in the browser - files: [], + files: ['test/**/*.html'], // list of files to exclude diff --git a/src/router-view.js b/src/router-view.js index dca4aeb..c72b0b5 100644 --- a/src/router-view.js +++ b/src/router-view.js @@ -1,5 +1,5 @@ import {Container, inject} from 'aurelia-dependency-injection'; -import {ViewSlot, ViewLocator, customElement, noView, BehaviorInstruction, bindable, CompositionTransaction} from 'aurelia-templating'; +import {ViewSlot, ViewLocator, customElement, noView, BehaviorInstruction, bindable, CompositionTransaction, CompositionEngine, ShadowDOM} from 'aurelia-templating'; import {Router} from 'aurelia-router'; import {Origin} from 'aurelia-metadata'; import {DOM} from 'aurelia-pal'; @@ -37,17 +37,21 @@ const swapStrategies = new SwapStrategies(); @customElement('router-view') @noView -@inject(DOM.Element, Container, ViewSlot, Router, ViewLocator, CompositionTransaction) +@inject(DOM.Element, Container, ViewSlot, Router, ViewLocator, CompositionTransaction, CompositionEngine) export class RouterView { @bindable swapOrder; + @bindable layoutView; + @bindable layoutViewModel; + @bindable layoutModel; - constructor(element, container, viewSlot, router, viewLocator, compositionTransaction) { + constructor(element, container, viewSlot, router, viewLocator, compositionTransaction, compositionEngine) { this.element = element; this.container = container; this.viewSlot = viewSlot; this.router = router; this.viewLocator = viewLocator; this.compositionTransaction = compositionTransaction; + this.compositionEngine = compositionEngine; this.router.registerViewPort(this, this.element.getAttribute('name')); if (!('initialComposition' in compositionTransaction)) { @@ -71,53 +75,83 @@ export class RouterView { let viewModel = component.viewModel; let viewModelResource = component.viewModelResource; let metadata = viewModelResource.metadata; + let config = component.router.currentInstruction.config; + let viewPort = config.viewPorts ? config.viewPorts[viewPortInstruction.name] : {}; + + // layoutInstruction is our layout viewModel + let layoutInstruction = { + viewModel: viewPort.layoutViewModel || config.layoutViewModel || this.layoutViewModel, + view: viewPort.layoutView || config.layoutView || this.layoutView, + model: viewPort.layoutModel || config.layoutModel || this.layoutModel, + router: viewPortInstruction.component.router, + childContainer: childContainer, + viewSlot: this.viewSlot + }; - let viewStrategy = this.viewLocator.getViewStrategy(component.view || viewModel); - if (viewStrategy) { - viewStrategy.makeRelativeTo(Origin.get(component.router.container.viewModel.constructor).moduleId); - } + return Promise.resolve(this.composeLayout(layoutInstruction)) + .then(layoutView => { + let viewStrategy = this.viewLocator.getViewStrategy(component.view || viewModel); - return metadata.load(childContainer, viewModelResource.value, null, viewStrategy, true).then(viewFactory => { - if (!this.compositionTransactionNotifier) { - this.compositionTransactionOwnershipToken = this.compositionTransaction.tryCapture(); + if (viewStrategy) { + viewStrategy.makeRelativeTo(Origin.get(component.router.container.viewModel.constructor).moduleId); } - viewPortInstruction.controller = metadata.create(childContainer, - BehaviorInstruction.dynamic( - this.element, - viewModel, - viewFactory - ) - ); + return metadata.load(childContainer, viewModelResource.value, null, viewStrategy, true) + .then(viewFactory => { + if (!this.compositionTransactionNotifier) { + this.compositionTransactionOwnershipToken = this.compositionTransaction.tryCapture(); + } - if (waitToSwap) { - return; - } + viewPortInstruction.layout = layoutView ? layoutView.view || layoutView : undefined; + + viewPortInstruction.controller = metadata.create(childContainer, + BehaviorInstruction.dynamic( + this.element, + viewModel, + viewFactory + ) + ); - this.swap(viewPortInstruction); + if (waitToSwap) { + return; + } + + this.swap(viewPortInstruction); + }); }); } + composeLayout(instruction) { + if (instruction.viewModel || instruction.view) { + return this.compositionEngine.compose(instruction); + } + } + swap(viewPortInstruction) { let work = () => { let previousView = this.view; - let viewSlot = this.viewSlot; let swapStrategy; + let layout = viewPortInstruction.layout; + let viewSlot = layout ? new ViewSlot(layout.firstChild, false) : this.viewSlot; + + if (layout) { + viewSlot.attached(); + } swapStrategy = this.swapOrder in swapStrategies ? swapStrategies[this.swapOrder] : swapStrategies.after; swapStrategy(viewSlot, previousView, () => { - return Promise.resolve(viewSlot.add(viewPortInstruction.controller.view)).then(() => { - if (this.compositionTransactionNotifier) { - this.compositionTransactionNotifier.done(); - this.compositionTransactionNotifier = null; - } - }); + if (layout) { + ShadowDOM.distributeView(viewPortInstruction.controller.view, layout.slots, viewSlot); + this._notify(); + } else { + return Promise.resolve(viewSlot.add(viewPortInstruction.controller.view)).then(() => { this._notify(); }); + } + + this.view = viewPortInstruction.controller.view; }); - - this.view = viewPortInstruction.controller.view; }; viewPortInstruction.controller.automate(this.overrideContext, this.owningView); @@ -131,4 +165,11 @@ export class RouterView { work(); } + + _notify() { + if (this.compositionTransactionNotifier) { + this.compositionTransactionNotifier.done(); + this.compositionTransactionNotifier = null; + } + } } diff --git a/test/layout-default-slot-alt.html b/test/layout-default-slot-alt.html new file mode 100644 index 0000000..5a126e5 --- /dev/null +++ b/test/layout-default-slot-alt.html @@ -0,0 +1,4 @@ + diff --git a/test/layout-default-slot.html b/test/layout-default-slot.html new file mode 100644 index 0000000..c7fa10e --- /dev/null +++ b/test/layout-default-slot.html @@ -0,0 +1,4 @@ + diff --git a/test/layout-default-slot.js b/test/layout-default-slot.js new file mode 100644 index 0000000..a7ea7bb --- /dev/null +++ b/test/layout-default-slot.js @@ -0,0 +1,9 @@ +import {testConstants} from '../test/test-constants'; + +export class LayoutDefaultSlot { + constants = testConstants; + + activate(value) { + this.value = value; + } +} diff --git a/test/layout-named-slots.html b/test/layout-named-slots.html new file mode 100644 index 0000000..da730d4 --- /dev/null +++ b/test/layout-named-slots.html @@ -0,0 +1,5 @@ + diff --git a/test/module-default-slot.html b/test/module-default-slot.html new file mode 100644 index 0000000..50397cb --- /dev/null +++ b/test/module-default-slot.html @@ -0,0 +1,3 @@ + diff --git a/test/module-default-slot.js b/test/module-default-slot.js new file mode 100644 index 0000000..68cdfc6 --- /dev/null +++ b/test/module-default-slot.js @@ -0,0 +1,5 @@ +import {testConstants} from 'test/test-constants'; + +export class ModuleDefaultSlot { + constants = testConstants; +} diff --git a/test/module-named-slots.html b/test/module-named-slots.html new file mode 100644 index 0000000..674867d --- /dev/null +++ b/test/module-named-slots.html @@ -0,0 +1,4 @@ + diff --git a/test/module-named-slots.js b/test/module-named-slots.js new file mode 100644 index 0000000..f117537 --- /dev/null +++ b/test/module-named-slots.js @@ -0,0 +1,5 @@ +import {testConstants} from 'test/test-constants'; + +export class ModuleNamedSlots { + constants = testConstants; +} diff --git a/test/router-view.spec.js b/test/router-view.spec.js index 0403a5b..72c24a2 100644 --- a/test/router-view.spec.js +++ b/test/router-view.spec.js @@ -1,5 +1,174 @@ -describe('router-view', () => { - it('should exist', () => { - expect(true).toBe(true); +import {StageComponent} from 'aurelia-testing'; +import {RouteLoader, AppRouter, Router} from 'aurelia-router'; +import {TemplatingRouteLoader} from 'src/route-loader'; +import {testConstants} from 'test/test-constants'; + +describe('router-view', () => { + let component; + + beforeEach(done => { + done(); + }); + + afterEach(done => { + component.viewModel.router.navigate('default').then(() => { + component.dispose(); + done(); + }); + }); + + it('has a router instance', done => { + component = withDefaultViewport({ moduleId: 'test/module-default-slot' }); + component.create() + .then(() => { + expect(component.viewModel.router).not.toBe(undefined); + }) + .then(done); + }); + + it('loads a non-layout based view', done => { + component = withDefaultViewport({ moduleId: 'test/module-default-slot' }); + component.create() + .then(() => { + return component.viewModel.router.navigate('route'); + }) + .then(() => { + expect(component.viewModel.element.innerText).toContain(testConstants.content); + }) + .then(done); + }); + + it('loads a view-only layout', done => { + component = withDefaultViewport({ moduleId: 'test/module-default-slot', layoutView: 'test/layout-default-slot.html' }); + component.create() + .then(() => { + return component.viewModel.router.navigate('route'); + }) + .then(() => { + expect(component.viewModel.element.innerText).toContain(testConstants.content); + expect(component.viewModel.element.innerText).toContain(testConstants.defaultLayout); + }) + .then(done); + }); + + it('loads a module based layout', done => { + component = withDefaultViewport({ moduleId: 'test/module-default-slot', layoutViewModel: 'test/layout-default-slot' }); + component.create() + .then(() => { + return component.viewModel.router.navigate('route'); + }) + .then(() => { + expect(component.viewModel.element.innerText).toContain(testConstants.content); + expect(component.viewModel.element.innerText).toContain(testConstants.defaultLayout); + expect(component.viewModel.viewSlot.children[0].controller.viewModel).not.toBe(undefined); + }) + .then(done); + }); + + it('loads a module based layout with a specific view', done => { + component = withDefaultViewport({ moduleId: 'test/module-default-slot', layoutView: 'test/layout-default-slot-alt.html', layoutViewModel: 'test/layout-default-slot' }); + component.create() + .then(() => { + return component.viewModel.router.navigate('route'); + }) + .then(() => { + expect(component.viewModel.element.innerText).toContain(testConstants.content); + expect(component.viewModel.element.innerText).toContain(testConstants.altLayout); + expect(component.viewModel.viewSlot.children[0].controller.viewModel).not.toBe(undefined); + }) + .then(done); + }); + + it('loads a layout with multiple slots', done => { + component = withDefaultViewport({ moduleId: 'test/module-named-slots', layoutView: 'test/layout-named-slots.html' }); + component.create() + .then(() => { + return component.viewModel.router.navigate('route'); + }) + .then(() => { + expect(component.viewModel.element.innerText).toContain(testConstants.content + '\n' + testConstants.content); + expect(component.viewModel.element.innerText).toContain(testConstants.namedSlotsLayout); + }) + .then(done); + }); + + it('loads layouts for a named viewport', done => { + component = withNamedViewport({ + viewPorts: { + viewport1: { moduleId: 'test/module-default-slot', layoutView: 'test/layout-default-slot.html' } + } + }); + component.create() + .then(() => { + return component.viewModel.router.navigate('route'); + }) + .then(() => { + expect(component.viewModel.element.innerText).toContain(testConstants.content); + expect(component.viewModel.element.innerText).toContain(testConstants.defaultLayout); + }) + .then(done); + }); + + it('activates the layout viewmodel with a model value', done => { + component = withDefaultViewport({ moduleId: 'test/module-default-slot', layoutViewModel: 'test/layout-default-slot', layoutModel: 1 }); + component.create() + .then(() => { + return component.viewModel.router.navigate('route'); + }) + .then(() => { + expect(component.viewModel.viewSlot.children[0].controller.viewModel.value).toBe(1); + }) + .then(done); }); }); + +function withDefaultViewport(routeConfig) { + let component = StageComponent + .withResources('src/router-view') + .inView(''); + bootstrap(component, { route: ['', 'default'], moduleId: 'test/module-default-slot', activationStrategy: 'replace'}, routeConfig); + return component; +} + +function withNamedViewport(routeConfig) { + let component = StageComponent + .withResources('src/router-view') + .inView(''); + bootstrap(component, + { + route: ['', 'default'], + viewPorts: { + viewport1: { moduleId: 'test/module-default-slot' } + }, + activationStrategy: 'replace' + }, + routeConfig); + return component; +} + +function bootstrap(component, defaultRoute, routeConfig) { + component.bootstrap(aurelia => { + aurelia.use.defaultBindingLanguage() + .defaultResources() + .history(); +// .developmentLogging(); + + aurelia.use.singleton(RouteLoader, TemplatingRouteLoader) + .singleton(Router, AppRouter) + .globalResources('src/router-view', 'src/route-href'); + + if (routeConfig) { + routeConfig.activationStrategy = 'replace'; + routeConfig.route = 'route'; + routeConfig = [defaultRoute, routeConfig]; + } else { + routeConfig = [defaultRoute]; + } + + aurelia.use.container.viewModel = { + configureRouter: (config, router) => { + config.map(routeConfig); + } + }; + }); +} diff --git a/test/setup.js b/test/setup.js index 30fb7eb..a2498cc 100644 --- a/test/setup.js +++ b/test/setup.js @@ -1 +1,3 @@ import 'aurelia-polyfills'; +import {initialize} from 'aurelia-pal-browser'; +initialize(); diff --git a/test/test-constants.js b/test/test-constants.js new file mode 100644 index 0000000..bc16d29 --- /dev/null +++ b/test/test-constants.js @@ -0,0 +1,6 @@ +export const testConstants = { + content: 'test content', + defaultLayout: 'default layout', + altLayout: 'alt layout', + namedSlotsLayout: 'named slots layout' +}; diff --git a/test/test-router-view.html b/test/test-router-view.html new file mode 100644 index 0000000..3f94534 --- /dev/null +++ b/test/test-router-view.html @@ -0,0 +1,4 @@ + diff --git a/test/test-router-view.js b/test/test-router-view.js new file mode 100644 index 0000000..ddd38f3 --- /dev/null +++ b/test/test-router-view.js @@ -0,0 +1,2 @@ +export class TestRouterView { +}