mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
431 lines
18 KiB
TypeScript
431 lines
18 KiB
TypeScript
// unit test ShellComponent with Spectator
|
|
|
|
import { Component } from '@angular/core';
|
|
import { Router } from '@angular/router';
|
|
import { RouterTestingModule } from '@angular/router/testing';
|
|
import { ApplicationProcess, ApplicationService } from '@core/application';
|
|
import { AuthService } from '@core/auth';
|
|
import { Config } from '@core/config';
|
|
import { BreadcrumbService } from '@core/breadcrumb';
|
|
import { DomainAvailabilityService } from '@domain/availability';
|
|
import { DomainDashboardService } from '@domain/isa';
|
|
import { NotificationsHub } from '@hub/notifications';
|
|
import { ModalNotificationsComponent } from '@modal/notifications';
|
|
import { Spectator, createComponentFactory, SpyObject, createSpyObject } from '@ngneat/spectator';
|
|
import { DashboardComponent } from '@page/dashboard';
|
|
import { ShellFooterComponent } from '@shell/footer';
|
|
import { ShellHeaderComponent } from '@shell/header';
|
|
import { ShellProcessComponent, ShellProcessTabComponent } from '@shell/process';
|
|
import { UiIconComponent } from '@ui/icon';
|
|
import { UiModalService } from '@ui/modal';
|
|
import { EnvelopeDTO, MessageBoardItemDTO } from 'apps/hub/notifications/src/lib/defs';
|
|
import { MockComponent } from 'ng-mocks';
|
|
import { of } from 'rxjs';
|
|
import { first } from 'rxjs/operators';
|
|
import { ShellComponent } from './shell.component';
|
|
import { WrongDestinationModalService } from 'apps/page/package-inspection/src/lib/components/wrong-destination-modal/wrong-destination-modal.service';
|
|
|
|
// DummyComponent Class
|
|
@Component({
|
|
selector: 'dummy-component',
|
|
template: '<div></div>',
|
|
})
|
|
class DummyComponent {
|
|
constructor() {}
|
|
}
|
|
|
|
describe('ShellComponent', () => {
|
|
let spectator: Spectator<ShellComponent>;
|
|
let applicationServiceMock: SpyObject<ApplicationService>;
|
|
let modalServiceMock: SpyObject<UiModalService>;
|
|
let notificationsHubMock: SpyObject<NotificationsHub>;
|
|
let router: Router;
|
|
let breadcrumbServiceMock: SpyObject<BreadcrumbService>;
|
|
let authServiceMock: SpyObject<AuthService>;
|
|
|
|
const createComponent = createComponentFactory({
|
|
component: ShellComponent,
|
|
imports: [
|
|
RouterTestingModule.withRoutes([
|
|
{ path: 'kunde', component: DummyComponent },
|
|
{ path: 'kunde/dashboard', component: DashboardComponent },
|
|
]),
|
|
],
|
|
declarations: [
|
|
MockComponent(ShellHeaderComponent),
|
|
MockComponent(ShellFooterComponent),
|
|
MockComponent(ShellProcessComponent),
|
|
MockComponent(ShellProcessTabComponent),
|
|
MockComponent(UiIconComponent),
|
|
],
|
|
mocks: [BreadcrumbService, DomainAvailabilityService, AuthService, DomainDashboardService, Config, WrongDestinationModalService],
|
|
});
|
|
|
|
beforeEach(() => {
|
|
applicationServiceMock = createSpyObject(ApplicationService);
|
|
applicationServiceMock.getSection$.and.returnValue(of('customer'));
|
|
applicationServiceMock.getProcesses$.and.returnValue(of([]));
|
|
applicationServiceMock.getProcessById$.and.returnValue(of({ id: 4000 }));
|
|
applicationServiceMock.getActivatedProcessId$.and.returnValue(of(undefined));
|
|
applicationServiceMock.getLastActivatedProcessWithSectionAndType$.and.returnValue(of({}));
|
|
applicationServiceMock.getLastActivatedProcessWithSection$.and.returnValue(of({}));
|
|
|
|
notificationsHubMock = createSpyObject(NotificationsHub);
|
|
notificationsHubMock.notifications$ = of({});
|
|
|
|
modalServiceMock = createSpyObject(UiModalService);
|
|
|
|
authServiceMock = createSpyObject(AuthService);
|
|
|
|
spectator = createComponent({
|
|
providers: [
|
|
{ provide: ApplicationService, useValue: applicationServiceMock },
|
|
{ provide: NotificationsHub, useValue: notificationsHubMock },
|
|
{ provide: UiModalService, useValue: modalServiceMock },
|
|
{ provide: AuthService, useValue: authServiceMock },
|
|
],
|
|
});
|
|
|
|
breadcrumbServiceMock = spectator.inject(BreadcrumbService);
|
|
router = spectator.inject(Router);
|
|
});
|
|
|
|
it('should create', () => {
|
|
expect(spectator.component).toBeTruthy();
|
|
});
|
|
|
|
describe('shell-header', () => {
|
|
it('should call setSection() on sectionChange event with the section argument', () => {
|
|
spyOn(spectator.component, 'setSection');
|
|
spectator.triggerEventHandler('shell-header', 'sectionChange', 'branch');
|
|
expect(spectator.component.setSection).toHaveBeenCalledWith('branch');
|
|
});
|
|
|
|
it('should render the header buttons', () => {
|
|
// Test verhält sich anders, wenn die größe des Browserfensters kleiner ist als 640px, da
|
|
// die Buttons dann unsichtbar werden und ins Drei-Punkt Menü verschoben werden.
|
|
if (document.body.clientWidth > 639) {
|
|
expect(spectator.query('shell-header .notifications-btn')).toBeVisible();
|
|
expect(spectator.query('shell-header .dashboard-btn')).toBeVisible();
|
|
expect(spectator.query('shell-header .logout-btn')).toBeVisible();
|
|
} else {
|
|
expect(spectator.query('shell-header .notifications-btn')).not.toBeVisible();
|
|
expect(spectator.query('shell-header .dashboard-btn')).not.toBeVisible();
|
|
expect(spectator.query('shell-header .logout-btn')).not.toBeVisible();
|
|
}
|
|
});
|
|
|
|
it('should have a anchor tag which navigates to /kunde/dashboard', () => {
|
|
const anchor = spectator.query('shell-header a');
|
|
expect(anchor).toHaveAttribute('href', '/kunde/dashboard');
|
|
});
|
|
});
|
|
|
|
describe('shell-process', () => {
|
|
it('should call addProcess() on addProcess event', () => {
|
|
spyOn(spectator.component, 'addProcess');
|
|
spectator.triggerEventHandler('shell-process', 'addProcess', undefined);
|
|
expect(spectator.component.addProcess).toHaveBeenCalled();
|
|
});
|
|
|
|
describe('shell-process-tab', () => {
|
|
it('should render for each process', () => {
|
|
const processes = [{}, {}, {}];
|
|
applicationServiceMock.getSection$.and.returnValue(of('customer'));
|
|
applicationServiceMock.getProcesses$.and.returnValue(of(processes));
|
|
spectator.detectComponentChanges();
|
|
expect(spectator.queryAll('shell-process-tab')).toHaveLength(processes.length);
|
|
});
|
|
|
|
it('should call activateProcess() on activateProcess event', () => {
|
|
const processes = [{ id: 1 }];
|
|
|
|
applicationServiceMock.getProcesses$.and.returnValue(of(processes));
|
|
spectator.detectComponentChanges();
|
|
|
|
spyOn(spectator.component, 'activateProcess');
|
|
spectator.triggerEventHandler('shell-process-tab', 'activateProcess', processes[0].id);
|
|
expect(spectator.component.activateProcess).toHaveBeenCalledWith(1);
|
|
});
|
|
|
|
it('should call closeProcess() on closeProcess event', () => {
|
|
const processes = [{ id: 1 }];
|
|
|
|
applicationServiceMock.getProcesses$.and.returnValue(of(processes));
|
|
spectator.detectComponentChanges();
|
|
|
|
spyOn(spectator.component, 'closeProcess');
|
|
spectator.triggerEventHandler('shell-process-tab', 'closeProcess', processes[0].id);
|
|
expect(spectator.component.closeProcess).toHaveBeenCalledWith(1);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('shell-footer', () => {
|
|
it('should render when section is set', () => {
|
|
applicationServiceMock.getSection$.and.returnValue(of('customer'));
|
|
spectator.detectComponentChanges();
|
|
expect(spectator.query('shell-footer')).toBeVisible();
|
|
});
|
|
|
|
it('should not render when section is undefined', () => {
|
|
applicationServiceMock.getSection$.and.returnValue(of(undefined));
|
|
spectator.detectComponentChanges();
|
|
expect(spectator.query('shell-footer')).not.toBeVisible();
|
|
});
|
|
|
|
it('should display the menu items for section customer', () => {
|
|
applicationServiceMock.getSection$.and.returnValue(of('customer'));
|
|
spectator.component.customerBasePath$ = of('/kunde/1');
|
|
spectator.detectComponentChanges();
|
|
|
|
const anchors = spectator.queryAll('shell-footer a');
|
|
expect(anchors[0]).toHaveText('Artikelsuche');
|
|
expect(anchors[0]).toHaveAttribute('href', '/kunde/1/product');
|
|
expect(anchors[1]).toHaveText('Kundensuche');
|
|
expect(anchors[1]).toHaveAttribute('href', '/kunde/1/customer');
|
|
expect(anchors[2]).toHaveText('Warenausgabe');
|
|
expect(anchors[2]).toHaveAttribute('href', '/kunde/1/goods/out');
|
|
});
|
|
|
|
it('should display the menu items for section branch', () => {
|
|
applicationServiceMock.getSection$.and.returnValue(of('branch'));
|
|
spectator.detectComponentChanges();
|
|
|
|
const anchors = spectator.queryAll('shell-footer a');
|
|
expect(anchors[0]).toHaveText('Tätigkeitskalender');
|
|
expect(anchors[0]).toHaveAttribute('href', '/filiale/task-calendar');
|
|
expect(anchors[1]).toHaveText('Abholfach');
|
|
expect(anchors[1]).toHaveAttribute('href', '/filiale/goods/in');
|
|
expect(anchors[2]).toHaveText('Remission');
|
|
expect(anchors[2]).toHaveAttribute('href', '/filiale/remission');
|
|
});
|
|
});
|
|
|
|
describe('activatedProcessId$', () => {
|
|
it('should call _appService.getActivatedProcessId$() and return its value', async () => {
|
|
applicationServiceMock.getActivatedProcessId$.and.returnValue(of(1));
|
|
const processId = await spectator.component.activatedProcessId$.pipe(first()).toPromise();
|
|
expect(processId).toBe(1);
|
|
expect(applicationServiceMock.getActivatedProcessId$).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('section$', () => {
|
|
it('should call _appService.getSection$() and return its value', async () => {
|
|
applicationServiceMock.getSection$.and.returnValue(of('branch'));
|
|
const section = await spectator.component.section$.pipe(first()).toPromise();
|
|
expect(section).toBe('branch');
|
|
expect(applicationServiceMock.getSection$).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('processes$', () => {
|
|
it('should call _appService.processes$() and return its value', async () => {
|
|
applicationServiceMock.getProcesses$.and.returnValue(of([{}, {}]));
|
|
const processes = await spectator.component.processes$.pipe(first()).toPromise();
|
|
expect(processes).toHaveLength(2);
|
|
expect(applicationServiceMock.getProcesses$).toHaveBeenCalledWith('customer');
|
|
});
|
|
});
|
|
|
|
describe('remissionProcess$', () => {
|
|
it('should call _appService.getProcessById$() with Remission Id and return its value', async () => {
|
|
applicationServiceMock.getProcessById$.and.returnValue(of({ id: 4000 }));
|
|
await spectator.component.remissionProcess$.pipe(first()).toPromise();
|
|
expect(applicationServiceMock.getProcessById$).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('remissionUrl$', () => {
|
|
it('should return the correct url if process.data.active is available', async () => {
|
|
const process = {
|
|
id: 4000,
|
|
data: {
|
|
active: 9999,
|
|
},
|
|
};
|
|
applicationServiceMock.getProcessById$.and.returnValue(of(process));
|
|
const url = await spectator.component.remissionUrl$.pipe(first()).toPromise();
|
|
expect(url).toBe('/filiale/remission/9999/list');
|
|
});
|
|
|
|
it('should return the correct url if process.data.active is not available', async () => {
|
|
const process = {
|
|
id: 4000,
|
|
data: {},
|
|
};
|
|
applicationServiceMock.getProcessById$.and.returnValue(of(process));
|
|
const url = await spectator.component.remissionUrl$.pipe(first()).toPromise();
|
|
expect(url).toBe('/filiale/remission');
|
|
});
|
|
});
|
|
|
|
describe('remissionQueryParams$', () => {
|
|
it('should return the correct queryParams if process.data.active and process.data.queryParams are available', async () => {
|
|
const process = {
|
|
id: 4000,
|
|
data: {
|
|
active: 9999,
|
|
queryParams: { filter: 'test' },
|
|
},
|
|
};
|
|
applicationServiceMock.getProcessById$.and.returnValue(of(process));
|
|
const queryParams = await spectator.component.remissionQueryParams$.pipe(first()).toPromise();
|
|
expect(queryParams).toEqual(process.data.queryParams);
|
|
});
|
|
|
|
it('should return the correct queryParams if process.data.active and process.data.queryParams are not available', async () => {
|
|
const process = {
|
|
id: 4000,
|
|
data: {},
|
|
};
|
|
applicationServiceMock.getProcessById$.and.returnValue(of(process));
|
|
const queryParams = await spectator.component.remissionQueryParams$.pipe(first()).toPromise();
|
|
expect(queryParams).toEqual({});
|
|
});
|
|
});
|
|
|
|
describe('setSection()', () => {
|
|
it('should call _appService.setSection() with the argument section', async () => {
|
|
await spectator.component.setSection('customer');
|
|
expect(applicationServiceMock.setSection).toHaveBeenCalledWith('customer');
|
|
});
|
|
|
|
it('should call activateProcess if getLastActivatedProcessWithSection returns a value', async () => {
|
|
applicationServiceMock.getLastActivatedProcessWithSection$.and.returnValue(of({ id: 1 }));
|
|
spyOn(spectator.component, 'activateProcess');
|
|
await spectator.component.setSection('customer');
|
|
expect(spectator.component.activateProcess).toHaveBeenCalledWith(1);
|
|
});
|
|
});
|
|
|
|
describe('logout()', () => {
|
|
it('should call _authService.logout()', () => {
|
|
spectator.component.logout();
|
|
expect(authServiceMock.logout).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('addProcess()', () => {
|
|
it('should call navigate to /kunde/{timestamp}/product', () => {
|
|
spyOn(router, 'navigate');
|
|
spyOn(Date, 'now').and.returnValue(123);
|
|
spectator.component.addProcess();
|
|
expect(router.navigate).toHaveBeenCalledWith(['/kunde', 123, 'product']);
|
|
});
|
|
});
|
|
|
|
describe('closeProcess()', () => {
|
|
it('should call _appService.removeProcess() with the processId argument', () => {
|
|
const processes = [{}, {}, {}];
|
|
applicationServiceMock.getSection$.and.returnValue(of('customer'));
|
|
applicationServiceMock.getProcesses$.and.returnValue(of(processes));
|
|
spectator.component.closeProcess(1);
|
|
expect(applicationServiceMock.removeProcess).toHaveBeenCalledWith(1);
|
|
});
|
|
|
|
it('should navigate to kunde/dashboard if no process is available', async () => {
|
|
spyOn(router, 'navigate');
|
|
applicationServiceMock.getSection$.and.returnValue(of('customer'));
|
|
applicationServiceMock.getProcesses$.and.returnValue(of([]));
|
|
spectator.detectComponentChanges();
|
|
await spectator.component.closeProcess(1);
|
|
expect(router.navigate).toHaveBeenCalledWith(['/kunde', 'dashboard']);
|
|
});
|
|
|
|
it('should not navigate to kunde/dashboard if processes are available', async () => {
|
|
spyOn(router, 'navigate');
|
|
const processes = [
|
|
{ id: 1, name: 'test', section: 'customer' },
|
|
{ id: 2, name: 'test', section: 'customer' },
|
|
];
|
|
|
|
applicationServiceMock.getLastActivatedProcessWithSection$.and.returnValue(of({}));
|
|
applicationServiceMock.getSection$.and.returnValue(of('customer'));
|
|
applicationServiceMock.getProcesses$.and.returnValue(of(processes));
|
|
await spectator.component.closeProcess(1);
|
|
expect(router.navigate).not.toHaveBeenCalledWith(['/kunde', 'dashboard']);
|
|
});
|
|
|
|
it('should activate the next process when it was not the last process', async () => {
|
|
spyOn(spectator.component, 'activateProcess');
|
|
|
|
applicationServiceMock.getLastActivatedProcessWithSection$.and.returnValue(
|
|
of({
|
|
id: 2,
|
|
name: 'test',
|
|
section: 'customer',
|
|
activated: 2,
|
|
})
|
|
);
|
|
|
|
const processes = [
|
|
{ id: 1, name: 'test', section: 'customer', activated: 1 },
|
|
{ id: 2, name: 'test', section: 'customer', activated: 2 },
|
|
];
|
|
applicationServiceMock.getSection$.and.returnValue(of('customer'));
|
|
applicationServiceMock.getProcesses$.and.returnValue(of(processes));
|
|
await spectator.component.closeProcess(1);
|
|
|
|
expect(spectator.component.activateProcess).toHaveBeenCalledWith(2);
|
|
});
|
|
});
|
|
|
|
describe('activateProcess()', () => {
|
|
it('should get the last activated breadcrumb by key and if it is defined it navigates to its path with queryParams', async () => {
|
|
const crumb = { path: '/kunde/product', params: { id: 1 } };
|
|
spyOn(router, 'navigate');
|
|
breadcrumbServiceMock.getLastActivatedBreadcrumbByKey$.and.returnValue(of(crumb));
|
|
|
|
await spectator.component.activateProcess(1);
|
|
expect(router.navigate).toHaveBeenCalledWith([crumb.path], { queryParams: crumb.params });
|
|
});
|
|
|
|
it('should navigate to /kunde if no breadcrumb for this process exists', async () => {
|
|
breadcrumbServiceMock.getLastActivatedBreadcrumbByKey$.and.returnValue(of(undefined));
|
|
spyOn(router, 'navigate');
|
|
|
|
await spectator.component.activateProcess(1);
|
|
expect(router.navigate).toHaveBeenCalledWith(['/kunde', 1, 'product']);
|
|
});
|
|
});
|
|
|
|
describe('processAction()', () => {
|
|
it('should navigate to cart when process type is cart', () => {
|
|
spyOn(router, 'navigate');
|
|
|
|
const process: ApplicationProcess = { id: 1, name: 'Vorgang', section: 'customer', type: 'cart' };
|
|
spectator.component.processAction(process);
|
|
expect(router.navigate).toHaveBeenCalledWith(['/kunde', process.id, 'cart']);
|
|
});
|
|
|
|
it('should not navigate to when process type is not cart', () => {
|
|
spyOn(router, 'navigate');
|
|
|
|
const process: ApplicationProcess = { id: 1, name: 'Vorgang', section: 'customer', type: 'goods-out' };
|
|
spectator.component.processAction(process);
|
|
expect(router.navigate).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('openNotifications()', () => {
|
|
it('should call modalService.open() with the ModalNotificationComponent', async () => {
|
|
const notifications: EnvelopeDTO<MessageBoardItemDTO[]> = {
|
|
data: [{}, {}, {}],
|
|
};
|
|
|
|
spectator.component.notifications$ = of(notifications);
|
|
|
|
await spectator.component.openNotifications();
|
|
expect(modalServiceMock.open).toHaveBeenCalledWith({
|
|
content: ModalNotificationsComponent,
|
|
data: notifications,
|
|
config: {
|
|
showScrollbarY: false,
|
|
},
|
|
});
|
|
});
|
|
});
|
|
});
|