diff --git a/packages/animations/browser/src/render/shared.ts b/packages/animations/browser/src/render/shared.ts index e8dc7ec8a4..e10cf6563a 100644 --- a/packages/animations/browser/src/render/shared.ts +++ b/packages/animations/browser/src/render/shared.ts @@ -36,13 +36,22 @@ export function normalizeKeyframes( Object.keys(kf).forEach(prop => { let normalizedProp = prop; let normalizedValue = kf[prop]; - if (normalizedValue == PRE_STYLE) { - normalizedValue = preStyles[prop]; - } else if (normalizedValue == AUTO_STYLE) { - normalizedValue = postStyles[prop]; - } else if (prop != 'offset') { - normalizedProp = normalizer.normalizePropertyName(prop, errors); - normalizedValue = normalizer.normalizeStyleValue(prop, normalizedProp, kf[prop], errors); + if (prop !== 'offset') { + normalizedProp = normalizer.normalizePropertyName(normalizedProp, errors); + switch (normalizedValue) { + case PRE_STYLE: + normalizedValue = preStyles[prop]; + break; + + case AUTO_STYLE: + normalizedValue = postStyles[prop]; + break; + + default: + normalizedValue = + normalizer.normalizeStyleValue(prop, normalizedProp, normalizedValue, errors); + break; + } } normalizedKeyframe[normalizedProp] = normalizedValue; }); diff --git a/packages/core/test/animation/animation_integration_spec.ts b/packages/core/test/animation/animation_integration_spec.ts index 4b51f0266d..dbaee6ecd9 100644 --- a/packages/core/test/animation/animation_integration_spec.ts +++ b/packages/core/test/animation/animation_integration_spec.ts @@ -5,7 +5,7 @@ * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -import {AUTO_STYLE, AnimationEvent, AnimationOptions, animate, animateChild, group, keyframes, query, state, style, transition, trigger} from '@angular/animations'; +import {AUTO_STYLE, AnimationEvent, AnimationOptions, animate, animateChild, group, keyframes, query, state, style, transition, trigger, ɵPRE_STYLE as PRE_STYLE} from '@angular/animations'; import {AnimationDriver, ɵAnimationEngine, ɵNoopAnimationDriver} from '@angular/animations/browser'; import {MockAnimationDriver, MockAnimationPlayer} from '@angular/animations/browser/testing'; import {Component, HostBinding, HostListener, RendererFactory2, ViewChild} from '@angular/core'; @@ -2225,6 +2225,87 @@ export function main() { }); }); + describe('animation normalization', () => { + it('should convert hyphenated properties to camelcase by default', () => { + @Component({ + selector: 'cmp', + template: ` +
+ `, + animations: [ + trigger( + 'myAnimation', + [ + transition( + '* => go', + [ + style({'background-color': 'red', height: '100px', fontSize: '100px'}), + animate( + '1s', + style( + {'background-color': 'blue', height: '200px', fontSize: '200px'})), + ]), + ]), + ] + }) + class Cmp { + exp: any = false; + } + + TestBed.configureTestingModule({declarations: [Cmp]}); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.exp = 'go'; + fixture.detectChanges(); + + const players = getLog(); + expect(players.length).toEqual(1); + expect(players[0].keyframes).toEqual([ + {backgroundColor: 'red', height: '100px', fontSize: '100px', offset: 0}, + {backgroundColor: 'blue', height: '200px', fontSize: '200px', offset: 1}, + ]); + }); + + it('should convert hyphenated properties to camelcase by default that are auto/pre style properties', + () => { + @Component({ + selector: 'cmp', + template: ` +
+ `, + animations: [ + trigger( + 'myAnimation', + [ + transition( + '* => go', + [ + style({'background-color': AUTO_STYLE, 'font-size': '100px'}), + animate( + '1s', style({'background-color': 'blue', 'font-size': PRE_STYLE})), + ]), + ]), + ] + }) + class Cmp { + exp: any = false; + } + + TestBed.configureTestingModule({declarations: [Cmp]}); + const fixture = TestBed.createComponent(Cmp); + const cmp = fixture.componentInstance; + cmp.exp = 'go'; + fixture.detectChanges(); + + const players = getLog(); + expect(players.length).toEqual(1); + expect(players[0].keyframes).toEqual([ + {backgroundColor: AUTO_STYLE, fontSize: '100px', offset: 0}, + {backgroundColor: 'blue', fontSize: PRE_STYLE, offset: 1}, + ]); + }); + }); + it('should throw neither state() or transition() are used inside of trigger()', () => { @Component({ selector: 'if-cmp',