refactor(core): fix animations host binding tests (#64225)

These tests were not properly validating against the host binding changes due to the fact that the styles were on the wrong components in some of the host binding cases.

PR Close #64225
This commit is contained in:
Jessica Janiuk
2025-10-02 16:30:48 -07:00
committed by Miles Malerba
parent 91c4f99d23
commit a52a2afb6e
2 changed files with 48 additions and 16 deletions
@@ -319,15 +319,18 @@ function animateLeaveClassRunner(
cleanupFns.push(renderer.listen(el, 'animationend', handleOutAnimationEnd));
cleanupFns.push(renderer.listen(el, 'transitionend', handleOutAnimationEnd));
});
trackLeavingNodes(tNode, el);
for (const item of classList) {
renderer.addClass(el, item);
}
// In the case that the classes added have no animations, we need to remove
// the element right away. This could happen because someone is intentionally
// preventing an animation via selector specificity.
ngZone.runOutsideAngular(() => {
requestAnimationFrame(() => {
// In the case that the classes added have no animations, we need to remove
// the element right away. This could happen because someone is intentionally
// preventing an animation via selector specificity.
determineLongestAnimation(el, longestAnimations, areAnimationSupported);
if (!longestAnimations.has(el)) {
clearLeavingNodes(tNode, el);
+42 -13
View File
@@ -374,7 +374,6 @@ describe('Animation', () => {
it('should be host bindable', fakeAsync(() => {
@Component({
selector: 'fade-cmp',
styles: styles,
host: {'animate.leave': 'fade'},
template: '<p>I should fade</p>',
encapsulation: ViewEncapsulation.None,
@@ -383,6 +382,7 @@ describe('Animation', () => {
@Component({
selector: 'test-cmp',
styles: styles,
imports: [FadeComponent],
template: '@if (show()) { <fade-cmp /> }',
encapsulation: ViewEncapsulation.None,
@@ -400,6 +400,7 @@ describe('Animation', () => {
expect(fixture.nativeElement.outerHTML).not.toContain('class="fade"');
cmp.show.set(false);
fixture.detectChanges();
tickAnimationFrames(1);
expect(cmp.show()).toBeFalsy();
expect(fixture.nativeElement.outerHTML).toContain('class="fade"');
fixture.detectChanges();
@@ -413,7 +414,6 @@ describe('Animation', () => {
it('should be host bindable with brackets', fakeAsync(() => {
@Component({
selector: 'fade-cmp',
styles: styles,
host: {'[animate.leave]': 'fade()'},
template: '<p>I should fade</p>',
encapsulation: ViewEncapsulation.None,
@@ -424,6 +424,7 @@ describe('Animation', () => {
@Component({
selector: 'test-cmp',
styles: styles,
imports: [FadeComponent],
template: '@if (show()) { <fade-cmp /> }',
encapsulation: ViewEncapsulation.None,
@@ -441,6 +442,7 @@ describe('Animation', () => {
expect(fixture.nativeElement.outerHTML).not.toContain('class="fade"');
cmp.show.set(false);
fixture.detectChanges();
tickAnimationFrames(1);
expect(cmp.show()).toBeFalsy();
expect(fixture.nativeElement.outerHTML).toContain('class="fade"');
fixture.detectChanges();
@@ -519,7 +521,6 @@ describe('Animation', () => {
`;
@Component({
selector: 'child-cmp',
styles: multiple,
host: {'[animate.leave]': 'slide()'},
template: '<p>I should fade</p>',
encapsulation: ViewEncapsulation.None,
@@ -670,7 +671,6 @@ describe('Animation', () => {
`;
@Component({
selector: 'child-cmp',
styles: multiple,
host: {'animate.leave': 'slide-out'},
template: '<p>I should fade</p>',
encapsulation: ViewEncapsulation.None,
@@ -1203,12 +1203,21 @@ describe('Animation', () => {
it('should be host bindable', fakeAsync(() => {
@Component({
selector: 'test-cmp',
styles: styles,
selector: 'child-cmp',
host: {'animate.enter': 'slide-in'},
template: '<p>I should fade</p>',
encapsulation: ViewEncapsulation.None,
})
class ChildComponent {}
@Component({
selector: 'test-cmp',
styles: styles,
imports: [ChildComponent],
host: {'animate.enter': 'slide-in'},
template: '<child-cmp />',
encapsulation: ViewEncapsulation.None,
})
class TestComponent {}
TestBed.configureTestingModule({animationsEnabled: true});
@@ -1227,15 +1236,23 @@ describe('Animation', () => {
it('should be host bindable with brackets', fakeAsync(() => {
@Component({
selector: 'test-cmp',
styles: styles,
selector: 'child-cmp',
host: {'[animate.enter]': 'slideIn()'},
template: '<p>I should fade</p>',
encapsulation: ViewEncapsulation.None,
})
class TestComponent {
class ChildComponent {
slideIn = signal('slide-in');
}
@Component({
selector: 'test-cmp',
styles: styles,
imports: [ChildComponent],
template: '<child-cmp />',
encapsulation: ViewEncapsulation.None,
})
class TestComponent {}
TestBed.configureTestingModule({animationsEnabled: true});
const fixture = TestBed.createComponent(TestComponent);
@@ -1254,12 +1271,26 @@ describe('Animation', () => {
it('should be host bindable with events', fakeAsync(() => {
const slideInCalled = jasmine.createSpy('slideInCalled');
@Component({
selector: 'test-cmp',
styles: styles,
selector: 'child-cmp',
host: {'(animate.enter)': 'slideIn($event)'},
template: '<p>I should fade</p>',
encapsulation: ViewEncapsulation.None,
})
class ChildComponent {
slideIn(event: AnimationCallbackEvent) {
slideInCalled();
event.target.classList.add('slide-in');
event.animationComplete();
}
}
@Component({
selector: 'test-cmp',
styles: styles,
imports: [ChildComponent],
template: '<child-cmp />',
encapsulation: ViewEncapsulation.None,
})
class TestComponent {
slideIn(event: AnimationCallbackEvent) {
slideInCalled();
@@ -1277,7 +1308,6 @@ describe('Animation', () => {
it('should compose class list when host binding and regular binding', fakeAsync(() => {
@Component({
selector: 'child-cmp',
styles: styles,
host: {'[animate.enter]': 'clazz'},
template: '<p>I should fade</p>',
encapsulation: ViewEncapsulation.None,
@@ -1320,7 +1350,6 @@ describe('Animation', () => {
it('should compose class list when host binding a string and regular class strings', fakeAsync(() => {
@Component({
selector: 'child-cmp',
styles: styles,
host: {'animate.enter': 'slide-in'},
template: '<p>I should fade</p>',
encapsulation: ViewEncapsulation.None,