diff --git a/dist/angular-breadcrumb.js b/dist/angular-breadcrumb.js index 53d025d..2a26666 100644 --- a/dist/angular-breadcrumb.js +++ b/dist/angular-breadcrumb.js @@ -1,28 +1,32 @@ -/*! angular-breadcrumb - v0.4.1-dev-2016-04-12 +/*! angular-breadcrumb - v0.4.1-dev-2016-05-03 * http://ncuillery.github.io/angular-breadcrumb * Copyright (c) 2016 Nicolas Cuillery; Licensed MIT */ (function (window, angular, undefined) { 'use strict'; -function isAOlderThanB(scopeA, scopeB) { - if(angular.equals(scopeA.length, scopeB.length)) { - return scopeA > scopeB; - } else { - return scopeA.length > scopeB.length; +function parseStateRef(ref) { + var parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/); + if (!parsed || parsed.length !== 4) { + throw new Error("Invalid state ref '" + ref + "'"); } + return {state: parsed[1], paramExpr: parsed[3] || null}; } -function parseStateRef(ref) { - var parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/); - if (!parsed || parsed.length !== 4) { throw new Error("Invalid state ref '" + ref + "'"); } - return { state: parsed[1], paramExpr: parsed[3] || null }; +function countKeys(obj) { + var keys = 0; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + keys++; + } + } + return keys; } var $registeredListeners = {}; function registerListenerOnce(tag, $rootScope, event, fn) { var deregisterListenerFn = $registeredListeners[tag]; - if ( deregisterListenerFn !== undefined ) { + if (deregisterListenerFn !== undefined) { deregisterListenerFn(); } deregisterListenerFn = $rootScope.$on(event, fn); @@ -37,28 +41,16 @@ function $Breadcrumb() { templateUrl: null, templateLast: 'default', templateLastUrl: null, - includeAbstract : false + includeAbstract: false }; - this.setOptions = function(options) { + this.setOptions = function (options) { angular.extend($$options, options); }; - this.$get = ['$state', '$stateParams', '$rootScope', function($state, $stateParams, $rootScope) { - - var $lastViewScope = $rootScope; - - // Early catch of $viewContentLoaded event - registerListenerOnce('$Breadcrumb.$viewContentLoaded', $rootScope, '$viewContentLoaded', function (event) { - // With nested views, the event occur several times, in "wrong" order - if(!event.targetScope.ncyBreadcrumbIgnore && - isAOlderThanB(event.targetScope.$id, $lastViewScope.$id)) { - $lastViewScope = event.targetScope; - } - }); - + this.$get = ['$state', '$stateParams', '$rootScope', '$injector', '$q', function ($state, $stateParams, $rootScope, $injector, $q) { // Get the parent state - var $$parentState = function(state) { + var $$parentState = function (state) { // Check if state has explicit parent OR we try guess parent from its name var parent = state.parent || (/^(.+)\.[^.]+$/.exec(state.name) || [])[1]; var isObjectParent = typeof parent === "object"; @@ -67,28 +59,26 @@ function $Breadcrumb() { }; // Add the state in the chain if not already in and if not abstract - var $$addStateInChain = function(chain, stateRef) { + var $$addStateInChain = function (chain, stateRef) { var conf, parentParams, ref = parseStateRef(stateRef), force = false, skip = false; - for(var i=0, l=chain.length; i' + - '
  • ' + - '{{step.ncyBreadcrumbLabel}}' + - '{{step.ncyBreadcrumbLabel}}' + - '/' + - '
  • ' + - '', + '
  • ' + + '{{step.ncyBreadcrumbLabel}}' + + '{{step.ncyBreadcrumbLabel}}' + + '/' + + '
  • ' + + '', bootstrap3: '' + '
  • ' + + '{{step.ncyBreadcrumbLabel}}' + + '{{step.ncyBreadcrumbLabel}}' + + '
  • ' + + '' }; return { @@ -237,26 +286,38 @@ function BreadcrumbDirective($interpolate, $breadcrumb, $rootScope) { post: function postLink(scope) { var labelWatchers = []; - var renderBreadcrumb = function() { + var renderBreadcrumb = function () { deregisterWatchers(labelWatchers); labelWatchers = []; var viewScope = $breadcrumb.$getLastViewScope(); - scope.steps = $breadcrumb.getStatesChain(); - angular.forEach(scope.steps, function (step) { - if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) { - var parseLabel = $interpolate(step.ncyBreadcrumb.label); - step.ncyBreadcrumbLabel = parseLabel(viewScope); - // Watcher for further viewScope updates - registerWatchers(labelWatchers, parseLabel, viewScope, step); - } else { - step.ncyBreadcrumbLabel = step.name; - } + var locals = $breadcrumb.$getLastViewLocals(); + $breadcrumb.getStatesChain().then(function (chain) { + scope.steps = chain; + angular.forEach(scope.steps, function (step) { + if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) { + var type = Object.prototype.toString.call(step.ncyBreadcrumb.label); + if (type === '[object Function]' || + type === '[object Array]') { + $q.when($injector.invoke(step.ncyBreadcrumb.label, null, locals)).then(function (label) { + step.ncyBreadcrumbLabel = label; + }); + } else { + var parseLabel = $interpolate(step.ncyBreadcrumb.label); + step.ncyBreadcrumbLabel = parseLabel(viewScope); + // Watcher for further viewScope updates + registerWatchers(labelWatchers, parseLabel, viewScope, step); + } + } else { + step.ncyBreadcrumbLabel = step.name; + } + }); }); }; registerListenerOnce('BreadcrumbDirective.$viewContentLoaded', $rootScope, '$viewContentLoaded', function (event) { - if(!event.targetScope.ncyBreadcrumbIgnore) { + var viewScope = $breadcrumb.$getLastViewScope(); + if ($rootScope === viewScope || event.targetScope === viewScope) { renderBreadcrumb(); } }); @@ -267,11 +328,11 @@ function BreadcrumbDirective($interpolate, $breadcrumb, $rootScope) { } }; } -BreadcrumbDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope']; +BreadcrumbDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope', '$injector', '$q']; -function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope) { +function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope, $injector, $q) { var $$templates = { - 'default': '{{ncyBreadcrumbLabel}}' + 'default': '{{ncyBreadcrumbLabel}}' }; return { @@ -279,13 +340,13 @@ function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope) { scope: {}, template: $breadcrumb.getTemplateLast($$templates), templateUrl: $breadcrumb.getTemplateLastUrl(), - compile: function(cElement, cAttrs) { + compile: function (cElement, cAttrs) { // Override the default template if ncyBreadcrumbLast has a value // This should likely be removed in a future version since global // templating is now available for ncyBreadcrumbLast var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbLast); - if(template) { + if (template) { cElement.html(template); } @@ -293,28 +354,40 @@ function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope) { post: function postLink(scope) { var labelWatchers = []; - var renderLabel = function() { + var renderLabel = function () { deregisterWatchers(labelWatchers); labelWatchers = []; var viewScope = $breadcrumb.$getLastViewScope(); - var lastStep = $breadcrumb.getLastStep(); - if(lastStep) { + var locals = $breadcrumb.$getLastViewLocals(); + $breadcrumb.getLastStep().then(function (lastStep) { + if (!lastStep) { + return; + } scope.ncyBreadcrumbLink = lastStep.ncyBreadcrumbLink; if (lastStep.ncyBreadcrumb && lastStep.ncyBreadcrumb.label) { - var parseLabel = $interpolate(lastStep.ncyBreadcrumb.label); - scope.ncyBreadcrumbLabel = parseLabel(viewScope); - // Watcher for further viewScope updates - // Tricky last arg: the last step is the entire scope of the directive ! - registerWatchers(labelWatchers, parseLabel, viewScope, scope); + var type = Object.prototype.toString.call(lastStep.ncyBreadcrumb.label); + if (type === '[object Function]' || + type === '[object Array]') { + $q.when($injector.invoke(lastStep.ncyBreadcrumb.label, null, locals)).then(function (label) { + scope.ncyBreadcrumbLabel = label; + }); + } else { + var parseLabel = $interpolate(lastStep.ncyBreadcrumb.label); + scope.ncyBreadcrumbLabel = parseLabel(viewScope); + // Watcher for further viewScope updates + // Tricky last arg: the last step is the entire scope of the directive ! + registerWatchers(labelWatchers, parseLabel, viewScope, scope); + } } else { scope.ncyBreadcrumbLabel = lastStep.name; } - } + }); }; registerListenerOnce('BreadcrumbLastDirective.$viewContentLoaded', $rootScope, '$viewContentLoaded', function (event) { - if(!event.targetScope.ncyBreadcrumbIgnore) { + var viewScope = $breadcrumb.$getLastViewScope(); + if ($rootScope === viewScope || event.targetScope === viewScope) { renderLabel(); } }); @@ -327,19 +400,19 @@ function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope) { } }; } -BreadcrumbLastDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope']; +BreadcrumbLastDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope', '$injector', '$q']; -function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope) { +function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope, $injector, $q) { return { restrict: 'A', scope: {}, template: '{{ncyBreadcrumbChain}}', - compile: function(cElement, cAttrs) { + compile: function (cElement, cAttrs) { // Override the default template if ncyBreadcrumbText has a value var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbText); - if(template) { + if (template) { cElement.html(template); } @@ -349,9 +422,9 @@ function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope) { post: function postLink(scope) { var labelWatchers = []; - var registerWatchersText = function(labelWatcherArray, interpolationFunction, viewScope) { - angular.forEach(getExpression(interpolationFunction), function(expression) { - var watcher = viewScope.$watch(expression, function(newValue, oldValue) { + var registerWatchersText = function (labelWatcherArray, interpolationFunction, viewScope) { + angular.forEach(getExpression(interpolationFunction), function (expression) { + var watcher = viewScope.$watch(expression, function (newValue, oldValue) { if (newValue !== oldValue) { renderLabel(); } @@ -360,29 +433,41 @@ function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope) { }); }; - var renderLabel = function() { + var renderLabel = function () { deregisterWatchers(labelWatchers); labelWatchers = []; var viewScope = $breadcrumb.$getLastViewScope(); - var steps = $breadcrumb.getStatesChain(); - var combinedLabels = []; - angular.forEach(steps, function (step) { - if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) { - var parseLabel = $interpolate(step.ncyBreadcrumb.label); - combinedLabels.push(parseLabel(viewScope)); - // Watcher for further viewScope updates - registerWatchersText(labelWatchers, parseLabel, viewScope); - } else { - combinedLabels.push(step.name); - } - }); + var locals = $breadcrumb.$getLastViewLocals(); + $breadcrumb.getStatesChain().then(function (steps) { + var combinedLabels = []; + angular.forEach(steps, function (step) { + if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) { + var type = Object.prototype.toString.call(step.ncyBreadcrumb.label); + if (type === '[object Function]' || + type === '[object Array]') { + combinedLabels.push($q.when($injector.invoke(step.ncyBreadcrumb.label, null, locals))); + } else { + var parseLabel = $interpolate(step.ncyBreadcrumb.label); + combinedLabels.push($q.when(parseLabel(viewScope))); + // Watcher for further viewScope updates + registerWatchersText(labelWatchers, parseLabel, viewScope); + } + } else { + combinedLabels.push($q.when(step.name)); + } + }); - scope.ncyBreadcrumbChain = combinedLabels.join(separator); + scope.ncyBreadcrumbChain = []; + $q.all(combinedLabels).then(function (labels) { + scope.ncyBreadcrumbChain = labels.join(separator); + }); + }); }; registerListenerOnce('BreadcrumbTextDirective.$viewContentLoaded', $rootScope, '$viewContentLoaded', function (event) { - if(!event.targetScope.ncyBreadcrumbIgnore) { + var viewScope = $breadcrumb.$getLastViewScope(); + if ($rootScope === viewScope || event.targetScope === viewScope) { renderLabel(); } }); @@ -395,7 +480,7 @@ function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope) { } }; } -BreadcrumbTextDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope']; +BreadcrumbTextDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope', '$injector', '$q']; angular.module('ncy-angular-breadcrumb', ['ui.router.state']) .provider('$breadcrumb', $Breadcrumb) diff --git a/dist/angular-breadcrumb.min.js b/dist/angular-breadcrumb.min.js index e91e05e..63f62d8 100644 --- a/dist/angular-breadcrumb.min.js +++ b/dist/angular-breadcrumb.min.js @@ -1,4 +1,4 @@ -/*! angular-breadcrumb - v0.4.1-dev-2016-04-12 +/*! angular-breadcrumb - v0.4.1-dev-2016-05-03 * http://ncuillery.github.io/angular-breadcrumb * Copyright (c) 2016 Nicolas Cuillery; Licensed MIT */ -!function(a,b,c){"use strict";function d(a,c){return b.equals(a.length,c.length)?a>c:a.length>c.length}function e(a){var b=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/);if(!b||4!==b.length)throw new Error("Invalid state ref '"+a+"'");return{state:b[1],paramExpr:b[3]||null}}function f(a,b,d,e){var f=k[a];f!==c&&f(),f=b.$on(d,e),k[a]=f}function g(){var a={prefixStateName:null,template:"bootstrap3",templateUrl:null,templateLast:"default",templateLastUrl:null,includeAbstract:!1};this.setOptions=function(c){b.extend(a,c)},this.$get=["$state","$stateParams","$rootScope",function(b,g,h){var i=h;f("$Breadcrumb.$viewContentLoaded",h,"$viewContentLoaded",function(a){!a.targetScope.ncyBreadcrumbIgnore&&d(a.targetScope.$id,i.$id)&&(i=a.targetScope)});var j=function(a){var b=a.parent||(/^(.+)\.[^.]+$/.exec(a.name)||[])[1],c="object"==typeof b;return c?b.name:b},k=function(c,d){for(var f,h,j=e(d),k=!1,l=!1,m=0,n=c.length;n>m;m+=1)if(c[m].name===j.state)return;f=b.get(j.state),f.ncyBreadcrumb&&(f.ncyBreadcrumb.force&&(k=!0),f.ncyBreadcrumb.skip&&(l=!0)),f["abstract"]&&!a.includeAbstract&&!k||l||(j.paramExpr&&(h=i.$eval(j.paramExpr)),f.ncyBreadcrumbLink=b.href(j.state,h||g||{}),f.ncyBreadcrumbStateRef=d,c.unshift(f))},l=function(a){var c=e(a),d=b.get(c.state);if(d.ncyBreadcrumb&&d.ncyBreadcrumb.parent){var f="function"==typeof d.ncyBreadcrumb.parent,g=f?d.ncyBreadcrumb.parent(i):d.ncyBreadcrumb.parent;if(g)return g}return j(d)};return{getTemplate:function(b){return a.templateUrl?null:b[a.template]?b[a.template]:a.template},getTemplateUrl:function(){return a.templateUrl},getTemplateLast:function(b){return a.templateLastUrl?null:b[a.templateLast]?b[a.templateLast]:a.templateLast},getTemplateLastUrl:function(){return a.templateLastUrl},getStatesChain:function(c){for(var d=[],e=b.$current.self.name;e;e=l(e))if(k(d,e),c&&d.length)return d;return a.prefixStateName&&k(d,a.prefixStateName),d},getLastStep:function(){var a=this.getStatesChain(!0);return a.length?a[0]:c},$getLastViewScope:function(){return i}}}]}function h(a,c,d){var e={bootstrap2:'',bootstrap3:''};return{restrict:"AE",replace:!0,scope:{},template:c.getTemplate(e),templateUrl:c.getTemplateUrl(),link:{post:function(e){var g=[],h=function(){n(g),g=[];var d=c.$getLastViewScope();e.steps=c.getStatesChain(),b.forEach(e.steps,function(b){if(b.ncyBreadcrumb&&b.ncyBreadcrumb.label){var c=a(b.ncyBreadcrumb.label);b.ncyBreadcrumbLabel=c(d),m(g,c,d,b)}else b.ncyBreadcrumbLabel=b.name})};f("BreadcrumbDirective.$viewContentLoaded",d,"$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||h()}),h()}}}}function i(a,b,c){var d={"default":"{{ncyBreadcrumbLabel}}"};return{restrict:"A",scope:{},template:b.getTemplateLast(d),templateUrl:b.getTemplateLastUrl(),compile:function(d,e){var g=d.attr(e.$attr.ncyBreadcrumbLast);return g&&d.html(g),{post:function(d){var e=[],g=function(){n(e),e=[];var c=b.$getLastViewScope(),f=b.getLastStep();if(f)if(d.ncyBreadcrumbLink=f.ncyBreadcrumbLink,f.ncyBreadcrumb&&f.ncyBreadcrumb.label){var g=a(f.ncyBreadcrumb.label);d.ncyBreadcrumbLabel=g(c),m(e,g,c,d)}else d.ncyBreadcrumbLabel=f.name};f("BreadcrumbLastDirective.$viewContentLoaded",c,"$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||g()}),g()}}}}}function j(a,c,d){return{restrict:"A",scope:{},template:"{{ncyBreadcrumbChain}}",compile:function(e,g){var h=e.attr(g.$attr.ncyBreadcrumbText);h&&e.html(h);var i=e.attr(g.$attr.ncyBreadcrumbTextSeparator)||" / ";return{post:function(e){var g=[],h=function(a,c,d){b.forEach(l(c),function(b){var c=d.$watch(b,function(a,b){a!==b&&j()});a.push(c)})},j=function(){n(g),g=[];var d=c.$getLastViewScope(),f=c.getStatesChain(),j=[];b.forEach(f,function(b){if(b.ncyBreadcrumb&&b.ncyBreadcrumb.label){var c=a(b.ncyBreadcrumb.label);j.push(c(d)),h(g,c,d)}else j.push(b.name)}),e.ncyBreadcrumbChain=j.join(i)};f("BreadcrumbTextDirective.$viewContentLoaded",d,"$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||j()}),j()}}}}}var k={},l=function(a){if(a.expressions)return a.expressions;var c=[];return b.forEach(a.parts,function(a){b.isFunction(a)&&c.push(a.exp)}),c},m=function(a,c,d,e){b.forEach(l(c),function(b){var f=d.$watch(b,function(){e.ncyBreadcrumbLabel=c(d)});a.push(f)})},n=function(a){b.forEach(a,function(a){a()})};h.$inject=["$interpolate","$breadcrumb","$rootScope"],i.$inject=["$interpolate","$breadcrumb","$rootScope"],j.$inject=["$interpolate","$breadcrumb","$rootScope"],b.module("ncy-angular-breadcrumb",["ui.router.state"]).provider("$breadcrumb",g).directive("ncyBreadcrumb",h).directive("ncyBreadcrumbLast",i).directive("ncyBreadcrumbText",j)}(window,window.angular); \ No newline at end of file +!function(a,b,c){"use strict";function d(a){var b=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/);if(!b||4!==b.length)throw new Error("Invalid state ref '"+a+"'");return{state:b[1],paramExpr:b[3]||null}}function e(a){var b=0;for(var c in a)a.hasOwnProperty(c)&&b++;return b}function f(a,b,d,e){var f=k[a];f!==c&&f(),f=b.$on(d,e),k[a]=f}function g(){var a={prefixStateName:null,template:"bootstrap3",templateUrl:null,templateLast:"default",templateLastUrl:null,includeAbstract:!1};this.setOptions=function(c){b.extend(a,c)},this.$get=["$state","$stateParams","$rootScope","$injector","$q",function(f,g,h,i,j){function k(){var a=f.$current,b=e(a.views);if(b){if(a.ncyBreadcrumb&&a.ncyBreadcrumb.mainView)return a.locals[a.ncyBreadcrumb.mainView];if(1===b){for(var c in a.views)if(a.views.hasOwnProperty(c))return a.locals[c]}else if(a.views["@"])return a.locals["@"];throw new Error("Multiple views found and mainView was not defined")}}function l(){var a=k();return a?a.$scope||h:h}function m(a,b,c){return q(b).then(function(b){return!b||c&&a.length?a:(p(a,b),m(a,b,c))})}function n(b){!a.prefixStateName||b.length&&a.prefixStateName===b[0].name||p(b,a.prefixStateName)}var o=function(a){var b=a.parent||(/^(.+)\.[^.]+$/.exec(a.name)||[])[1],c="object"==typeof b;return c?b.name:b},p=function(c,e){var h,i,j=d(e),k=!1,m=!1;h=b.copy(f.get(j.state)),h.ncyBreadcrumb&&(h.ncyBreadcrumb.force&&(k=!0),h.ncyBreadcrumb.skip&&(m=!0)),h["abstract"]&&!a.includeAbstract&&!k||m||(j.paramExpr&&(i=l().$eval(j.paramExpr)),h.ncyBreadcrumbLink=f.href(j.state,i||g||{}),h.ncyBreadcrumbStateRef=e,c.unshift(h))},q=function(a){var b=d(a),c=f.get(b.state);if(c.ncyBreadcrumb&&c.ncyBreadcrumb.parent){var e,g,h=Object.prototype.toString.call(c.ncyBreadcrumb.parent);if("[object Function]"===h||"[object Array]"===h?(g=k(),e=i.invoke(c.ncyBreadcrumb.parent,null,g)):e=c.ncyBreadcrumb.parent,e)return j.when(e)}return j.when(o(c))};return{getTemplate:function(b){return a.templateUrl?null:b[a.template]?b[a.template]:a.template},getTemplateUrl:function(){return a.templateUrl},getTemplateLast:function(b){return a.templateLastUrl?null:b[a.templateLast]?b[a.templateLast]:a.templateLast},getTemplateLastUrl:function(){return a.templateLastUrl},getStatesChain:function(a){var b=[];if(!f.$current.self.name)return n(b),j.when(b);if(p(b,f.$current.self.name),a&&b.length)return j.when(b);var c=m(b,f.$current.self.name,a);return j.when(c).then(function(){return n(b),b})},getLastStep:function(){return this.getStatesChain(!0).then(function(a){return a.length?a[0]:c})},$getLastViewScope:l,$getLastViewLocals:k}}]}function h(a,c,d,e,g){var h={bootstrap2:'',bootstrap3:''};return{restrict:"AE",replace:!0,scope:{},template:c.getTemplate(h),templateUrl:c.getTemplateUrl(),link:{post:function(h){var i=[],j=function(){n(i),i=[];var d=c.$getLastViewScope(),f=c.$getLastViewLocals();c.getStatesChain().then(function(c){h.steps=c,b.forEach(h.steps,function(b){if(b.ncyBreadcrumb&&b.ncyBreadcrumb.label){var c=Object.prototype.toString.call(b.ncyBreadcrumb.label);if("[object Function]"===c||"[object Array]"===c)g.when(e.invoke(b.ncyBreadcrumb.label,null,f)).then(function(a){b.ncyBreadcrumbLabel=a});else{var h=a(b.ncyBreadcrumb.label);b.ncyBreadcrumbLabel=h(d),m(i,h,d,b)}}else b.ncyBreadcrumbLabel=b.name})})};f("BreadcrumbDirective.$viewContentLoaded",d,"$viewContentLoaded",function(a){var b=c.$getLastViewScope();(d===b||a.targetScope===b)&&j()}),j()}}}}function i(a,b,c,d,e){var g={"default":"{{ncyBreadcrumbLabel}}"};return{restrict:"A",scope:{},template:b.getTemplateLast(g),templateUrl:b.getTemplateLastUrl(),compile:function(g,h){var i=g.attr(h.$attr.ncyBreadcrumbLast);return i&&g.html(i),{post:function(g){var h=[],i=function(){n(h),h=[];var c=b.$getLastViewScope(),f=b.$getLastViewLocals();b.getLastStep().then(function(b){if(b)if(g.ncyBreadcrumbLink=b.ncyBreadcrumbLink,b.ncyBreadcrumb&&b.ncyBreadcrumb.label){var i=Object.prototype.toString.call(b.ncyBreadcrumb.label);if("[object Function]"===i||"[object Array]"===i)e.when(d.invoke(b.ncyBreadcrumb.label,null,f)).then(function(a){g.ncyBreadcrumbLabel=a});else{var j=a(b.ncyBreadcrumb.label);g.ncyBreadcrumbLabel=j(c),m(h,j,c,g)}}else g.ncyBreadcrumbLabel=b.name})};f("BreadcrumbLastDirective.$viewContentLoaded",c,"$viewContentLoaded",function(a){var d=b.$getLastViewScope();(c===d||a.targetScope===d)&&i()}),i()}}}}}function j(a,c,d,e,g){return{restrict:"A",scope:{},template:"{{ncyBreadcrumbChain}}",compile:function(h,i){var j=h.attr(i.$attr.ncyBreadcrumbText);j&&h.html(j);var k=h.attr(i.$attr.ncyBreadcrumbTextSeparator)||" / ";return{post:function(h){var i=[],j=function(a,c,d){b.forEach(l(c),function(b){var c=d.$watch(b,function(a,b){a!==b&&m()});a.push(c)})},m=function(){n(i),i=[];var d=c.$getLastViewScope(),f=c.$getLastViewLocals();c.getStatesChain().then(function(c){var l=[];b.forEach(c,function(b){if(b.ncyBreadcrumb&&b.ncyBreadcrumb.label){var c=Object.prototype.toString.call(b.ncyBreadcrumb.label);if("[object Function]"===c||"[object Array]"===c)l.push(g.when(e.invoke(b.ncyBreadcrumb.label,null,f)));else{var h=a(b.ncyBreadcrumb.label);l.push(g.when(h(d))),j(i,h,d)}}else l.push(g.when(b.name))}),h.ncyBreadcrumbChain=[],g.all(l).then(function(a){h.ncyBreadcrumbChain=a.join(k)})})};f("BreadcrumbTextDirective.$viewContentLoaded",d,"$viewContentLoaded",function(a){var b=c.$getLastViewScope();(d===b||a.targetScope===b)&&m()}),m()}}}}}var k={},l=function(a){if(a.expressions)return a.expressions;var c=[];return b.forEach(a.parts,function(a){b.isFunction(a)&&c.push(a.exp)}),c},m=function(a,c,d,e){b.forEach(l(c),function(b){var f=d.$watch(b,function(){e.ncyBreadcrumbLabel=c(d)});a.push(f)})},n=function(a){b.forEach(a,function(a){a()})};h.$inject=["$interpolate","$breadcrumb","$rootScope","$injector","$q"],i.$inject=["$interpolate","$breadcrumb","$rootScope","$injector","$q"],j.$inject=["$interpolate","$breadcrumb","$rootScope","$injector","$q"],b.module("ncy-angular-breadcrumb",["ui.router.state"]).provider("$breadcrumb",g).directive("ncyBreadcrumb",h).directive("ncyBreadcrumbLast",i).directive("ncyBreadcrumbText",j)}(window,window.angular); \ No newline at end of file diff --git a/karma.conf.js b/karma.conf.js index 899112b..b16337c 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -19,6 +19,7 @@ module.exports = function(config) { 'bower_components/underscore/underscore.js', 'src/angular-breadcrumb.js', 'sample/app.js', + 'sample/controllers/room_list.js', 'sample/controllers/room_detail.js', 'test/mock/**/*.js', 'test/spec/**/*.js' diff --git a/release/angular-breadcrumb.js b/release/angular-breadcrumb.js index ba6e5dc..e773f87 100644 --- a/release/angular-breadcrumb.js +++ b/release/angular-breadcrumb.js @@ -1,4 +1,4 @@ -/*! angular-breadcrumb - v0.4.1 +/*! angular-breadcrumb - v0.4.1-dev-2015-09-08 * http://ncuillery.github.io/angular-breadcrumb * Copyright (c) 2015 Nicolas Cuillery; Licensed MIT */ @@ -180,7 +180,7 @@ var deregisterWatchers = function(labelWatcherArray) { }); }; -function BreadcrumbDirective($interpolate, $breadcrumb, $rootScope) { +function BreadcrumbDirective($interpolate, $breadcrumb, $rootScope, $injector) { var $$templates = { bootstrap2: '', + '
  • ' + + '{{step.ncyBreadcrumbLabel}}' + + '{{step.ncyBreadcrumbLabel}}' + + '/' + + '
  • ' + + '', bootstrap3: '' + '
  • ' + + '{{step.ncyBreadcrumbLabel}}' + + '{{step.ncyBreadcrumbLabel}}' + + '
  • ' + + '' }; return { @@ -232,26 +281,38 @@ function BreadcrumbDirective($interpolate, $breadcrumb, $rootScope) { post: function postLink(scope) { var labelWatchers = []; - var renderBreadcrumb = function() { + var renderBreadcrumb = function () { deregisterWatchers(labelWatchers); labelWatchers = []; var viewScope = $breadcrumb.$getLastViewScope(); - scope.steps = $breadcrumb.getStatesChain(); - angular.forEach(scope.steps, function (step) { - if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) { - var parseLabel = $interpolate(step.ncyBreadcrumb.label); - step.ncyBreadcrumbLabel = parseLabel(viewScope); - // Watcher for further viewScope updates - registerWatchers(labelWatchers, parseLabel, viewScope, step); - } else { - step.ncyBreadcrumbLabel = step.name; - } + var locals = $breadcrumb.$getLastViewLocals(); + $breadcrumb.getStatesChain().then(function (chain) { + scope.steps = chain; + angular.forEach(scope.steps, function (step) { + if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) { + var type = Object.prototype.toString.call(step.ncyBreadcrumb.label); + if (type === '[object Function]' || + type === '[object Array]') { + $q.when($injector.invoke(step.ncyBreadcrumb.label, null, locals)).then(function (label) { + step.ncyBreadcrumbLabel = label; + }); + } else { + var parseLabel = $interpolate(step.ncyBreadcrumb.label); + step.ncyBreadcrumbLabel = parseLabel(viewScope); + // Watcher for further viewScope updates + registerWatchers(labelWatchers, parseLabel, viewScope, step); + } + } else { + step.ncyBreadcrumbLabel = step.name; + } + }); }); }; registerListenerOnce('BreadcrumbDirective.$viewContentLoaded', $rootScope, '$viewContentLoaded', function (event) { - if(!event.targetScope.ncyBreadcrumbIgnore) { + var viewScope = $breadcrumb.$getLastViewScope(); + if ($rootScope === viewScope || event.targetScope === viewScope) { renderBreadcrumb(); } }); @@ -262,11 +323,11 @@ function BreadcrumbDirective($interpolate, $breadcrumb, $rootScope) { } }; } -BreadcrumbDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope']; +BreadcrumbDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope', '$injector', '$q']; -function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope) { +function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope, $injector, $q) { var $$templates = { - 'default': '{{ncyBreadcrumbLabel}}' + 'default': '{{ncyBreadcrumbLabel}}' }; return { @@ -274,13 +335,13 @@ function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope) { scope: {}, template: $breadcrumb.getTemplateLast($$templates), templateUrl: $breadcrumb.getTemplateLastUrl(), - compile: function(cElement, cAttrs) { + compile: function (cElement, cAttrs) { // Override the default template if ncyBreadcrumbLast has a value // This should likely be removed in a future version since global // templating is now available for ncyBreadcrumbLast var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbLast); - if(template) { + if (template) { cElement.html(template); } @@ -288,28 +349,40 @@ function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope) { post: function postLink(scope) { var labelWatchers = []; - var renderLabel = function() { + var renderLabel = function () { deregisterWatchers(labelWatchers); labelWatchers = []; var viewScope = $breadcrumb.$getLastViewScope(); - var lastStep = $breadcrumb.getLastStep(); - if(lastStep) { + var locals = $breadcrumb.$getLastViewLocals(); + $breadcrumb.getLastStep().then(function (lastStep) { + if (!lastStep) { + return; + } scope.ncyBreadcrumbLink = lastStep.ncyBreadcrumbLink; if (lastStep.ncyBreadcrumb && lastStep.ncyBreadcrumb.label) { - var parseLabel = $interpolate(lastStep.ncyBreadcrumb.label); - scope.ncyBreadcrumbLabel = parseLabel(viewScope); - // Watcher for further viewScope updates - // Tricky last arg: the last step is the entire scope of the directive ! - registerWatchers(labelWatchers, parseLabel, viewScope, scope); + var type = Object.prototype.toString.call(lastStep.ncyBreadcrumb.label); + if (type === '[object Function]' || + type === '[object Array]') { + $q.when($injector.invoke(lastStep.ncyBreadcrumb.label, null, locals)).then(function (label) { + scope.ncyBreadcrumbLabel = label; + }); + } else { + var parseLabel = $interpolate(lastStep.ncyBreadcrumb.label); + scope.ncyBreadcrumbLabel = parseLabel(viewScope); + // Watcher for further viewScope updates + // Tricky last arg: the last step is the entire scope of the directive ! + registerWatchers(labelWatchers, parseLabel, viewScope, scope); + } } else { scope.ncyBreadcrumbLabel = lastStep.name; } - } + }); }; registerListenerOnce('BreadcrumbLastDirective.$viewContentLoaded', $rootScope, '$viewContentLoaded', function (event) { - if(!event.targetScope.ncyBreadcrumbIgnore) { + var viewScope = $breadcrumb.$getLastViewScope(); + if ($rootScope === viewScope || event.targetScope === viewScope) { renderLabel(); } }); @@ -322,19 +395,19 @@ function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope) { } }; } -BreadcrumbLastDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope']; +BreadcrumbLastDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope', '$injector', '$q']; -function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope) { +function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope, $injector, $q) { return { restrict: 'A', scope: {}, template: '{{ncyBreadcrumbChain}}', - compile: function(cElement, cAttrs) { + compile: function (cElement, cAttrs) { // Override the default template if ncyBreadcrumbText has a value var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbText); - if(template) { + if (template) { cElement.html(template); } @@ -344,9 +417,9 @@ function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope) { post: function postLink(scope) { var labelWatchers = []; - var registerWatchersText = function(labelWatcherArray, interpolationFunction, viewScope) { - angular.forEach(getExpression(interpolationFunction), function(expression) { - var watcher = viewScope.$watch(expression, function(newValue, oldValue) { + var registerWatchersText = function (labelWatcherArray, interpolationFunction, viewScope) { + angular.forEach(getExpression(interpolationFunction), function (expression) { + var watcher = viewScope.$watch(expression, function (newValue, oldValue) { if (newValue !== oldValue) { renderLabel(); } @@ -355,29 +428,41 @@ function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope) { }); }; - var renderLabel = function() { + var renderLabel = function () { deregisterWatchers(labelWatchers); labelWatchers = []; var viewScope = $breadcrumb.$getLastViewScope(); - var steps = $breadcrumb.getStatesChain(); - var combinedLabels = []; - angular.forEach(steps, function (step) { - if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) { - var parseLabel = $interpolate(step.ncyBreadcrumb.label); - combinedLabels.push(parseLabel(viewScope)); - // Watcher for further viewScope updates - registerWatchersText(labelWatchers, parseLabel, viewScope); - } else { - combinedLabels.push(step.name); - } - }); + var locals = $breadcrumb.$getLastViewLocals(); + $breadcrumb.getStatesChain().then(function (steps) { + var combinedLabels = []; + angular.forEach(steps, function (step) { + if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) { + var type = Object.prototype.toString.call(step.ncyBreadcrumb.label); + if (type === '[object Function]' || + type === '[object Array]') { + combinedLabels.push($q.when($injector.invoke(step.ncyBreadcrumb.label, null, locals))); + } else { + var parseLabel = $interpolate(step.ncyBreadcrumb.label); + combinedLabels.push($q.when(parseLabel(viewScope))); + // Watcher for further viewScope updates + registerWatchersText(labelWatchers, parseLabel, viewScope); + } + } else { + combinedLabels.push($q.when(step.name)); + } + }); - scope.ncyBreadcrumbChain = combinedLabels.join(separator); + scope.ncyBreadcrumbChain = []; + $q.all(combinedLabels).then(function (labels) { + scope.ncyBreadcrumbChain = labels.join(separator); + }); + }); }; registerListenerOnce('BreadcrumbTextDirective.$viewContentLoaded', $rootScope, '$viewContentLoaded', function (event) { - if(!event.targetScope.ncyBreadcrumbIgnore) { + var viewScope = $breadcrumb.$getLastViewScope(); + if ($rootScope === viewScope || event.targetScope === viewScope) { renderLabel(); } }); @@ -390,7 +475,7 @@ function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope) { } }; } -BreadcrumbTextDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope']; +BreadcrumbTextDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope', '$injector', '$q']; angular.module('ncy-angular-breadcrumb', ['ui.router.state']) .provider('$breadcrumb', $Breadcrumb) diff --git a/test/mock/test-modules.js b/test/mock/test-modules.js index 3cfbd0d..32c868a 100644 --- a/test/mock/test-modules.js +++ b/test/mock/test-modules.js @@ -5,14 +5,14 @@ */ angular.module('ncy-basic-conf', []).config(function($stateProvider) { $stateProvider - .state('A', {url: '/a', ncyBreadcrumb: {label: 'State A'}}) - .state('A.B', {url: '/b', ncyBreadcrumb: {label: 'State B'}}) - .state('A.B.C', {url: '/c', ncyBreadcrumb: {label: 'State C'}}) - .state('D', {parent: 'A.B.C', url: '/d', ncyBreadcrumb: {label: 'State D'}}) // Explicit parent - .state('D.E', {url: '/e', ncyBreadcrumb: {label: 'State E', skip: true}}) - .state('D.E.F', {url: '/f', ncyBreadcrumb: {label: 'State F'}}) - .state('G', {url: '/g', ncyBreadcrumb: {label: 'State G', skip: true}}) - .state('G.H', {url: '/h', ncyBreadcrumb: {label: 'State H'}}); + .state('A', {url: '/a', template: '
    ', ncyBreadcrumb: {label: 'State A'}}) + .state('A.B', {url: '/b', template: '
    ', ncyBreadcrumb: {label: 'State B'}}) + .state('A.B.C', {url: '/c', template: '
    ', ncyBreadcrumb: {label: 'State C'}}) + .state('D', {parent: 'A.B.C', url: '/d', template: '
    ', ncyBreadcrumb: {label: 'State D'}}) // Explicit parent + .state('D.E', {url: '/e', template: '
    ', ncyBreadcrumb: {label: 'State E', skip: true}}) + .state('D.E.F', {url: '/f', template: '
    ', ncyBreadcrumb: {label: 'State F'}}) + .state('G', {url: '/g', template: '
    ', ncyBreadcrumb: {label: 'State G', skip: true}}) + .state('G.H', {url: '/h', template: '
    ', ncyBreadcrumb: {label: 'State H'}}); }); /** @@ -20,18 +20,18 @@ angular.module('ncy-basic-conf', []).config(function($stateProvider) { */ angular.module('ncy-abstract-conf', []).config(function($stateProvider) { $stateProvider - .state('A', {url: '/a', abstract: true, ncyBreadcrumb: {label: 'State A'}}) - .state('A.B', {url: '/b', ncyBreadcrumb: {label: 'State B'}}) - .state('A.B.C', {url: '/c', ncyBreadcrumb: {label: 'State C'}}) - .state('D', {url: '/d', ncyBreadcrumb: {label: 'State D'}}) - .state('D.E', {url: '/e', abstract: true, ncyBreadcrumb: {label: 'State E'}}) - .state('D.E.F', {url: '/f', ncyBreadcrumb: {label: 'State F'}}) - .state('G', {url: '/g', abstract: true, ncyBreadcrumb: {label: 'State G', skip: true}}) - .state('G.H', {url: '/h', ncyBreadcrumb: {label: 'State H'}}) - .state('I', {url: '/i', abstract: true, ncyBreadcrumb: {label: 'State I', force: true}}) - .state('I.J', {url: '/j', ncyBreadcrumb: {label: 'State J'}}) - .state('K', {url: '/k', abstract: true, ncyBreadcrumb: {label: 'State K', skip: true, force: true}}) - .state('K.L', {url: '/l', ncyBreadcrumb: {label: 'State L'}}); + .state('A', {url: '/a', template: '
    ', abstract: true, ncyBreadcrumb: {label: 'State A'}}) + .state('A.B', {url: '/b', template: '
    ', ncyBreadcrumb: {label: 'State B'}}) + .state('A.B.C', {url: '/c', template: '
    ', ncyBreadcrumb: {label: 'State C'}}) + .state('D', {url: '/d', template: '
    ', ncyBreadcrumb: {label: 'State D'}}) + .state('D.E', {url: '/e', template: '
    ', abstract: true, ncyBreadcrumb: {label: 'State E'}}) + .state('D.E.F', {url: '/f', template: '
    ', ncyBreadcrumb: {label: 'State F'}}) + .state('G', {url: '/g', template: '
    ', abstract: true, ncyBreadcrumb: {label: 'State G', skip: true}}) + .state('G.H', {url: '/h', template: '
    ', ncyBreadcrumb: {label: 'State H'}}) + .state('I', {url: '/i', template: '
    ', abstract: true, ncyBreadcrumb: {label: 'State I', force: true}}) + .state('I.J', {url: '/j', template: '
    ', ncyBreadcrumb: {label: 'State J'}}) + .state('K', {url: '/k', template: '
    ', abstract: true, ncyBreadcrumb: {label: 'State K', skip: true, force: true}}) + .state('K.L', {url: '/l', template: '
    ', ncyBreadcrumb: {label: 'State L'}}); }); /** @@ -41,11 +41,13 @@ angular.module('ncy-object-parent-conf', []).config(function($stateProvider) { var A = { name: 'A', url: '/a', + template: '
    ', ncyBreadcrumb: {label: 'State A'} }; var A_B = { name: 'B', url: '/b', + template: '
    ', ncyBreadcrumb: {label: 'State B'}, parent: A }; @@ -59,20 +61,23 @@ angular.module('ncy-object-parent-conf', []).config(function($stateProvider) { */ angular.module('ncy-dynamic-parent-conf', []).config(function($stateProvider) { $stateProvider - .state('A', {url: '/a', ncyBreadcrumb: {label: 'State A'}}) - .state('A.B', {url: '/b', ncyBreadcrumb: {label: 'State B'}}) - .state('C', {url: '/c', ncyBreadcrumb: {label: 'State C'}}) - .state('D', {url: '/d', ncyBreadcrumb: {label: 'State D'}}) - .state('D.E', {url: '/e', ncyBreadcrumb: {label: 'State E'}}) - .state('D.E.F', {url:'/f', ncyBreadcrumb: {label: 'State F', parent: 'A.B'}}) // Specific parent for breadcrumb - .state('D.E.G', {url:'/g', ncyBreadcrumb: {label: 'State G', parent: function() { + .state('A', {url: '/a', template: '
    ', ncyBreadcrumb: {label: 'State A'}}) + .state('A.B', {url: '/b', template: '
    ', ncyBreadcrumb: {label: 'State B'}}) + .state('C', {url: '/c', template: '
    ', ncyBreadcrumb: {label: 'State C'}}) + .state('D', {url: '/d', template: '
    ', ncyBreadcrumb: {label: 'State D'}}) + .state('D.E', {url: '/e', template: '
    ', ncyBreadcrumb: {label: 'State E'}}) + .state('D.E.F', {url:'/f', template: '
    ', ncyBreadcrumb: {label: 'State F', parent: 'A.B'}}) // Specific parent for breadcrumb + .state('D.E.G', {url:'/g', template: '
    ', ncyBreadcrumb: {label: 'State G', parent: function() { return 'A'; }}}) - .state('D.E.H', {url:'/h', ncyBreadcrumb: {label: 'State H', parent: function($scope) { + .state('D.E.H', {url:'/h', template: '
    ', controller: 'ReturnCCtrl', ncyBreadcrumb: {label: 'State H', parent: function($scope) { return $scope.parentState; }}}) - .state('I', {url: '/i/:x/:y', ncyBreadcrumb: {label:'State I'}}) - .state('J', {url: '/j', ncyBreadcrumb: {label:'State J', parent: 'I({x: \'love\', y: \'you\'})'}}); + .state('D.E.K', {url:'/k', template: '
    ', controller: 'UndefinedCtrl', ncyBreadcrumb: {label: 'State K', parent: function($scope) { + return $scope.parentState; + }}}) + .state('I', {url: '/i/:x/:y', template: '
    ', ncyBreadcrumb: {label:'State I'}}) + .state('J', {url: '/j', template: '
    ', ncyBreadcrumb: {label:'State J', parent: 'I({x: \'love\', y: \'you\'})'}}); }).controller('UndefinedCtrl', function($scope) { $scope.parentState = undefined; }).controller('ReturnCCtrl', function($scope) { @@ -84,11 +89,11 @@ angular.module('ncy-dynamic-parent-conf', []).config(function($stateProvider) { */ angular.module('ncy-ui-sref-template-conf', []).config(function($stateProvider, $breadcrumbProvider) { $stateProvider - .state('A', {url: '/a', ncyBreadcrumb: {label: 'State A'}}) - .state('A.B', {url: '/b', ncyBreadcrumb: {label: 'State B'}}) - .state('I', {url: '/i/:x/:y', ncyBreadcrumb: {label:'State I'}}) - .state('J', {url: '/j', ncyBreadcrumb: {label:'State J', parent: 'I({x: \'love\', y: \'you\'})'}}) - .state('K', {url: '/k', ncyBreadcrumb: {label:'State K', parent: function() { + .state('A', {url: '/a', template: '
    ', ncyBreadcrumb: {label: 'State A'}}) + .state('A.B', {url: '/b', template: '
    ', ncyBreadcrumb: {label: 'State B'}}) + .state('I', {url: '/i/:x/:y', template: '
    ', ncyBreadcrumb: {label:'State I'}}) + .state('J', {url: '/j', template: '
    ', ncyBreadcrumb: {label:'State J', parent: 'I({x: \'love\', y: \'you\'})'}}) + .state('K', {url: '/k', template: '
    ', ncyBreadcrumb: {label:'State K', parent: function() { return 'I({x: \'love\', y: \'you\'})'; }}}); @@ -102,10 +107,10 @@ angular.module('ncy-ui-sref-template-conf', []).config(function($stateProvider, */ angular.module('ncy-interpolation-conf', []).config(function($stateProvider) { $stateProvider - .state('A', {url: '/a', controller: 'ACtrl', template: '
    View A
    ', ncyBreadcrumb: {label: 'State A'}}) - .state('A.B', {url: '/b', controller: 'BCtrl', template: '
    View B
    ', ncyBreadcrumb: {label: 'State {{tripleB}}'}}) - .state('A.B.C', {url: '/c', ncyBreadcrumb: {label: 'State C'}}) // no controller - .state('A.B.D', {url: '/d', controller: function($scope) {$scope.tripleD='DDD';}, template: '
    View D
    ', ncyBreadcrumb: {label: 'State {{tripleD}}'}}); // inline controller + .state('A', {url: '/a', controller: 'ACtrl', template: '
    View A
    ', ncyBreadcrumb: {label: 'State A'}}) + .state('A.B', {url: '/b', controller: 'BCtrl', template: '
    View B
    ', ncyBreadcrumb: {label: 'State {{tripleB}}'}}) + .state('A.B.C', {url: '/c', template:'
    ', ncyBreadcrumb: {label: 'State C'}}) // no controller + .state('A.B.D', {url: '/d', controller: function($scope) { $scope.tripleD='DDD'; }, template: '
    View D
    ', ncyBreadcrumb: {label: 'State {{tripleD}}'}}); // inline controller }).controller('ACtrl', function($scope) { $scope.tripleA = 'AAA'; }).controller('BCtrl', function($scope) { @@ -117,7 +122,7 @@ angular.module('ncy-interpolation-conf', []).config(function($stateProvider) { */ angular.module('ncy-html-conf', ['ngSanitize']).config(function($stateProvider) { $stateProvider - .state('html', {url: '/html', ncyBreadcrumb: {label: 'Html is interpreted'}}); + .state('html', {url: '/html', template: '
    ', ncyBreadcrumb: {label: 'Html is interpreted'}}); }); angular.module('ncy-sample-conf', ['ncy-sample', 'ngMock']).config(function($urlRouterProvider) { diff --git a/test/spec/directive-basic-test.js b/test/spec/directive-basic-test.js index cd5b06d..90bd8e0 100644 --- a/test/spec/directive-basic-test.js +++ b/test/spec/directive-basic-test.js @@ -1,27 +1,23 @@ /*jshint undef: false */ -describe('Breadcrumb directive with basic conf', function() { +describe('Breadcrumb directive with basic conf', function () { - var element, scope; + var element, $rootScope; - beforeEach(function() { + beforeEach(function () { module('ncy-basic-conf'); }); - beforeEach(inject(function($rootScope, $compile) { - element = angular.element(''); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + beforeEach(inject(function (_$rootScope_, $compile) { + var elem = angular.element('
    '); + $rootScope = _$rootScope_; + element = $compile(elem)($rootScope.$new()); })); - it('renders the correct state chain', inject(function() { + it('renders the correct state chain', inject(function () { goToState('D'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); + $rootScope.$digest(); - console.info('Directive content : ' + element.text()); expect(element.text()).toContain('State A'); expect(element.text()).toContain('State B'); expect(element.text()).toContain('State C'); @@ -35,12 +31,9 @@ describe('Breadcrumb directive with basic conf', function() { expect(element.find('a').eq(2).attr('href')).toBe('#/a/b/c'); })); - it('should work with one state', inject(function() { + it('should work with one state', inject(function () { goToState('A'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - console.info('Directive content : ' + element.text()); expect(element.text()).toContain('State A'); expect(element.children().length).toBe(1); diff --git a/test/spec/directive-dynamic-parent-test.js b/test/spec/directive-dynamic-parent-test.js index 1cdb0da..718c32c 100644 --- a/test/spec/directive-dynamic-parent-test.js +++ b/test/spec/directive-dynamic-parent-test.js @@ -1,65 +1,40 @@ /*jshint undef: false */ -describe('Breadcrumb directive with dynamic parent conf', function() { +describe('Breadcrumb directive with dynamic parent conf', function () { + var element, $rootScope; - var element, scope, controller, compile; - - beforeEach(function() { + beforeEach(function () { module('ncy-dynamic-parent-conf'); }); - beforeEach(inject(function($rootScope, $compile, $controller) { - element = angular.element('
    '); - compile = $compile(element); - scope = $rootScope.$new(); - controller = $controller; + beforeEach(inject(function (_$rootScope_, $compile) { + var elem = angular.element('
    '); + $rootScope = _$rootScope_; + element = $compile(elem)($rootScope.$new()); })); - it('should use the custom breadcrumb\'s parent property referencing a variable of the scope', inject(function() { + it('should use the custom breadcrumb\'s parent property referencing a variable of the scope', inject(function () { goToState('D.E.H'); - - controller('ReturnCCtrl', {'$scope' : scope} ); - compile(scope); - expect(scope.parentState).toBeDefined(); - - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); + $rootScope.$digest(); expect(element.text()).toContain('State C'); expect(element.text()).toContain('State H'); expect(element.text()).not.toContain('State E'); })); - it('should ignore the custom breadcrumb\'s parent property if it is a function returning undefined', inject(function() { - goToState('D.E.H'); - - controller('UndefinedCtrl', {'$scope' : scope} ); - compile(scope); - expect(scope.parentState).toBeUndefined(); - - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); + it('should ignore the custom breadcrumb\'s parent property if it is a function returning undefined', inject(function () { + goToState('D.E.K'); + $rootScope.$digest(); expect(element.text()).toContain('State D'); expect(element.text()).toContain('State E'); - expect(element.text()).toContain('State H'); - + expect(element.text()).toContain('State K'); })); - it('deals with url params correctly', inject(function() { + it('deals with url params correctly', inject(function () { goToState('J'); - - compile(scope); - - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - + $rootScope.$digest(); + expect(element.text()).toContain('State I'); expect(element.text()).toContain('State J'); diff --git a/test/spec/directive-interpolation-test.js b/test/spec/directive-interpolation-test.js index f79ff3a..ee2152f 100644 --- a/test/spec/directive-interpolation-test.js +++ b/test/spec/directive-interpolation-test.js @@ -1,56 +1,34 @@ /*jshint undef: false */ -describe('Breadcrumb directive with interpolation conf', function() { +describe('Breadcrumb directive with interpolation conf', function () { + var element, $rootScope; - var element, scope, controller, compile; - - beforeEach(function() { + beforeEach(function () { module('ncy-interpolation-conf'); }); - beforeEach(inject(function($rootScope, $compile, $controller) { - element = angular.element('
    '); - compile = $compile(element); - scope = $rootScope.$new(); - controller = $controller; + beforeEach(inject(function (_$rootScope_, $compile) { + var elem = angular.element('
    '); + $rootScope = _$rootScope_; + element = $compile(elem)($rootScope.$new()); })); - it('interpolates labels correctly', inject(function() { + it('interpolates labels correctly', inject(function () { goToState('A.B'); - controller('BCtrl', {'$scope' : scope} ); - compile(scope); - - expect(scope.tripleB).toBeDefined(); - - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - expect(element.text()).toContain('State BBB'); expect(element.find('a').eq(0).attr('href')).toBe('#/a'); })); - it('deals with further updates of the scope', inject(function() { + it('deals with further updates of the scope', inject(function ($state) { goToState('A.B'); - controller('BCtrl', {'$scope' : scope} ); - compile(scope); - - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - expect(element.text()).toContain('State BBB'); - scope.tripleB = 'HACKED'; - scope.$digest(); + $state.$current.locals['@A'].$scope.tripleB = 'HACKED'; + $rootScope.$digest(); expect(element.text()).toContain('State HACKED'); - })); - }); diff --git a/test/spec/directive-last-basic-test.js b/test/spec/directive-last-basic-test.js index 1ec1245..f9cf99a 100644 --- a/test/spec/directive-last-basic-test.js +++ b/test/spec/directive-last-basic-test.js @@ -2,7 +2,7 @@ describe('Last step directive with basic conf', function() { - var element, scope; + var element; beforeEach(function() { module('ncy-basic-conf'); @@ -11,19 +11,13 @@ describe('Last step directive with basic conf', function() { describe('without template', function() { beforeEach(inject(function($rootScope, $compile) { - element = angular.element(''); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('renders the last step label correctly', inject(function() { goToState('D'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); + expect(element.text()).toBe('State D'); })); @@ -32,19 +26,13 @@ describe('Last step directive with basic conf', function() { describe('with template', function() { beforeEach(inject(function($rootScope, $compile) { - element = angular.element(''); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('renders the template correctly', inject(function() { goToState('D'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); + expect(element.text()).toBe('State D|#/a/b/c/d'); })); @@ -62,19 +50,13 @@ describe('Last step directive with basic conf', function() { }); beforeEach(inject(function($rootScope, $compile) { - element = angular.element(''); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('correctly', inject(function() { goToState('D'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.html()); + expect(element[0].tagName.toLowerCase()).toBe('span'); expect(element.find('i').length).toBe(1); })); @@ -92,19 +74,13 @@ describe('Last step directive with basic conf', function() { }); beforeEach(inject(function($rootScope, $compile) { - element = angular.element(''); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('correctly', inject(function() { goToState('html'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.html()); + expect(element[0].tagName.toLowerCase()).toBe('span'); expect(element.find('i').length).toBe(2); diff --git a/test/spec/directive-last-interpolation-test.js b/test/spec/directive-last-interpolation-test.js index 081fae4..6bb34d5 100644 --- a/test/spec/directive-last-interpolation-test.js +++ b/test/spec/directive-last-interpolation-test.js @@ -1,56 +1,34 @@ /*jshint undef: false */ -describe('Last step directive with interpolation conf', function() { +describe('Last step directive with interpolation conf', function () { - var element, scope, controller, compile; + var element, $rootScope; - beforeEach(function() { + beforeEach(function () { module('ncy-interpolation-conf'); }); - beforeEach(inject(function($rootScope, $compile, $controller) { - element = angular.element(''); - compile = $compile(element); - scope = $rootScope.$new(); - controller = $controller; + beforeEach(inject(function (_$rootScope_, $compile) { + var elem = angular.element('
    '); + $rootScope = _$rootScope_; + element = $compile(elem)($rootScope.$new()); })); - it('interpolates labels correctly', inject(function() { + it('interpolates labels correctly', inject(function () { goToState('A.B'); - controller('BCtrl', {'$scope' : scope} ); - compile(scope); - - expect(scope.tripleB).toBeDefined(); - - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - expect(element.text()).toBe('test|State BBB'); })); - it('deals with further updates of the scope', inject(function() { + it('deals with further updates of the scope', inject(function ($state) { goToState('A.B'); - controller('BCtrl', {'$scope' : scope} ); - compile(scope); - - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - expect(element.text()).toBe('test|State BBB'); - scope.tripleB = 'HACKED'; - scope.$digest(); + $state.$current.locals['@A'].$scope.tripleB = 'HACKED'; + $rootScope.$digest(); expect(element.text()).toBe('test|State HACKED'); })); - - - }); diff --git a/test/spec/directive-last-sample-test.js b/test/spec/directive-last-sample-test.js index 2fe9f0f..9ac25fb 100644 --- a/test/spec/directive-last-sample-test.js +++ b/test/spec/directive-last-sample-test.js @@ -2,32 +2,21 @@ describe('Last step directive with sample conf', function() { - var element, scope, controller, compile; + var element, $rootScope; beforeEach(function() { module('ncy-sample-conf'); }); - beforeEach(inject(function($rootScope, $compile, $controller) { - element = angular.element(''); - compile = $compile(element); - scope = $rootScope.$new(); - controller = $controller; + beforeEach(inject(function(_$rootScope_, $compile) { + var elem = angular.element('
    '); + $rootScope = _$rootScope_; + element = $compile(elem)($rootScope.$new()); })); it('interpolates "room.detail" label correctly', inject(function() { goToStateAndFlush('room.detail', {roomId: 3}); - controller('RoomDetailCtrl', {'$scope' : scope} ); - compile(scope); - - expect(scope.room).toBeDefined(); - - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - expect(element.find('a').text()).toBe('Room 103'); expect(element.find('a').attr("href")).toBe('#/room/3'); })); diff --git a/test/spec/directive-ncyBreadcrumbIgnore-test.js b/test/spec/directive-ncyBreadcrumbIgnore-test.js deleted file mode 100644 index 51ff3e3..0000000 --- a/test/spec/directive-ncyBreadcrumbIgnore-test.js +++ /dev/null @@ -1,108 +0,0 @@ -/*jshint undef: false */ - - -var element, scope; - -describe('Breadcrumb directive with multiple-interpolation conf', function() { - - beforeEach(function () { - module('ncy-multiple-interpolation-conf'); - }); - - describe('when ncyBreadcrumbIgnore is undefined on parent view scope', function () { - describe('when the parent view located before child view ', function () { - beforeEach(inject(function ($rootScope, $compile) { - element = angular.element('
    '); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); - })); - - it('renders the correct state chain and views content', inject(function () { - goToState('A.B'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - - expect(element.text()).toContain('AState BBBView AView B'); - })); - }); - - describe('when the parent view located after child view ', function () { - beforeEach(inject(function ($rootScope, $compile) { - element = angular.element('
    '); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); - })); - - it('renders the incorrect state chain', inject(function () { - goToState('A.B'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - - expect(element.text()).not.toContain('State BBB'); - })); - }); - }); -}); - -describe('Breadcrumb directive with multiple-interpolation conf', function() { - beforeEach(function () { - module('ncy-multiple-interpolation-conf', function ($controllerProvider) { - $controllerProvider.register('ACtrl', function ($scope) { - $scope.ncyBreadcrumbIgnore = true; - }); - }); - }); - - describe('when ncyBreadcrumbIgnore property equals true on parent view scope', function () { - describe('when the parent view located before child view ', function () { - beforeEach(inject(function ($rootScope, $compile) { - element = angular.element('
    '); - var compile = $compile(element); - scope = $rootScope.$new(); - - compile(scope); - scope.$digest(); - })); - - it('renders the correct state chain and views content', inject(function () { - goToState('A.B'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - - expect(element.text()).toContain('AState BBBView AView B'); - })); - }); - - describe('when the parent view located after child view ', function () { - beforeEach(inject(function ($rootScope, $compile) { - element = angular.element('
    '); - var compile = $compile(element); - scope = $rootScope.$new(); - - compile(scope); - scope.$digest(); - })); - - it('renders the correct state chain and views content', inject(function () { - goToState('A.B'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - - expect(element.text()).toContain('AState BBBView BView A'); - })); - }); - }); - -}); diff --git a/test/spec/directive-object-parent-test.js b/test/spec/directive-object-parent-test.js index 14435da..6538fe0 100644 --- a/test/spec/directive-object-parent-test.js +++ b/test/spec/directive-object-parent-test.js @@ -2,26 +2,20 @@ describe('Breadcrumb directive with object parent conf', function() { - var element, scope; + var element; beforeEach(function() { module('ncy-object-parent-conf'); }); beforeEach(inject(function($rootScope, $compile) { - element = angular.element(''); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('should handle parents provided by object reference', inject(function() { goToState('B'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); + expect(element.text()).toContain('State A'); expect(element.text()).toContain('State B'); })); diff --git a/test/spec/directive-sample-test.js b/test/spec/directive-sample-test.js index 4622e69..cc47756 100644 --- a/test/spec/directive-sample-test.js +++ b/test/spec/directive-sample-test.js @@ -2,32 +2,20 @@ describe('Breadcrumb directive with sample conf', function() { - var element, scope, controller, compile; + var element; beforeEach(function() { module('ncy-sample-conf'); }); - beforeEach(inject(function($rootScope, $compile, $controller) { - element = angular.element('
    '); - compile = $compile(element); - scope = $rootScope.$new(); - controller = $controller; + beforeEach(inject(function($rootScope, $compile) { + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('interpolates "room.detail" label correctly', inject(function() { goToStateAndFlush('room.detail.edit', {roomId: 3}); - controller('RoomDetailCtrl', {'$scope' : scope} ); - compile(scope); - - expect(scope.room).toBeDefined(); - - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - expect(element.text()).toContain('Home'); expect(element.text()).toContain('Sample'); expect(element.text()).toContain('Rooms'); diff --git a/test/spec/directive-template-test.js b/test/spec/directive-template-test.js index 9a92ce2..6d954a2 100644 --- a/test/spec/directive-template-test.js +++ b/test/spec/directive-template-test.js @@ -2,7 +2,7 @@ describe('Breadcrumb directive', function() { - var element, scope; + var element; describe('uses default template (bootstrap3)', function() { beforeEach(function() { @@ -10,19 +10,13 @@ describe('Breadcrumb directive', function() { }); beforeEach(inject(function($rootScope, $compile) { - element = angular.element('
    '); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('correctly', inject(function() { goToState('D'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); + expect(element[0].tagName.toLowerCase()).toBe('ol'); expect(element.children().length).toBe(4); @@ -43,19 +37,13 @@ describe('Breadcrumb directive', function() { }); beforeEach(inject(function($rootScope, $compile) { - element = angular.element('
    '); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('correctly', inject(function() { goToState('D'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); + expect(element[0].tagName.toLowerCase()).toBe('ul'); expect(element.children().length).toBe(4); @@ -80,19 +68,13 @@ describe('Breadcrumb directive', function() { }); beforeEach(inject(function($rootScope, $compile) { - element = angular.element('
    '); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('correctly', inject(function() { goToState('D'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.html()); + expect(element[0].tagName.toLowerCase()).toBe('table'); expect(element.find('tr').length).toBe(4); @@ -115,19 +97,13 @@ describe('Breadcrumb directive', function() { }); beforeEach(inject(function($rootScope, $compile) { - element = angular.element('
    '); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('correctly', inject(function() { goToState('html'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.html()); + expect(element[0].tagName.toLowerCase()).toBe('div'); expect(element.find('span').length).toBe(2); @@ -135,5 +111,4 @@ describe('Breadcrumb directive', function() { expect(element.find('span').eq(1).text()).toBe('Html is interpreted'); })); }); - }); diff --git a/test/spec/directive-text-basic-separator-test.js b/test/spec/directive-text-basic-separator-test.js index 10623ad..1fc01c1 100644 --- a/test/spec/directive-text-basic-separator-test.js +++ b/test/spec/directive-text-basic-separator-test.js @@ -1,8 +1,7 @@ /*jshint undef: false */ describe('Text directive with separator with basic conf', function() { - - var element, scope; + var element; beforeEach(function() { module('ncy-basic-conf'); @@ -11,19 +10,13 @@ describe('Text directive with separator with basic conf', function() { describe('without template', function() { beforeEach(inject(function($rootScope, $compile) { - element = angular.element(''); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('renders the text label correctly', inject(function() { goToState('D'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); + expect(element.text()).toBe('State A>State B>State C>State D'); })); @@ -32,19 +25,13 @@ describe('Text directive with separator with basic conf', function() { describe('with template', function() { beforeEach(inject(function($rootScope, $compile) { - element = angular.element(''); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('renders the template correctly', inject(function() { goToState('D'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); + expect(element.text()).toBe('State A>State B>State C>State D - MyApp'); })); diff --git a/test/spec/directive-text-basic-test.js b/test/spec/directive-text-basic-test.js index f74b370..e3751b7 100644 --- a/test/spec/directive-text-basic-test.js +++ b/test/spec/directive-text-basic-test.js @@ -2,7 +2,7 @@ describe('Text directive with basic conf', function() { - var element, scope; + var element; beforeEach(function() { module('ncy-basic-conf'); @@ -11,19 +11,13 @@ describe('Text directive with basic conf', function() { describe('without template', function() { beforeEach(inject(function($rootScope, $compile) { - element = angular.element(''); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('renders the text label correctly', inject(function() { goToState('D'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); + expect(element.text()).toBe('State A / State B / State C / State D'); })); @@ -32,19 +26,13 @@ describe('Text directive with basic conf', function() { describe('with template', function() { beforeEach(inject(function($rootScope, $compile) { - element = angular.element(''); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('renders the template correctly', inject(function() { goToState('D'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); + expect(element.text()).toBe('State A / State B / State C / State D - MyApp'); })); diff --git a/test/spec/directive-text-interpolation-test.js b/test/spec/directive-text-interpolation-test.js index f9fd3d6..f932de8 100644 --- a/test/spec/directive-text-interpolation-test.js +++ b/test/spec/directive-text-interpolation-test.js @@ -1,56 +1,32 @@ /*jshint undef: false */ describe('Text directive with interpolation conf', function() { - - var element, scope, controller, compile; + var element, $rootScope; beforeEach(function() { module('ncy-interpolation-conf'); }); - beforeEach(inject(function($rootScope, $compile, $controller) { - element = angular.element(''); - compile = $compile(element); - scope = $rootScope.$new(); - controller = $controller; + beforeEach(inject(function(_$rootScope_, $compile) { + var elem = angular.element('
    '); + $rootScope = _$rootScope_; + element = $compile(elem)($rootScope.$new()); })); it('interpolates labels correctly', inject(function() { goToState('A.B'); - controller('BCtrl', {'$scope' : scope} ); - compile(scope); - - expect(scope.tripleB).toBeDefined(); - - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - expect(element.text()).toBe('test|State A / State BBB'); })); - it('deals with further updates of the scope', inject(function() { + it('deals with further updates of the scope', inject(function($state) { goToState('A.B'); - controller('BCtrl', {'$scope' : scope} ); - compile(scope); - - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - expect(element.text()).toBe('test|State A / State BBB'); - scope.tripleB = 'HACKED'; - scope.$digest(); + $state.$current.locals['@A'].$scope.tripleB = 'HACKED'; + $rootScope.$digest(); expect(element.text()).toBe('test|State A / State HACKED'); - })); - - - }); diff --git a/test/spec/directive-text-sample-test.js b/test/spec/directive-text-sample-test.js index 5b1e694..fad52e5 100644 --- a/test/spec/directive-text-sample-test.js +++ b/test/spec/directive-text-sample-test.js @@ -1,34 +1,20 @@ /*jshint undef: false */ describe('Text directive with sample conf', function() { - - var element, scope, controller, compile; + var element; beforeEach(function() { module('ncy-sample-conf'); }); - beforeEach(inject(function($rootScope, $compile, $controller) { - element = angular.element(''); - compile = $compile(element); - scope = $rootScope.$new(); - controller = $controller; + beforeEach(inject(function($rootScope, $compile) { + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('interpolates "room.detail" label correctly', inject(function() { goToStateAndFlush('room.detail', {roomId: 3}); - controller('RoomDetailCtrl', {'$scope' : scope} ); - compile(scope); - - expect(scope.room).toBeDefined(); - - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); - expect(element.text()).toBe('MyApp: Home / Sample / Rooms / Room 103'); })); - }); diff --git a/test/spec/directive-ui-sref-template-test.js b/test/spec/directive-ui-sref-template-test.js index 83dc216..3dcbe08 100644 --- a/test/spec/directive-ui-sref-template-test.js +++ b/test/spec/directive-ui-sref-template-test.js @@ -2,26 +2,20 @@ describe('Breadcrumb directive with ui-sref template', function() { - var element, scope; + var element; beforeEach(function() { module('ncy-ui-sref-template-conf'); }); beforeEach(inject(function($rootScope, $compile) { - element = angular.element('
    '); - var compile = $compile(element); - scope = $rootScope.$new(); - compile(scope); - scope.$digest(); + var elem = angular.element('
    '); + element = $compile(elem)($rootScope.$new()); })); it('should work correctly', inject(function() { goToState('A.B'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); + expect(element.text()).toContain('State A'); expect(element.text()).toContain('State B'); expect(element.find('a').eq(0).attr('href')).toBe('#/a'); @@ -30,10 +24,6 @@ describe('Breadcrumb directive with ui-sref template', function() { it('should deal with url params correctly', inject(function() { goToState('J'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); expect(element.text()).toContain('State I'); expect(element.text()).toContain('State J'); @@ -44,10 +34,6 @@ describe('Breadcrumb directive with ui-sref template', function() { it('should deal with url params correctly even with dynamic parent', inject(function() { goToState('K'); - scope.$emit('$viewContentLoaded'); - scope.$digest(); - - console.info('Directive content : ' + element.text()); expect(element.text()).toContain('State I'); expect(element.text()).toContain('State K'); diff --git a/test/spec/scope-compare-test.js b/test/spec/scope-compare-test.js deleted file mode 100644 index 0c87f83..0000000 --- a/test/spec/scope-compare-test.js +++ /dev/null @@ -1,47 +0,0 @@ -/*jshint undef: false */ - -describe('The scope', function() { - - beforeEach(function() { - module('ncy-basic-conf'); - }); - - it('00A is older than 001', function() { - expect(isAOlderThanB('00A', '001')).toBe(true); - }); - - it('010 is older than 00Y', function() { - expect(isAOlderThanB('010', '00Y')).toBe(true); - }); - - it('01P is older than 010', function() { - expect(isAOlderThanB('01P', '010')).toBe(true); - }); - - it('FOO is older than BAR', function() { - expect(isAOlderThanB('FOO', 'BAR')).toBe(true); - }); - - it('F00 is older than BAR', function() { - expect(isAOlderThanB('F00', 'BAR')).toBe(true); - }); - - it('0000 is older than ZZZ', function() { - expect(isAOlderThanB('0000', 'ZZZ')).toBe(true); - }); - - it('(newly created) is always older than the precedent one', inject(function($rootScope) { - var scope = $rootScope.$new(); - for(var i = 0; i < 100000; i++) { - var newScope = $rootScope.$new(); - var isOlder = isAOlderThanB(newScope.$id, scope.$id); - expect(isOlder).toBe(true); - if(!isOlder) { - console.log(newScope.$id, scope.$id, isOlder, i); - break; - } - scope = newScope; - } - })); - -}); diff --git a/test/spec/service-abstract-test.js b/test/spec/service-abstract-test.js index 2ce250d..e29588c 100644 --- a/test/spec/service-abstract-test.js +++ b/test/spec/service-abstract-test.js @@ -1,77 +1,98 @@ /*jshint undef: false */ -describe('Service with abstract conf', function() { +describe('Service with abstract conf', function () { - describe('with default options', function() { - - beforeEach(function() { + describe('with default options', function () { + var $rootScope; + + beforeEach(function () { module('ncy-abstract-conf'); }); + + beforeEach(inject(function (_$rootScope_) { + $rootScope = _$rootScope_; + })); - it('should have a 2-step route to C state', inject(function($breadcrumb) { + it('should have a 2-step route to C state', inject(function ($breadcrumb) { goToState('A.B.C'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('A.B --> A.B.C'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('A.B --> A.B.C'); + }); + $rootScope.$digest(); })); - it('should have a 2-step route to F state', inject(function($breadcrumb) { + it('should have a 2-step route to F state', inject(function ($breadcrumb) { goToState('D.E.F'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('D --> D.E.F'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('D --> D.E.F'); + }); + $rootScope.$digest(); })); - it('should return a one step chain to G.H', inject(function($breadcrumb) { + it('should return a one step chain to G.H', inject(function ($breadcrumb) { goToState('G.H'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('G.H'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('G.H'); + }); + $rootScope.$digest(); })); - it('should return a two step route to I.J', inject(function($breadcrumb) { + it('should return a two step route to I.J', inject(function ($breadcrumb) { goToState('I.J'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('I --> I.J'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('I --> I.J'); + }); + $rootScope.$digest(); })); - it('should return a one step chain to K.L', inject(function($breadcrumb) { + it('should return a one step chain to K.L', inject(function ($breadcrumb) { goToState('K.L'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('K.L'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('K.L'); + }); + $rootScope.$digest(); })); }); - describe('with abstract state inclusion', function() { + describe('with abstract state inclusion', function () { + var $rootScope; - beforeEach(function() { + beforeEach(function () { angular.module('ncy-abstract-conf') - .config(function($breadcrumbProvider) { + .config(function ($breadcrumbProvider) { $breadcrumbProvider.setOptions({ includeAbstract: true }); }); module('ncy-abstract-conf'); }); + + beforeEach(inject(function (_$rootScope_) { + $rootScope = _$rootScope_; + })); - it('should have a 3-step route to C state', inject(function($breadcrumb) { + it('should have a 3-step route to C state', inject(function ($breadcrumb) { goToState('A.B.C'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('A --> A.B --> A.B.C'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('A --> A.B --> A.B.C'); + }); + $rootScope.$digest(); })); - it('should have a 3-step route to F state', inject(function($breadcrumb) { + it('should have a 3-step route to F state', inject(function ($breadcrumb) { goToState('D.E.F'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('D --> D.E --> D.E.F'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('D --> D.E --> D.E.F'); + }); + $rootScope.$digest(); })); - it('should still return a one step chain to G.H (state-level option skip is priority)', inject(function($breadcrumb) { + it('should still return a one step chain to G.H (state-level option skip is priority)', inject(function ($breadcrumb) { goToState('G.H'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('G.H'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('G.H'); + }); + $rootScope.$digest(); })); }); - - - - - }); diff --git a/test/spec/service-basic-test.js b/test/spec/service-basic-test.js index ab8587d..345845d 100644 --- a/test/spec/service-basic-test.js +++ b/test/spec/service-basic-test.js @@ -1,6 +1,7 @@ /*jshint undef: false */ describe('Service with basic conf', function() { + var $rootScope; beforeEach(function() { module('ncy-basic-conf'); @@ -10,70 +11,106 @@ describe('Service with basic conf', function() { expect($breadcrumb).toBeDefined(); })); + beforeEach(inject(function (_$rootScope_) { + $rootScope = _$rootScope_; + })); + it('should have a 3-step route to C state', inject(function($breadcrumb) { goToState('A.B.C'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('A --> A.B --> A.B.C'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('A --> A.B --> A.B.C'); + }); - var lastStep = $breadcrumb.getLastStep(); - expect(lastStep.name).toBe('A.B.C'); + $breadcrumb.getLastStep().then(function (lastStep) { + expect(lastStep.name).toBe('A.B.C'); + }); + + $rootScope.$digest(); })); it('should work also with "parent" state\'s property', inject(function($breadcrumb) { goToState('D'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('A --> A.B --> A.B.C --> D'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('A --> A.B --> A.B.C --> D'); + }); + + $breadcrumb.getLastStep().then(function (lastStep) { + expect(lastStep.name).toBe('D'); + }); - var lastStep = $breadcrumb.getLastStep(); - expect(lastStep.name).toBe('D'); + $rootScope.$digest(); })); it('must build a correct link for each steps', inject(function($breadcrumb) { goToState('D'); - var statesChain = $breadcrumb.getStatesChain(); - expect(statesChain[0].ncyBreadcrumbLink).toBe('#/a'); - expect(statesChain[1].ncyBreadcrumbLink).toBe('#/a/b'); - expect(statesChain[2].ncyBreadcrumbLink).toBe('#/a/b/c'); - expect(statesChain[3].ncyBreadcrumbLink).toBe('#/a/b/c/d'); + + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(statesChain[0].ncyBreadcrumbLink).toBe('#/a'); + expect(statesChain[1].ncyBreadcrumbLink).toBe('#/a/b'); + expect(statesChain[2].ncyBreadcrumbLink).toBe('#/a/b/c'); + expect(statesChain[3].ncyBreadcrumbLink).toBe('#/a/b/c/d'); + }); + + $rootScope.$digest(); })); it('should expose the state conf', inject(function($breadcrumb) { goToState('A.B'); - var lastStep = $breadcrumb.getLastStep(); - expect(lastStep.ncyBreadcrumbStateRef).toBe('A.B'); + + $breadcrumb.getLastStep().then(function (lastStep) { + expect(lastStep.ncyBreadcrumbStateRef).toBe('A.B'); + }); + + $rootScope.$digest(); })); it('should not return the step for E state', inject(function($breadcrumb) { goToState('D.E'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('A --> A.B --> A.B.C --> D'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('A --> A.B --> A.B.C --> D'); + }); + + $breadcrumb.getLastStep().then(function (lastStep) { + expect(lastStep.name).toBe('D'); + }); - var lastStep = $breadcrumb.getLastStep(); - expect(lastStep.name).toBe('D'); + $rootScope.$digest(); })); it('should have a 5-step route to F state (E skipped)', inject(function($breadcrumb) { goToState('D.E.F'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('A --> A.B --> A.B.C --> D --> D.E.F'); + + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('A --> A.B --> A.B.C --> D --> D.E.F'); + }); + + $rootScope.$digest(); })); it('should return an empty array for skipped G', inject(function($breadcrumb) { goToState('G'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe(''); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe(''); + }); + + $breadcrumb.getLastStep().then(function (lastStep) { + expect(lastStep).toBeUndefined(); + }); - var lastStep = $breadcrumb.getLastStep(); - expect(lastStep).toBeUndefined(); + $rootScope.$digest(); })); it('should return a one step chain to G.H', inject(function($breadcrumb) { goToState('G.H'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('G.H'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('G.H'); + }); + + $breadcrumb.getLastStep().then(function (lastStep) { + expect(lastStep.name).toBe('G.H'); + }); - var lastStep = $breadcrumb.getLastStep(); - expect(lastStep.name).toBe('G.H'); + $rootScope.$digest(); })); }); diff --git a/test/spec/service-dynamic-parent-test.js b/test/spec/service-dynamic-parent-test.js index f285cf6..7e86e32 100644 --- a/test/spec/service-dynamic-parent-test.js +++ b/test/spec/service-dynamic-parent-test.js @@ -1,6 +1,7 @@ /*jshint undef: false */ describe('Service with dynamic parent conf', function() { + var $rootScope; beforeEach(function() { module('ncy-dynamic-parent-conf'); @@ -10,25 +11,41 @@ describe('Service with dynamic parent conf', function() { expect($breadcrumb).toBeDefined(); })); + beforeEach(inject(function (_$rootScope_) { + $rootScope = _$rootScope_; + })); + it('should use the custom breadcrumb\'s parent property for D.E.F (a string)', inject(function($breadcrumb) { goToState('D.E.F'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('A --> A.B --> D.E.F'); + + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('A --> A.B --> D.E.F'); + }); + + $rootScope.$digest(); })); it('should use the custom breadcrumb\'s parent property for D.E.G (a function)', inject(function($breadcrumb) { goToState('D.E.G'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('A --> D.E.G'); + + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('A --> D.E.G'); + }); + + $rootScope.$digest(); })); it('should deals with url params correctly', inject(function($breadcrumb) { goToState('J'); - var statesChain = $breadcrumb.getStatesChain(); - expect(stringifyStateChain(statesChain)).toBe('I --> J'); - expect(statesChain[0].name).toBe('I'); - expect(statesChain[0].ncyBreadcrumbLink).toBe('#/i/love/you'); - expect(statesChain[0].ncyBreadcrumbStateRef).toBe('I({x: \'love\', y: \'you\'})'); + + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('I --> J'); + expect(statesChain[0].name).toBe('I'); + expect(statesChain[0].ncyBreadcrumbLink).toBe('#/i/love/you'); + expect(statesChain[0].ncyBreadcrumbStateRef).toBe('I({x: \'love\', y: \'you\'})'); + }); + + $rootScope.$digest(); })); }); diff --git a/test/spec/service-sample-test.js b/test/spec/service-sample-test.js index 8c5d8c2..22a19ca 100644 --- a/test/spec/service-sample-test.js +++ b/test/spec/service-sample-test.js @@ -1,54 +1,76 @@ /*jshint undef: false */ -describe('Service with sample conf', function() { +describe('Service with sample conf', function () { + var $rootScope; - beforeEach(function() { + beforeEach(function () { module('ncy-sample-conf'); }); - it('generate a unique step for the "home" state', inject(function($breadcrumb) { + beforeEach(inject(function (_$rootScope_, $compile) { + var elem = angular.element('
    '); + $rootScope = _$rootScope_; + $compile(elem)($rootScope.$new()); + })); + + it('generate a unique step for the "home" state', inject(function ($breadcrumb) { goToStateAndFlush('home'); - var statesChain = $breadcrumb.getStatesChain(); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('home'); + }); - expect(stringifyStateChain(statesChain)).toBe('home'); + $breadcrumb.getLastStep().then(function (lastStep) { + expect(lastStep.name).toBe('home'); + }); - var lastStep = $breadcrumb.getLastStep(); - expect(lastStep.name).toBe('home'); + $rootScope.$digest(); })); - it('generate three steps for the "room" state', inject(function($breadcrumb) { + it('generate three steps for the "room" state', inject(function ($breadcrumb) { goToStateAndFlush('room'); - var statesChain = $breadcrumb.getStatesChain(); + + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('home --> sample --> room'); + }); - expect(stringifyStateChain(statesChain)).toBe('home --> sample --> room'); + $breadcrumb.getLastStep().then(function (lastStep) { + expect(lastStep.name).toBe('room'); + }); - var lastStep = $breadcrumb.getLastStep(); - expect(lastStep.name).toBe('room'); + $rootScope.$digest(); })); - it('generate four steps for the "room.detail" state', inject(function($breadcrumb) { + it('generate four steps for the "room.detail" state', inject(function ($breadcrumb) { goToStateAndFlush('room.detail', {roomId: 1}); - var statesChain = $breadcrumb.getStatesChain(); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('home --> sample --> room --> room.detail'); + }); - expect(stringifyStateChain(statesChain)).toBe('home --> sample --> room --> room.detail'); + $breadcrumb.getLastStep().then(function (lastStep) { + expect(lastStep.name).toBe('room.detail'); + }); - var lastStep = $breadcrumb.getLastStep(); - expect(lastStep.name).toBe('room.detail'); + $rootScope.$digest(); })); - it('generate four steps for the "room.detail.edit" state with working links', inject(function($breadcrumb) { + it('generate four steps for the "room.detail.edit" state with working links', inject(function ($breadcrumb) { goToStateAndFlush('room.detail.edit', {roomId: 1}); - var statesChain = $breadcrumb.getStatesChain(); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('home --> sample --> room --> room.detail --> room.detail.edit'); + expect(statesChain[3].ncyBreadcrumbLink).toBe('#/room/1'); + expect(statesChain[4].ncyBreadcrumbLink).toBe('#/room/1/edit'); + }); - expect(stringifyStateChain(statesChain)).toBe('home --> sample --> room --> room.detail --> room.detail.edit'); - expect(statesChain[3].ncyBreadcrumbLink).toBe('#/room/1'); - expect(statesChain[4].ncyBreadcrumbLink).toBe('#/room/1/edit'); + $rootScope.$digest(); })); - it('must build a correct link for each steps', inject(function($breadcrumb) { + it('must build a correct link for each steps', inject(function ($breadcrumb) { goToStateAndFlush('room'); - var statesChain = $breadcrumb.getStatesChain(); - expect(statesChain[0].ncyBreadcrumbLink).toBe('#/home'); - expect(statesChain[1].ncyBreadcrumbLink).toBe('#/sample'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(statesChain[0].ncyBreadcrumbLink).toBe('#/home'); + expect(statesChain[1].ncyBreadcrumbLink).toBe('#/sample'); + }); + + $rootScope.$digest(); })); }); diff --git a/test/spec/service-ui-router-sample-test.js b/test/spec/service-ui-router-sample-test.js index 479b6af..8ee586e 100644 --- a/test/spec/service-ui-router-sample-test.js +++ b/test/spec/service-ui-router-sample-test.js @@ -1,60 +1,77 @@ /*jshint undef: false */ describe('Service with ui-router\'s sample conf', function() { + var $rootScope; beforeEach(function() { module('ncy-ui-router-conf'); }); + beforeEach(inject(function (_$rootScope_) { + $rootScope = _$rootScope_; + })); + it('generate a unique step for the "home" state', inject(function($breadcrumb) { goToState('home'); - var statesChain = $breadcrumb.getStatesChain(); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('home'); + }); - expect(stringifyStateChain(statesChain)).toBe('home'); + $breadcrumb.getLastStep().then(function (lastStep) { + expect(lastStep.name).toBe('home'); + }); - var lastStep = $breadcrumb.getLastStep(); - expect(lastStep.name).toBe('home'); + $rootScope.$digest(); })); it('generate two steps for the "contacts.list" state', inject(function($breadcrumb) { goToStateAndFlush('contacts.list'); - var statesChain = $breadcrumb.getStatesChain(); - - expect(stringifyStateChain(statesChain)).toBe('home --> contacts.list'); - - var lastStep = $breadcrumb.getLastStep(); - expect(lastStep.name).toBe('contacts.list'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('home --> contacts.list'); + }); + + $breadcrumb.getLastStep().then(function (lastStep) { + expect(lastStep.name).toBe('contacts.list'); + }); + + $rootScope.$digest(); })); it('generate three steps for the "contacts.detail" state', inject(function($breadcrumb) { goToStateAndFlush('contacts.detail', {contactId: 42}); - var statesChain = $breadcrumb.getStatesChain(); - - expect(stringifyStateChain(statesChain)).toBe('home --> contacts.list --> contacts.detail'); - - var lastStep = $breadcrumb.getLastStep(); - expect(lastStep.name).toBe('contacts.detail'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('home --> contacts.list --> contacts.detail'); + }); + + $breadcrumb.getLastStep().then(function (lastStep) { + expect(lastStep.name).toBe('contacts.detail'); + }); + + $rootScope.$digest(); })); it('generate four steps for the "contacts.detail.item" state', inject(function($breadcrumb) { goToStateAndFlush('contacts.detail.item', {contactId: 42, itemId: "a"}); - var statesChain = $breadcrumb.getStatesChain(); - - expect(stringifyStateChain(statesChain)).toBe('home --> contacts.list --> contacts.detail --> contacts.detail.item'); - - - var lastStep = $breadcrumb.getLastStep(); - expect(lastStep.name).toBe('contacts.detail.item'); + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('home --> contacts.list --> contacts.detail --> contacts.detail.item'); + }); + + $breadcrumb.getLastStep().then(function (lastStep) { + expect(lastStep.name).toBe('contacts.detail.item'); + }); + + $rootScope.$digest(); })); it('generate five steps for the "contacts.detail.item.edit" state with working links', inject(function($breadcrumb) { goToStateAndFlush('contacts.detail.item.edit', {contactId: 42, itemId: "a"}); - var statesChain = $breadcrumb.getStatesChain(); - - expect(stringifyStateChain(statesChain)).toBe('home --> contacts.list --> contacts.detail --> contacts.detail.item --> contacts.detail.item.edit'); - expect(statesChain[2].ncyBreadcrumbLink).toBe('#/contacts/42'); - expect(statesChain[3].ncyBreadcrumbLink).toBe('#/contacts/42/item/a'); - expect(statesChain[4].ncyBreadcrumbLink).toBe('#/contacts/42/item/a'); // (state with no URL) + $breadcrumb.getStatesChain().then(function (statesChain) { + expect(stringifyStateChain(statesChain)).toBe('home --> contacts.list --> contacts.detail --> contacts.detail.item --> contacts.detail.item.edit'); + expect(statesChain[2].ncyBreadcrumbLink).toBe('#/contacts/42'); + expect(statesChain[3].ncyBreadcrumbLink).toBe('#/contacts/42/item/a'); + expect(statesChain[4].ncyBreadcrumbLink).toBe('#/contacts/42/item/a'); // (state with no URL) + }); + + $rootScope.$digest(); })); - });