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

Commit cb74999

Browse files
committed
test: fix failing tests on MS Edge
Includes the following fixes (per component): * `$sniffer`: Properly determine the expected `vendorPrefix` for MS Edge * `input`: MS Edge does not support dates with years with more than 4 digits. Trying to set the value of an `input[datetime-local]` to `9999-12-31T23.59.59.999` throws an error (probably related to converting the date to one with a year with more than 4 digits, due to timezone offset). * `$sanitize`: Fix failing tests on MS Edge * `$animateCss`: Although the detected `vendorPrefix` for MS Edge is "ms", it doesn't seem to recognize some vendor-prefixed CSS rules (e.g. `-ms-animation-*`). Other browsers (currently) recognize either vendor-prefixed rules only or both. Fixed by adding and retrieving styles using both prefixed and un-prefixed names. * `$compile`: Skip failing `foreignObject` test on MS Edge. For unknown reasons, an `<svg>` element inside a `<foreignObject>` element on MS Edge has no size, causing the included `<circle>` element to also have no size and thus fails an assertion (relying on the element having a non-zero size). This seems to be an MS Edge issue; i.e. it is also reproducible without Angular. (Tested with MS Edge version 25.10586.0.0 on Windows 10.) Closes #13686
1 parent 2764536 commit cb74999

File tree

6 files changed

+95
-64
lines changed

6 files changed

+95
-64
lines changed

test/helpers/privateMocks.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function browserSupportsCssAnimations() {
4040
return true;
4141
}
4242

43-
function createMockStyleSheet(doc) {
43+
function createMockStyleSheet(doc, prefix) {
4444
doc = doc ? doc[0] : document;
4545

4646
var node = doc.createElement('style');
@@ -62,6 +62,18 @@ function createMockStyleSheet(doc) {
6262
}
6363
},
6464

65+
addPossiblyPrefixedRule: function(selector, styles) {
66+
if (prefix) {
67+
var prefixedStyles = styles.split(/\s*;\s*/g).map(function(style) {
68+
return !style ? '' : prefix + style;
69+
}).join('; ');
70+
71+
this.addRule(selector, prefixedStyles);
72+
}
73+
74+
this.addRule(selector, styles);
75+
},
76+
6577
destroy: function() {
6678
head.removeChild(node);
6779
}

test/ng/compileSpec.js

+16-11
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ describe('$compile', function() {
230230

231231

232232
describe('svg namespace transcludes', function() {
233+
var ua = window.navigator.userAgent;
234+
var isEdge = /Edge/.test(ua);
235+
233236
// this method assumes some sort of sized SVG element is being inspected.
234237
function assertIsValidSvgCircle(elem) {
235238
expect(isUnknownElement(elem)).toBe(false);
@@ -300,17 +303,19 @@ describe('$compile', function() {
300303
}));
301304

302305
// NOTE: This test may be redundant.
303-
it('should handle custom svg containers that transclude to foreignObject' +
304-
' that transclude to custom svg containers that transclude to custom elements', inject(function() {
305-
element = jqLite('<div><svg-container>' +
306-
'<my-foreign-object><svg-container><svg-circle></svg-circle></svg-container></my-foreign-object>' +
307-
'</svg-container></div>');
308-
$compile(element.contents())($rootScope);
309-
document.body.appendChild(element[0]);
310-
311-
var circle = element.find('circle');
312-
assertIsValidSvgCircle(circle[0]);
313-
}));
306+
if (!isEdge) {
307+
it('should handle custom svg containers that transclude to foreignObject' +
308+
' that transclude to custom svg containers that transclude to custom elements', inject(function() {
309+
element = jqLite('<div><svg-container>' +
310+
'<my-foreign-object><svg-container><svg-circle></svg-circle></svg-container></my-foreign-object>' +
311+
'</svg-container></div>');
312+
$compile(element.contents())($rootScope);
313+
document.body.appendChild(element[0]);
314+
315+
var circle = element.find('circle');
316+
assertIsValidSvgCircle(circle[0]);
317+
}));
318+
}
314319
}
315320

316321
it('should handle directives with templates that manually add the transclude further down', inject(function() {

test/ng/directive/inputSpec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1196,7 +1196,7 @@ describe('input', function() {
11961196

11971197
it('should validate if max is empty', function() {
11981198
$rootScope.maxVal = undefined;
1199-
$rootScope.value = new Date(9999, 11, 31, 23, 59, 59);
1199+
$rootScope.value = new Date(3000, 11, 31, 23, 59, 59);
12001200
$rootScope.$digest();
12011201

12021202
expect($rootScope.form.alias.$error.max).toBeFalsy();

test/ng/snifferSpec.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ describe('$sniffer', function() {
8888
inject(function($sniffer, $window) {
8989
var expectedPrefix;
9090
var ua = $window.navigator.userAgent.toLowerCase();
91-
if (/chrome/i.test(ua) || /safari/i.test(ua) || /webkit/i.test(ua)) {
91+
if (/edge/i.test(ua)) {
92+
expectedPrefix = 'Ms';
93+
} else if (/chrome/i.test(ua) || /safari/i.test(ua) || /webkit/i.test(ua)) {
9294
expectedPrefix = 'Webkit';
9395
} else if (/firefox/i.test(ua)) {
9496
expectedPrefix = 'Moz';

test/ngAnimate/animateCssSpec.js

+56-48
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ describe("ngAnimate $animateCss", function() {
1212
: expect(className).not.toMatch(regex);
1313
}
1414

15+
function getPossiblyPrefixedStyleValue(element, styleProp) {
16+
var value = element.css(prefix + styleProp);
17+
if (isUndefined(value)) value = element.css(styleProp);
18+
19+
return value;
20+
}
21+
1522
function keyframeProgress(element, duration, delay) {
1623
browserTrigger(element, 'animationend',
1724
{ timeStamp: Date.now() + ((delay || 1) * 1000), elapsedTime: duration });
@@ -30,7 +37,8 @@ describe("ngAnimate $animateCss", function() {
3037
beforeEach(module(function() {
3138
return function($document, $sniffer, $$rAF, $animate) {
3239
prefix = '-' + $sniffer.vendorPrefix.toLowerCase() + '-';
33-
ss = createMockStyleSheet($document);
40+
ss = createMockStyleSheet($document, prefix);
41+
3442
$animate.enabled(true);
3543
triggerAnimationStartFrame = function() {
3644
$$rAF.flush();
@@ -325,7 +333,7 @@ describe("ngAnimate $animateCss", function() {
325333
triggerAnimationStartFrame();
326334

327335
runner.pause();
328-
expect(element.css(prefix + 'animation-play-state')).toEqual('paused');
336+
expect(getPossiblyPrefixedStyleValue(element, 'animation-play-state')).toEqual('paused');
329337
runner.resume();
330338
expect(element.attr('style')).toBeFalsy();
331339
}));
@@ -346,7 +354,7 @@ describe("ngAnimate $animateCss", function() {
346354
triggerAnimationStartFrame();
347355

348356
runner.pause();
349-
expect(element.css(prefix + 'animation-play-state')).toEqual('paused');
357+
expect(getPossiblyPrefixedStyleValue(element, 'animation-play-state')).toEqual('paused');
350358
runner.end();
351359
expect(element.attr('style')).toBeFalsy();
352360
}));
@@ -784,8 +792,8 @@ describe("ngAnimate $animateCss", function() {
784792

785793
jqLite($document[0].body).append($rootElement);
786794

787-
ss.addRule('.ng-enter-stagger', prefix + 'animation-delay:0.2s');
788-
ss.addRule('.ng-enter', prefix + 'animation:my_animation 2s;');
795+
ss.addPossiblyPrefixedRule('.ng-enter-stagger', 'animation-delay:0.2s');
796+
ss.addPossiblyPrefixedRule('.ng-enter', 'animation:my_animation 2s;');
789797

790798
var i, element, elements = [];
791799
for (i = 0; i < 5; i++) {
@@ -803,7 +811,7 @@ describe("ngAnimate $animateCss", function() {
803811
if (i === 0) { // the first element is always run right away
804812
expect(element.attr('style')).toBeFalsy();
805813
} else {
806-
expect(element.css(prefix + 'animation-play-state')).toBe('paused');
814+
expect(getPossiblyPrefixedStyleValue(element, 'animation-play-state')).toBe('paused');
807815
}
808816
}
809817
}));
@@ -879,7 +887,7 @@ describe("ngAnimate $animateCss", function() {
879887
jqLite($document[0].body).append($rootElement);
880888

881889
ss.addRule('.ng-enter-stagger', 'transition-delay:0.2s');
882-
ss.addRule('.transition-animation', prefix + 'animation:2s 5s my_animation;');
890+
ss.addPossiblyPrefixedRule('.transition-animation', 'animation: 2s 5s my_animation;');
883891

884892
for (var i = 0; i < 5; i++) {
885893
var elm = jqLite('<div class="transition-animation"></div>');
@@ -898,11 +906,11 @@ describe("ngAnimate $animateCss", function() {
898906

899907
jqLite($document[0].body).append($rootElement);
900908

901-
ss.addRule('.ng-enter-stagger', 'transition-delay:0.5s;' +
902-
prefix + 'animation-delay:1s');
909+
ss.addPossiblyPrefixedRule('.ng-enter-stagger', 'transition-delay: 0.5s; ' +
910+
'animation-delay: 1s');
903911

904-
ss.addRule('.ng-enter', 'transition:10s linear all;' +
905-
prefix + 'animation:my_animation 20s');
912+
ss.addPossiblyPrefixedRule('.ng-enter', 'transition: 10s linear all; ' +
913+
'animation: 20s my_animation');
906914

907915
var i, elm, elements = [];
908916
for (i = 0; i < 5; i++) {
@@ -1258,14 +1266,14 @@ describe("ngAnimate $animateCss", function() {
12581266
// At this point, the animation should still be running (closing timeout is 7500ms ... duration * 1.5 + delay => 7.5)
12591267
$timeout.flush(7000);
12601268

1261-
expect(element.css(prefix + 'transition-delay')).toBe('3s');
1262-
expect(element.css(prefix + 'transition-duration')).toBe('3s');
1269+
expect(getPossiblyPrefixedStyleValue(element, 'transition-delay')).toBe('3s');
1270+
expect(getPossiblyPrefixedStyleValue(element, 'transition-duration')).toBe('3s');
12631271

12641272
// Let's flush the remaining amount of time for the timeout timer to kick in
12651273
$timeout.flush(500);
12661274

1267-
expect(element.css(prefix + 'transition-duration')).toBeOneOf('', '0s');
1268-
expect(element.css(prefix + 'transition-delay')).toBeOneOf('', '0s');
1275+
expect(getPossiblyPrefixedStyleValue(element, 'transition-duration')).toBeOneOf('', '0s');
1276+
expect(getPossiblyPrefixedStyleValue(element, 'transition-delay')).toBeOneOf('', '0s');
12691277
}));
12701278

12711279
it("should ignore a boolean options.delay value for the closing timeout",
@@ -1291,14 +1299,14 @@ describe("ngAnimate $animateCss", function() {
12911299
// At this point, the animation should still be running (closing timeout is 4500ms ... duration * 1.5 => 4.5)
12921300
$timeout.flush(4000);
12931301

1294-
expect(element.css(prefix + 'transition-delay')).toBeOneOf('initial', '0s');
1295-
expect(element.css(prefix + 'transition-duration')).toBe('3s');
1302+
expect(getPossiblyPrefixedStyleValue(element, 'transition-delay')).toBeOneOf('initial', '0s');
1303+
expect(getPossiblyPrefixedStyleValue(element, 'transition-duration')).toBe('3s');
12961304

12971305
// Let's flush the remaining amount of time for the timeout timer to kick in
12981306
$timeout.flush(500);
12991307

1300-
expect(element.css(prefix + 'transition-duration')).toBeOneOf('', '0s');
1301-
expect(element.css(prefix + 'transition-delay')).toBeOneOf('', '0s');
1308+
expect(getPossiblyPrefixedStyleValue(element, 'transition-duration')).toBeOneOf('', '0s');
1309+
expect(getPossiblyPrefixedStyleValue(element, 'transition-delay')).toBeOneOf('', '0s');
13021310
}));
13031311

13041312
});
@@ -2104,7 +2112,7 @@ describe("ngAnimate $animateCss", function() {
21042112
triggerAnimationStartFrame();
21052113

21062114

2107-
expect(element.css(prefix + 'animation-duration')).toEqual('5s');
2115+
expect(getPossiblyPrefixedStyleValue(element, 'animation-duration')).toEqual('5s');
21082116
}));
21092117

21102118
it("should remove all inline keyframe styling when an animation completes if a custom duration was applied",
@@ -2145,7 +2153,7 @@ describe("ngAnimate $animateCss", function() {
21452153
triggerAnimationStartFrame();
21462154

21472155

2148-
expect(element.css(prefix + 'animation-delay')).toEqual('5s');
2156+
expect(getPossiblyPrefixedStyleValue(element, 'animation-delay')).toEqual('5s');
21492157

21502158
browserTrigger(element, 'animationend',
21512159
{ timeStamp: Date.now() + 5000, elapsedTime: 1.5 });
@@ -2299,7 +2307,7 @@ describe("ngAnimate $animateCss", function() {
22992307
triggerAnimationStartFrame();
23002308

23012309

2302-
expect(element.css(prefix + 'animation-delay')).toEqual('400s');
2310+
expect(getPossiblyPrefixedStyleValue(element, 'animation-delay')).toEqual('400s');
23032311
expect(element.attr('style')).not.toContain('transition-delay');
23042312
}));
23052313

@@ -2323,7 +2331,7 @@ describe("ngAnimate $animateCss", function() {
23232331
triggerAnimationStartFrame();
23242332

23252333

2326-
expect(element.css(prefix + 'animation-delay')).toEqual('10s');
2334+
expect(getPossiblyPrefixedStyleValue(element, 'animation-delay')).toEqual('10s');
23272335
expect(element.css('transition-delay')).toEqual('10s');
23282336
}));
23292337

@@ -2363,7 +2371,7 @@ describe("ngAnimate $animateCss", function() {
23632371
var assertionsRun = false;
23642372
classSpy = function() {
23652373
assertionsRun = true;
2366-
expect(element.css(prefix + 'animation-delay')).toEqual('2s');
2374+
expect(getPossiblyPrefixedStyleValue(element, 'animation-delay')).toEqual('2s');
23672375
expect(element.css('transition-delay')).toEqual('2s');
23682376
expect(element).not.toHaveClass('superman');
23692377
};
@@ -2397,8 +2405,8 @@ describe("ngAnimate $animateCss", function() {
23972405
it("should consider a negative value when delay:true is used with a keyframe animation",
23982406
inject(function($animateCss, $rootElement) {
23992407

2400-
ss.addRule('.ng-enter', prefix + 'animation:2s keyframe_animation; ' +
2401-
prefix + 'animation-delay: -1s;');
2408+
ss.addPossiblyPrefixedRule('.ng-enter', 'animation: 2s keyframe_animation; ' +
2409+
'animation-delay: -1s;');
24022410

24032411
var options = {
24042412
delay: true,
@@ -2411,7 +2419,7 @@ describe("ngAnimate $animateCss", function() {
24112419
animator.start();
24122420
triggerAnimationStartFrame();
24132421

2414-
expect(element.css(prefix + 'animation-delay')).toContain('-1s');
2422+
expect(getPossiblyPrefixedStyleValue(element, 'animation-delay')).toContain('-1s');
24152423
}));
24162424

24172425
they("should consider a negative value when a negative option delay is provided for a $prop animation", {
@@ -2421,17 +2429,17 @@ describe("ngAnimate $animateCss", function() {
24212429
css: 'transition:2s linear all'
24222430
};
24232431
},
2424-
'keyframe': function(prefix) {
2432+
'keyframe': function() {
24252433
return {
2426-
prop: prefix + 'animation-delay',
2427-
css: prefix + 'animation:2s keyframe_animation'
2434+
prop: 'animation-delay',
2435+
css: 'animation: 2s keyframe_animation'
24282436
};
24292437
}
24302438
}, function(testDetailsFactory) {
24312439
inject(function($animateCss, $rootElement) {
24322440
var testDetails = testDetailsFactory(prefix);
24332441

2434-
ss.addRule('.ng-enter', testDetails.css);
2442+
ss.addPossiblyPrefixedRule('.ng-enter', testDetails.css);
24352443
var options = {
24362444
delay: -2,
24372445
event: 'enter',
@@ -2443,7 +2451,7 @@ describe("ngAnimate $animateCss", function() {
24432451
animator.start();
24442452
triggerAnimationStartFrame();
24452453

2446-
expect(element.css(testDetails.prop)).toContain('-2s');
2454+
expect(getPossiblyPrefixedStyleValue(element, testDetails.prop)).toContain('-2s');
24472455
});
24482456
});
24492457

@@ -2454,18 +2462,18 @@ describe("ngAnimate $animateCss", function() {
24542462
css: 'transition:5s linear all; transition-delay: -2s'
24552463
};
24562464
},
2457-
'animation': function(prefix) {
2465+
'animation': function() {
24582466
return {
24592467
event: 'animationend',
2460-
css: prefix + 'animation:5s keyframe_animation; ' + prefix + 'animation-delay: -2s;'
2468+
css: 'animation: 5s keyframe_animation; animation-delay: -2s;'
24612469
};
24622470
}
24632471
}, function(testDetailsFactory) {
24642472
inject(function($animateCss, $rootElement) {
2465-
var testDetails = testDetailsFactory(prefix);
2473+
var testDetails = testDetailsFactory();
24662474
var event = testDetails.event;
24672475

2468-
ss.addRule('.ng-enter', testDetails.css);
2476+
ss.addPossiblyPrefixedRule('.ng-enter', testDetails.css);
24692477
var options = { event: 'enter', structural: true };
24702478

24712479
var animator = $animateCss(element, options);
@@ -2571,15 +2579,15 @@ describe("ngAnimate $animateCss", function() {
25712579
$animateCss(element, options).start();
25722580
triggerAnimationStartFrame();
25732581

2574-
expect(element.css(prefix + 'transition-delay')).not.toEqual('4s');
2575-
expect(element.css(prefix + 'transition-duration')).not.toEqual('6s');
2582+
expect(getPossiblyPrefixedStyleValue(element, 'transition-delay')).not.toEqual('4s');
2583+
expect(getPossiblyPrefixedStyleValue(element, 'transition-duration')).not.toEqual('6s');
25762584

25772585
options.to = { color: 'brown' };
25782586
$animateCss(element, options).start();
25792587
triggerAnimationStartFrame();
25802588

2581-
expect(element.css(prefix + 'transition-delay')).toEqual('4s');
2582-
expect(element.css(prefix + 'transition-duration')).toEqual('6s');
2589+
expect(getPossiblyPrefixedStyleValue(element, 'transition-delay')).toEqual('4s');
2590+
expect(getPossiblyPrefixedStyleValue(element, 'transition-duration')).toEqual('6s');
25832591
}));
25842592
});
25852593

@@ -2652,9 +2660,9 @@ describe("ngAnimate $animateCss", function() {
26522660
triggerAnimationStartFrame();
26532661

26542662

2655-
expect(element.css(prefix + 'animation-delay')).toEqual('50s');
2656-
expect(element.css(prefix + 'animation-duration')).toEqual('5.5s');
2657-
expect(element.css(prefix + 'animation-name')).toEqual('my_animation');
2663+
expect(getPossiblyPrefixedStyleValue(element, 'animation-delay')).toEqual('50s');
2664+
expect(getPossiblyPrefixedStyleValue(element, 'animation-duration')).toEqual('5.5s');
2665+
expect(getPossiblyPrefixedStyleValue(element, 'animation-name')).toEqual('my_animation');
26582666
}));
26592667

26602668
it("should be able to execute the animation if it is the only provided value",
@@ -2669,9 +2677,9 @@ describe("ngAnimate $animateCss", function() {
26692677
animator.start();
26702678
triggerAnimationStartFrame();
26712679

2672-
expect(element.css(prefix + 'animation-delay')).toEqual('10s');
2673-
expect(element.css(prefix + 'animation-duration')).toEqual('5.5s');
2674-
expect(element.css(prefix + 'animation-name')).toEqual('my_animation');
2680+
expect(getPossiblyPrefixedStyleValue(element, 'animation-delay')).toEqual('10s');
2681+
expect(getPossiblyPrefixedStyleValue(element, 'animation-duration')).toEqual('5.5s');
2682+
expect(getPossiblyPrefixedStyleValue(element, 'animation-name')).toEqual('my_animation');
26752683
}));
26762684
});
26772685

@@ -2964,7 +2972,7 @@ describe("ngAnimate $animateCss", function() {
29642972

29652973

29662974
expect(element.css('transition-duration')).toMatch('10s');
2967-
expect(element.css(prefix + 'animation-duration')).toEqual('10s');
2975+
expect(getPossiblyPrefixedStyleValue(element, 'animation-duration')).toEqual('10s');
29682976
}));
29692977
});
29702978

@@ -3004,7 +3012,7 @@ describe("ngAnimate $animateCss", function() {
30043012
inject(function($animateCss) {
30053013

30063014
ss.addRule('.red', 'transition: 1s linear all;');
3007-
ss.addRule('.blue', prefix + 'animation:my_keyframe 1s;');
3015+
ss.addPossiblyPrefixedRule('.blue', 'animation: 1s my_keyframe;');
30083016
var easing = 'ease-out';
30093017
var animator = $animateCss(element, { addClass: 'red blue', easing: easing });
30103018
animator.start();

0 commit comments

Comments
 (0)