From 38db01c78e05d42337b411eeeed0594de7869e5c Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Wed, 22 Apr 2020 00:39:24 +0300 Subject: [PATCH] test: enable and improve ToasterService specs --- .../src/lib/tests/toaster.service.spec.ts | 155 +++++++++++------- 1 file changed, 95 insertions(+), 60 deletions(-) diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts index 90f35cb339..0807bf632e 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/toaster.service.spec.ts @@ -1,87 +1,122 @@ import { CoreModule } from '@abp/ng.core'; -import { Component } from '@angular/core'; -import { RouterTestingModule } from '@angular/router/testing'; -import { createComponentFactory, Spectator } from '@ngneat/spectator/jest'; +import { NgModule } from '@angular/core'; +import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest'; import { NgxsModule } from '@ngxs/store'; +import { timer } from 'rxjs'; +import { ToastContainerComponent } from '../components/toast-container/toast-container.component'; +import { ToastComponent } from '../components/toast/toast.component'; import { ToasterService } from '../services/toaster.service'; -import { ThemeSharedModule } from '../theme-shared.module'; -import { OAuthService } from 'angular-oauth2-oidc'; - -@Component({ - selector: 'abp-dummy', - template: ` - - `, + +@NgModule({ + exports: [ToastContainerComponent], + entryComponents: [ToastContainerComponent], + declarations: [ToastContainerComponent, ToastComponent], + imports: [CoreModule.forTest()], }) -class DummyComponent { - constructor(public toaster: ToasterService) {} -} +export class MockModule {} describe('ToasterService', () => { - let spectator: Spectator; + let spectator: SpectatorService; let service: ToasterService; - const createComponent = createComponentFactory({ - component: DummyComponent, - imports: [CoreModule, ThemeSharedModule.forRoot(), NgxsModule.forRoot(), RouterTestingModule], - mocks: [OAuthService], + const createService = createServiceFactory({ + service: ToasterService, + imports: [NgxsModule.forRoot(), CoreModule.forTest(), MockModule], }); beforeEach(() => { - spectator = createComponent(); - service = spectator.get(ToasterService); + spectator = createService(); + service = spectator.service; + }); + + afterEach(() => { + clearElements(); }); - test.skip('should display an error toast', () => { - service.error('test', 'title'); + test('should display a toast', async () => { + service.show('MESSAGE', 'TITLE'); - spectator.detectChanges(); + await timer(0).toPromise(); + service['containerComponentRef'].changeDetectorRef.detectChanges(); - expect(spectator.query('div.toast')).toBeTruthy(); - expect(spectator.query('.toast-icon i')).toHaveClass('fa-times-circle'); - expect(spectator.query('div.toast-title')).toHaveText('title'); - expect(spectator.query('p.toast-message')).toHaveText('test'); + expect(selectToasterElement('.fa-exclamation-circle')).toBeTruthy(); + expect(selectToasterContent('.toast-title')).toBe('TITLE'); + expect(selectToasterContent('.toast-message')).toBe('MESSAGE'); }); - test.skip('should display a warning toast', () => { - service.warn('test', 'title'); - spectator.detectChanges(); - expect(spectator.query('.toast-icon i')).toHaveClass('fa-exclamation-triangle'); + test.each` + type | selector | icon + ${'info'} | ${'.toast-info'} | ${'.fa-info-circle'} + ${'success'} | ${'.toast-success'} | ${'.fa-check-circle'} + ${'warn'} | ${'.toast-warning'} | ${'.fa-exclamation-triangle'} + ${'error'} | ${'.toast-error'} | ${'.fa-times-circle'} + `('should display $type toast', async ({ type, selector, icon }) => { + service[type]('MESSAGE', 'TITLE'); + + await timer(0).toPromise(); + service['containerComponentRef'].changeDetectorRef.detectChanges(); + + expect(selectToasterContent('.toast-title')).toBe('TITLE'); + expect(selectToasterContent('.toast-message')).toBe('MESSAGE'); + expect(selectToasterElement()).toBe(document.querySelector(selector)); + expect(selectToasterElement(icon)).toBeTruthy(); }); - test.skip('should display a success toast', () => { - service.success('test', 'title'); - spectator.detectChanges(); - expect(spectator.query('.toast-icon i')).toHaveClass('fa-check-circle'); + test('should display multiple toasts', async () => { + service.show('MESSAGE_1', 'TITLE_1'); + service.show('MESSAGE_2', 'TITLE_2'); + + await timer(0).toPromise(); + service['containerComponentRef'].changeDetectorRef.detectChanges(); + + const titles = document.querySelectorAll('.toast-title'); + expect(titles.length).toBe(2); + + const messages = document.querySelectorAll('.toast-message'); + expect(messages.length).toBe(2); }); - test.skip('should display an info toast', () => { - service.info('test', 'title'); - spectator.detectChanges(); - expect(spectator.query('.toast-icon i')).toHaveClass('fa-info-circle'); + test('should remove a toast when remove is called', async () => { + service.show('MESSAGE'); + service.remove(0); + + await timer(0).toPromise(); + service['containerComponentRef'].changeDetectorRef.detectChanges(); + + expect(selectToasterElement()).toBeNull(); }); - test.skip('should display multiple toasts', () => { - service.info('detail1', 'summary1'); - service.info('detail2', 'summary2'); - - spectator.detectChanges(); - expect(spectator.queryAll('div.toast-title').map(node => node.textContent.trim())).toEqual([ - 'summary1', - 'summary2', - ]); - expect(spectator.queryAll('p.toast-message').map(node => node.textContent.trim())).toEqual([ - 'detail1', - 'detail2', - ]); + test('should remove toasts when clear is called', async () => { + service.show('MESSAGE'); + service.clear(); + + await timer(0).toPromise(); + service['containerComponentRef'].changeDetectorRef.detectChanges(); + + expect(selectToasterElement()).toBeNull(); }); - test.skip('should remove the opened toasts', () => { - service.info('test', 'title'); - spectator.detectChanges(); - expect(spectator.query('div.toast')).toBeTruthy(); + test('should remove toasts based on containerKey when clear is called with key', async () => { + service.show('MESSAGE_1', 'TITLE_1', 'neutral', { containerKey: 'x' }); + service.show('MESSAGE_2', 'TITLE_2', 'neutral', { containerKey: 'y' }); + service.clear('x'); - service.clear(); - spectator.detectChanges(); - expect(spectator.query('p-div.toast')).toBeFalsy(); + await timer(0).toPromise(); + service['containerComponentRef'].changeDetectorRef.detectChanges(); + + expect(selectToasterElement('.fa-exclamation-circle')).toBeTruthy(); + expect(selectToasterContent('.toast-title')).toBe('TITLE_2'); + expect(selectToasterContent('.toast-message')).toBe('MESSAGE_2'); }); }); + +function clearElements(selector = '.toast') { + document.querySelectorAll(selector).forEach(element => element.parentNode.removeChild(element)); +} + +function selectToasterContent(selector = '.toast'): string { + return selectToasterElement(selector).textContent.trim(); +} + +function selectToasterElement(selector = '.toast'): T { + return document.querySelector(selector); +}