From 1fddd5c462255494ff9289047907dbfeba139a0b Mon Sep 17 00:00:00 2001 From: Ed Clement Date: Wed, 8 Dec 2021 16:34:47 +0200 Subject: [PATCH 1/2] test(input): fix tests on Firefox v93+ Since version 93, Firefox started more closely following the spec on formatting `datetime-local` input values by removing trailing zeros from the string representation of the value. This causes some of our tests to fail ([example failure][1]). For example, a value is reported by Firefox as `2009-01-06T16:25` while the tests expect `2009-01-06T16:25:00.000`. I.e. Firefox started leaving out seconds/milliseconds if they are zero. According to [MDN][2], this is the correct behavior according to the spec. Indeed the spec says that [if the value of the element is a valid local date and time string, then it must be set to a **valid normalized local date and time string**][3], where **valid normalized local date and time string** is [defined as consisting of][4]: > - A valid date string representing the date. > - A U+0054 LATIN CAPITAL LETTER T character (T). > - A valid time string representing the time, expressed as the > **shortest possible string** for the given time (e.g. **omitting the > seconds component** entirely if the given time is zero seconds past > the minute). This commit fixes the relevant tests by explicitly specifying non-zero values for seconds and milliseconds. [1]: https://circleci.com/gh/angular/angular.js/3527 [2]: https://developer.mozilla.org/en-US/docs/Web/HTML/Date_and_time_formats #local_date_and_time_strings [3]: https://html.spec.whatwg.org/multipage/input.html #local-date-and-time-state-(type=datetime-local) [4]: https://html.spec.whatwg.org/multipage/common-microsyntaxes.html #concept-datetime-local Co-authored-by: George Kalpakas --- test/ng/directive/inputSpec.js | 48 +++++++++++++++++----------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index e7159cba9ba7..34ae2e127734 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -1271,10 +1271,10 @@ describe('input', function() { var inputElm = helper.compileInput(''); $rootScope.$apply(function() { - $rootScope.breakMe = new Date(2009, 0, 6, 16, 25, 0); + $rootScope.breakMe = new Date(2009, 0, 6, 16, 25, 1, 337); }); - expect(inputElm.val()).toBe('2009-01-06T16:25:00.000'); + expect(inputElm.val()).toBe('2009-01-06T16:25:01.337'); //set to text for browsers with datetime-local validation. inputElm[0].setAttribute('type', 'text'); @@ -1324,32 +1324,32 @@ describe('input', function() { it('should use UTC if specified in the options', function() { var inputElm = helper.compileInput(''); - helper.changeInputValueTo('2000-01-01T01:02'); - expect(+$rootScope.value).toBe(Date.UTC(2000, 0, 1, 1, 2, 0)); + helper.changeInputValueTo('2000-01-01T01:02:03.456'); + expect(+$rootScope.value).toBe(Date.UTC(2000, 0, 1, 1, 2, 3, 456)); $rootScope.$apply(function() { - $rootScope.value = new Date(Date.UTC(2001, 0, 1, 1, 2, 0)); + $rootScope.value = new Date(Date.UTC(2001, 0, 1, 1, 2, 3, 456)); }); - expect(inputElm.val()).toBe('2001-01-01T01:02:00.000'); + expect(inputElm.val()).toBe('2001-01-01T01:02:03.456'); }); it('should be possible to override the timezone', function() { var inputElm = helper.compileInput(''); - helper.changeInputValueTo('2000-01-01T01:02'); - expect(+$rootScope.value).toBe(Date.UTC(2000, 0, 1, 1, 2, 0)); + helper.changeInputValueTo('2000-01-01T01:02:03.456'); + expect(+$rootScope.value).toBe(Date.UTC(2000, 0, 1, 1, 2, 3, 456)); inputElm.controller('ngModel').$overrideModelOptions({timezone: '+0500'}); $rootScope.$apply(function() { - $rootScope.value = new Date(Date.UTC(2001, 0, 1, 1, 2, 0)); + $rootScope.value = new Date(Date.UTC(2001, 0, 1, 1, 2, 3, 456)); }); - expect(inputElm.val()).toBe('2001-01-01T06:02:00.000'); + expect(inputElm.val()).toBe('2001-01-01T06:02:03.456'); inputElm.controller('ngModel').$overrideModelOptions({timezone: 'UTC'}); - helper.changeInputValueTo('2000-01-01T01:02'); - expect(+$rootScope.value).toBe(Date.UTC(2000, 0, 1, 1, 2, 0)); + helper.changeInputValueTo('2000-01-01T01:02:03.456'); + expect(+$rootScope.value).toBe(Date.UTC(2000, 0, 1, 1, 2, 3, 456)); }); @@ -1360,13 +1360,13 @@ describe('input', function() { var inputElm = helper.compileInput( ''); - helper.changeInputValueTo('2000-01-01T06:02'); - expect(+$rootScope.value).toBe(Date.UTC(2000, 0, 1, 1, 2, 0)); + helper.changeInputValueTo('2000-01-01T06:02:03.456'); + expect(+$rootScope.value).toBe(Date.UTC(2000, 0, 1, 1, 2, 3, 456)); $rootScope.$apply(function() { - $rootScope.value = new Date(Date.UTC(2001, 0, 1, 1, 2, 0)); + $rootScope.value = new Date(Date.UTC(2001, 0, 1, 1, 2, 3, 456)); }); - expect(inputElm.val()).toBe('2001-01-01T06:02:00.000'); + expect(inputElm.val()).toBe('2001-01-01T06:02:03.456'); } ); @@ -1401,13 +1401,13 @@ describe('input', function() { it('should allow to specify the seconds', function() { var inputElm = helper.compileInput(''); - helper.changeInputValueTo('2000-01-01T01:02:03'); - expect(+$rootScope.value).toBe(+new Date(2000, 0, 1, 1, 2, 3)); + helper.changeInputValueTo('2000-01-01T01:02:03.456'); + expect(+$rootScope.value).toBe(+new Date(2000, 0, 1, 1, 2, 3, 456)); $rootScope.$apply(function() { - $rootScope.value = new Date(2001, 0, 1, 1, 2, 3); + $rootScope.value = new Date(2001, 0, 1, 1, 2, 3, 456); }); - expect(inputElm.val()).toBe('2001-01-01T01:02:03.000'); + expect(inputElm.val()).toBe('2001-01-01T01:02:03.456'); }); @@ -1425,13 +1425,13 @@ describe('input', function() { it('should allow four or more digits in year', function() { var inputElm = helper.compileInput(''); - helper.changeInputValueTo('10123-01-01T01:02'); - expect(+$rootScope.value).toBe(+new Date(10123, 0, 1, 1, 2, 0)); + helper.changeInputValueTo('10123-01-01T01:02:03.456'); + expect(+$rootScope.value).toBe(+new Date(10123, 0, 1, 1, 2, 3, 456)); $rootScope.$apply(function() { - $rootScope.value = new Date(20456, 1, 1, 1, 2, 0); + $rootScope.value = new Date(20456, 1, 1, 1, 2, 3, 456); }); - expect(inputElm.val()).toBe('20456-02-01T01:02:00.000'); + expect(inputElm.val()).toBe('20456-02-01T01:02:03.456'); } ); } From ca0a16671e010298506b0c5da9d18264807b47e7 Mon Sep 17 00:00:00 2001 From: Ed Clement Date: Wed, 8 Dec 2021 16:36:25 +0200 Subject: [PATCH 2/2] test(Angular): fix `angularInit()` tests on Safari v15+ Previously, the `angularInit()` tests assumed that the Safari browser uses the `safari-extension:` protocol for browser extension URLs. This is true for versions <15. However, since v15, Safari on iOS only recognizes the `chrome-extension:` protocol, which causes the tests to fail ([example failure][1]). This commit updates the tests to use the correct protocol according to the version of Safari used. NOTE: On macOS, Safari v15+ recognizes both `safari-extension:` and `chrome-extension:`, so it is OK to always use the later with Safari v15+ (regardless of the platform). [1]: https://circleci.com/gh/angular/angular.js/3527 Co-authored-by: George Kalpakas --- test/AngularSpec.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/AngularSpec.js b/test/AngularSpec.js index 3e270b962968..cf7e28cc5701 100644 --- a/test/AngularSpec.js +++ b/test/AngularSpec.js @@ -1793,7 +1793,12 @@ describe('angular', function() { } else if (/Chrome\//.test(userAgent)) { protocol = 'chrome-extension:'; } else if (/Safari\//.test(userAgent)) { - protocol = 'safari-extension:'; + // On iOS, Safari versions <15 recognize `safari-extension:`, while versions >=15 only + // recognize `chrome-extension:`. + // (On macOS, Safari v15 recognizes both protocols, so it is fine to use either.) + var majorVersionMatch = /Version\/(\d+)/.exec(userAgent); + var majorVersion = majorVersionMatch ? parseInt(majorVersionMatch[1], 10) : 0; + protocol = (majorVersion < 15) ? 'safari-extension:' : 'chrome-extension:'; } else { protocol = 'browserext:'; // Upcoming standard scheme. }