diff --git a/.gitignore b/.gitignore
index 107a9ca..9e5b91b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,7 @@ libpeerconnection.log
npm-debug.log
.agignore
/coverage
+.idea
+/.idea/jsLibraryMappings.xml
+/.idea/misc.xml
+/.idea/libraries/ngMidwayTester_node_modules.xml
diff --git a/Gruntfile.js b/Gruntfile.js
index 0856f51..65baf7a 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -18,7 +18,7 @@ module.exports = function(grunt) {
},
bower_install: {
command: 'node ./node_modules/bower/bin/bower install'
- },
+ }
},
connect: {
diff --git a/bower.json b/bower.json
index fe537cc..14be849 100644
--- a/bower.json
+++ b/bower.json
@@ -1,7 +1,10 @@
{
"name": "ngMidwayTester",
"devDependencies": {
- "angularjs": "http://code.angularjs.org/1.2.0-rc.3/angular.js",
- "angularjs-route": "http://code.angularjs.org/1.2.0-rc.3/angular-route.js"
+ "angular": "1.4.7",
+ "angular-ui-router": "0.2.15"
+ },
+ "dependencies": {
+ "jasmine-core": "jasmine#~2.3.4"
}
}
diff --git a/package.json b/package.json
index 222c0d9..66d85b8 100644
--- a/package.json
+++ b/package.json
@@ -1,33 +1,39 @@
{
"name": "ng-midway-tester",
- "version": "2.0.5",
+ "version": "2.0.6",
"repository": {
"type": "git",
- "url": "git@github.com:yearofmoo/ngMidwayTester.git"
+ "url": "https://github.com/gaelazzo/ngMidwayTester"
},
"scripts": {
"test": "grunt travis"
},
"devDependencies": {
- "bower": "latest",
+ "bower": "~1.3.12",
"yuidocjs": "~0.3.45",
- "grunt": "~0.4.1",
- "grunt-contrib-connect": "~0.5.0",
- "grunt-shell": "~0.5.0",
+ "grunt": "^0.4.5",
+ "grunt-contrib-connect": "~0.9.0",
+ "grunt-shell": "^1.1.1",
"grunt-open": "~0.2.2",
- "karma-script-launcher": "~0.1.0",
- "karma-chrome-launcher": "~0.1.0",
- "karma-firefox-launcher": "~0.1.0",
+ "karma": "~0.12.37",
+ "karma-chrome-launcher": "~0.2.0",
+ "karma-coffee-preprocessor": "~0.2.1",
+ "karma-firefox-launcher": "~0.1.6",
"karma-html2js-preprocessor": "~0.1.0",
- "karma-jasmine": "~0.1.3",
- "karma-requirejs": "~0.1.0",
- "karma-coffee-preprocessor": "~0.1.0",
- "karma-phantomjs-launcher": "~0.1.0",
- "karma": "~0.10.2",
- "grunt-karma": "~0.6.2",
- "mocha": "~1.13.0",
+ "karma-jade-preprocessor": "0.0.11",
+ "karma-jasmine": "~0.3.6",
+ "karma-ng-html2js-preprocessor": "~0.1.0",
+ "karma-ng-jade2js-preprocessor": "^0.2.1",
+ "karma-ng-scenario": "~0.1.0",
+ "karma-phantomjs-launcher": "^0.2.1",
+ "karma-requirejs": "~0.2.2",
+ "karma-script-launcher": "~0.1.0",
+ "load-grunt-tasks": "~3.1.0",
+ "grunt-karma": "~0.11.1",
+ "mocha": "^2.1.0",
"karma-mocha": "~0.1.0",
- "chai": "~1.8.1",
+ "chai": "^1.10.0",
"karma-coverage": "~0.1.0"
}
+
}
diff --git a/src/ngMidwayTester.js b/src/ngMidwayTester.js
index 08216b6..8af260b 100644
--- a/src/ngMidwayTester.js
+++ b/src/ngMidwayTester.js
@@ -1,6 +1,6 @@
/**
- * Creates an instance of the midway tester on the specified module.
- *
+ * Creates an instance of the midway tester on the specified module.
+ *
* @class ngMidwayTester
* @constructor
* @param moduleName the AngularJS module that you wish to test
@@ -12,254 +12,419 @@
* @param {Object} [config.mockLocationPaths=true] Whether or not to fake the URL change in the browser address bar
* @return {Object} An instance of the midway tester
*/
-;var ngMidwayTester = function(moduleName, options) {
-
- options = options || {};
- var doc = options.document || document;
- var wind = options.window || window;
- var noop = angular.noop;
-
- var mockLocationPaths = options.mockLocationPaths == null ? true : !!options.mockLocationPaths;
-
- var $rootElement = angular.element(doc.createElement('div')),
- $timers = [],
- $viewContainer,
- $terminalElement,
- $viewCounter = 0;
-
- var viewSelector = 'ng-view, [ng-view], .ng-view, [x-ng-view], [data-ng-view]';
-
- var midwayModule = angular.module('ngMidway', []);
-
- if(mockLocationPaths) {
- midwayModule.config(function($provide) {
- $provide.decorator('$location', ['$delegate', '$rootScope', function($delegate, $rootScope) {
- var _path = $delegate.path();
- $delegate.path = function(path) {
- if(path) {
- _path = path;
- $rootScope.$broadcast('$locationChangeSuccess', path);
- return this;
- }
- else {
- return _path;
- }
- };
- return $delegate;
- }]);
- });
- }
-
- if(options.templateUrl) {
- var request = new XMLHttpRequest();
- request.open('GET', options.templateUrl, false);
- request.send(null);
-
- if (request.status != 200) {
- throw new Error('ngMidwayTester: Unable to download template file');
+
+
+;
+var ngMidwayTester = function (moduleName, options, deferred) {
+
+ options = options || {};
+ var doc = options.document || document;
+ var wind = options.window || window;
+ var noop = angular.noop;
+
+ var mockLocationPaths = options.mockLocationPaths == null ? true : !!options.mockLocationPaths;
+
+
+ var $rootElement = angular.element(doc.createElement('div')),
+ $timers = [],
+ $viewContainer,
+ $terminalElement,
+ $viewCounter = 0;
+
+ var viewSelector = 'ui-view, [ui-view], .ui-view, [x-ui-view], [data-ui-view]';
+ var $injector;
+
+
+ var midwayModule = angular.module('ngMidway', [])
+ .config(
+ ['$injector', function ($i) {
+ $injector = $i;
+ if (deferred) deferred.resolve();
+ }]
+ );
+
+
+
+ if (mockLocationPaths) {
+ midwayModule.config(function ($provide) {
+ $provide.decorator('$location', ['$delegate', '$rootScope', function ($delegate, $rootScope) {
+ var _path = $delegate.path();
+ $delegate.path = function (path) {
+ if (path) {
+ _path = path;
+ //console.log('$rootScope.$broadcast("$locationChangeSuccess", ', path,');');
+ $rootScope.$broadcast('$locationChangeStart', path);
+ $rootScope.$broadcast('$locationChangeSuccess', path);
+ return this;
+ }
+ else {
+ return _path;
+ }
+ };
+ return $delegate;
+ }]);
+ });
}
+ var notifyOnLocationChangeSuccess =[];
- options.template = request.responseText;
- }
-
- if(options.template) {
- $rootElement.html(options.template);
- var view = angular.element($rootElement[0].querySelector(viewSelector));
- $viewContainer = view.parent();
- }
- else {
- $viewContainer = angular.element('
');
- $rootElement.append($viewContainer);
- }
-
- $terminalElement = angular.element('');
- $rootElement.append($terminalElement);
-
- var $injector = angular.bootstrap($rootElement, ['ng','ngMidway',moduleName]);
- var $rootModule = angular.module(moduleName);
- angular.element(doc.body).append($rootElement);
-
- return {
- /**
- * @method module
- * @return {Object} Returns the module container object acquired from angular.module(moduleName)
- */
- module : function() {
- return $rootModule;
- },
-
- /**
- * Attaches the $rootElement module to the provided body element
- * @param {Element} [body=document.body] The element that will be used as the parent (defaults to document.body)
- * @method attach
- */
- attach : function(body) {
- angular.element(body || doc.body).append($rootElement);
- },
-
- /**
- * Attaches the $rootElement module to the provided body element
- * @method controller
- * @param {String} name The name of the controller
- * @param {Object} [locals] A key/value map of all the injectable services for when the controller is instantiated
- * @return {Object} The instance of the controller
- */
- controller : function(name, locals) {
- return this.inject('$controller')(name, locals);
- },
-
- /**
- * @method rootScope
- * @return {Object} The $rootScope object of the module
- */
- rootScope : function() {
- return this.inject('$rootScope');
- },
-
- /**
- * @method rootElement
- * @return {Object} The $rootElement object of the module
- */
- rootElement : function() {
- return $rootElement;
- },
-
- /**
- * @method viewElement
- * @return {Element} The current element that has ng-view attached to it
- */
- viewElement : function() {
- return angular.element($viewContainer[0].querySelector(viewSelector));
- },
-
- /**
- * @method viewElement
- * @return {Object} The scope of the current view element
- */
- viewScope : function() {
- return this.viewElement().scope();
- },
-
- /**
- * Runs $scope.$evalAsync() on the provided scope
- * @param {function} fn The function to be provided to evalAsync
- * @param {Object} [scope=$rootScope] The scope object which will be used for the eval call
- * @method evalAsync
- */
- evalAsync : function(fn, scope) {
- (scope || this.rootScope()).$evalAsync(fn);
- },
-
- /**
- * Compiles and links the given HTML
- *
- * @method compile
- * @param {String|Element} html the html or element node which will be compiled
- * @param {Object} [scope=$rootScope] The scope object which will be linked to the compile
- * @return {Element} The element node which which is the result of the compilation
- */
- compile : function(html, scope) {
- return this.inject('$compile')(html)(scope || this.rootScope());
- },
-
- /**
- * Performs a digest operation on the given scope
- *
- * @method digest
- * @param {Object} [scope=$rootScope] The scope object which will be used for the compilation
- */
- digest : function(scope) {
- (scope || this.rootScope()).$digest();
- },
-
- /**
- * Performs an apply operation on the given scope
- *
- * @method apply
- * @param {function} fn The callback function which will be used in the apply digest
- * @param {Object} [scope=$rootScope] scope The scope object which the apply process will be run on
- */
- apply : function(fn, scope) {
- scope = scope || this.inject('$rootScope');
- scope.$$phase ? fn() : scope.$apply(fn);
- },
-
- /*
- * @method inject
- * @param {String} item The name of the service which will be fetched
- * @return {Object} The service fetched from the injection call
- */
- inject : function(item) {
- return $injector.get(item);
- },
-
- /**
- * @method injector
- * @return {Object} Returns the AngularJS $injector service
- */
- injector : function() {
- return $injector;
- },
-
- /**
- * @method path
- * @return {String} Returns the path of the current route
- */
- path : function() {
- return this.inject('$location').path();
- },
-
- /**
- * Changes the current route of the page and then fires the callback when the page has loaded
- *
- * @param {String} path The given path that the current route will be changed to
- * @param {function} [callback] The given callback to fire once the view has been fully loaded
- * @method visit
- */
- visit : function(path, callback) {
- this.rootScope().__view_status = ++$viewCounter;
- this.until(function() {
- return parseInt($terminalElement.attr('status')) >= $viewCounter;
- }, callback || noop);
-
- var $location = this.inject('$location');
- this.apply(function() {
- $location.path(path);
- });
- },
-
- /**
- * Keeps checking an expression until it returns a truthy value and then runs the provided callback
- *
- * @param {function} exp The given function to poll
- * @param {function} callback The given callback to fire once the exp function returns a truthy value
- * @method until
- */
- until : function(exp, callback) {
- var timer, delay = 50;
- timer = setInterval(function() {
- if(exp()) {
- clearTimeout(timer);
- callback();
+
+ if (options.templateUrl) {
+ var request = new XMLHttpRequest();
+ request.open('GET', options.templateUrl, false);
+ request.send(null);
+
+ if (request.status != 200) {
+ throw new Error('ngMidwayTester: Unable to download template file');
}
- }, delay);
- $timers.push(timer);
- },
-
- /**
- * Removes the $rootElement and clears the module from the page
- *
- * @method destroy
- */
- destroy : function() {
- angular.forEach($timers, function(timer) {
- clearTimeout(timer);
- });
-
- var body = angular.element(document.body);
- body.removeData();
- $rootElement.remove();
- this.rootScope().$destroy();
+
+ options.template = request.responseText;
}
- };
+
+ if (options.template) {
+ $rootElement.html(options.template);
+ var view = angular.element($rootElement[0].querySelector(viewSelector));
+ $viewContainer = view.parent();
+ }
+ else {
+ $viewContainer = angular.element('');
+ $rootElement.append($viewContainer);
+ }
+
+ $terminalElement = angular.element('');
+ $rootElement.append($terminalElement);
+
+ $injector = angular.bootstrap($rootElement, ['ng', 'ngMidway', moduleName]);
+ var $rootModule = angular.module(moduleName);
+
+
+
+ angular.element(doc.body).prepend($rootElement);
+
+
+
+ return {
+
+
+ /**
+ * @method module
+ * @return {Object} Returns the module container object acquired from angular.module(moduleName)
+ */
+ module: function () {
+ return $rootModule;
+ },
+
+ /**
+ * Attaches the $rootElement module to the provided body element
+ * @param {Element} [body=document.body] The element that will be used as the parent (defaults to document.body)
+ * @method attach
+ */
+ attach: function (body) {
+ angular.element(body || doc.body).append($rootElement);
+ },
+
+ /**
+ * Attaches the $rootElement module to the provided body element
+ * @method controller
+ * @param {String} name The name of the controller
+ * @param {Object} [locals] A key/value map of all the injectable services for when the controller is instantiated
+ * @return {Object} The instance of the controller
+ */
+ controller: function (name, locals) {
+ return this.inject('$controller')(name, locals);
+ },
+
+
+ /**
+ * @method rootScope
+ * @return {Object} The $rootScope object of the module
+ */
+ rootScope: function () {
+ return this.inject('$rootScope');
+ },
+
+ /**
+ * @method rootElement
+ * @return {Object} The $rootElement object of the module
+ */
+ rootElement: function () {
+ return $rootElement;
+ },
+
+ /**
+ * @method viewElement
+ * @param {string|array} [viewName] if array, the view is searched recursively
+ * @return {Element} The current element that has ng-view attached to it
+ */
+ viewElement: function (viewName) {
+ if (!viewName) return angular.element($viewContainer[0].querySelector(viewSelector));
+ if (typeof viewName === 'string') {
+ return angular.element($viewContainer[0].querySelector('[ui-view="' + viewName + '"]'));
+ }
+ var curr = $viewContainer;
+ for (var i = 0; i < viewName.length; i++) {
+ //console.log('searching:', viewName[i]);
+ if (!curr) return curr;
+ curr = angular.element(curr[0].querySelector('[ui-view="' + viewName[i] + '"]'));
+ }
+ return curr;
+ },
+
+ /**
+ * @method viewElement
+ * @return {Object} The scope of the current view element
+ */
+ viewScope: function (viewName) {
+ return this.viewElement(viewName).scope();
+ },
+
+ /**
+ * Runs $scope.$evalAsync() on the provided scope
+ * @param {function} fn The function to be provided to evalAsync
+ * @param {Object} [scope=$rootScope] The scope object which will be used for the eval call
+ * @method evalAsync
+ */
+ evalAsync: function (fn, scope) {
+ (scope || this.rootScope()).$evalAsync(fn);
+ },
+
+ /**
+ * Compiles and links the given HTML
+ *
+ * @method compile
+ * @param {String|Element} html the html or element node which will be compiled
+ * @param {Object} [scope=$rootScope] The scope object which will be linked to the compile
+ * @return {Element} The element node which which is the result of the compilation
+ */
+ compile: function (html, scope) {
+ return this.inject('$compile')(html)(scope || this.rootScope());
+ },
+
+ /**
+ * Performs a digest operation on the given scope
+ *
+ * @method digest
+ * @param {Object} [scope=$rootScope] The scope object which will be used for the compilation
+ */
+ digest: function (scope) {
+ //(scope || this.rootScope()).$digest();
+ var s = scope || this.rootScope();
+ if (!s.$$phase) {
+ s.$digest();
+ }
+ else {
+ var $timeout = this.inject('$timeout');
+ //console.log('skipped digest');
+ $timeout(this.digest);
+ }
+ },
+
+ /**
+ * Performs an apply operation on the given scope
+ *
+ * @method apply
+ * @param {function} fn The callback function which will be used in the apply digest
+ * @param {Object} [scope=$rootScope] scope The scope object which the apply process will be run on
+ */
+ apply: function (fn, scope) {
+ scope = scope || scope || this.inject('$rootScope'); //$rootScope
+ scope.$$phase ? fn() : scope.$apply(fn);
+ },
+
+ /*
+ * @method inject
+ * @param {String} item The name of the service which will be fetched
+ * @return {Object} The service fetched from the injection call
+ */
+ inject: function (item) {
+ return $injector.get(item);
+ },
+
+ /**
+ * @method injector
+ * @return {Object} Returns the AngularJS $injector service
+ */
+ injector: function () {
+ return $injector;
+ },
+
+ /**
+ * @method path
+ * @return {String} Returns the path of the current route
+ */
+ path: function () {
+ return this.inject('$location').path();
+ },
+
+ state: function () {
+ return this.inject('$state');
+ },
+
+ currentState: function () {
+ return this.inject('$state').$current;
+ },
+
+
+ /**
+ * Changes the current route of the page and then fires the callback when the page has loaded
+ * @method visit
+ * @param {String} path The given path that the current route will be changed to
+ */
+ visit: function (path) {
+ var $location = this.inject('$location');
+ this.apply(function () {
+
+ $location.path(path);
+ });
+
+ },
+
+ /**
+ * @method timeOut
+ * Calls a method after a angular timeout
+ * @param fn
+ */
+ callFnOnTimeOut: function(fn, args){
+ var $timeout = this.inject('$timeout');
+ return function() {
+ $timeout(function () {
+ fn.apply(null, args);
+ })
+ }
+ },
+
+ /**
+ * Transforms a function into a function that will be called after a view will be available
+ * @method waitForViewElement
+ * @param {function} [fn] The given callback to fire once the view has been fully loaded
+ * @param {bool} [noView] when false, does not wait for viewScope() to be available and ready
+ * @returns {*}
+ */
+ waitForViewScopeCondition: function (fn, viewName, condition){
+ var that = this;
+ if (fn.$$$isViewDelayed) {
+ return fn; //just to be sure a function is never double delayed
+ }
+ return function () {
+ this.$$$isViewDelayed = true; //just to be sure a function is never double delayed
+ var args = Array.prototype.slice.call(arguments);
+ var myFun = that.callFnOnTimeOut(fn,args);
+ that.until(function () {
+ //console.log(that.viewElement(viewName));
+ if (!that.viewElement(viewName))return false;
+ if (!that.viewElement(viewName).scope) return false;
+ var scope = that.viewElement(viewName).scope();
+ //console.log(scope);
+ return condition(scope);
+ }, myFun || noop);
+ }
+ },
+
+ waitForControllerInViewScope: function (fn, viewName, controllerName){
+ return this.waitForViewScopeCondition(fn, viewName, function(scope){
+ if (!scope) return false;
+ if (!scope[controllerName])return false;
+ return (scope[controllerName].constructor instanceof Function);
+ })
+ },
+
+
+ /**
+ * Transforms a function into a function that will be called after a view will be available
+ * @method waitForViewElement
+ * @param {function} [fn] The given callback to fire once the view has been fully loaded
+ * @param {bool} [noView] when false, does not wait for viewScope() to be available and ready
+ * @returns {*}
+ */
+ waitForViewCondition: function (fn, viewName, condition){
+ var that = this;
+ if (fn.$$$isViewDelayed) {
+ return fn; //just to be sure a function is never double delayed
+ }
+ return function () {
+ this.$$$isViewDelayed = true; //just to be sure a function is never double delayed
+ var args = Array.prototype.slice.call(arguments);
+ var myFun = that.callFnOnTimeOut(fn,args);
+ that.until(function () {
+ var view=that.viewElement(viewName);
+ if (!view)return false;
+ //console.log(scope);
+ return condition(view);
+ }, myFun || noop);
+ }
+ },
+
+
+ /**
+ * Transforms a function into a function that will be called after a complete digest will have happened
+ * @method waitForDigest
+ * @param {function} [fn] The given callback to fire once the view has been fully loaded
+ * @param {bool} [noView] when false, does not wait for viewScope() to be available and ready
+ * @returns {*}
+ */
+ waitForDigest: function (fn, noView) {
+ var that = this;
+ if (fn.$$$isDigestDelayed) {
+ return fn; //just to be sure a function is never double delayed
+ }
+ if (noView === undefined) {
+ noView = false;
+ }
+
+ return function () {
+ this.$$$isDigestDelayed = true; //just to be sure a function is never double delayed
+ var args = Array.prototype.slice.call(arguments);
+ var myFun = that.callFnOnTimeOut(fn,args);
+ that.rootScope().__view_status = ++$viewCounter;
+ that.until(function () {
+ if (!noView) {
+ if (!that.viewScope()) {
+ return false;
+ }
+ if (that.viewScope().$$phase) {
+ return false;
+ }
+ }
+ return parseInt($terminalElement.attr('status')) >= $viewCounter;
+ }, myFun || noop);
+ }
+ },
+ /**
+ * Keeps checking an expression until it returns a truthy value and then runs the provided callback
+ *
+ * @param {function} exp The given function to poll
+ * @param {function} callback The given callback to fire once the exp function returns a truthy value
+ * @method until
+ */
+ until: function (exp, callback) {
+
+ var timer, delay = 0;
+ timer = setInterval(function () {
+ if (exp()) {
+ clearInterval(timer);
+ callback();
+ }
+ else {
+ active = true;
+ }
+ }, delay);
+ $timers.push(timer);
+ },
+
+
+ /**
+ * Removes the $rootElement and clears the module from the page
+ *
+ * @method destroy
+ */
+ destroy: function () {
+ angular.forEach($timers, function (timer) {
+ clearInterval(timer);
+ });
+
+ var body = angular.element(document.body);
+ body.removeData();
+ $rootElement.remove();
+ this.rootScope().$destroy();
+ }
+ };
};
diff --git a/test/karma.conf.js b/test/karma.conf.js
index 8f08d49..6ce3bc4 100644
--- a/test/karma.conf.js
+++ b/test/karma.conf.js
@@ -1,19 +1,36 @@
module.exports = function(config) {
config.set({
+ reporters: ['dots'], //dots progress
basePath : '../',
files : [
'./node_modules/chai/chai.js',
- './bower_components/angularjs/index.js',
- './bower_components/angularjs-route/index.js',
+ './bower_components/angular/angular.js',
+ './bower_components/angular-ui-router/release/angular-ui-router.min.js',
'./src/ngMidwayTester.js',
- './test/lib/chai.js',
- './test/spec/ngMidwayTesterSpec.js'
+ './test/spec/*.js'
],
- singleRun: true,
+ logLevel : config.LOG_INFO,
frameworks: ['mocha'],
- browsers: ['Chrome'],
+
+ // Start these browsers, currently available:
+ // - Chrome
+ // - ChromeCanary
+ // - Firefox
+ // - Opera
+ // - Safari (only Mac)
+ // - PhantomJS
+ // - IE (only Windows)
+ browsers: ['PhantomJS'],
proxies: {
'/': 'http://localhost:8844/'
}
+ ,
+
+ // Which plugins to enable
+ plugins: [
+ 'karma-phantomjs-launcher',
+ 'karma-mocha'
+ // 'karma-jasmine'
+ ]
});
};
diff --git a/test/lib/chai.js b/test/lib/chai.js
deleted file mode 100644
index 35da615..0000000
--- a/test/lib/chai.js
+++ /dev/null
@@ -1 +0,0 @@
-var expect = chai.expect;
diff --git a/test/spec/custom-view.html b/test/spec/custom-view.html
index 3ecf9f1..441999b 100644
--- a/test/spec/custom-view.html
+++ b/test/spec/custom-view.html
@@ -1,5 +1,5 @@
Hello
How's it going?
-
+
diff --git a/test/spec/custom-view2.html b/test/spec/custom-view2.html
new file mode 100644
index 0000000..62bf4ec
--- /dev/null
+++ b/test/spec/custom-view2.html
@@ -0,0 +1,9 @@
+
+
+
Hello
+
Nice view
+
{{dog.page}}
+
+
+
+
diff --git a/test/spec/custom-view3.html b/test/spec/custom-view3.html
new file mode 100644
index 0000000..89d493c
--- /dev/null
+++ b/test/spec/custom-view3.html
@@ -0,0 +1,7 @@
+
+
View3
+
Sub-Nested view
+
+
+
+
diff --git a/test/spec/custom-view4.html b/test/spec/custom-view4.html
new file mode 100644
index 0000000..688b8fa
--- /dev/null
+++ b/test/spec/custom-view4.html
@@ -0,0 +1,6 @@
+
+
Bad view
+
this is old
+
+
this is old, too
+
\ No newline at end of file
diff --git a/test/spec/ngMidwayTesterSpec.js b/test/spec/ngMidwayTesterSpec.js
index f88b9c2..bb79f54 100644
--- a/test/spec/ngMidwayTesterSpec.js
+++ b/test/spec/ngMidwayTesterSpec.js
@@ -1,3 +1,5 @@
+var expect = chai.expect;
+
describe('ngMidwayTester', function() {
var tester,
@@ -40,86 +42,223 @@ describe('ngMidwayTester', function() {
});
describe('template options', function() {
- it('should use a custom index.html template string', function(done) {
- var example = angular.module(appName, ['ngRoute'])
- .run(function($rootScope) {
- $rootScope.value = 'true';
- })
- .config(function($routeProvider) {
- $routeProvider.when('/path2', {
- controller: function($scope) {
- $scope.page = 'two';
- },
- template : 'two'
+ it('should use a custom index.html template string', function (done) {
+ var example = angular.module(appName, ['ui.router'])
+ .run(function ($rootScope) {
+ $rootScope.value = 'true';
+ })
+ .config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
+ $stateProvider
+ .state('path2', {
+ url: '/path2',
+ controller: function ($scope) {
+ this.woof = 'hello';
+ },
+ controllerAs: 'dog',
+ template: 'two {{dog.woof}}'
+ })
+ });
+
+
+ tester = ngMidwayTester(appName, {
+ template: 'title
' +
+ ''
});
- });
-
- tester = ngMidwayTester(appName, {
- template : 'title
' +
- ''
+ expect(tester.module()).to.equal(example);
+ expect(tester.rootScope().value).to.equal('true');
+
+ tester.visit('/path2');
+ tester.waitForControllerInViewScope(function () {
+ expect(tester.path()).to.equal('/path2');
+ expect(tester.viewElement().text()).to.contain('two');
+ expect(tester.viewElement().text()).to.contain('hello');
+ expect(tester.currentState().controllerAs).to.equal('dog');
+ done();
+ },null,'dog')();
});
- expect(tester.module()).to.equal(example);
- expect(tester.rootScope().value).to.equal('true');
- tester.visit('/path2', function() {
- expect(tester.path()).to.equal('/path2');
- expect(tester.viewElement().text()).to.contain('two');
- done();
- });
- });
-
- it('should use a custom index.html template file', function(done) {
- var example = angular.module(appName, ['ngRoute'])
- .run(function($rootScope) {
- $rootScope.value = 'true';
- })
- .config(function($routeProvider) {
- $routeProvider.when('/path-10', {
- controller: function($scope) {
- $scope.page = 'ten';
- },
- template : 'ten'
+ it('should use a custom index.html template file', function (done) {
+ var example = angular.module(appName, ['ui.router'])
+ .run(function ($rootScope) {
+ $rootScope.value = 'true';
+ })
+ .config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
+ $stateProvider
+ .state('path-10', {
+ url: '/path-10',
+ controller: function ($scope) {
+ $scope.page = 'ten';
+ },
+ template: 'ten'
+ })
+ });
+ tester = ngMidwayTester(appName, {
+ templateUrl: './test/spec/custom-view.html'
});
- });
- tester = ngMidwayTester(appName, {
- templateUrl : './test/spec/custom-view.html'
+ expect(tester.module()).to.equal(example);
+ expect(tester.rootScope().value).to.equal('true');
+
+ tester.visit('/path-10');
+ tester.waitForViewScopeCondition(function () {
+ expect(tester.path()).to.equal('/path-10');
+ var html = tester.rootElement().html();
+ expect(html).to.contain('');
+ expect(html).to.contain('ten');
+ var viewEl = tester.viewElement().html();
+ expect(viewEl).to.contain('ten');
+ done();
+ },null,
+ function(scope){
+ return scope.page;
+ })();
});
- expect(tester.module()).to.equal(example);
- expect(tester.rootScope().value).to.equal('true');
+ it('should use a custom index.html template file with nested views', function (done) {
+ var example = angular.module(appName, ['ui.router'])
+ .run(function ($rootScope) {
+ $rootScope.value = 'true';
+ })
+ .config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
+ $urlRouterProvider.otherwise("/nested");
+ $locationProvider.html5Mode(false).hashPrefix('!');
+ $stateProvider
+ .state('nested', {
+ url: '/nested',
+
+ views:{
+ '':{
+ controller: function ($scope) {
+ this.page = 'ten';
+ },
+ controllerAs:'dog'
+ },
+ 'main@nested':{
+ template:'MainContent'
+ },
+ 'secondary@nested':{
+ template:'SecondaryContent'
+ }
+ }
+ })
+ });
+
+
+ tester = ngMidwayTester(appName, {
+ templateUrl: './test/spec/custom-view2.html'
+ });
- tester.visit('/path-10', function() {
- expect(tester.path()).to.equal('/path-10');
- var html = tester.rootElement().html();
- expect(html).to.contain('');
- expect(html).to.contain('ten');
- done();
+ expect(tester.module()).to.equal(example);
+ expect(tester.rootScope().value).to.equal('true');
+
+ tester.visit('/nested');
+ tester.waitForViewScopeCondition(function () {
+ expect(tester.path()).to.equal('/nested');
+ var html = tester.viewElement().html();
+ expect(html).to.contain('Nice view');
+ expect(html).to.contain('MainContent');
+ done();
+ },null,function(scope){
+ return scope.dog && scope.dog.page;
+ })();
});
- });
- it('should throw an error when a file downloaded from templateUrl is not found', function() {
- var example = angular.module(appName, ['ngRoute'])
- .run(function($rootScope) {
- $rootScope.value = 'true';
- })
- .config(function($routeProvider) {
- $routeProvider.when('/path-10', {
- controller: function($scope) {
- $scope.page = 'ten';
- },
- template : 'ten'
+ it('should get data from nested views', function (done) {
+ var example = angular.module(appName, ['ui.router'])
+ .run(function ($rootScope) {
+ $rootScope.value = 'true';
+ })
+ .config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
+ $urlRouterProvider.otherwise("/nested");
+ $locationProvider.html5Mode(false).hashPrefix('!');
+ $stateProvider
+ .state('nested', {
+ url: '/nested',
+ views: {
+ '':{
+ controller: function ($scope) {
+ this.page = 'ten';
+ },
+ controllerAs:'cat'
+ },
+ 'main@nested': {
+ template: 'MainContent'
+ },
+ 'secondary@nested': {
+ templateUrl: './test/spec/custom-view4.html'
+ },
+ 'main3@nested': {
+ template: 'hot content'
+ },
+ 'secondary3@nested': {
+ templateUrl: './test/spec/custom-view3.html'
+ },
+ 'blue@nested': {
+ template: 'I like blue'
+ },
+ 'red@nested': {
+ template: 'I also like red'
+ }
+ }
+ })
+ });
+
+
+ tester = ngMidwayTester(appName, {
+ templateUrl: './test/spec/custom-view2.html'
});
- });
- var fn = function() {
- tester = ngMidwayTester(appName, {
- templateUrl : '../../some-file.html'
- });
- };
+ expect(tester.module()).to.equal(example);
+ expect(tester.rootScope().value).to.equal('true');
+
+ tester.visit('/nested');
+ tester.waitForControllerInViewScope(function () {
+ expect(tester.path()).to.equal('/nested');
+ var htmlMain = tester.viewElement('main').html();
+ expect(htmlMain).to.contain('MainContent');
+ var htmlSecondary = tester.viewElement('secondary').html();
+ expect(htmlSecondary).to.contain('Bad view');
+ var htmlSecondaryMain = tester.viewElement(['secondary', 'main3']).html();
+ expect(htmlSecondaryMain).to.contain('hot content');
+ var htmlBlueSecondaryMain = tester.viewElement(['secondary', 'secondary3', 'blue']).html();
+ expect(htmlBlueSecondaryMain).to.contain('I like blue');
+ var htmlRedSecondaryMain = tester.viewElement(['secondary', 'secondary3', 'red']).html();
+ expect(htmlRedSecondaryMain).to.contain('I also like red');
+ done();
+ },null,'cat')();
- expect(fn).to.throw('ngMidwayTester: Unable to download template file');
- });
+
+ });
+
+
+ it('should throw an error when a file downloaded from templateUrl is not found', function () {
+ var example = angular.module(appName, ['ui.router'])
+ .run(function ($rootScope) {
+ $rootScope.value = 'true';
+ })
+ .config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
+ $urlRouterProvider.otherwise("/path-10");
+ $locationProvider.html5Mode(false).hashPrefix('!');
+
+ $stateProvider
+ .state('path-10', {
+ url: '/path-10',
+ controller: function ($scope) {
+ $scope.page = 'ten';
+ },
+ template: 'ten'
+ })
+ });
+
+
+ var fn = function () {
+ tester = ngMidwayTester(appName, {
+ templateUrl: '../../some-file.html'
+ });
+ };
+
+ expect(fn).to.throw('ngMidwayTester: Unable to download template file');
+ });
});
describe('scope', function() {
@@ -154,53 +293,78 @@ describe('ngMidwayTester', function() {
});
describe('routing', function() {
- it('should change the path', function(done) {
- var example = angular.module(appName, ['ngRoute'])
- .run(function($rootScope) {
- $rootScope.value = 'true';
- });
-
- tester = ngMidwayTester(appName, true);
- tester.visit('/', function() {
- expect(tester.path()).to.equal('/');
- done();
+ it('should change the path', function (done) {
+ var example = angular.module(appName, ['ui.router'])
+ .run(function ($rootScope) {
+ $rootScope.value = 'true';
+ });
+
+ tester = ngMidwayTester(appName, true);
+ tester.visit('/');
+ tester.waitForDigest(function () {
+ expect(tester.path()).to.equal('/');
+ done();
+ })();
});
- });
- it('should update the when by the time the callback is called', function(done) {
- var example = angular.module(appName, ['ngRoute'])
- .config(function($routeProvider) {
- $routeProvider.when('/path', {
- controller: function($scope) {
- $scope.page = 'one';
- },
- template : '...'
+ it('should update the when by the time the callback is called', function (done) {
+ var example = angular.module(appName, ['ui.router'])
+ .config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
+ $urlRouterProvider.otherwise("/path");
+ $locationProvider.html5Mode(false).hashPrefix('!');
+
+ $stateProvider
+ .state('path', {
+ url: '/path',
+ views:{
+ '':{
+ controller: function ($scope) {
+ $scope.page = 'one';
+ },
+ template: '...'
+ }
+ }
+
+ })
+ .state('path2', {
+ url: '/path2',
+ views: {
+ '':{
+ controller: function ($scope) {
+ $scope.page = 'two';
+ },
+ template: '==='
+ }
+ }
+
+ })
+ });
+
+
+ tester = ngMidwayTester(appName, true);
+ tester.attach();
+
+ tester.visit('/path');
+ var f1, f2;
+ f1 = tester.waitForViewScopeCondition(function(){
+ expect(tester.path()).to.equal('/path');
+ expect(tester.rootElement().text()).to.equal('...');
+ expect(tester.viewScope().page).to.equal('one');
+ tester.visit('/path2');
+ f2();
+ },null,function(scope){
+ return scope.page && scope.page==='one';
});
- $routeProvider.when('/path2', {
- controller: function($scope) {
- $scope.page = 'two';
- },
- template : '==='
+ f2 = tester.waitForViewScopeCondition(function () {
+ expect(tester.path()).to.equal('/path2');
+ expect(tester.rootElement().text()).to.equal('===');
+ expect(tester.viewScope().page).to.equal('two');
+ done();
+ }, null,function(scope){
+ return scope.page && scope.page==='two';
});
- });
-
- tester = ngMidwayTester(appName, true);
- tester.attach();
-
- tester.visit('/path', function() {
- expect(tester.path()).to.equal('/path');
- expect(tester.rootElement().text()).to.equal('...');
- expect(tester.viewScope().page).to.equal('one');
-
- tester.visit('/path2', function() {
- expect(tester.path()).to.equal('/path2');
- expect(tester.rootElement().text()).to.equal('===');
- expect(tester.viewScope().page).to.equal('two');
-
- done();
- });
+ f1();
});
- });
});
describe('controllers', function() {
@@ -263,4 +427,41 @@ describe('ngMidwayTester', function() {
tester3.destroy();
});
});
+
+ describe ('System functions', function(){
+
+ beforeEach(function() {
+ example = angular.module(appName, [])
+ .factory('factory', function() {
+ return function() {
+ return 'hello';
+ }
+ })
+ .controller('HomeCtrl', function($scope, factory) {
+ $scope.factory = factory;
+ });
+
+ tester = ngMidwayTester(appName, {
+ template : '' +
+ '' +
+ '' +
+ '
Help Desk
' +
+ '
' +
+ '
'
+ });
+ newScope = tester.rootScope().$new();
+ });
+
+
+ it ('calling setTimeout should call a function after some time', function(done){
+ var s = function(){
+ expect(s).to.exist();
+ clearTimeout(s);
+ done();
+ };
+ setTimeout(s,1000);
+ });
+ })
});