mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(tabs): switch to fakeAsync tests (#10263)
* Reworks the tabs unit tests to run in the `fakeAsync` zone, rather than `async`. This has the advantage of being quicker, cleaner and avoiding timeouts in IE and Edge when the browser isn't focused. * Fixes a few unit tests that weren't asserting correctly, because their assertions were inside `whenStable` promises that weren't resolving.
This commit is contained in:
committed by
Jeremy Elbourn
parent
a943b36c7b
commit
8228c5f1fd
@@ -77,10 +77,8 @@ export class MatTabBodyPortal extends CdkPortalOutlet implements OnInit, OnDestr
|
||||
this.attach(this._host._content);
|
||||
}
|
||||
this._centeringSub = this._host._beforeCentering.subscribe((isCentering: boolean) => {
|
||||
if (isCentering) {
|
||||
if (!this.hasAttached()) {
|
||||
this.attach(this._host._content);
|
||||
}
|
||||
if (isCentering && !this.hasAttached()) {
|
||||
this.attach(this._host._content);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import {MatTab, MatTabGroup, MatTabHeaderPosition, MatTabsModule} from './index'
|
||||
|
||||
|
||||
describe('MatTabGroup', () => {
|
||||
beforeEach(async(() => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [MatTabsModule, NoopAnimationsModule],
|
||||
declarations: [
|
||||
@@ -59,7 +59,7 @@ describe('MatTabGroup', () => {
|
||||
checkSelectedIndex(2, fixture);
|
||||
});
|
||||
|
||||
it('should support two-way binding for selectedIndex', async(() => {
|
||||
it('should support two-way binding for selectedIndex', fakeAsync(() => {
|
||||
let component = fixture.componentInstance;
|
||||
component.selectedIndex = 0;
|
||||
|
||||
@@ -67,13 +67,13 @@ describe('MatTabGroup', () => {
|
||||
|
||||
let tabLabel = fixture.debugElement.queryAll(By.css('.mat-tab-label'))[1];
|
||||
tabLabel.nativeElement.click();
|
||||
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
expect(component.selectedIndex).toBe(1);
|
||||
});
|
||||
tick();
|
||||
|
||||
expect(component.selectedIndex).toBe(1);
|
||||
}));
|
||||
|
||||
// Note: needs to be `async` in order to fail when we expect it to.
|
||||
it('should set to correct tab on fast change', async(() => {
|
||||
let component = fixture.componentInstance;
|
||||
component.selectedIndex = 0;
|
||||
@@ -255,74 +255,76 @@ describe('MatTabGroup', () => {
|
||||
describe('dynamic binding tabs', () => {
|
||||
let fixture: ComponentFixture<SimpleDynamicTabsTestApp>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
fixture = TestBed.createComponent(SimpleDynamicTabsTestApp);
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
it('should be able to add a new tab, select it, and have correct origin position', () => {
|
||||
fixture.detectChanges();
|
||||
const component: MatTabGroup =
|
||||
fixture.debugElement.query(By.css('mat-tab-group')).componentInstance;
|
||||
it('should be able to add a new tab, select it, and have correct origin position',
|
||||
fakeAsync(() => {
|
||||
const component: MatTabGroup =
|
||||
fixture.debugElement.query(By.css('mat-tab-group')).componentInstance;
|
||||
|
||||
let tabs: MatTab[] = component._tabs.toArray();
|
||||
expect(tabs[0].origin).toBe(null);
|
||||
expect(tabs[1].origin).toBe(0);
|
||||
expect(tabs[2].origin).toBe(null);
|
||||
let tabs: MatTab[] = component._tabs.toArray();
|
||||
expect(tabs[0].origin).toBe(null);
|
||||
expect(tabs[1].origin).toBe(0);
|
||||
expect(tabs[2].origin).toBe(null);
|
||||
|
||||
// Add a new tab on the right and select it, expect an origin >= than 0 (animate right)
|
||||
fixture.componentInstance.tabs.push({label: 'New tab', content: 'to right of index'});
|
||||
fixture.componentInstance.selectedIndex = 4;
|
||||
fixture.detectChanges();
|
||||
// Add a new tab on the right and select it, expect an origin >= than 0 (animate right)
|
||||
fixture.componentInstance.tabs.push({label: 'New tab', content: 'to right of index'});
|
||||
fixture.componentInstance.selectedIndex = 4;
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
tabs = component._tabs.toArray();
|
||||
expect(tabs[3].origin).toBeGreaterThanOrEqual(0);
|
||||
tabs = component._tabs.toArray();
|
||||
expect(tabs[3].origin).toBeGreaterThanOrEqual(0);
|
||||
|
||||
// Add a new tab in the beginning and select it, expect an origin < than 0 (animate left)
|
||||
fixture.componentInstance.tabs.push({label: 'New tab', content: 'to left of index'});
|
||||
fixture.componentInstance.selectedIndex = 0;
|
||||
fixture.detectChanges();
|
||||
// Add a new tab in the beginning and select it, expect an origin < than 0 (animate left)
|
||||
fixture.componentInstance.tabs.push({label: 'New tab', content: 'to left of index'});
|
||||
fixture.componentInstance.selectedIndex = 0;
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
tabs = component._tabs.toArray();
|
||||
expect(tabs[0].origin).toBeLessThan(0);
|
||||
});
|
||||
tabs = component._tabs.toArray();
|
||||
expect(tabs[0].origin).toBeLessThan(0);
|
||||
}));
|
||||
|
||||
|
||||
it('should update selected index if the last tab removed while selected', () => {
|
||||
fixture.detectChanges();
|
||||
it('should update selected index if the last tab removed while selected', fakeAsync(() => {
|
||||
const component: MatTabGroup =
|
||||
fixture.debugElement.query(By.css('mat-tab-group')).componentInstance;
|
||||
|
||||
const numberOfTabs = component._tabs.length;
|
||||
fixture.componentInstance.selectedIndex = numberOfTabs - 1;
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
// Remove last tab while last tab is selected, expect next tab over to be selected
|
||||
fixture.componentInstance.tabs.pop();
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
expect(component.selectedIndex).toBe(numberOfTabs - 2);
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
describe('async tabs', () => {
|
||||
let fixture: ComponentFixture<AsyncTabsTestApp>;
|
||||
|
||||
it('should show tabs when they are available', async(() => {
|
||||
it('should show tabs when they are available', fakeAsync(() => {
|
||||
fixture = TestBed.createComponent(AsyncTabsTestApp);
|
||||
|
||||
let labels = fixture.debugElement.queryAll(By.css('.mat-tab-label'));
|
||||
|
||||
expect(labels.length).toBe(0);
|
||||
expect(fixture.debugElement.queryAll(By.css('.mat-tab-label')).length).toBe(0);
|
||||
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
labels = fixture.debugElement.queryAll(By.css('.mat-tab-label'));
|
||||
expect(labels.length).toBe(2);
|
||||
});
|
||||
expect(fixture.debugElement.queryAll(By.css('.mat-tab-label')).length).toBe(2);
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -330,50 +332,48 @@ describe('MatTabGroup', () => {
|
||||
let fixture: ComponentFixture<TabGroupWithSimpleApi>;
|
||||
let tabGroup: MatTabGroup;
|
||||
|
||||
beforeEach(() => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
fixture = TestBed.createComponent(TabGroupWithSimpleApi);
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
tabGroup =
|
||||
fixture.debugElement.query(By.directive(MatTabGroup)).componentInstance as MatTabGroup;
|
||||
});
|
||||
}));
|
||||
|
||||
it('should support a tab-group with the simple api', async(() => {
|
||||
it('should support a tab-group with the simple api', fakeAsync(() => {
|
||||
expect(getSelectedLabel(fixture).textContent).toMatch('Junk food');
|
||||
expect(getSelectedContent(fixture).textContent).toMatch('Pizza, fries');
|
||||
|
||||
tabGroup.selectedIndex = 2;
|
||||
fixture.detectChanges();
|
||||
// Use whenStable to wait for async observables and change detection to run in content.
|
||||
fixture.whenStable().then(() => {
|
||||
tick();
|
||||
|
||||
expect(getSelectedLabel(fixture).textContent).toMatch('Fruit');
|
||||
expect(getSelectedContent(fixture).textContent).toMatch('Apples, grapes');
|
||||
expect(getSelectedLabel(fixture).textContent).toMatch('Fruit');
|
||||
expect(getSelectedContent(fixture).textContent).toMatch('Apples, grapes');
|
||||
|
||||
fixture.componentInstance.otherLabel = 'Chips';
|
||||
fixture.componentInstance.otherContent = 'Salt, vinegar';
|
||||
fixture.detectChanges();
|
||||
fixture.componentInstance.otherLabel = 'Chips';
|
||||
fixture.componentInstance.otherContent = 'Salt, vinegar';
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(getSelectedLabel(fixture).textContent).toMatch('Chips');
|
||||
expect(getSelectedContent(fixture).textContent).toMatch('Salt, vinegar');
|
||||
});
|
||||
expect(getSelectedLabel(fixture).textContent).toMatch('Chips');
|
||||
expect(getSelectedContent(fixture).textContent).toMatch('Salt, vinegar');
|
||||
}));
|
||||
|
||||
it('should support @ViewChild in the tab content', () => {
|
||||
expect(fixture.componentInstance.legumes).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should only have the active tab in the DOM', async(() => {
|
||||
it('should only have the active tab in the DOM', fakeAsync(() => {
|
||||
expect(fixture.nativeElement.textContent).toContain('Pizza, fries');
|
||||
expect(fixture.nativeElement.textContent).not.toContain('Peanuts');
|
||||
|
||||
tabGroup.selectedIndex = 3;
|
||||
fixture.detectChanges();
|
||||
// Use whenStable to wait for async observables and change detection to run in content.
|
||||
fixture.whenStable().then(() => {
|
||||
expect(fixture.nativeElement.textContent).not.toContain('Pizza, fries');
|
||||
expect(fixture.nativeElement.textContent).toContain('Peanuts');
|
||||
});
|
||||
tick();
|
||||
|
||||
expect(fixture.nativeElement.textContent).not.toContain('Pizza, fries');
|
||||
expect(fixture.nativeElement.textContent).toContain('Peanuts');
|
||||
}));
|
||||
|
||||
it('should support setting the header position', () => {
|
||||
@@ -389,20 +389,20 @@ describe('MatTabGroup', () => {
|
||||
});
|
||||
|
||||
describe('lazy loaded tabs', () => {
|
||||
it('should lazy load the second tab', async () => {
|
||||
let fixture = TestBed.createComponent(TemplateTabs);
|
||||
it('should lazy load the second tab', fakeAsync(() => {
|
||||
const fixture = TestBed.createComponent(TemplateTabs);
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
let secondLabel = fixture.debugElement.queryAll(By.css('.mat-tab-label'))[1];
|
||||
const secondLabel = fixture.debugElement.queryAll(By.css('.mat-tab-label'))[1];
|
||||
secondLabel.nativeElement.click();
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
let child = fixture.debugElement.query(By.css('.child'));
|
||||
expect(child.nativeElement).toBeDefined();
|
||||
});
|
||||
});
|
||||
const child = fixture.debugElement.query(By.css('.child'));
|
||||
expect(child.nativeElement).toBeDefined();
|
||||
}));
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -436,7 +436,7 @@ describe('MatTabGroup', () => {
|
||||
|
||||
|
||||
describe('nested MatTabGroup with enabled animations', () => {
|
||||
beforeEach(async(() => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [MatTabsModule, BrowserAnimationsModule],
|
||||
declarations: [NestedTabs]
|
||||
@@ -445,10 +445,11 @@ describe('nested MatTabGroup with enabled animations', () => {
|
||||
TestBed.compileComponents();
|
||||
}));
|
||||
|
||||
it('should not throw when creating a component with nested tab groups', async(() => {
|
||||
it('should not throw when creating a component with nested tab groups', fakeAsync(() => {
|
||||
expect(() => {
|
||||
let fixture = TestBed.createComponent(NestedTabs);
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
}).not.toThrow();
|
||||
}));
|
||||
});
|
||||
@@ -594,7 +595,7 @@ class AsyncTabsTestApp {
|
||||
ngOnInit() {
|
||||
// Use ngOnInit because there is some issue with scheduling the async task in the constructor.
|
||||
this.tabs = Observable.create((observer: any) => {
|
||||
requestAnimationFrame(() => observer.next(this._tabs));
|
||||
setTimeout(() => observer.next(this._tabs));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user