test(animations): test various combinations of animations with host bindings (#15251)
PR Close #15251
This commit is contained in:
parent
0d3e314df0
commit
aeb99645bb
|
@ -162,42 +162,247 @@ export function main() {
|
||||||
const cmp2 = TestBed.createComponent(Cmp2);
|
const cmp2 = TestBed.createComponent(Cmp2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('host bindings', () => {
|
||||||
|
it('should trigger a state change animation from state => state on the component host element',
|
||||||
|
fakeAsync(() => {
|
||||||
|
@Component({
|
||||||
|
selector: 'my-cmp',
|
||||||
|
template: '...',
|
||||||
|
animations: [trigger(
|
||||||
|
'myAnimation',
|
||||||
|
[transition(
|
||||||
|
'a => b',
|
||||||
|
[style({'opacity': '0'}), animate(500, style({'opacity': '1'}))])])],
|
||||||
|
})
|
||||||
|
class Cmp {
|
||||||
|
@HostBinding('@myAnimation')
|
||||||
|
exp = 'a';
|
||||||
|
}
|
||||||
|
|
||||||
it('should trigger a state change animation from void => state on the component host element',
|
TestBed.configureTestingModule({declarations: [Cmp]});
|
||||||
() => {
|
|
||||||
@Component({
|
|
||||||
selector: 'my-cmp',
|
|
||||||
template: '...',
|
|
||||||
animations: [trigger(
|
|
||||||
'myAnimation',
|
|
||||||
[transition(
|
|
||||||
'a => b', [style({'opacity': '0'}), animate(500, style({'opacity': '1'}))])])],
|
|
||||||
})
|
|
||||||
class Cmp {
|
|
||||||
@HostBinding('@myAnimation')
|
|
||||||
get binding() { return this.exp ? 'b' : 'a'; }
|
|
||||||
exp: any = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TestBed.configureTestingModule({declarations: [Cmp]});
|
const engine = TestBed.get(ɵAnimationEngine);
|
||||||
|
const fixture = TestBed.createComponent(Cmp);
|
||||||
|
const cmp = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
engine.flush();
|
||||||
|
expect(getLog().length).toEqual(0);
|
||||||
|
|
||||||
const engine = TestBed.get(ɵAnimationEngine);
|
cmp.exp = 'b';
|
||||||
const fixture = TestBed.createComponent(Cmp);
|
fixture.detectChanges();
|
||||||
const cmp = fixture.componentInstance;
|
engine.flush();
|
||||||
cmp.exp = false;
|
expect(getLog().length).toEqual(1);
|
||||||
fixture.detectChanges();
|
|
||||||
engine.flush();
|
|
||||||
expect(getLog().length).toEqual(0);
|
|
||||||
|
|
||||||
cmp.exp = true;
|
const data = getLog().pop();
|
||||||
fixture.detectChanges();
|
expect(data.element).toEqual(fixture.elementRef.nativeElement);
|
||||||
engine.flush();
|
expect(data.keyframes).toEqual([{offset: 0, opacity: '0'}, {offset: 1, opacity: '1'}]);
|
||||||
expect(getLog().length).toEqual(1);
|
}));
|
||||||
|
|
||||||
const data = getLog().pop();
|
// nonAnimationRenderer => animationRenderer
|
||||||
expect(data.element).toEqual(fixture.elementRef.nativeElement);
|
it('should trigger a leave animation when the inner components host binding updates',
|
||||||
expect(data.keyframes).toEqual([{offset: 0, opacity: '0'}, {offset: 1, opacity: '1'}]);
|
fakeAsync(() => {
|
||||||
});
|
@Component({
|
||||||
|
selector: 'parent-cmp',
|
||||||
|
template: `
|
||||||
|
<child-cmp *ngIf="exp"></child-cmp>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class ParentCmp {
|
||||||
|
public exp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'child-cmp',
|
||||||
|
template: '...',
|
||||||
|
animations: [trigger(
|
||||||
|
'host',
|
||||||
|
[transition(
|
||||||
|
':leave', [style({opacity: 1}), animate(1000, style({opacity: 0}))])])]
|
||||||
|
})
|
||||||
|
class ChildCmp {
|
||||||
|
@HostBinding('@host') public hostAnimation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]});
|
||||||
|
|
||||||
|
const engine = TestBed.get(ɵAnimationEngine);
|
||||||
|
const fixture = TestBed.createComponent(ParentCmp);
|
||||||
|
const cmp = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
engine.flush();
|
||||||
|
expect(getLog().length).toEqual(0);
|
||||||
|
|
||||||
|
cmp.exp = false;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.debugElement.nativeElement.children.length).toBe(1);
|
||||||
|
|
||||||
|
engine.flush();
|
||||||
|
expect(getLog().length).toEqual(1);
|
||||||
|
|
||||||
|
const [player] = getLog();
|
||||||
|
expect(player.keyframes).toEqual([
|
||||||
|
{opacity: '1', offset: 0},
|
||||||
|
{opacity: '0', offset: 1},
|
||||||
|
]);
|
||||||
|
|
||||||
|
flushMicrotasks();
|
||||||
|
expect(fixture.debugElement.nativeElement.children.length).toBe(0);
|
||||||
|
}));
|
||||||
|
|
||||||
|
// animationRenderer => nonAnimationRenderer
|
||||||
|
it('should trigger a leave animation when the outer components element binding updates on the host component element',
|
||||||
|
fakeAsync(() => {
|
||||||
|
@Component({
|
||||||
|
selector: 'parent-cmp',
|
||||||
|
animations: [trigger(
|
||||||
|
'host',
|
||||||
|
[transition(
|
||||||
|
':leave', [style({opacity: 1}), animate(1000, style({opacity: 0}))])])],
|
||||||
|
template: `
|
||||||
|
<child-cmp *ngIf="exp" @host></child-cmp>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class ParentCmp {
|
||||||
|
public exp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'child-cmp',
|
||||||
|
template: '...',
|
||||||
|
})
|
||||||
|
class ChildCmp {
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]});
|
||||||
|
|
||||||
|
const engine = TestBed.get(ɵAnimationEngine);
|
||||||
|
const fixture = TestBed.createComponent(ParentCmp);
|
||||||
|
const cmp = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
engine.flush();
|
||||||
|
expect(getLog().length).toEqual(0);
|
||||||
|
|
||||||
|
cmp.exp = false;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.debugElement.nativeElement.children.length).toBe(1);
|
||||||
|
|
||||||
|
engine.flush();
|
||||||
|
expect(getLog().length).toEqual(1);
|
||||||
|
|
||||||
|
const [player] = getLog();
|
||||||
|
expect(player.keyframes).toEqual([
|
||||||
|
{opacity: '1', offset: 0},
|
||||||
|
{opacity: '0', offset: 1},
|
||||||
|
]);
|
||||||
|
|
||||||
|
flushMicrotasks();
|
||||||
|
expect(fixture.debugElement.nativeElement.children.length).toBe(0);
|
||||||
|
}));
|
||||||
|
|
||||||
|
// animationRenderer => animationRenderer
|
||||||
|
it('should trigger a leave animation when both the inner and outer components trigger on the same element',
|
||||||
|
fakeAsync(() => {
|
||||||
|
@Component({
|
||||||
|
selector: 'parent-cmp',
|
||||||
|
animations: [trigger(
|
||||||
|
'host',
|
||||||
|
[transition(
|
||||||
|
':leave',
|
||||||
|
[style({height: '100px'}), animate(1000, style({height: '0px'}))])])],
|
||||||
|
template: `
|
||||||
|
<child-cmp *ngIf="exp" @host></child-cmp>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class ParentCmp {
|
||||||
|
public exp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'child-cmp',
|
||||||
|
template: '...',
|
||||||
|
animations: [trigger(
|
||||||
|
'host', [transition(
|
||||||
|
':leave',
|
||||||
|
[style({width: '100px'}), animate(1000, style({width: '0px'}))])])]
|
||||||
|
})
|
||||||
|
class ChildCmp {
|
||||||
|
@HostBinding('@host') public hostAnimation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]});
|
||||||
|
|
||||||
|
const engine = TestBed.get(ɵAnimationEngine);
|
||||||
|
const fixture = TestBed.createComponent(ParentCmp);
|
||||||
|
const cmp = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
engine.flush();
|
||||||
|
expect(getLog().length).toEqual(0);
|
||||||
|
|
||||||
|
cmp.exp = false;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.debugElement.nativeElement.children.length).toBe(1);
|
||||||
|
|
||||||
|
engine.flush();
|
||||||
|
expect(getLog().length).toEqual(2);
|
||||||
|
|
||||||
|
const [p1, p2] = getLog();
|
||||||
|
expect(p1.keyframes).toEqual([
|
||||||
|
{height: '100px', offset: 0},
|
||||||
|
{height: '0px', offset: 1},
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(p2.keyframes).toEqual([
|
||||||
|
{width: '100px', offset: 0},
|
||||||
|
{width: '0px', offset: 1},
|
||||||
|
]);
|
||||||
|
|
||||||
|
flushMicrotasks();
|
||||||
|
expect(fixture.debugElement.nativeElement.children.length).toBe(0);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should not throw when the host element is removed and no animation triggers',
|
||||||
|
fakeAsync(() => {
|
||||||
|
@Component({
|
||||||
|
selector: 'parent-cmp',
|
||||||
|
template: `
|
||||||
|
<child-cmp *ngIf="exp"></child-cmp>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class ParentCmp {
|
||||||
|
public exp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'child-cmp',
|
||||||
|
template: '...',
|
||||||
|
animations: [trigger('host', [transition('a => b', [style({height: '100px'})])])],
|
||||||
|
})
|
||||||
|
class ChildCmp {
|
||||||
|
@HostBinding('@host') public hostAnimation = 'a';
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({declarations: [ParentCmp, ChildCmp]});
|
||||||
|
|
||||||
|
const engine = TestBed.get(ɵAnimationEngine);
|
||||||
|
const fixture = TestBed.createComponent(ParentCmp);
|
||||||
|
const cmp = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.debugElement.nativeElement.children.length).toBe(1);
|
||||||
|
|
||||||
|
engine.flush();
|
||||||
|
expect(getLog().length).toEqual(0);
|
||||||
|
|
||||||
|
cmp.exp = false;
|
||||||
|
fixture.detectChanges();
|
||||||
|
engine.flush();
|
||||||
|
flushMicrotasks();
|
||||||
|
expect(getLog().length).toEqual(0);
|
||||||
|
expect(fixture.debugElement.nativeElement.children.length).toBe(0);
|
||||||
|
|
||||||
|
flushMicrotasks();
|
||||||
|
expect(fixture.debugElement.nativeElement.children.length).toBe(0);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
it('should cancel and merge in mid-animation styles into the follow-up animation', () => {
|
it('should cancel and merge in mid-animation styles into the follow-up animation', () => {
|
||||||
@Component({
|
@Component({
|
||||||
|
|
Loading…
Reference in New Issue