aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/FiltersSpec.js28
-rw-r--r--test/angular-mocks.js102
2 files changed, 113 insertions, 17 deletions
diff --git a/test/FiltersSpec.js b/test/FiltersSpec.js
index 6bbc09ae..4dd108ac 100644
--- a/test/FiltersSpec.js
+++ b/test/FiltersSpec.js
@@ -87,18 +87,11 @@ describe('filter', function(){
});
describe('date', function(){
- var morning = angular.String.toDate('2010-09-03T23:05:08Z');
- var midnight = angular.String.toDate('2010-09-03T23:05:08Z');
- var noon = angular.String.toDate('2010-09-03T23:05:08Z');
- morning.setHours(7);
- noon.setHours(12);
- midnight.setHours(0);
-
- //butt-ugly hack: force the date to be 2pm PDT for locale testing
- morning.getTimezoneOffset =
- noon.getTimezoneOffset =
- midnight.getTimezoneOffset =
- function() {return 7 * 60;};
+
+ var morning = new TzDate(+5, '2010-09-03T12:05:08Z'); //7am
+ var noon = new TzDate(+5, '2010-09-03T17:05:08Z'); //12pm
+ var midnight = new TzDate(+5, '2010-09-03T05:05:08Z'); //12am
+
it('should ignore falsy inputs', function() {
expect(filter.date(null)).toEqual(null);
@@ -116,16 +109,17 @@ describe('filter', function(){
});
it('should accept format', function() {
+ expect(filter.date(morning, "yy-MM-dd HH:mm:ss")).
+ toEqual('10-09-03 07:05:08');
+
expect(filter.date(midnight, "yyyy-M-d h=H:m:saZ")).
- toEqual('2010-9-3 12=0:5:8am0700');
+ toEqual('2010-9-3 12=0:5:8am0500');
expect(filter.date(midnight, "yyyy-MM-dd hh=HH:mm:ssaZ")).
- toEqual('2010-09-03 12=00:05:08am0700');
+ toEqual('2010-09-03 12=00:05:08am0500');
expect(filter.date(noon, "yyyy-MM-dd hh=HH:mm:ssaZ")).
- toEqual('2010-09-03 12=12:05:08pm0700');
-
+ toEqual('2010-09-03 12=12:05:08pm0500');
});
});
});
-
diff --git a/test/angular-mocks.js b/test/angular-mocks.js
index efe5b5b3..a090f0e8 100644
--- a/test/angular-mocks.js
+++ b/test/angular-mocks.js
@@ -162,3 +162,105 @@ MockBrowser.prototype = {
angular.service('$browser', function(){
return new MockBrowser();
});
+
+
+/**
+ * Mock of the Date type which has its timezone specified via constroctor 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
+ * 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;
+ *
+ *
+ * !!!! 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".
+ */
+function TzDate(offset, timestamp) {
+ if (angular.isString(timestamp)) {
+ var tsStr = timestamp;
+ timestamp = new Date(timestamp).getTime();
+ if (isNaN(timestamp))
+ throw {
+ name: "Illegal Argument",
+ message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string"
+ };
+ }
+
+ var localOffset = new Date(timestamp).getTimezoneOffset();
+ this.offsetDiff = localOffset*60*1000 - offset*1000*60*60;
+ this.date = new Date(timestamp + this.offsetDiff);
+
+ this.getTime = function() {
+ return this.date.getTime() - this.offsetDiff;
+ };
+
+ this.toLocaleDateString = function() {
+ return this.date.toLocaleDateString();
+ };
+
+ this.getFullYear = function() {
+ return this.date.getFullYear();
+ };
+
+ this.getMonth = function() {
+ return this.date.getMonth();
+ };
+
+ this.getDate = function() {
+ return this.date.getDate();
+ };
+
+ this.getHours = function() {
+ return this.date.getHours();
+ };
+
+ this.getMinutes = function() {
+ return this.date.getMinutes();
+ };
+
+ this.getSeconds = function() {
+ return this.date.getSeconds();
+ };
+
+ this.getTimezoneOffset = function() {
+ return offset * 60;
+ };
+
+ //hide all methods not implemented in this mock that the Date prototype exposes
+ var unimplementedMethods = ['getDay', 'getMilliseconds', 'getTime', 'getUTCDate', 'getUTCDay',
+ 'getUTCFullYear', 'getUTCHours', 'getUTCMilliseconds', 'getUTCMinutes', 'getUTCMonth',
+ 'getUTCSeconds', 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds',
+ 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear',
+ 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds',
+ 'setYear', 'toDateString', 'toJSON', 'toGMTString', 'toLocaleFormat', 'toLocaleString',
+ 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf'];
+
+ angular.foreach(unimplementedMethods, function(methodName) {
+ this[methodName] = function() {
+ throw {
+ name: "MethodNotImplemented",
+ message: "Method '" + methodName + "' is not implemented in the TzDate mock"
+ };
+ };
+ });
+}
+
+//make "tzDateInstance instanceof Date" return true
+TzDate.prototype = Date.prototype;