diff --git a/Gemfile b/Gemfile index 443635f2f..95ec2f42d 100755 --- a/Gemfile +++ b/Gemfile @@ -2,14 +2,13 @@ source 'https://rubygems.org' ruby '2.1.1' +gem 'rails', '4.1.0' + #Dokku demands this one. gem 'rails_12factor' gem 'ng-rails-csrf' -# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '4.1.0' - gem 'mongoid', '~> 4.0.0.beta1', github: 'mongoid/mongoid' gem 'sass-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 0cd399eba..5d1fe4b53 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,16 +1,16 @@ GIT remote: git://github.com/mongoid/mongoid.git - revision: e93a4837b0266db46c24aae172e184f57c847b04 + revision: 50b633c8baf2fa467e8c36b18a013a2cd50e0454 specs: - mongoid (4.0.0.beta1) - activemodel (>= 4.0.0) - moped (~> 2.0.beta6) + mongoid (4.0.0) + activemodel (~> 4.0) + moped (~> 2.0.0) origin (~> 2.1) tzinfo (>= 0.3.37) GIT remote: git://github.com/plataformatec/devise.git - revision: 6129215afecc0b3628e0d46f5253f89e2a862c6b + revision: b6af1675d5b4123b2481dd2630fe5197829994ec specs: devise (3.2.4) bcrypt (~> 3.0) @@ -53,11 +53,11 @@ GEM arrayfields (4.9.2) awesome_print (1.2.0) bcrypt (3.1.7) - bson (2.2.3) + bson (2.3.0) builder (3.2.2) cane (2.6.2) parallel - capybara (2.2.1) + capybara (2.3.0) mime-types (>= 1.16) nokogiri (>= 1.3.3) rack (>= 1.0.0) @@ -86,9 +86,9 @@ GEM colored (1.2) connection_pool (2.0.0) diff-lcs (1.2.5) - docile (1.1.3) + docile (1.1.5) erubis (2.7.0) - execjs (2.0.2) + execjs (2.2.0) factory_girl (4.4.0) activesupport (>= 3.0.0) factory_girl_rails (4.4.1) @@ -100,17 +100,17 @@ GEM figaro (0.7.0) bundler (~> 1.0) rails (>= 3, < 5) - flay (2.4.0) + flay (2.5.0) ruby_parser (~> 3.0) sexp_processor (~> 4.0) - flog (4.2.0) + flog (4.2.1) ruby_parser (~> 3.1, > 3.1.0) sexp_processor (~> 4.4) haml (4.0.5) tilt high_voltage (2.1.0) hike (1.2.3) - hirb (0.7.1) + hirb (0.7.2) i18n (0.6.9) jasmine-core (2.0.0) jasmine-rails (0.9.0) @@ -133,7 +133,7 @@ GEM chronic (>= 0.6.2) fattr (>= 2.2.0) map (>= 5.1.0) - map (6.5.3) + map (6.5.4) method_source (0.8.2) metric_fu (4.11.1) cane (~> 2.5, >= 2.5.2) @@ -151,25 +151,25 @@ GEM roodi (~> 3.1) metric_fu-Saikuro (1.1.3) mime-types (1.25.1) - mini_portile (0.5.3) - minitest (5.3.3) - moped (2.0.0.rc1) + mini_portile (0.6.0) + minitest (5.3.5) + moped (2.0.0) bson (~> 2.2) connection_pool (~> 2.0) optionable (~> 0.2.0) - multi_json (1.10.0) + multi_json (1.10.1) ng-rails-csrf (0.1.0) - nokogiri (1.6.1) - mini_portile (~> 0.5.0) + nokogiri (1.6.2.1) + mini_portile (= 0.6.0) optionable (0.2.0) origin (2.1.1) orm_adapter (0.5.0) parallel (1.0.0) phantomjs (1.9.7.1) - polyglot (0.3.4) - pry (0.9.12.6) - coderay (~> 1.0) - method_source (~> 0.8) + polyglot (0.3.5) + pry (0.10.0) + coderay (~> 1.1.0) + method_source (~> 0.8.1) slop (~> 3.4) rack (1.5.2) rack-test (0.6.2) @@ -205,7 +205,7 @@ GEM rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rainbow (2.0.0) - rake (10.3.1) + rake (10.3.2) rdoc (4.1.1) json (~> 1.4) redcard (1.1.0) @@ -219,22 +219,26 @@ GEM mime-types (>= 1.16) roodi (3.3.1) ruby_parser (~> 3.2, >= 3.2.2) - rspec (2.14.1) - rspec-core (~> 2.14.0) - rspec-expectations (~> 2.14.0) - rspec-mocks (~> 2.14.0) - rspec-core (2.14.8) - rspec-expectations (2.14.5) - diff-lcs (>= 1.1.3, < 2.0) - rspec-mocks (2.14.6) - rspec-rails (2.14.2) + rspec (3.0.0) + rspec-core (~> 3.0.0) + rspec-expectations (~> 3.0.0) + rspec-mocks (~> 3.0.0) + rspec-core (3.0.2) + rspec-support (~> 3.0.0) + rspec-expectations (3.0.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.0.0) + rspec-mocks (3.0.2) + rspec-support (~> 3.0.0) + rspec-rails (3.0.1) actionpack (>= 3.0) - activemodel (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 2.14.0) - rspec-expectations (~> 2.14.0) - rspec-mocks (~> 2.14.0) + rspec-core (~> 3.0.0) + rspec-expectations (~> 3.0.0) + rspec-mocks (~> 3.0.0) + rspec-support (~> 3.0.0) + rspec-support (3.0.2) ruby-progressbar (1.5.1) ruby2ruby (2.0.8) ruby_parser (~> 3.1) @@ -267,14 +271,14 @@ GEM activesupport (>= 3.0) sprockets (~> 2.8) thor (0.19.1) - thread_safe (0.3.3) + thread_safe (0.3.4) tilt (1.4.1) treetop (1.4.15) polyglot polyglot (>= 0.3.1) - tzinfo (1.1.0) + tzinfo (1.2.1) thread_safe (~> 0.1) - uglifier (2.5.0) + uglifier (2.5.1) execjs (>= 0.3.0) json (>= 1.8.0) warden (1.2.3) diff --git a/app/assets/javascripts/angular/angular-mock.js b/app/assets/javascripts/angular/angular-mock.js index a391c8a96..07add61f9 100644 --- a/app/assets/javascripts/angular/angular-mock.js +++ b/app/assets/javascripts/angular/angular-mock.js @@ -1,11 +1,10 @@ /** - * @license AngularJS v1.2.9 - * (c) 2010-2014 Google, Inc. http://angularjs.org + * @license AngularJS v"NG_VERSION_FULL" + * (c) 2010-2012 Google, Inc. http://angularjs.org * License: MIT + * + * TODO(vojta): wrap whole file into closure during build */ -(function(window, angular, undefined) { - -'use strict'; /** * @ngdoc overview @@ -76,13 +75,6 @@ angular.mock.$Browser = function() { }; - /** - * @name ngMock.$browser#defer.now - * @propertyOf ngMock.$browser - * - * @description - * Current milliseconds mock time. - */ self.defer.now = 0; @@ -118,7 +110,7 @@ angular.mock.$Browser = function() { if (self.deferredFns.length) { self.defer.now = self.deferredFns[self.deferredFns.length-1].time; } else { - throw new Error('No deferred tasks to be flushed'); + throw Error('No deferred tasks to be flushed'); } } @@ -127,6 +119,29 @@ angular.mock.$Browser = function() { } }; + /** + * @name ngMock.$browser#defer.flushNext + * @methodOf ngMock.$browser + * + * @description + * Flushes next pending request and compares it to the provided delay + * + * @param {number=} expectedDelay the delay value that will be asserted against the delay of the next timeout function + */ + self.defer.flushNext = function(expectedDelay) { + var tick = self.deferredFns.shift(); + expect(tick.time).toEqual(expectedDelay); + tick.fn(); + }; + + /** + * @name ngMock.$browser#defer.now + * @propertyOf ngMock.$browser + * + * @description + * Current milliseconds mock time. + */ + self.$$baseHref = ''; self.baseHref = function() { return this.$$baseHref; @@ -163,7 +178,7 @@ angular.mock.$Browser.prototype = { cookies: function(name, value) { if (name) { - if (angular.isUndefined(value)) { + if (value == undefined) { delete this.cookieHash[name]; } else { if (angular.isString(value) && //strings only @@ -191,8 +206,8 @@ angular.mock.$Browser.prototype = { * @name ngMock.$exceptionHandlerProvider * * @description - * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors - * passed into the `$exceptionHandler`. + * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors passed + * into the `$exceptionHandler`. */ /** @@ -245,10 +260,10 @@ angular.mock.$ExceptionHandlerProvider = function() { * - `rethrow`: If any errors are passed into the handler in tests, it typically * means that there is a bug in the application or test, so this mock will * make these tests fail. - * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log` - * mode stores an array of errors in `$exceptionHandler.errors`, to allow later - * assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and - * {@link ngMock.$log#reset reset()} + * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log` mode stores an + * array of errors in `$exceptionHandler.errors`, to allow later assertion of them. + * See {@link ngMock.$log#assertEmpty assertEmpty()} and + * {@link ngMock.$log#reset reset()} */ this.mode = function(mode) { switch(mode) { @@ -271,7 +286,7 @@ angular.mock.$ExceptionHandlerProvider = function() { handler.errors = errors; break; default: - throw new Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!"); + throw Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!"); } }; @@ -301,7 +316,7 @@ angular.mock.$LogProvider = function() { } this.debugEnabled = function(flag) { - if (angular.isDefined(flag)) { + if (isDefined(flag)) { debug = flag; return this; } else { @@ -405,7 +420,7 @@ angular.mock.$LogProvider = function() { * var first = $log.debug.logs.unshift(); * */ - $log.debug.logs = []; + $log.debug.logs = [] }; /** @@ -414,22 +429,20 @@ angular.mock.$LogProvider = function() { * @methodOf ngMock.$log * * @description - * Assert that the all of the logging methods have no logged messages. If messages present, an - * exception is thrown. + * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown. */ $log.assertEmpty = function() { var errors = []; angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) { angular.forEach($log[logLevel].logs, function(log) { angular.forEach(log, function (logItem) { - errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + - (logItem.stack || '')); + errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + (logItem.stack || '')); }); }); }); if (errors.length) { - errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or "+ - "an expected log message was not checked and removed:"); + errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or an expected " + + "log message was not checked and removed:"); errors.push(''); throw new Error(errors.join('\n---------\n')); } @@ -441,357 +454,207 @@ angular.mock.$LogProvider = function() { }; -/** - * @ngdoc service - * @name ngMock.$interval - * - * @description - * Mock implementation of the $interval service. - * - * Use {@link ngMock.$interval#methods_flush `$interval.flush(millis)`} to - * move forward by `millis` milliseconds and trigger any functions scheduled to run in that - * time. - * - * @param {function()} fn A function that should be called repeatedly. - * @param {number} delay Number of milliseconds between each function call. - * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat - * indefinitely. - * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise - * will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block. - * @returns {promise} A promise which will be notified on each iteration. - */ -angular.mock.$IntervalProvider = function() { - this.$get = ['$rootScope', '$q', - function($rootScope, $q) { - var repeatFns = [], - nextRepeatId = 0, - now = 0; +(function() { + var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/; - var $interval = function(fn, delay, count, invokeApply) { - var deferred = $q.defer(), - promise = deferred.promise, - iteration = 0, - skipApply = (angular.isDefined(invokeApply) && !invokeApply); - - count = (angular.isDefined(count)) ? count : 0, - promise.then(null, null, fn); - - promise.$$intervalId = nextRepeatId; - - function tick() { - deferred.notify(iteration++); - - if (count > 0 && iteration >= count) { - var fnIndex; - deferred.resolve(iteration); - - angular.forEach(repeatFns, function(fn, index) { - if (fn.id === promise.$$intervalId) fnIndex = index; - }); - - if (fnIndex !== undefined) { - repeatFns.splice(fnIndex, 1); - } - } - - if (!skipApply) $rootScope.$apply(); + function jsonStringToDate(string) { + var match; + if (match = string.match(R_ISO8061_STR)) { + var date = new Date(0), + tzHour = 0, + tzMin = 0; + if (match[9]) { + tzHour = int(match[9] + match[10]); + tzMin = int(match[9] + match[11]); } - - repeatFns.push({ - nextTime:(now + delay), - delay: delay, - fn: tick, - id: nextRepeatId, - deferred: deferred - }); - repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;}); - - nextRepeatId++; - return promise; - }; - - $interval.cancel = function(promise) { - var fnIndex; - - angular.forEach(repeatFns, function(fn, index) { - if (fn.id === promise.$$intervalId) fnIndex = index; - }); - - if (fnIndex !== undefined) { - repeatFns[fnIndex].deferred.reject('canceled'); - repeatFns.splice(fnIndex, 1); - return true; - } - - return false; - }; - - /** - * @ngdoc method - * @name ngMock.$interval#flush - * @methodOf ngMock.$interval - * @description - * - * Runs interval tasks scheduled to be run in the next `millis` milliseconds. - * - * @param {number=} millis maximum timeout amount to flush up until. - * - * @return {number} The amount of time moved forward. - */ - $interval.flush = function(millis) { - now += millis; - while (repeatFns.length && repeatFns[0].nextTime <= now) { - var task = repeatFns[0]; - task.fn(); - task.nextTime += task.delay; - repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;}); - } - return millis; - }; - - return $interval; - }]; -}; - - -/* jshint -W101 */ -/* The R_ISO8061_STR regex is never going to fit into the 100 char limit! - * This directive should go inside the anonymous function but a bug in JSHint means that it would - * not be enacted early enough to prevent the warning. - */ -var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/; - -function jsonStringToDate(string) { - var match; - if (match = string.match(R_ISO8061_STR)) { - var date = new Date(0), - tzHour = 0, - tzMin = 0; - if (match[9]) { - tzHour = int(match[9] + match[10]); - tzMin = int(match[9] + match[11]); + date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3])); + date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0)); + return date; } - date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3])); - date.setUTCHours(int(match[4]||0) - tzHour, - int(match[5]||0) - tzMin, - int(match[6]||0), - int(match[7]||0)); - return date; - } - return string; -} - -function int(str) { - return parseInt(str, 10); -} - -function padNumber(num, digits, trim) { - var neg = ''; - if (num < 0) { - neg = '-'; - num = -num; - } - num = '' + num; - while(num.length < digits) num = '0' + num; - if (trim) - num = num.substr(num.length - digits); - return neg + num; -} - - -/** - * @ngdoc object - * @name angular.mock.TzDate - * @description - * - * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`. - * - * Mock of the Date type which has its timezone specified via constructor arg. - * - * The main purpose is to create Date-like instances with timezone fixed to the specified timezone - * offset, so that we can test code that depends on local timezone settings without dependency on - * the time zone settings of the machine where the code is running. - * - * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored) - * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC* - * - * @example - * !!!! WARNING !!!!! - * This is not a complete Date object so only methods that were implemented can be called safely. - * To make matters worse, TzDate instances inherit stuff from Date via a prototype. - * - * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is - * incomplete we might be missing some non-standard methods. This can result in errors like: - * "Date.prototype.foo called on incompatible Object". - * - *
- * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
- * newYearInBratislava.getTimezoneOffset() => -60;
- * newYearInBratislava.getFullYear() => 2010;
- * newYearInBratislava.getMonth() => 0;
- * newYearInBratislava.getDate() => 1;
- * newYearInBratislava.getHours() => 0;
- * newYearInBratislava.getMinutes() => 0;
- * newYearInBratislava.getSeconds() => 0;
- * 
- * - */ -angular.mock.TzDate = function (offset, timestamp) { - var self = new Date(0); - if (angular.isString(timestamp)) { - var tsStr = timestamp; - - self.origDate = jsonStringToDate(timestamp); - - timestamp = self.origDate.getTime(); - if (isNaN(timestamp)) - throw { - name: "Illegal Argument", - message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string" - }; - } else { - self.origDate = new Date(timestamp); + return string; } - var localOffset = new Date(timestamp).getTimezoneOffset(); - self.offsetDiff = localOffset*60*1000 - offset*1000*60*60; - self.date = new Date(timestamp + self.offsetDiff); + function int(str) { + return parseInt(str, 10); + } - self.getTime = function() { - return self.date.getTime() - self.offsetDiff; - }; + function padNumber(num, digits, trim) { + var neg = ''; + if (num < 0) { + neg = '-'; + num = -num; + } + num = '' + num; + while(num.length < digits) num = '0' + num; + if (trim) + num = num.substr(num.length - digits); + return neg + num; + } - self.toLocaleDateString = function() { - return self.date.toLocaleDateString(); - }; - self.getFullYear = function() { - return self.date.getFullYear(); - }; + /** + * @ngdoc object + * @name angular.mock.TzDate + * @description + * + * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`. + * + * Mock of the Date type which has its timezone specified via constructor arg. + * + * The main purpose is to create Date-like instances with timezone fixed to the specified timezone + * offset, so that we can test code that depends on local timezone settings without dependency on + * the time zone settings of the machine where the code is running. + * + * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored) + * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC* + * + * @example + * !!!! WARNING !!!!! + * This is not a complete Date object so only methods that were implemented can be called safely. + * To make matters worse, TzDate instances inherit stuff from Date via a prototype. + * + * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is + * incomplete we might be missing some non-standard methods. This can result in errors like: + * "Date.prototype.foo called on incompatible Object". + * + *
+   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
+   * newYearInBratislava.getTimezoneOffset() => -60;
+   * newYearInBratislava.getFullYear() => 2010;
+   * newYearInBratislava.getMonth() => 0;
+   * newYearInBratislava.getDate() => 1;
+   * newYearInBratislava.getHours() => 0;
+   * newYearInBratislava.getMinutes() => 0;
+   * newYearInBratislava.getSeconds() => 0;
+   * 
+ * + */ + angular.mock.TzDate = function (offset, timestamp) { + var self = new Date(0); + if (angular.isString(timestamp)) { + var tsStr = timestamp; - self.getMonth = function() { - return self.date.getMonth(); - }; + self.origDate = jsonStringToDate(timestamp); - self.getDate = function() { - return self.date.getDate(); - }; + timestamp = self.origDate.getTime(); + if (isNaN(timestamp)) + throw { + name: "Illegal Argument", + message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string" + }; + } else { + self.origDate = new Date(timestamp); + } - self.getHours = function() { - return self.date.getHours(); - }; + var localOffset = new Date(timestamp).getTimezoneOffset(); + self.offsetDiff = localOffset*60*1000 - offset*1000*60*60; + self.date = new Date(timestamp + self.offsetDiff); - self.getMinutes = function() { - return self.date.getMinutes(); - }; - - self.getSeconds = function() { - return self.date.getSeconds(); - }; - - self.getMilliseconds = function() { - return self.date.getMilliseconds(); - }; - - self.getTimezoneOffset = function() { - return offset * 60; - }; - - self.getUTCFullYear = function() { - return self.origDate.getUTCFullYear(); - }; - - self.getUTCMonth = function() { - return self.origDate.getUTCMonth(); - }; - - self.getUTCDate = function() { - return self.origDate.getUTCDate(); - }; - - self.getUTCHours = function() { - return self.origDate.getUTCHours(); - }; - - self.getUTCMinutes = function() { - return self.origDate.getUTCMinutes(); - }; - - self.getUTCSeconds = function() { - return self.origDate.getUTCSeconds(); - }; - - self.getUTCMilliseconds = function() { - return self.origDate.getUTCMilliseconds(); - }; - - self.getDay = function() { - return self.date.getDay(); - }; - - // provide this method only on browsers that already have it - if (self.toISOString) { - self.toISOString = function() { - return padNumber(self.origDate.getUTCFullYear(), 4) + '-' + - padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' + - padNumber(self.origDate.getUTCDate(), 2) + 'T' + - padNumber(self.origDate.getUTCHours(), 2) + ':' + - padNumber(self.origDate.getUTCMinutes(), 2) + ':' + - padNumber(self.origDate.getUTCSeconds(), 2) + '.' + - padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'; + self.getTime = function() { + return self.date.getTime() - self.offsetDiff; }; - } - //hide all methods not implemented in this mock that the Date prototype exposes - var unimplementedMethods = ['getUTCDay', - 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', - 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', - 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', - 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString', - 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf']; - - angular.forEach(unimplementedMethods, function(methodName) { - self[methodName] = function() { - throw new Error("Method '" + methodName + "' is not implemented in the TzDate mock"); + self.toLocaleDateString = function() { + return self.date.toLocaleDateString(); }; - }); - return self; -}; + self.getFullYear = function() { + return self.date.getFullYear(); + }; -//make "tzDateInstance instanceof Date" return true -angular.mock.TzDate.prototype = Date.prototype; -/* jshint +W101 */ + self.getMonth = function() { + return self.date.getMonth(); + }; -// TODO(matias): remove this IMMEDIATELY once we can properly detect the -// presence of a registered module -var animateLoaded; -try { - angular.module('ngAnimate'); - animateLoaded = true; -} catch(e) {} + self.getDate = function() { + return self.date.getDate(); + }; -if(animateLoaded) { - angular.module('ngAnimate').config(['$provide', function($provide) { - var reflowQueue = []; - $provide.value('$$animateReflow', function(fn) { - reflowQueue.push(fn); - return angular.noop; - }); - $provide.decorator('$animate', function($delegate) { - $delegate.triggerReflow = function() { - if(reflowQueue.length === 0) { - throw new Error('No animation reflows present'); - } - angular.forEach(reflowQueue, function(fn) { - fn(); - }); - reflowQueue = []; + self.getHours = function() { + return self.date.getHours(); + }; + + self.getMinutes = function() { + return self.date.getMinutes(); + }; + + self.getSeconds = function() { + return self.date.getSeconds(); + }; + + self.getMilliseconds = function() { + return self.date.getMilliseconds(); + }; + + self.getTimezoneOffset = function() { + return offset * 60; + }; + + self.getUTCFullYear = function() { + return self.origDate.getUTCFullYear(); + }; + + self.getUTCMonth = function() { + return self.origDate.getUTCMonth(); + }; + + self.getUTCDate = function() { + return self.origDate.getUTCDate(); + }; + + self.getUTCHours = function() { + return self.origDate.getUTCHours(); + }; + + self.getUTCMinutes = function() { + return self.origDate.getUTCMinutes(); + }; + + self.getUTCSeconds = function() { + return self.origDate.getUTCSeconds(); + }; + + self.getUTCMilliseconds = function() { + return self.origDate.getUTCMilliseconds(); + }; + + self.getDay = function() { + return self.date.getDay(); + }; + + // provide this method only on browsers that already have it + if (self.toISOString) { + self.toISOString = function() { + return padNumber(self.origDate.getUTCFullYear(), 4) + '-' + + padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' + + padNumber(self.origDate.getUTCDate(), 2) + 'T' + + padNumber(self.origDate.getUTCHours(), 2) + ':' + + padNumber(self.origDate.getUTCMinutes(), 2) + ':' + + padNumber(self.origDate.getUTCSeconds(), 2) + '.' + + padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z' + } + } + + //hide all methods not implemented in this mock that the Date prototype exposes + var unimplementedMethods = ['getUTCDay', + 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', + 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', + 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', + 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString', + 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf']; + + angular.forEach(unimplementedMethods, function(methodName) { + self[methodName] = function() { + throw Error("Method '" + methodName + "' is not implemented in the TzDate mock"); }; - return $delegate; }); - }]); -} + + return self; + }; + + //make "tzDateInstance instanceof Date" return true + angular.mock.TzDate.prototype = Date.prototype; +})(); angular.mock.animate = angular.module('mock.animate', ['ng']) @@ -803,18 +666,13 @@ angular.mock.animate = angular.module('mock.animate', ['ng']) enabled : $delegate.enabled, flushNext : function(name) { var tick = animate.queue.shift(); - - if (!tick) throw new Error('No animation to be flushed'); - if(tick.method !== name) { - throw new Error('The next animation is not "' + name + - '", but is "' + tick.method + '"'); - } + expect(tick.method).toBe(name); tick.fn(); return tick; } }; - angular.forEach(['enter','leave','move','addClass','removeClass'], function(method) { + forEach(['enter','leave','move','addClass','removeClass'], function(method) { animate[method] = function() { var params = arguments; animate.queue.push({ @@ -843,11 +701,9 @@ angular.mock.animate = angular.module('mock.animate', ['ng']) * * *NOTE*: this is not an injectable instance, just a globally available function. * - * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for - * debugging. + * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging. * - * This method is also available on window, where it can be used to display objects on debug - * console. + * This method is also available on window, where it can be used to display objects on debug console. * * @param {*} object - any object to turn into string. * @return {string} a serialized string of the argument @@ -877,8 +733,7 @@ angular.mock.dump = function(object) { } else if (object instanceof Error) { out = object.stack || ('' + object.name + ': ' + object.message); } else { - // TODO(i): this prevents methods being logged, - // we should have a better way to serialize objects + // TODO(i): this prevents methods to be logged, we should have a better way to serialize objects out = angular.toJson(object, true); } } else { @@ -892,7 +747,7 @@ angular.mock.dump = function(object) { offset = offset || ' '; var log = [offset + 'Scope(' + scope.$id + '): {']; for ( var key in scope ) { - if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) { + if (scope.hasOwnProperty(key) && !key.match(/^(\$|this)/)) { log.push(' ' + key + ': ' + angular.toJson(scope[key])); } } @@ -917,7 +772,7 @@ angular.mock.dump = function(object) { * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}. * * During unit testing, we want our unit tests to run quickly and have no external dependencies so - * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or + * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is * to verify whether a certain request has been sent or not, or alternatively just let the * application make requests, respond with pre-trained responses and assert that the end result is @@ -1073,7 +928,7 @@ angular.mock.dump = function(object) { var controller = createController(); $httpBackend.flush(); - // now you don’t care about the authentication, but + // now you don’t care about the authentication, but // the controller will still send the request and // $httpBackend will respond without you having to // specify the expectation and response for this request @@ -1124,8 +979,7 @@ function createHttpBackendMock($rootScope, $delegate, $browser) { var definitions = [], expectations = [], responses = [], - responsesPush = angular.bind(responses, responses.push), - copy = angular.copy; + responsesPush = angular.bind(responses, responses.push); function createResponse(status, data, headers) { if (angular.isFunction(status)) return status; @@ -1157,7 +1011,7 @@ function createHttpBackendMock($rootScope, $delegate, $browser) { function handleResponse() { var response = wrapped.response(method, url, data, headers); xhr.$$respHeaders = response[2]; - callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders()); + callback(response[0], response[1], xhr.getAllResponseHeaders()); } function handleTimeout() { @@ -1178,8 +1032,7 @@ function createHttpBackendMock($rootScope, $delegate, $browser) { if (!expectation.matchHeaders(headers)) throw new Error('Expected ' + expectation + ' with different headers\n' + - 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' + - prettyPrint(headers)); + 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' + prettyPrint(headers)); expectations.shift(); @@ -1198,7 +1051,7 @@ function createHttpBackendMock($rootScope, $delegate, $browser) { ($browser ? $browser.defer : responsesPush)(wrapResponse(definition)); } else if (definition.passThrough) { $delegate(method, url, data, callback, headers, timeout, withCredentials); - } else throw new Error('No response defined !'); + } else throw Error('No response defined !'); return; } } @@ -1221,12 +1074,11 @@ function createHttpBackendMock($rootScope, $delegate, $browser) { * data string and returns true if the data is as expected. * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header * object and returns true if the headers match the current definition. - * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * @returns {requestHandler} Returns an object with `respond` method that control how a matched * request is handled. * - * - respond – - * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` - * – The respond method takes a set of static data to be returned or a function that can return + * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}` + * – The respond method takes a set of static data to be returned or a function that can return * an array containing response status (number), response data (string) and response headers * (Object). */ @@ -1348,9 +1200,8 @@ function createHttpBackendMock($rootScope, $delegate, $browser) { * @returns {requestHandler} Returns an object with `respond` method that control how a matched * request is handled. * - * - respond – - * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` - * – The respond method takes a set of static data to be returned or a function that can return + * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}` + * – The respond method takes a set of static data to be returned or a function that can return * an array containing response status (number), response data (string) and response headers * (Object). */ @@ -1479,11 +1330,11 @@ function createHttpBackendMock($rootScope, $delegate, $browser) { */ $httpBackend.flush = function(count) { $rootScope.$digest(); - if (!responses.length) throw new Error('No pending request to flush !'); + if (!responses.length) throw Error('No pending request to flush !'); if (angular.isDefined(count)) { while (count--) { - if (!responses.length) throw new Error('No more pending request to flush !'); + if (!responses.length) throw Error('No more pending request to flush !'); responses.shift()(); } } else { @@ -1534,7 +1385,7 @@ function createHttpBackendMock($rootScope, $delegate, $browser) { */ $httpBackend.verifyNoOutstandingRequest = function() { if (responses.length) { - throw new Error('Unflushed requests: ' + responses.length); + throw Error('Unflushed requests: ' + responses.length); } }; @@ -1559,14 +1410,14 @@ function createHttpBackendMock($rootScope, $delegate, $browser) { function createShortMethods(prefix) { angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) { $httpBackend[prefix + method] = function(url, headers) { - return $httpBackend[prefix](method, url, undefined, headers); - }; + return $httpBackend[prefix](method, url, undefined, headers) + } }); angular.forEach(['PUT', 'POST', 'PATCH'], function(method) { $httpBackend[prefix + method] = function(url, data, headers) { - return $httpBackend[prefix](method, url, data, headers); - }; + return $httpBackend[prefix](method, url, data, headers) + } }); } } @@ -1600,7 +1451,7 @@ function MockHttpExpectation(method, url, data, headers) { if (angular.isUndefined(data)) return true; if (data && angular.isFunction(data.test)) return data.test(d); if (data && angular.isFunction(data)) return data(d); - if (data && !angular.isString(data)) return angular.equals(data, angular.fromJson(d)); + if (data && !angular.isString(data)) return angular.toJson(data) == d; return data == d; }; @@ -1609,10 +1460,6 @@ function MockHttpExpectation(method, url, data, headers) { }; } -function createMockXhr() { - return new MockXhr(); -} - function MockXhr() { // hack for testing $http, $httpBackend @@ -1635,8 +1482,7 @@ function MockXhr() { }; this.getResponseHeader = function(name) { - // the lookup must be case insensitive, - // that's why we try two quick lookups first and full scan last + // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last var header = this.$$respHeaders[name]; if (header) return header; @@ -1689,6 +1535,20 @@ angular.mock.$TimeoutDecorator = function($delegate, $browser) { $browser.defer.flush(delay); }; + /** + * @ngdoc method + * @name ngMock.$timeout#flushNext + * @methodOf ngMock.$timeout + * @description + * + * Flushes the next timeout in the queue and compares it to the provided delay + * + * @param {number=} expectedDelay the delay value that will be asserted against the delay of the next timeout function + */ + $delegate.flushNext = function(expectedDelay) { + $browser.defer.flushNext(expectedDelay); + }; + /** * @ngdoc method * @name ngMock.$timeout#verifyNoPendingTasks @@ -1722,7 +1582,7 @@ angular.mock.$TimeoutDecorator = function($delegate, $browser) { angular.mock.$RootElementProvider = function() { this.$get = function() { return angular.element('
'); - }; + } }; /** @@ -1730,27 +1590,18 @@ angular.mock.$RootElementProvider = function() { * @name ngMock * @description * - * # ngMock - * - * The `ngMock` module providers support to inject and mock Angular services into unit tests. - * In addition, ngMock also extends various core ng services such that they can be - * inspected and controlled in a synchronous manner within test code. - * - * {@installModule mocks} - * - *
- * + * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful + * mocks to the {@link AUTO.$injector $injector}. */ angular.module('ngMock', ['ng']).provider({ $browser: angular.mock.$BrowserProvider, $exceptionHandler: angular.mock.$ExceptionHandlerProvider, $log: angular.mock.$LogProvider, - $interval: angular.mock.$IntervalProvider, $httpBackend: angular.mock.$HttpBackendProvider, $rootElement: angular.mock.$RootElementProvider -}).config(['$provide', function($provide) { +}).config(function($provide) { $provide.decorator('$timeout', angular.mock.$TimeoutDecorator); -}]); +}); /** * @ngdoc overview @@ -1761,9 +1612,9 @@ angular.module('ngMock', ['ng']).provider({ * Currently there is only one mock present in this module - * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock. */ -angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) { +angular.module('ngMockE2E', ['ng']).config(function($provide) { $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator); -}]); +}); /** * @ngdoc object @@ -1828,12 +1679,11 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) { * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that * control how a matched request is handled. * - * - respond – - * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` - * – The respond method takes a set of static data to be returned or a function that can return + * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}` + * – The respond method takes a set of static data to be returned or a function that can return * an array containing response status (number), response data (string) and response headers * (Object). - * - passThrough – `{function()}` – Any request matching a backend definition with `passThrough` + * - passThrough – `{function()}` – Any request matching a backend definition with `passThrough` * handler, will be pass through to the real backend (an XHR request will be made to the * server. */ @@ -1931,8 +1781,7 @@ angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) { * control how a matched request is handled. */ angular.mock.e2e = {}; -angular.mock.e2e.$httpBackendDecorator = - ['$rootScope', '$delegate', '$browser', createHttpBackendMock]; +angular.mock.e2e.$httpBackendDecorator = ['$rootScope', '$delegate', '$browser', createHttpBackendMock]; angular.mock.clearDataCache = function() { @@ -1940,7 +1789,7 @@ angular.mock.clearDataCache = function() { cache = angular.element.cache; for(key in cache) { - if (Object.prototype.hasOwnProperty.call(cache,key)) { + if (cache.hasOwnProperty(key)) { var handle = cache[key].handle; handle && angular.element(handle.elem).off(); @@ -1950,13 +1799,10 @@ angular.mock.clearDataCache = function() { }; -if(window.jasmine || window.mocha) { - var currentSpec = null, - isSpecRunning = function() { - return currentSpec && (window.mocha || currentSpec.queue.running); - }; +(window.jasmine || window.mocha) && (function(window) { + var currentSpec = null; beforeEach(function() { currentSpec = this; @@ -1989,6 +1835,10 @@ if(window.jasmine || window.mocha) { angular.callbacks.counter = 0; }); + function isSpecRunning() { + return !!currentSpec; + } + /** * @ngdoc function * @name angular.mock.module @@ -2001,11 +1851,9 @@ if(window.jasmine || window.mocha) { * * See {@link angular.mock.inject inject} for usage example * - * @param {...(string|Function|Object)} fns any number of modules which are represented as string + * @param {...(string|Function)} fns any number of modules which are represented as string * aliases or as anonymous module initialization functions. The modules are used to - * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an - * object literal is passed they will be register as values in the module, the key being - * the module name and the value being what is returned. + * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. */ window.module = angular.mock.module = function() { var moduleFns = Array.prototype.slice.call(arguments, 0); @@ -2013,19 +1861,11 @@ if(window.jasmine || window.mocha) { ///////////////////// function workFn() { if (currentSpec.$injector) { - throw new Error('Injector already created, can not register a module!'); + throw Error('Injector already created, can not register a module!'); } else { var modules = currentSpec.$modules || (currentSpec.$modules = []); angular.forEach(moduleFns, function(module) { - if (angular.isObject(module) && !angular.isArray(module)) { - modules.push(function($provide) { - angular.forEach(module, function(value, key) { - $provide.value(key, value); - }); - }); - } else { - modules.push(module); - } + modules.push(module); }); } } @@ -2042,40 +1882,8 @@ if(window.jasmine || window.mocha) { * instance of {@link AUTO.$injector $injector} per test, which is then used for * resolving references. * + * See also {@link angular.mock.module module} * - * ## Resolving References (Underscore Wrapping) - * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this - * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable - * that is declared in the scope of the `describe()` block. Since we would, most likely, want - * the variable to have the same name of the reference we have a problem, since the parameter - * to the `inject()` function would hide the outer variable. - * - * To help with this, the injected parameters can, optionally, be enclosed with underscores. - * These are ignored by the injector when the reference name is resolved. - * - * For example, the parameter `_myService_` would be resolved as the reference `myService`. - * Since it is available in the function body as _myService_, we can then assign it to a variable - * defined in an outer scope. - * - * ``` - * // Defined out reference variable outside - * var myService; - * - * // Wrap the parameter in underscores - * beforeEach( inject( function(_myService_){ - * myService = _myService_; - * })); - * - * // Use myService in a series of tests. - * it('makes use of myService', function() { - * myService.doStuff(); - * }); - * - * ``` - * - * See also {@link angular.mock.module angular.mock.module} - * - * ## Example * Example of what a typical jasmine tests looks like with the inject method. *
    *
@@ -2108,27 +1916,13 @@ if(window.jasmine || window.mocha) {
    *       inject(function(version) {
    *         expect(version).toEqual('overridden');
    *       });
-   *     });
+   *     ));
    *   });
    *
    * 
* * @param {...Function} fns any number of functions which will be injected using the injector. */ - - - - var ErrorAddingDeclarationLocationStack = function(e, errorForStack) { - this.message = e.message; - this.name = e.name; - if (e.line) this.line = e.line; - if (e.sourceId) this.sourceId = e.sourceId; - if (e.stack && errorForStack) - this.stack = e.stack + '\n' + errorForStack.stack; - if (e.stackArray) this.stackArray = e.stackArray; - }; - ErrorAddingDeclarationLocationStack.prototype.toString = Error.prototype.toString; - window.inject = angular.mock.inject = function() { var blockFns = Array.prototype.slice.call(arguments, 0); var errorForStack = new Error('Declaration Location'); @@ -2145,13 +1939,9 @@ if(window.jasmine || window.mocha) { } for(var i = 0, ii = blockFns.length; i < ii; i++) { try { - /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */ injector.invoke(blockFns[i] || angular.noop, this); - /* jshint +W040 */ } catch (e) { - if (e.stack && errorForStack) { - throw new ErrorAddingDeclarationLocationStack(e, errorForStack); - } + if(e.stack && errorForStack) e.stack += '\n' + errorForStack.stack; throw e; } finally { errorForStack = null; @@ -2159,7 +1949,4 @@ if(window.jasmine || window.mocha) { } } }; -} - - -})(window, window.angular); \ No newline at end of file +})(window); \ No newline at end of file diff --git a/spec/javascripts/example_spec.coffee b/spec/javascripts/example_spec.coffee new file mode 100644 index 000000000..613e9b29c --- /dev/null +++ b/spec/javascripts/example_spec.coffee @@ -0,0 +1,15 @@ +#= require application +#= require angular/angular-mock + +describe "Restauranteur controllers", -> + beforeEach -> + module("FarmBot") + inject ($controller) -> + @scope = {} + @ctrl = $controller("OverviewController", $scope: scope) + + describe "OverviewController", -> + it "initializes X, Y and Z", -> + expect(scope.x).toBe(0) + expect(scope.y).toBe(0) + expect(scope.z).toBe(0) \ No newline at end of file diff --git a/spec/javascripts/example_spec.js b/spec/javascripts/example_spec.js deleted file mode 100644 index ae74674f4..000000000 --- a/spec/javascripts/example_spec.js +++ /dev/null @@ -1,19 +0,0 @@ -//= require application -//= require angular/angular-mock -describe('FarmBot', function () { - var scope, controller; - - beforeEach(function () { - module('FarmBot'); - inject(function ($rootScope, $controller) { - scope = $rootScope.$new(); - controller = $controller('OverviewController', { - '$scope': scope - }); - }); -}) - - it('does stuff', function () { - expect(2 + 2).toBe(4); - }); -}); \ No newline at end of file