diff --git a/package.json b/package.json index 89e2308..283209f 100644 --- a/package.json +++ b/package.json @@ -29,14 +29,14 @@ "@angular/platform-browser": "^4.3.6", "@angular/router": "^4.3.6", "@skyux/animations": "^3.0.0-rc.0", - "@skyux/core": "^3.1.0", + "@skyux/core": "^3.5.0", "@skyux/i18n": "^3.3.0", "@skyux/indicators": "^3.0.0-rc.1" }, "dependencies": {}, "devDependencies": { - "@blackbaud/skyux": "2.28.1", - "@blackbaud/skyux-builder": "1.28.0", + "@blackbaud/skyux": "2.34.0", + "@blackbaud/skyux-builder": "1.30.0", "@skyux-sdk/builder-plugin-skyux": "1.0.0-rc.5" } } diff --git a/screenshots-baseline/toast-Lg-Component-chrome-1044x788-dpr-1.png b/screenshots-baseline/toast-Lg-Component-chrome-1044x788-dpr-1.png deleted file mode 100644 index 734b3e2..0000000 Binary files a/screenshots-baseline/toast-Lg-Component-chrome-1044x788-dpr-1.png and /dev/null differ diff --git a/screenshots-baseline/toast-Xs-Component-chrome-480x788-dpr-1.png b/screenshots-baseline/toast-Xs-Component-chrome-480x788-dpr-1.png deleted file mode 100644 index 734b3e2..0000000 Binary files a/screenshots-baseline/toast-Xs-Component-chrome-480x788-dpr-1.png and /dev/null differ diff --git a/src/app/public/modules/toast/fixtures/toast-fixtures.module.ts b/src/app/public/modules/toast/fixtures/toast-fixtures.module.ts index 20aeba9..dcef849 100644 --- a/src/app/public/modules/toast/fixtures/toast-fixtures.module.ts +++ b/src/app/public/modules/toast/fixtures/toast-fixtures.module.ts @@ -15,10 +15,6 @@ import { SkyLibResourcesService } from '@skyux/i18n'; -import { - SkyLibResourcesTestService -} from '@skyux/i18n/testing'; - import { SkyToastModule } from '../toast.module'; @@ -55,10 +51,7 @@ import { SkyToastBodyTestComponent ], providers: [ - { - provide: SkyLibResourcesService, - useClass: SkyLibResourcesTestService - } + SkyLibResourcesService ] }) export class SkyToastFixturesModule { } diff --git a/src/app/public/modules/toast/toast-adapter.service.spec.ts b/src/app/public/modules/toast/toast-adapter.service.spec.ts index 6c4dd3e..2a82dfb 100644 --- a/src/app/public/modules/toast/toast-adapter.service.spec.ts +++ b/src/app/public/modules/toast/toast-adapter.service.spec.ts @@ -1,10 +1,12 @@ // #region imports import { - RendererFactory2 + RendererFactory2, + ApplicationRef } from '@angular/core'; import { - TestBed + TestBed, + inject } from '@angular/core/testing'; import { @@ -23,6 +25,7 @@ describe('Toast adapter service', () => { appendCalledCount: 0, removeCalledCount: 0 }; + let applicationRef: ApplicationRef; beforeEach(() => { let rendererMock = { @@ -44,13 +47,31 @@ describe('Toast adapter service', () => { adapter = TestBed.get(SkyToastAdapterService); }); - it('should append element to body', () => { - adapter.appendToBody(undefined); - expect(rendererCallCounts.appendCalledCount).toBe(1); - }); + beforeEach( + inject( + [ + ApplicationRef + ], + ( + _applicationRef: ApplicationRef + ) => { + applicationRef = _applicationRef; + } + ) + ); - it('should remove element from body', () => { - adapter.removeHostElement(); - expect(rendererCallCounts.removeCalledCount).toBe(1); + it('should scroll to the bottom of an element correctly', () => { + spyOn(window, 'setTimeout').and.callFake((fun: Function) => { + fun(); + }); + let elementRefMock: any = { + nativeElement: { + scrollTop: undefined, + scrollHeight: 40 + } + }; + adapter.scrollBottom(elementRefMock); + applicationRef.tick(); + expect(elementRefMock.nativeElement.scrollTop).toBe(40); }); }); diff --git a/src/app/public/modules/toast/toast-adapter.service.ts b/src/app/public/modules/toast/toast-adapter.service.ts index 6a99c41..260127f 100644 --- a/src/app/public/modules/toast/toast-adapter.service.ts +++ b/src/app/public/modules/toast/toast-adapter.service.ts @@ -1,9 +1,7 @@ // #region imports import { ElementRef, - Injectable, - Renderer2, - RendererFactory2 + Injectable } from '@angular/core'; import { @@ -13,26 +11,10 @@ import { @Injectable() export class SkyToastAdapterService { - private hostElement: any; - private renderer: Renderer2; constructor( - private rendererFactory: RendererFactory2, private windowRef: SkyWindowRefService - ) { - this.renderer = this.rendererFactory.createRenderer(undefined, undefined); - } - - public appendToBody(element: any): void { - const body = this.windowRef.getWindow().document.body; - this.hostElement = element; - this.renderer.appendChild(body, element); - } - - public removeHostElement(): void { - const document = this.windowRef.getWindow().document; - this.renderer.removeChild(document.body, this.hostElement); - } + ) { } public scrollBottom(elementRef: ElementRef): void { const element = elementRef.nativeElement; diff --git a/src/app/public/modules/toast/toast.component.spec.ts b/src/app/public/modules/toast/toast.component.spec.ts index 2b6632f..8254e7d 100644 --- a/src/app/public/modules/toast/toast.component.spec.ts +++ b/src/app/public/modules/toast/toast.component.spec.ts @@ -21,6 +21,10 @@ import { import { SkyToastComponent } from './toast.component'; + +import { + SkyToastService +} from './toast.service'; // #endregion describe('Toast component', () => { @@ -41,6 +45,8 @@ describe('Toast component', () => { }); afterEach(() => { + TestBed.get(SkyToastService).ngOnDestroy(); + fixture.detectChanges(); fixture.destroy(); }); diff --git a/src/app/public/modules/toast/toast.module.ts b/src/app/public/modules/toast/toast.module.ts index d99424b..e4adcc2 100644 --- a/src/app/public/modules/toast/toast.module.ts +++ b/src/app/public/modules/toast/toast.module.ts @@ -2,16 +2,20 @@ import { NgModule } from '@angular/core'; + import { CommonModule } from '@angular/common'; +import { + SkyWindowRefService, + SkyDynamicComponentModule +} from '@skyux/core'; + import { SkyI18nModule } from '@skyux/i18n'; -import { - SkyWindowRefService -} from '@skyux/core'; + import { SkyIconModule } from '@skyux/indicators'; @@ -23,15 +27,19 @@ import { import { SkyToastAdapterService } from './toast-adapter.service'; + import { SkyToastBodyComponent } from './toast-body.component'; + import { SkyToastComponent } from './toast.component'; + import { SkyToasterComponent } from './toaster.component'; + import { SkyToastService } from './toast.service'; @@ -45,6 +53,7 @@ import { ], imports: [ CommonModule, + SkyDynamicComponentModule, SkyI18nModule, SkyIconModule, SkyToastResourcesModule diff --git a/src/app/public/modules/toast/toast.service.spec.ts b/src/app/public/modules/toast/toast.service.spec.ts index 89581ba..383f153 100644 --- a/src/app/public/modules/toast/toast.service.spec.ts +++ b/src/app/public/modules/toast/toast.service.spec.ts @@ -4,7 +4,8 @@ import { } from '@angular/core'; import { - TestBed + TestBed, + inject } from '@angular/core/testing'; import 'rxjs/add/operator/take'; @@ -13,6 +14,10 @@ import { expect } from '@blackbaud/skyux-builder/runtime/testing/browser'; +import { + SkyDynamicComponentService +} from '@skyux/core'; + import { SkyToastFixturesModule } from './fixtures'; @@ -36,6 +41,7 @@ import { describe('Toast service', () => { let toastService: SkyToastService; + let applicationRef: ApplicationRef; beforeEach(() => { TestBed.configureTestingModule({ @@ -49,13 +55,6 @@ describe('Toast service', () => { appendToBody() { }, removeHostElement() { } } - }, - { - provide: ApplicationRef, - useValue: { - attachView() {}, - detachView() {} - } } ] }); @@ -63,6 +62,24 @@ describe('Toast service', () => { toastService = TestBed.get(SkyToastService); }); + beforeEach( + inject( + [ + ApplicationRef + ], + ( + _applicationRef: ApplicationRef + ) => { + applicationRef = _applicationRef; + } + ) + ); + + afterEach(() => { + toastService.ngOnDestroy(); + applicationRef.tick(); + }); + it('should only create a single host component', () => { const spy = spyOn(toastService as any, 'createHostComponent').and.callThrough(); toastService.openMessage('message'); @@ -77,7 +94,8 @@ describe('Toast service', () => { it('should only remove the host element if it exists', () => { toastService.openMessage('message'); - const spy = spyOn(toastService['host'], 'destroy').and.callThrough(); + const dynamicService = TestBed.get(SkyDynamicComponentService); + const spy = spyOn(dynamicService, 'removeComponent').and.callThrough(); toastService['removeHostComponent'](); toastService['removeHostComponent'](); expect(spy.calls.count()).toEqual(1); diff --git a/src/app/public/modules/toast/toast.service.ts b/src/app/public/modules/toast/toast.service.ts index e081e19..48f1e75 100644 --- a/src/app/public/modules/toast/toast.service.ts +++ b/src/app/public/modules/toast/toast.service.ts @@ -1,11 +1,7 @@ // #region imports import { - ApplicationRef, ComponentRef, - ComponentFactoryResolver, - EmbeddedViewRef, Injectable, - Injector, OnDestroy, Provider } from '@angular/core'; @@ -18,6 +14,10 @@ import { Observable } from 'rxjs/Observable'; +import { + SkyDynamicComponentService +} from '@skyux/core'; + import { SkyToastConfig } from './types'; @@ -26,10 +26,6 @@ import { SkyToast } from './toast'; -import { - SkyToastAdapterService -} from './toast-adapter.service'; - import { SkyToastBodyComponent } from './toast-body.component'; @@ -59,15 +55,14 @@ export class SkyToastService implements OnDestroy { private _toastStream = new BehaviorSubject([]); constructor( - private appRef: ApplicationRef, - private resolver: ComponentFactoryResolver, - private injector: Injector, - private adapter: SkyToastAdapterService + private dynamicComponentService: SkyDynamicComponentService ) { } public ngOnDestroy() { - this.closeAll(); - this.removeHostComponent(); + if (this.host) { + this.closeAll(); + this.removeHostComponent(); + } this._toastStream.complete(); } @@ -125,7 +120,7 @@ export class SkyToastService implements OnDestroy { private addToast(toast: SkyToast): void { if (!this.host) { - this.host = this.createHostComponent(); + this.createHostComponent(); } this.toasts.push(toast); @@ -141,25 +136,15 @@ export class SkyToastService implements OnDestroy { } private createHostComponent(): ComponentRef { - const componentRef = this.resolver - .resolveComponentFactory(SkyToasterComponent) - .create(this.injector); - - const domElem = (componentRef.hostView as EmbeddedViewRef).rootNodes[0]; - - this.appRef.attachView(componentRef.hostView); - this.adapter.appendToBody(domElem); - - return componentRef; + this.host = this.dynamicComponentService.createComponent(SkyToasterComponent); + return this.host; } private removeHostComponent() { if (this.host) { - this.appRef.detachView(this.host.hostView); - this.host.destroy(); + this.dynamicComponentService.removeComponent(this.host); this.host = undefined; } - this.adapter.removeHostElement(); } } diff --git a/src/app/public/modules/toast/toaster.component.spec.ts b/src/app/public/modules/toast/toaster.component.spec.ts index dc08197..e9c9ce1 100644 --- a/src/app/public/modules/toast/toaster.component.spec.ts +++ b/src/app/public/modules/toast/toaster.component.spec.ts @@ -2,6 +2,7 @@ import { ApplicationRef } from '@angular/core'; + import { ComponentFixture, fakeAsync, @@ -9,6 +10,7 @@ import { TestBed, tick } from '@angular/core/testing'; + import { NoopAnimationsModule } from '@angular/platform-browser/animations'; @@ -23,9 +25,11 @@ import { SkyToastBodyTestComponent, SkyToastBodyTestContext } from './fixtures'; + import { SkyToastInstance } from './toast-instance'; + import { SkyToastService } from './toast.service'; @@ -59,7 +63,7 @@ describe('Toast component', () => { )); afterEach(fakeAsync(() => { - toastService.closeAll(); + toastService.ngOnDestroy(); applicationRef.tick(); tick(); fixture.detectChanges(); diff --git a/src/app/public/modules/toast/toaster.component.ts b/src/app/public/modules/toast/toaster.component.ts index 9a76d37..3c82519 100644 --- a/src/app/public/modules/toast/toaster.component.ts +++ b/src/app/public/modules/toast/toaster.component.ts @@ -80,9 +80,11 @@ export class SkyToasterComponent implements AfterViewInit { } public closeAll(): void { - this.toastComponents.forEach((toastComponent) => { - toastComponent.close(); - }); + if (this.toastComponents) { + this.toastComponents.forEach((toastComponent) => { + toastComponent.close(); + }); + } } private injectToastContent(): void { diff --git a/src/app/visual/toast/toast-demo.component.ts b/src/app/visual/toast/toast-demo.component.ts index d965e4f..3acd116 100644 --- a/src/app/visual/toast/toast-demo.component.ts +++ b/src/app/visual/toast/toast-demo.component.ts @@ -5,7 +5,7 @@ import { import { SkyToastInstance -} from '@blackbaud/skyux/dist/core'; +} from '../../public/modules/toast/toast-instance'; @Component({ selector: 'sky-test-cmp-toast',