igniteui-angular-sovn
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
601 lines (529 loc) • 27.4 kB
text/typescript
import { Component, ViewChild, DebugElement } from '@angular/core';
import { TestBed, ComponentFixture, tick, fakeAsync, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { IgxBannerComponent } from './banner.component';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { configureTestSuite } from '../test-utils/configure-suite';
import { IgxIconComponent } from '../icon/icon.component';
import { IgxBannerActionsDirective } from './banner.directives';
import { IgxCardComponent, IgxCardContentDirective, IgxCardHeaderComponent } from '../card/card.component';
import { IgxAvatarComponent } from '../avatar/avatar.component';
const CSS_CLASS_EXPANSION_PANEL = 'igx-expansion-panel';
const CSS_CLASS_EXPANSION_PANEL_BODY = 'igx-expansion-panel__body';
const CSS_CLASS_BANNER = 'igx-banner';
const CSS_CLASS_BANNER_MESSAGE = 'igx-banner__message';
const CSS_CLASS_BANNER_ILLUSTRATION = 'igx-banner__illustration';
const CSS_CLASS_BANNER_TEXT = 'igx-banner__text';
const CSS_CLASS_BANNER_ACTIONS = 'igx-banner__actions';
describe('igxBanner', () => {
let bannerElement: DebugElement = null;
let bannerMessageElement: DebugElement = null;
let bannerIllustrationElement: DebugElement = null;
let bannerTextElement: DebugElement = null;
let bannerActionsElement: DebugElement = null;
configureTestSuite();
beforeAll(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
NoopAnimationsModule,
IgxBannerEmptyComponent,
IgxBannerOneButtonComponent,
IgxBannerSampleComponent,
IgxBannerCustomTemplateComponent,
SimpleBannerEventsComponent
]
}).compileComponents();
}));
describe('General tests: ', () => {
it('Should initialize properly banner component with empty template', () => {
const fixture = TestBed.createComponent(IgxBannerEmptyComponent);
fixture.detectChanges();
const banner = fixture.componentInstance.banner;
expect(fixture.componentInstance).toBeDefined();
expect(banner).toBeDefined();
expect(banner.collapsed).toBeTruthy();
expect(banner.useDefaultTemplate).toBeTruthy();
});
it(`Should properly initialize banner component with message`, () => {
const fixture = TestBed.createComponent(SimpleBannerEventsComponent);
fixture.detectChanges();
const banner = fixture.componentInstance.banner;
expect(fixture.componentInstance).toBeDefined();
expect(banner).toBeDefined();
expect(banner.collapsed).toBeTruthy();
expect(banner.useDefaultTemplate).toBeTruthy();
banner.toggle();
const bannerMessage = banner.element.querySelector('.' + CSS_CLASS_BANNER_TEXT);
expect(bannerMessage.innerHTML.trim()).toEqual('Simple message');
});
it('Should initialize properly banner component with message and a button', () => {
const fixture = TestBed.createComponent(IgxBannerOneButtonComponent);
fixture.detectChanges();
const banner = fixture.componentInstance.banner;
expect(fixture.componentInstance).toBeDefined();
expect(banner).toBeDefined();
expect(banner.collapsed).toBeTruthy();
expect(banner.useDefaultTemplate).toBeFalsy();
banner.toggle();
const bannerMessage = banner.element.querySelector('.' + CSS_CLASS_BANNER_TEXT);
expect(bannerMessage.innerHTML.trim()).toEqual('You have lost connection to the internet.');
const button = banner.element.querySelector('button');
expect(button.innerHTML).toEqual('TURN ON WIFI');
});
it('Should initialize properly banner component with message and buttons', () => {
const fixture: ComponentFixture<IgxBannerSampleComponent> = TestBed.createComponent(IgxBannerSampleComponent);
fixture.detectChanges();
const banner = fixture.componentInstance.banner;
expect(fixture.componentInstance).toBeDefined();
expect(banner).toBeDefined();
expect(banner.collapsed).toBeTruthy();
expect(banner.useDefaultTemplate).toBeFalsy();
banner.toggle();
const bannerMessage = banner.element.querySelector('.' + CSS_CLASS_BANNER_TEXT);
expect(bannerMessage.innerHTML.trim()).toEqual('Unfortunately, the credit card did not go through, please try again.');
const buttons = banner.element.querySelectorAll('button');
expect(buttons[0].innerHTML).toEqual('UPDATE');
expect(buttons[1].innerHTML).toEqual('DISMISS');
});
it('Should properly set base classes', fakeAsync(() => {
const fixture: ComponentFixture<IgxBannerSampleComponent> = TestBed.createComponent(IgxBannerSampleComponent);
fixture.detectChanges();
getBaseClassElements(fixture);
expect(bannerElement).toBeNull();
expect(bannerMessageElement).toBeNull();
expect(bannerIllustrationElement).toBeNull();
expect(bannerTextElement).toBeNull();
expect(bannerActionsElement).toBeNull();
const banner = fixture.componentInstance.banner;
banner.open();
tick();
fixture.detectChanges();
getBaseClassElements(fixture);
expect(bannerElement).toBeDefined();
expect(bannerMessageElement).toBeDefined();
expect(bannerIllustrationElement).toBeDefined();
expect(bannerTextElement).toBeDefined();
expect(bannerActionsElement).toBeDefined();
}));
it('Should initialize banner with at least one and up to two buttons', fakeAsync(() => {
const fixture: ComponentFixture<IgxBannerEmptyComponent> = TestBed.createComponent(IgxBannerSampleComponent);
fixture.detectChanges();
getBaseClassElements(fixture);
expect(bannerElement).toBeNull();
expect(bannerMessageElement).toBeNull();
expect(bannerIllustrationElement).toBeNull();
expect(bannerTextElement).toBeNull();
expect(bannerActionsElement).toBeNull();
const banner = fixture.componentInstance.banner;
banner.open();
tick();
fixture.detectChanges();
getBaseClassElements(fixture);
expect(bannerElement).not.toBeNull();
expect(bannerMessageElement).not.toBeNull();
expect(bannerIllustrationElement).not.toBeNull();
expect(bannerTextElement).not.toBeNull();
expect(bannerActionsElement).not.toBeNull();
banner.close();
tick();
fixture.detectChanges();
getBaseClassElements(fixture);
expect(bannerElement).toBeNull();
expect(bannerMessageElement).toBeNull();
expect(bannerIllustrationElement).toBeNull();
expect(bannerTextElement).toBeNull();
expect(bannerActionsElement).toBeNull();
}));
it('Should position buttons next to the banner content', fakeAsync(() => {
const fixture: ComponentFixture<IgxBannerSampleComponent> = TestBed.createComponent(IgxBannerSampleComponent);
fixture.detectChanges();
const banner: IgxBannerComponent = fixture.componentInstance.banner;
banner.open();
tick();
fixture.detectChanges();
getBaseClassElements(fixture);
const bannerMessageElementTop = bannerMessageElement.nativeElement.getClientRects().y;
const bannerActionsElementTop = bannerActionsElement.nativeElement.getClientRects().y;
expect(bannerMessageElementTop).toBe(bannerActionsElementTop);
}));
it('Should span the entire width of the parent element', fakeAsync(() => {
const fixture: ComponentFixture<IgxBannerOneButtonComponent> = TestBed.createComponent(IgxBannerOneButtonComponent);
fixture.detectChanges();
const banner: IgxBannerComponent = fixture.componentInstance.banner;
banner.open();
tick();
fixture.detectChanges();
getBaseClassElements(fixture);
const parentElement = fixture.debugElement.query(By.css('#wrapper'));
const parentElementRect = parentElement.nativeElement.getBoundingClientRect();
const bannerElementRect = banner.elementRef.nativeElement.getBoundingClientRect();
expect(parentElementRect.left).toBe(bannerElementRect.left);
expect(parentElementRect.top).toBe(bannerElementRect.top);
expect(parentElementRect.right).toBe(bannerElementRect.right);
expect(parentElementRect.bottom).toBe(bannerElementRect.bottom);
}));
it('Should push parent element content downwards on loading', fakeAsync(() => {
const fixture: ComponentFixture<IgxBannerSampleComponent> = TestBed.createComponent(IgxBannerSampleComponent);
fixture.detectChanges();
let pageContentElement = fixture.debugElement.query(By.css('#content'));
let pageContentElementTop = pageContentElement.nativeElement.getBoundingClientRect().top;
const banner: IgxBannerComponent = fixture.componentInstance.banner;
banner.open();
tick();
fixture.detectChanges();
const bannerElementRect = banner.elementRef.nativeElement.getBoundingClientRect();
expect(pageContentElementTop).toBe(bannerElementRect.top);
pageContentElement = fixture.debugElement.query(By.css('#content'));
pageContentElementTop = pageContentElement.nativeElement.getBoundingClientRect().top;
expect(pageContentElementTop).toBe(bannerElementRect.bottom);
banner.close();
tick();
fixture.detectChanges();
pageContentElement = fixture.debugElement.query(By.css('#content'));
pageContentElementTop = pageContentElement.nativeElement.getBoundingClientRect().top;
expect(pageContentElementTop).toBe(bannerElementRect.top);
}));
});
describe('Action tests: ', () => {
it('Should dismiss/confirm banner on button clicking', fakeAsync(() => {
const fixture = TestBed.createComponent(IgxBannerSampleComponent);
fixture.detectChanges();
const banner = fixture.componentInstance.banner;
expect(banner.collapsed).toBeTruthy();
spyOn(banner.opened, 'emit');
spyOn(banner.closed, 'emit');
spyOn(banner, 'onExpansionPanelClose').and.callThrough();
spyOn(banner, 'onExpansionPanelOpen').and.callThrough();
spyOn(banner, 'open').and.callThrough();
spyOn(banner, 'close').and.callThrough();
banner.open();
tick();
fixture.detectChanges();
expect(banner.open).toHaveBeenCalledTimes(1);
expect(banner.opened.emit).toHaveBeenCalledTimes(1);
expect(banner.onExpansionPanelOpen).toHaveBeenCalledTimes(1);
expect(banner.collapsed).toBeFalsy();
getBaseClassElements(fixture);
expect(bannerMessageElement).not.toBeNull();
expect(bannerIllustrationElement).not.toBeNull();
expect(bannerTextElement).not.toBeNull();
expect(bannerTextElement.nativeElement.innerHTML.trim()).
toEqual('Unfortunately, the credit card did not go through, please try again.');
expect(bannerActionsElement).not.toBeNull();
const buttons = bannerActionsElement.nativeElement.querySelectorAll('button');
expect(buttons.length).toEqual(2);
buttons[0].click();
tick();
fixture.detectChanges();
getBaseClassElements(fixture);
expect(banner.close).toHaveBeenCalledTimes(1);
expect(banner.closed.emit).toHaveBeenCalledTimes(1);
expect(banner.onExpansionPanelClose).toHaveBeenCalledTimes(1);
expect(banner.collapsed).toBeTruthy();
expect(bannerMessageElement).toBeNull();
expect(bannerActionsElement).toBeNull();
banner.open();
tick();
fixture.detectChanges();
getBaseClassElements(fixture);
expect(banner.open).toHaveBeenCalledTimes(2);
expect(banner.opened.emit).toHaveBeenCalledTimes(2);
expect(banner.onExpansionPanelOpen).toHaveBeenCalledTimes(2);
expect(banner.collapsed).toBeFalsy();
expect(bannerMessageElement).not.toBeNull();
expect(bannerIllustrationElement).not.toBeNull();
expect(bannerTextElement).not.toBeNull();
expect(bannerTextElement.nativeElement.innerHTML.trim()).
toEqual('Unfortunately, the credit card did not go through, please try again.');
expect(bannerActionsElement).not.toBeNull();
buttons[1].click();
tick();
fixture.detectChanges();
getBaseClassElements(fixture);
expect(banner.close).toHaveBeenCalledTimes(2);
expect(banner.closed.emit).toHaveBeenCalledTimes(2);
expect(banner.onExpansionPanelClose).toHaveBeenCalledTimes(2);
expect(banner.collapsed).toBeTruthy();
expect(bannerMessageElement).toBeNull();
expect(bannerActionsElement).toBeNull();
}));
it('Should not be dismissed on user actions outside the component', () => {
const fixture = TestBed.createComponent(IgxBannerSampleComponent);
fixture.detectChanges();
const banner = fixture.componentInstance.banner;
const targetDiv = document.createElement('DIV');
const bannerNode: HTMLElement = banner.elementRef.nativeElement;
targetDiv.style.height = '3000px';
targetDiv.style.width = '1000px';
targetDiv.style.backgroundColor = '#aa44bb';
targetDiv.tabIndex = 1;
bannerNode.parentNode.appendChild(targetDiv);
expect(banner.collapsed).toBeTruthy();
banner.open();
fixture.detectChanges();
expect(banner.collapsed).toBeFalsy();
targetDiv.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
fixture.detectChanges();
expect(banner.collapsed).toBeFalsy();
targetDiv.click();
fixture.detectChanges();
expect(banner.collapsed).toBeFalsy();
targetDiv.focus();
fixture.detectChanges();
expect(banner.collapsed).toBeFalsy();
targetDiv.style.height = '3000px';
fixture.detectChanges();
targetDiv.dispatchEvent(new Event('scroll'));
fixture.detectChanges();
expect(banner.collapsed).toBeFalsy();
targetDiv.parentNode.removeChild(targetDiv);
});
it('Should properly emit events', fakeAsync(() => {
const fixture = TestBed.createComponent(IgxBannerSampleComponent);
fixture.detectChanges();
const banner = fixture.componentInstance.banner;
spyOn(banner.closed, 'emit');
spyOn(banner.closing, 'emit');
spyOn(banner.opened, 'emit');
spyOn(banner.opening, 'emit');
expect(banner.collapsed).toEqual(true);
expect(banner.opening.emit).toHaveBeenCalledTimes(0);
expect(banner.opened.emit).toHaveBeenCalledTimes(0);
expect(banner.closing.emit).toHaveBeenCalledTimes(0);
expect(banner.closed.emit).toHaveBeenCalledTimes(0);
banner.toggle();
tick();
expect(banner.opening.emit).toHaveBeenCalledTimes(1);
expect(banner.opened.emit).toHaveBeenCalledTimes(1);
expect(banner.closing.emit).toHaveBeenCalledTimes(0);
expect(banner.closed.emit).toHaveBeenCalledTimes(0);
banner.toggle();
tick();
expect(banner.opening.emit).toHaveBeenCalledTimes(1);
expect(banner.opened.emit).toHaveBeenCalledTimes(1);
expect(banner.closing.emit).toHaveBeenCalledTimes(1);
expect(banner.closed.emit).toHaveBeenCalledTimes(1);
}));
it('Should properly cancel opening and closing', fakeAsync(() => {
const fixture = TestBed.createComponent(SimpleBannerEventsComponent);
fixture.detectChanges();
const banner = fixture.componentInstance.banner;
spyOn(banner.closing, 'emit').and.callThrough();
spyOn(banner.opening, 'emit').and.callThrough();
spyOn(banner.closed, 'emit').and.callThrough();
spyOn(banner.opened, 'emit').and.callThrough();
expect(banner.collapsed).toEqual(true);
fixture.componentInstance.cancelFlag = true;
banner.toggle();
tick();
expect(banner.collapsed).toEqual(true);
expect(banner.opening.emit).toHaveBeenCalledTimes(1);
expect(banner.opened.emit).toHaveBeenCalledTimes(0);
fixture.componentInstance.cancelFlag = false;
banner.toggle();
tick();
expect(banner.collapsed).toEqual(false);
expect(banner.opening.emit).toHaveBeenCalledTimes(2);
expect(banner.opened.emit).toHaveBeenCalledTimes(1);
fixture.componentInstance.cancelFlag = true;
banner.toggle();
tick();
expect(banner.collapsed).toEqual(false);
expect(banner.closing.emit).toHaveBeenCalledTimes(1);
expect(banner.closed.emit).toHaveBeenCalledTimes(0);
fixture.componentInstance.cancelFlag = false;
banner.toggle();
tick();
expect(banner.collapsed).toEqual(true);
expect(banner.closing.emit).toHaveBeenCalledTimes(2);
expect(banner.closed.emit).toHaveBeenCalledTimes(1);
}));
});
describe('Rendering tests: ', () => {
it('Should apply all appropriate classes on initialization_default template', fakeAsync(() => {
const fixture = TestBed.createComponent(IgxBannerSampleComponent);
fixture.detectChanges();
const banner = fixture.componentInstance.banner;
const bannerNode: HTMLElement = banner.elementRef.nativeElement;
expect(banner.collapsed).toBeTruthy();
expect(bannerNode.childElementCount).toEqual(1); // collapsed expansion panel
expect(bannerNode.firstElementChild.childElementCount).toEqual(0); // no content
getBaseClassElements(fixture);
expect(bannerElement).toBeNull();
expect(bannerMessageElement).toBeNull();
expect(bannerIllustrationElement).toBeNull();
expect(bannerTextElement).toBeNull();
expect(bannerActionsElement).toBeNull();
banner.toggle();
tick();
fixture.detectChanges();
getBaseClassElements(fixture);
expect(bannerElement).not.toBeNull();
expect(bannerMessageElement).not.toBeNull();
expect(bannerIllustrationElement).not.toBeNull();
expect(bannerTextElement).not.toBeNull();
expect(bannerActionsElement).not.toBeNull();
banner.toggle();
tick();
fixture.detectChanges();
getBaseClassElements(fixture);
expect(bannerElement).toBeNull();
expect(bannerMessageElement).toBeNull();
expect(bannerIllustrationElement).toBeNull();
expect(bannerTextElement).toBeNull();
expect(bannerActionsElement).toBeNull();
}));
it('Should apply all appropriate classes on initialization_custom template', fakeAsync(() => {
const fixture = TestBed.createComponent(IgxBannerCustomTemplateComponent);
fixture.detectChanges();
const banner = fixture.componentInstance.banner;
const panel = fixture.nativeElement.querySelector('.' + CSS_CLASS_EXPANSION_PANEL);
expect(panel).not.toBeNull();
expect(panel.attributes.getNamedItem('ng-reflect-collapsed').nodeValue).toEqual('true');
expect(panel.childElementCount).toEqual(0);
banner.open();
tick();
fixture.detectChanges();
expect(panel.attributes.getNamedItem('ng-reflect-collapsed').nodeValue).toEqual('false');
expect(panel.childElementCount).toEqual(1);
const panelBody = panel.children[0];
expect(panelBody.attributes.getNamedItem('class').nodeValue).toContain(CSS_CLASS_EXPANSION_PANEL_BODY);
expect(panelBody.attributes.getNamedItem('role').nodeValue).toEqual('region');
expect(panelBody.childElementCount).toEqual(1);
}));
it('Should apply the appropriate display style to the banner host', fakeAsync(() => {
const fixture = TestBed.createComponent(IgxBannerOneButtonComponent);
fixture.detectChanges();
const banner = fixture.componentInstance.banner;
// Banner is collapsed, display is '';
expect(banner.elementRef.nativeElement.style.display).toEqual('');
banner.toggle();
tick();
// Banner is expanded, display is 'block';
fixture.detectChanges();
expect(banner.elementRef.nativeElement.style.display).toEqual('block');
expect(banner.collapsed).toBeFalsy();
banner.toggle();
tick();
// Banner is collapsING, display is 'block';
expect(banner.elementRef.nativeElement.style.display).toEqual('block');
tick();
fixture.detectChanges();
// Banner is collapsed, display is '';
expect(banner.elementRef.nativeElement.style.display).toEqual('');
expect(banner.collapsed).toBeTruthy();
}));
});
const getBaseClassElements = <T>(fixture: ComponentFixture<T>) => {
bannerElement = fixture.debugElement.query(By.css('.' + CSS_CLASS_BANNER));
bannerMessageElement = fixture.debugElement.query(By.css('.' + CSS_CLASS_BANNER_MESSAGE));
bannerIllustrationElement = fixture.debugElement.query(By.css('.' + CSS_CLASS_BANNER_ILLUSTRATION));
bannerTextElement = fixture.debugElement.query(By.css('.' + CSS_CLASS_BANNER_TEXT));
bannerActionsElement = fixture.debugElement.query(By.css('.' + CSS_CLASS_BANNER_ACTIONS));
};
});
@Component({
template: `
<div id="wrapper" style = "width:900px">
<igx-banner></igx-banner>
</div>
<div id="content" style="height:200px; border: 1px solid red;"> SOME PAGE CONTENT</div>`,
standalone: true,
imports: [ IgxBannerComponent ]
})
export class IgxBannerEmptyComponent {
@ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true })
public banner: IgxBannerComponent;
}
@Component({
template: `
<div id="wrapper" style = "width:900px;">
<igx-banner>
You have lost connection to the internet.
<igx-banner-actions>
<button igxButton="raised">TURN ON WIFI</button>
</igx-banner-actions>
</igx-banner>
</div>
<div id="content" style="height:200px; border: 1px solid red;"> SOME PAGE CONTENT</div>
`,
standalone: true,
imports: [ IgxBannerComponent, IgxBannerActionsDirective ]
})
export class IgxBannerOneButtonComponent {
@ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true })
public banner: IgxBannerComponent;
}
@Component({
template: `
<div id="wrapper" style = "width:900px">
<igx-banner>
<igx-icon>error</igx-icon>
Unfortunately, the credit card did not go through, please try again.
<igx-banner-actions>
<button igxButton="raised" (click)="banner.close()">UPDATE</button>
<button igxButton="raised" (click)="banner.close()">DISMISS</button>
</igx-banner-actions>
</igx-banner>
</div>
<div id="content" style="height:200px; border: 1px solid red;"> SOME PAGE CONTENT</div>
`,
standalone: true,
imports: [ IgxBannerComponent, IgxBannerActionsDirective, IgxIconComponent ]
})
export class IgxBannerSampleComponent {
@ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true })
public banner: IgxBannerComponent;
}
@Component({
template: `
<div id="wrapper" style = "width:900px">
<igx-banner>
<igx-card>
<igx-card-header class="compact">
<igx-avatar
src="https://www.infragistics.com/angular-demos/assets/images/card/avatars/brad_stanley.jpg">
</igx-avatar>
<div class="igx-card-header__tgroup">
<h3 class="igx-card-header__title--small">Brad Stanley</h3>
<h5 class="igx-card-header__subtitle">Audi AG</h5>
</div>
</igx-card-header>
<igx-card-content>
<p class="igx-card-content__text">Brad Stanley has requested to follow you.</p>
</igx-card-content>
</igx-card>
<igx-banner-actions>
<button igxButton igxRipple >Dismiss</button>
<button igxButton igxRipple >Approve</button>
</igx-banner-actions>
</igx-banner>
</div>
<div id="content" style="height:200px; border: 1px solid red;"> SOME PAGE CONTENT</div>`,
standalone: true,
imports: [ IgxBannerComponent, IgxCardComponent, IgxCardHeaderComponent, IgxCardContentDirective, IgxBannerActionsDirective, IgxAvatarComponent ]
})
export class IgxBannerCustomTemplateComponent {
@ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true })
public banner: IgxBannerComponent;
}
@Component({
template: `
<div id="wrapper" style = "width:900px">
<igx-banner (opening)="handleOpening($event)" (closing)="handleClosing($event)">Simple message</igx-banner>
</div>
<div id="content" style="height:200px; border: 1px solid red;"> SOME PAGE CONTENT</div>`,
standalone: true,
imports: [ IgxBannerComponent ]
})
export class SimpleBannerEventsComponent {
@ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true })
public banner: IgxBannerComponent;
public cancelFlag = false;
public handleOpening(event: any) {
event.cancel = this.cancelFlag;
}
public handleClosing(event: any) {
event.cancel = this.cancelFlag;
}
}