mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Unit Tests for ShellSideMenuComponent
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<button
|
||||
type="button"
|
||||
(click)="createProcess()"
|
||||
class="hidden w-full py-[0.625rem] start-process-btn desktop:grid grid-flow-row items-center justify-center"
|
||||
class="create-process-btn hidden w-full py-[0.625rem] start-process-btn desktop:grid grid-flow-row items-center justify-center"
|
||||
>
|
||||
<div class="bg-brand text-white w-[2.375rem] h-[2.375rem] rounded-full grid items-center justify-center mx-auto mb-1">
|
||||
<ui-svg-icon icon="add"></ui-svg-icon>
|
||||
@@ -12,7 +12,10 @@
|
||||
</button>
|
||||
</div>
|
||||
<ng-container [ngSwitch]="section$ | async">
|
||||
<nav class="grid grid-flow-row gap-6 side-menu-nav desktop:mt-6 max-h-[calc(100vh-30.625rem)]" *ngSwitchCase="'customer'">
|
||||
<nav
|
||||
class="customer-section grid grid-flow-row gap-6 side-menu-nav desktop:mt-6 max-h-[calc(100vh-30.625rem)]"
|
||||
*ngSwitchCase="'customer'"
|
||||
>
|
||||
<a class="side-menu-nav-item" (click)="closeSideMenu()" [routerLink]="[customerBasePath$ | async, 'product']">
|
||||
<div class="side-menu-nav-item-icon">
|
||||
<ui-svg-icon icon="import-contacts"></ui-svg-icon>
|
||||
@@ -43,7 +46,10 @@
|
||||
<span class="side-menu-nav-item-name">Kundenbestellung</span>
|
||||
</a>
|
||||
</nav>
|
||||
<nav class="grid grid-flow-row gap-6 side-menu-nav desktop:mt-6 max-h-[calc(100vh-30.625rem)] overflow-y-auto" *ngSwitchCase="'branch'">
|
||||
<nav
|
||||
class="branch-section grid grid-flow-row gap-6 side-menu-nav desktop:mt-6 max-h-[calc(100vh-30.625rem)] overflow-y-auto"
|
||||
*ngSwitchCase="'branch'"
|
||||
>
|
||||
<a class="side-menu-nav-item" (click)="closeSideMenu()" [routerLink]="['/filiale', 'assortment']">
|
||||
<div class="side-menu-nav-item-icon">
|
||||
<ui-svg-icon icon="shape-outline"></ui-svg-icon>
|
||||
@@ -83,7 +89,7 @@
|
||||
</ng-container>
|
||||
<div class="grow"></div>
|
||||
<hr class="divider" />
|
||||
<button type="button" class="side-menu-processes" (click)="closeAllProcesses()">
|
||||
<button type="button" class="side-menu-processes close-all-processes-btn" (click)="closeAllProcesses()">
|
||||
<div class="side-menu-processes-open mx-auto mb-1">
|
||||
<span class="isa-label customer:bg-accent-1 branch:bg-accent-2 text-accent-1-content">
|
||||
{{ processesCount$ | async }}
|
||||
@@ -97,13 +103,13 @@
|
||||
</div>
|
||||
<div class="bg-surface panel rounded-tr-[5px]">
|
||||
<nav class="grid grid-flow-row gap-2 py-2 side-bottom-menu">
|
||||
<a class="side-bottom-menu-item" (click)="closeSideMenu()" [routerLink]="['/kunde', 'dashboard']">
|
||||
<a class="dashboard-btn side-bottom-menu-item" (click)="closeSideMenu()" [routerLink]="['/kunde', 'dashboard']">
|
||||
<div class="side-bottom-menu-item-icon">
|
||||
<ui-svg-icon icon="receipt-long"></ui-svg-icon>
|
||||
</div>
|
||||
<span class="side-menu-nav-item-name">Dashboard</span>
|
||||
</a>
|
||||
<button class="side-bottom-menu-item" (click)="logout()">
|
||||
<button class="logout-btn side-bottom-menu-item" (click)="logout()">
|
||||
<div class="side-bottom-menu-item-icon">
|
||||
<ui-svg-icon icon="logout"></ui-svg-icon>
|
||||
</div>
|
||||
|
||||
237
apps/shared/shell/src/lib/side-menu/side-menu.component.spec.ts
Normal file
237
apps/shared/shell/src/lib/side-menu/side-menu.component.spec.ts
Normal file
@@ -0,0 +1,237 @@
|
||||
import { Spectator, createComponentFactory } from '@ngneat/spectator';
|
||||
import { ShellSideMenuComponent } from './side-menu.component';
|
||||
import { ShellService } from '../shell.service';
|
||||
import { AuthService } from '@core/auth';
|
||||
import { StockService } from '@swagger/wws';
|
||||
import { ApplicationProcess, ApplicationService } from '@core/application';
|
||||
import { WrongDestinationModalService } from '@shared/modals/wrong-destination-modal';
|
||||
import { of } from 'rxjs';
|
||||
import { IfRoleDirective } from 'apps/core/auth/src/lib/if-role.directive';
|
||||
import { MockComponents, MockDirectives } from 'ng-mocks';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { UISvgIconComponent, UiIconComponent } from '@ui/icon';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
fdescribe('ShellSideMenuComponent', () => {
|
||||
let spectator: Spectator<ShellSideMenuComponent>;
|
||||
const createComponent = createComponentFactory({
|
||||
component: ShellSideMenuComponent,
|
||||
imports: [RouterTestingModule],
|
||||
mocks: [ShellService, AuthService, WrongDestinationModalService],
|
||||
declarations: [MockDirectives(IfRoleDirective), MockComponents(UISvgIconComponent, UiIconComponent, UISvgIconComponent)],
|
||||
providers: [
|
||||
{
|
||||
provide: ApplicationService,
|
||||
useValue: jasmine.createSpyObj<ApplicationService>(
|
||||
'ApplicationService',
|
||||
{
|
||||
getSection$: of('customer'),
|
||||
getProcesses$: of([]),
|
||||
getProcessById$: of(undefined),
|
||||
createProcess: Promise.resolve(),
|
||||
removeProcess: undefined,
|
||||
},
|
||||
{ activatedProcessId$: of(undefined) }
|
||||
),
|
||||
},
|
||||
{
|
||||
provide: StockService,
|
||||
useValue: jasmine.createSpyObj(StockService, {
|
||||
StockCurrentBranch: of({ result: { key: 'test' } }),
|
||||
}),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
spectator = createComponent();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(spectator.component).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('closeSideMenu()', () => {
|
||||
it('should call shellService.closeSideMenu', () => {
|
||||
const shellService = spectator.inject(ShellService);
|
||||
spectator.component.closeSideMenu();
|
||||
expect(shellService.closeSideMenu).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('logout()', () => {
|
||||
it('should call authService.logout', () => {
|
||||
const authService = spectator.inject(AuthService);
|
||||
spectator.component.logout();
|
||||
expect(authService.logout).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('createProcess()', () => {
|
||||
it('should call this.createCartProcess and this.navigateToCatalog with the created process', async () => {
|
||||
const process: ApplicationProcess = { id: 1, name: '', section: 'customer' };
|
||||
const spy = spyOn(spectator.component, 'createCartProcess').and.returnValue(Promise.resolve(process));
|
||||
const spy2 = spyOn(spectator.component, 'navigateToCatalog');
|
||||
await spectator.component.createProcess();
|
||||
expect(spy).toHaveBeenCalled();
|
||||
expect(spy2).toHaveBeenCalledWith(process);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createCartProcess()', () => {
|
||||
it('should create a new process and return it', async () => {
|
||||
const applicationService = spectator.inject(ApplicationService);
|
||||
spyOn(spectator.component, 'getNextProcessName').and.returnValue(Promise.resolve('Vorgang 3'));
|
||||
spyOn(spectator.component, 'getNextProcessId').and.returnValue(123);
|
||||
|
||||
const expected: ApplicationProcess = {
|
||||
id: 123,
|
||||
name: 'Vorgang 3',
|
||||
section: 'customer',
|
||||
type: 'cart',
|
||||
closeable: true,
|
||||
};
|
||||
|
||||
const result = await spectator.component.createCartProcess();
|
||||
|
||||
expect(applicationService.createProcess).toHaveBeenCalledWith(expected);
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getNextProcessName()', () => {
|
||||
it('should return the next process name by getting all "customer" processes and filter by type "cart" and name starting with "Vorgang " returns the next higher number', async () => {
|
||||
const applicationService = spectator.inject(ApplicationService);
|
||||
(applicationService.getProcesses$ as jasmine.Spy).and.returnValue(
|
||||
of([
|
||||
{ id: 1, name: 'Vorgang 1', section: 'customer', type: 'cart' },
|
||||
{ id: 2, name: 'Vorgang 2', section: 'customer', type: 'cart' },
|
||||
{ id: 3, name: 'Vorgang 3', section: 'customer', type: 'cart' },
|
||||
{ id: 4, name: 'Unit Test', section: 'customer', type: 'cart' },
|
||||
])
|
||||
);
|
||||
const result = await spectator.component.getNextProcessName();
|
||||
expect(result).toEqual('Vorgang 4');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getNextProcessId()', () => {
|
||||
it('should return the next process id using Date.now()', () => {
|
||||
const result = spectator.component.getNextProcessId();
|
||||
expect(result).toEqual(Date.now());
|
||||
});
|
||||
});
|
||||
|
||||
describe('navigateToCatalog(process: ApplicationProcess)', () => {
|
||||
it('should call Router.navigate with ["/kunde", <process.id>, "product", "search"]', () => {
|
||||
const router = spectator.inject(Router);
|
||||
const process: ApplicationProcess = { id: 1, name: '', section: 'customer' };
|
||||
const spy = spyOn(router, 'navigate');
|
||||
spectator.component.navigateToCatalog(process);
|
||||
expect(spy).toHaveBeenCalledWith(['/kunde', 1, 'product', 'search']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('navigateToDashboard()', () => {
|
||||
it('should call Router.navigate with ["/kunde", "dashboard"]', () => {
|
||||
const router = spectator.inject(Router);
|
||||
const spy = spyOn(router, 'navigate');
|
||||
spectator.component.navigateToDashboard();
|
||||
expect(spy).toHaveBeenCalledWith(['/kunde', 'dashboard']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('closeAllProcesses()', () => {
|
||||
it('should get processes$ and iterate over them and call applicationService.removeProcess with the process id ', async () => {
|
||||
const applicationService = spectator.inject(ApplicationService);
|
||||
spectator.component.processes$ = of([
|
||||
{ id: 1, name: 'Vorgang 1', section: 'customer', type: 'cart' },
|
||||
{ id: 2, name: 'Vorgang 2', section: 'customer', type: 'cart' },
|
||||
{ id: 3, name: 'Vorgang 3', section: 'customer', type: 'cart' },
|
||||
{ id: 4, name: 'Unit Test', section: 'customer', type: 'cart' },
|
||||
]);
|
||||
|
||||
spyOn(spectator.component, 'navigateToDashboard');
|
||||
|
||||
await spectator.component.closeAllProcesses();
|
||||
expect(applicationService.removeProcess).toHaveBeenCalledWith(1);
|
||||
expect(applicationService.removeProcess).toHaveBeenCalledWith(2);
|
||||
expect(applicationService.removeProcess).toHaveBeenCalledWith(3);
|
||||
expect(applicationService.removeProcess).toHaveBeenCalledWith(4);
|
||||
|
||||
expect(spectator.component.navigateToDashboard).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchAndOpenPackages()', () => {
|
||||
it('shuld call WrongDestinationModalService.fetchAndOpen()', () => {
|
||||
const wrongDestinationModalService = spectator.inject(WrongDestinationModalService);
|
||||
spectator.component.fetchAndOpenPackages();
|
||||
expect(wrongDestinationModalService.fetchAndOpen).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('template', () => {
|
||||
describe('.create-process-btn should call createProcess()', () => {
|
||||
it('should call createProcess()', () => {
|
||||
const spy = spyOn(spectator.component, 'createProcess');
|
||||
spectator.click('.create-process-btn');
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('nav.customer-section', () => {
|
||||
it('should render a nav.customer-section when section$ returns "customer"', () => {
|
||||
spectator.setInput({ section$: of('customer') });
|
||||
expect(spectator.query('nav.customer-section')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not render a nav.customer-section when section$ returns "branch"', () => {
|
||||
spectator.setInput({ section$: of('branch') });
|
||||
expect(spectator.query('nav.customer-section')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('nav.branch-section', () => {
|
||||
it('should render a nav.branch-section when section$ returns "branch"', () => {
|
||||
spectator.setInput({ section$: of('branch') });
|
||||
expect(spectator.query('nav.branch-section')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not render a nav.branch-section when section$ returns "customer"', () => {
|
||||
spectator.setInput({ section$: of('customer') });
|
||||
expect(spectator.query('nav.branch-section')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('.close-all-processes-btn', () => {
|
||||
it('should call closeAllProcesses() when clicked', () => {
|
||||
const spy = spyOn(spectator.component, 'closeAllProcesses');
|
||||
spectator.click('.close-all-processes-btn');
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should render the process count', () => {
|
||||
spectator.component.processesCount$ = of<any>(3);
|
||||
spectator.detectComponentChanges();
|
||||
expect(spectator.query('.close-all-processes-btn .isa-label').textContent).toContain('3');
|
||||
});
|
||||
});
|
||||
|
||||
describe('.dashboard-btn', () => {
|
||||
it('should call closeSideMenu() when clicked', () => {
|
||||
const spy = spyOn(spectator.component, 'closeSideMenu');
|
||||
spectator.click('.dashboard-btn');
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('.logout-btn', () => {
|
||||
it('should call logout() when clicked', () => {
|
||||
const spy = spyOn(spectator.component, 'logout');
|
||||
spectator.click('.logout-btn');
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -19,12 +19,12 @@ export class ShellSideMenuComponent {
|
||||
map((x) => x.result.key)
|
||||
);
|
||||
|
||||
processes$ = this._app.getSection$().pipe(switchMap((section) => this._app.getProcesses$(section)));
|
||||
section$ = this._app.getSection$();
|
||||
|
||||
processes$ = this.section$.pipe(switchMap((section) => this._app.getProcesses$(section)));
|
||||
|
||||
processesCount$ = this.processes$.pipe(map((processes) => processes?.length ?? 0));
|
||||
|
||||
section$ = this._app.getSection$();
|
||||
|
||||
activeProcess$ = this._app.activatedProcessId$.pipe(switchMap((processId) => this._app.getProcessById$(processId)));
|
||||
|
||||
customerBasePath$ = this.activeProcess$.pipe(
|
||||
@@ -62,14 +62,12 @@ export class ShellSideMenuComponent {
|
||||
}
|
||||
|
||||
async createCartProcess() {
|
||||
const processes = await this._app.getProcesses$('customer').pipe(first()).toPromise();
|
||||
|
||||
const count = processes.filter((x) => x.type === 'cart' && x.name.startsWith('Vorgang ')).length;
|
||||
const nextProcessName = await this.getNextProcessName();
|
||||
|
||||
const process: ApplicationProcess = {
|
||||
id: Date.now(),
|
||||
id: this.getNextProcessId(),
|
||||
type: 'cart',
|
||||
name: `Vorgang ${count + 1}`,
|
||||
name: nextProcessName,
|
||||
section: 'customer',
|
||||
closeable: true,
|
||||
};
|
||||
@@ -79,6 +77,23 @@ export class ShellSideMenuComponent {
|
||||
return process;
|
||||
}
|
||||
|
||||
async getNextProcessName() {
|
||||
let processes = await this._app.getProcesses$('customer').pipe(first()).toPromise();
|
||||
|
||||
processes = processes.filter((x) => x.type === 'cart' && x.name.startsWith('Vorgang '));
|
||||
|
||||
const maxProcessNumber = processes.reduce((max, process) => {
|
||||
const number = parseInt(process.name.replace('Vorgang ', ''), 10);
|
||||
return number > max ? number : max;
|
||||
}, 0);
|
||||
|
||||
return `Vorgang ${maxProcessNumber + 1}`;
|
||||
}
|
||||
|
||||
getNextProcessId() {
|
||||
return Date.now();
|
||||
}
|
||||
|
||||
navigateToCatalog(process: ApplicationProcess) {
|
||||
this._router.navigate(['/kunde', process.id, 'product', 'search']);
|
||||
}
|
||||
@@ -88,9 +103,9 @@ export class ShellSideMenuComponent {
|
||||
}
|
||||
|
||||
async closeAllProcesses() {
|
||||
const section = await this._app.getSection$().pipe(take(1)).toPromise();
|
||||
const processes = await this._app.getProcesses$(section).pipe(take(1)).toPromise();
|
||||
processes.filter((f) => f.closeable).forEach((process) => this._app.removeProcess(process.id));
|
||||
const processes = await this.processes$.pipe(take(1)).toPromise();
|
||||
|
||||
processes.forEach((process) => this._app.removeProcess(process.id));
|
||||
|
||||
this.navigateToDashboard();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user