Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Chrome unit test fails on newly clean build (mock.tzDate) (Expected '12/31/1969' to match '1970') #14272

Closed
cesardariogar opened this issue Mar 18, 2016 · 8 comments

Comments

@cesardariogar
Copy link

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
Unit Test suite fails on Chrome at test # 5146

What is the expected behavior?
All test should pass on a clean build.

I've just cloned the '/angular/angular.js' (Version 1.5.1), build it without errors and with the clean build when run the preloaded unit tests with grunt (grunt test:unit) it throws the same error mentioned by @wagnerfrancisco when tests Chrome.

(All the test PASS except this one)

$ grunt test:unit
Running "shell:npm-install" (shell) task
:-) npm dependencies are looking good!

Running "tests:jqlite" (tests) task
17 03 2016 23:06:54.565:WARN [watcher]: All files matched by "/home/cgarcia/Documents/angular.js/src/angular.bind.js" were excluded.
17 03 2016 23:06:54.651:INFO [karma]: Karma v0.13.19 server started at http://localhost:9876/
17 03 2016 23:06:54.660:INFO [launcher]: Starting browser Chrome
17 03 2016 23:06:55.564:INFO [Chrome 49.0.2623 (Linux 0.0.0)]: Connected on socket /#3JfmMhoSkySvkvFcAAAA with id 98102530
Chrome 49.0.2623 (Linux 0.0.0) ngMock TzDate should fake getLocalDateString method FAILED
    Expected '12/31/1969' to match '1970'.
    Error: Expected '12/31/1969' to match '1970'.
        at .<anonymous> (/home/cgarcia/Documents/angular.js/test/ngMock/angular-mocksSpec.js:35:39)
Chrome 49.0.2623 (Linux 0.0.0): Executed 5146 of 5146 (1 FAILED) (21.706 secs / 21.783 secs)
Warning: Karma test(s) failed. Exit code: 1 Use --force to continue.

Aborted due to warnings.

Reproducable: Always
Browser: Chrome 49.0.2623
Operating System: Ubuntu 15.10 (Wily Werewolf)

steps to reproduce:
1)Clone the repository of Angular.js

git clone https://github.com/angular/angular.js.git

2)Building & Testing
Have node v 0.12.4 pre-installed
Have java version 1.8.0_74 pre-installed
Install Grunt & Bower:

npm install -g grunt-cli
npm install -g bower

# Add the main AngularJS repository as an upstream remote to your repository:
git remote add upstream "https://github.com/angular/angular.js.git"

# Install node.js dependencies:
npm install

# Install bower components:
bower install

# Build AngularJS:
grunt package

3)Running the Test Suite

grunt test:unit

The piece of code that runs this test is:
(/angular.js/test/ngMock/angular-mocksSpec.js)

    it('should fake getLocalDateString method', function() {
      //0 in -3h
      var t0 = new angular.mock.TzDate(-3, 0);
      expect(t0.toLocaleDateString()).toMatch('1970');

      //0 in +0h
      var t1 = new angular.mock.TzDate(0, 0);
      expect(t1.toLocaleDateString()).toMatch('1970');

      //0 in +3h
      var t2 = new angular.mock.TzDate(3, 0);
      expect(t2.toLocaleDateString()).toMatch('1969');
    });

and the code that is referenced:
(/angular.js/src/ngMock/angular-mock.js)

/**
 * @ngdoc type
 * @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".
 *
 * ```js
 * 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);
  }

  var localOffset = new Date(timestamp).getTimezoneOffset();
  self.offsetDiff = localOffset * 60 * 1000 - offset * 1000 * 60 * 60;
  self.date = new Date(timestamp + self.offsetDiff);

  self.getTime = function() {
    return self.date.getTime() - self.offsetDiff;
  };

  self.toLocaleDateString = function() {
    return self.date.toLocaleDateString();
  };

  self.getFullYear = function() {
    return self.date.getFullYear();
  };

  self.getMonth = function() {
    return self.date.getMonth();
  };

  self.getDate = function() {
    return self.date.getDate();
  };

  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 padNumberInMock(self.origDate.getUTCFullYear(), 4) + '-' +
            padNumberInMock(self.origDate.getUTCMonth() + 1, 2) + '-' +
            padNumberInMock(self.origDate.getUTCDate(), 2) + 'T' +
            padNumberInMock(self.origDate.getUTCHours(), 2) + ':' +
            padNumberInMock(self.origDate.getUTCMinutes(), 2) + ':' +
            padNumberInMock(self.origDate.getUTCSeconds(), 2) + '.' +
            padNumberInMock(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 new Error("Method '" + methodName + "' is not implemented in the TzDate mock");
    };
  });

  return self;
};

//make "tzDateInstance instanceof Date" return true
angular.mock.TzDate.prototype = Date.prototype;
/* jshint +W101 */

I want to contribute to the angular.js project but I'm not sure if this is a legit problem to work on

sorry if the post is too long :).

@cesardariogar
Copy link
Author

Reference to the same problem.
Unit tests fail on chrome #3033

@cesardariogar
Copy link
Author

Unit tests fail when run in Australia #5017

@cesardariogar
Copy link
Author

Local fail on master on one of date filter tests #4218

@cesardariogar
Copy link
Author

date filter not adding appropriate + / - sign for 'Z' timezone offset resulting in invalid ISO 8601 #1532

Perhaps related ...

@CarlosMiguelCuevas
Copy link
Contributor

fix it :D

@gkalpak gkalpak added this to the Backlog milestone Mar 20, 2016
gkalpak added a commit to gkalpak/angular.js that referenced this issue Mar 21, 2016
Probably due to implementation differences in browsers for pre-DST period (see
angular#5017 and especially
angular#5017 (comment) for context), some
`TzDate` tests had different behavior on different Timezones/Regions (e.g. failed in Australia,
which started to observe DST in 1971).
Since the used year (`1970`) didn't have any particular significance, this commit fixes the issue
by using a year that is more consistently handled by browsers (`2000`).

Fixes angular#14272
@gkalpak
Copy link
Member

gkalpak commented Mar 21, 2016

@cesardariogarcia, could you test if #14285 fixes the issue for you (it does for me locally when setting my locale settings to Australia/Sydney).
You can grab the files from here.

@cesardariogar
Copy link
Author

Sure I will give it a try later today.

@cesardariogar
Copy link
Author

@gkalpak #14285 indeed Fixed the issue.

I changed the getLocalDateString test as in:
test(TzDate): fix test in Australia #14285
and it works on Chrome 49.0.2623 now.

    it('should fake getLocalDateString method', function() {
      var millenium = new Date('2000').getTime();

      // millenium in -3h
      var t0 = new angular.mock.TzDate(-3, millenium);
      expect(t0.toLocaleDateString()).toMatch('2000');

      // millenium in +0h
      var t1 = new angular.mock.TzDate(0, millenium);
      expect(t1.toLocaleDateString()).toMatch('2000');

      // millenium in +3h
      var t2 = new angular.mock.TzDate(3, millenium);
      expect(t2.toLocaleDateString()).toMatch('1999');
    });

So i guess this will work over all the browsers that maintain differences over their pre-DST time implementation.

Thanks gkalpak, greetings.

The results:

cgarcia@NSL-CGARCIA:~/Documents/@Versioning_control/@Forks/angular.js$ grunt test:unit
Running "shell:npm-install" (shell) task
:-) npm dependencies are looking good!

Running "tests:jqlite" (tests) task
21 03 2016 10:05:47.284:WARN [watcher]: All files matched by "/home/cgarcia/Documents/@Versioning_control/@Forks/angular.js/src/angular.bind.js" were excluded.
21 03 2016 10:05:47.438:INFO [karma]: Karma v0.13.22 server started at http://localhost:9876/
21 03 2016 10:05:47.453:INFO [launcher]: Starting browser Chrome
21 03 2016 10:05:48.415:INFO [Chrome 49.0.2623 (Linux 0.0.0)]: Connected on socket /#Rg4v4jJk5nSfsS72AAAA with id 62592696
Chrome 49.0.2623 (Linux 0.0.0): Executed 5146 of 5146 SUCCESS (37.022 secs / 35.887 secs)

Running "tests:jquery" (tests) task
21 03 2016 10:06:30.410:WARN [watcher]: All files matched by "/home/cgarcia/Documents/@Versioning_control/@Forks/angular.js/src/angular.bind.js" were excluded.
21 03 2016 10:06:30.566:INFO [karma]: Karma v0.13.22 server started at http://localhost:9876/
21 03 2016 10:06:30.580:INFO [launcher]: Starting browser Chrome
21 03 2016 10:06:31.976:INFO [Chrome 49.0.2623 (Linux 0.0.0)]: Connected on socket /#sY97bLstuc8edHPqAAAA with id 89191529
Chrome 49.0.2623 (Linux 0.0.0): Executed 5158 of 5158 SUCCESS (38.564 secs / 37.469 secs)

Running "tests:jquery-2.1" (tests) task
21 03 2016 10:07:15.059:WARN [watcher]: All files matched by "/home/cgarcia/Documents/@Versioning_control/@Forks/angular.js/src/angular.bind.js" were excluded.
21 03 2016 10:07:15.128:INFO [karma]: Karma v0.13.22 server started at http://localhost:9876/
21 03 2016 10:07:15.136:INFO [launcher]: Starting browser Chrome
21 03 2016 10:07:15.952:INFO [Chrome 49.0.2623 (Linux 0.0.0)]: Connected on socket /#uBXyhlqfRhwmZz0UAAAA with id 14286701
Chrome 49.0.2623 (Linux 0.0.0): Executed 5158 of 5158 SUCCESS (35.925 secs / 34.926 secs)

Running "build:scenario" (build) task
>> File build/angular-scenario.js created.

Running "build:angular" (build) task
>> File build/angular.js created.

Running "build:loader" (build) task
>> File build/angular-loader.js created.

Running "build:touch" (build) task
>> File build/angular-touch.js created.

Running "build:mocks" (build) task
>> File build/angular-mocks.js created.

Running "build:sanitize" (build) task
>> File build/angular-sanitize.js created.

Running "build:resource" (build) task
>> File build/angular-resource.js created.

Running "build:messageformat" (build) task
>> File build/angular-message-format.js created.

Running "build:messages" (build) task
>> File build/angular-messages.js created.

Running "build:animate" (build) task
>> File build/angular-animate.js created.

Running "build:route" (build) task
>> File build/angular-route.js created.

Running "build:cookies" (build) task
>> File build/angular-cookies.js created.

Running "build:aria" (build) task
>> File build/angular-aria.js created.

Running "build:promises-aplus-adapter" (build) task
>> File tmp/promises-aplus-adapter++.js created.

Running "tests:modules" (tests) task
21 03 2016 10:07:57.554:INFO [karma]: Karma v0.13.22 server started at http://localhost:9876/
21 03 2016 10:07:57.576:INFO [launcher]: Starting browser Chrome
21 03 2016 10:07:58.732:INFO [Chrome 49.0.2623 (Linux 0.0.0)]: Connected on socket /#pzNJeMKRTvVyMw4MAAAA with id 62530143
Chrome 49.0.2623 (Linux 0.0.0): Executed 760 of 760 SUCCESS (6.538 secs / 6.262 secs)

Done, without errors.

gkalpak added a commit that referenced this issue Mar 21, 2016
Probably due to implementation differences in browsers for pre-DST period (see
#5017 and especially
#5017 (comment) for context), some
`TzDate` tests had different behavior on different Timezones/Regions (e.g. failed in Australia,
which started to observe DST in 1971).
Since the used year (`1970`) didn't have any particular significance, this commit fixes the issue
by using a year that is more consistently handled by browsers (`2000`).

Fixes #14272

Closes #14285
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants