Skip to content
Snippets Groups Projects
Verified Commit af93218a authored by Sebastian Bergandy's avatar Sebastian Bergandy :keyboard:
Browse files

Merge branch 'main' into OZG-7507-admin-organisationsEinheit-loeschen

# Conflicts:
#	alfa-client/libs/design-component/src/lib/open-dialog-button/open-dialog-button.component.spec.ts
#	alfa-client/libs/design-component/src/lib/open-dialog-button/open-dialog-button.component.ts
parents a915b3b2 0f98194e
Branches
Tags
1 merge request!82OZG-7507 use new open dialog button
Showing
with 208 additions and 81 deletions
...@@ -24,14 +24,20 @@ ...@@ -24,14 +24,20 @@
import 'cypress-real-events'; import 'cypress-real-events';
import { convertToDataTestId } from '../../support/tech-util'; import { convertToDataTestId } from '../../support/tech-util';
//TODO BenutzerListPage erstellen welche den Button und die Liste enthaelt.
export class BenutzerListE2EComponent { export class BenutzerListE2EComponent {
private readonly headline: string = 'user-list-headline'; private readonly headline: string = 'user-list-headline';
private readonly list: string = 'user-list';
private readonly benutzerHinzufuegenButton: string = 'add-user-button'; private readonly benutzerHinzufuegenButton: string = 'add-user-button';
public getHeadline(): Cypress.Chainable<Element> { public getHeadline(): Cypress.Chainable<Element> {
return cy.getTestElement(this.headline); return cy.getTestElement(this.headline);
} }
public getList(): Cypress.Chainable<Element> {
return cy.getTestElement(this.list);
}
public getHinzufuegenButton(): Cypress.Chainable<Element> { public getHinzufuegenButton(): Cypress.Chainable<Element> {
return cy.getTestElement(this.benutzerHinzufuegenButton); return cy.getTestElement(this.benutzerHinzufuegenButton);
} }
...@@ -98,10 +104,16 @@ export class BenutzerE2EComponent { ...@@ -98,10 +104,16 @@ export class BenutzerE2EComponent {
private readonly loeschenCheckbox: string = 'Loschen-checkbox-editor'; private readonly loeschenCheckbox: string = 'Loschen-checkbox-editor';
private readonly userCheckbox: string = 'User-checkbox-editor'; private readonly userCheckbox: string = 'User-checkbox-editor';
private readonly postCheckbox: string = 'Poststelle-checkbox-editor'; private readonly postCheckbox: string = 'Poststelle-checkbox-editor';
private readonly datenbeauftragungCheckbox: string = 'Datenbeauftragung-checkbox-editor';
private readonly organisationsEinheitCheckboxSuffix: string = '-checkbox-editor'; private readonly organisationsEinheitCheckboxSuffix: string = '-checkbox-editor';
private readonly saveButton: string = 'save-button'; private readonly saveButton: string = 'save-button';
private readonly deleteButton: string = 'delete-button';
public getHeadline(): Cypress.Chainable<Element> {
return cy.getTestElement(this.headline);
}
public getVornameInput(): Cypress.Chainable<Element> { public getVornameInput(): Cypress.Chainable<Element> {
return cy.getTestElement(this.userVorname); return cy.getTestElement(this.userVorname);
...@@ -135,15 +147,32 @@ export class BenutzerE2EComponent { ...@@ -135,15 +147,32 @@ export class BenutzerE2EComponent {
return cy.getTestElement(this.postCheckbox); return cy.getTestElement(this.postCheckbox);
} }
public getSaveButton(): Cypress.Chainable<Element> { public getDatenbeauftragungCheckbox(): Cypress.Chainable<Element> {
return cy.getTestElement(this.saveButton); return cy.getTestElement(this.datenbeauftragungCheckbox);
} }
public getOrganisationsEinheitCheckbox(einheit: string): Cypress.Chainable<Element> { public getOrganisationsEinheitCheckbox(einheit: string): Cypress.Chainable<Element> {
return cy.getTestElement(einheit + this.organisationsEinheitCheckboxSuffix); return cy.getTestElement(einheit + this.organisationsEinheitCheckboxSuffix);
} }
public getHeadline(): Cypress.Chainable<Element> { public getSaveButton(): Cypress.Chainable<Element> {
return cy.getTestElement(this.headline); return cy.getTestElement(this.saveButton);
}
public getDeleteButton(): Cypress.Chainable<Element> {
return cy.getTestElement(this.deleteButton);
}
}
export class BenutzerDeleteDialogE2EComponent {
private readonly deleteButton: string = 'dialog-delete';
private readonly cancelButton: string = 'cancel-dialog';
public getCancelButton(): Cypress.Chainable<Element> {
return cy.getTestElement(this.cancelButton);
}
public getDeleteButton(): Cypress.Chainable<Element> {
return cy.getTestElement(this.deleteButton);
} }
} }
import { faker } from '@faker-js/faker';
import { E2EBenutzerHelper } from 'apps/admin-e2e/src/helper/benutzer/benutzer.helper';
import { E2EBenutzerVerifier } from 'apps/admin-e2e/src/helper/benutzer/benutzer.verifier';
import { AdminUserE2E } from 'apps/admin-e2e/src/model/util';
import { loginAsAriane } from 'apps/admin-e2e/src/support/user-util';
describe('Benutzer Löschen', () => {
const benutzerVerifier: E2EBenutzerVerifier = new E2EBenutzerVerifier();
const benutzerHelper: E2EBenutzerHelper = new E2EBenutzerHelper();
const userName: string = 'testtheo' + faker.string.uuid();
const user: AdminUserE2E = {
vorname: 'Theo',
nachname: 'Testuser',
username: userName,
email: 'theo' + faker.string.uuid() + '@ozg-sh.de',
isUser: true,
organisationseinheiten: [],
};
before(() => {
loginAsAriane();
});
it('should delete user', () => {
benutzerHelper.openNewBenutzerPage();
benutzerHelper.addBenutzerAndSave(user);
benutzerHelper.deleteBenutzer(userName);
benutzerVerifier.verifyUserNotInList(userName);
});
});
import { BenutzerE2EComponent } from '../../components/benutzer/benutzer.e2e.component'; import {
BenutzerDeleteDialogE2EComponent,
BenutzerE2EComponent,
BenutzerListE2EComponent,
} from '../../components/benutzer/benutzer.e2e.component';
import { SnackBarE2EComponent } from '../../components/ui/snackbar.e2e.component'; import { SnackBarE2EComponent } from '../../components/ui/snackbar.e2e.component';
import { OrganisationsEinheitE2E } from '../../model/organisations-einheit'; import { OrganisationsEinheitE2E } from '../../model/organisations-einheit';
import { AdminUserE2E } from '../../model/util'; import { AdminUserE2E } from '../../model/util';
...@@ -7,6 +11,8 @@ import { exist, notExist } from '../../support/cypress.util'; ...@@ -7,6 +11,8 @@ import { exist, notExist } from '../../support/cypress.util';
export class E2EBenutzerExecutor { export class E2EBenutzerExecutor {
private benutzerPage: BenutzerE2EComponent = new BenutzerE2EComponent(); private benutzerPage: BenutzerE2EComponent = new BenutzerE2EComponent();
private snackBar: SnackBarE2EComponent = new SnackBarE2EComponent(); private snackBar: SnackBarE2EComponent = new SnackBarE2EComponent();
private benutzerDeleteDialog: BenutzerDeleteDialogE2EComponent = new BenutzerDeleteDialogE2EComponent();
private benutzerListPage: BenutzerListE2EComponent = new BenutzerListE2EComponent();
public modifyBenutzer(user: AdminUserE2E): void { public modifyBenutzer(user: AdminUserE2E): void {
this.benutzerPage.getVornameInput().type(user.vorname); this.benutzerPage.getVornameInput().type(user.vorname);
...@@ -39,9 +45,17 @@ export class E2EBenutzerExecutor { ...@@ -39,9 +45,17 @@ export class E2EBenutzerExecutor {
exist(this.snackBar.getMessage()); exist(this.snackBar.getMessage());
this.snackBar.getCloseButton().click(); this.snackBar.getCloseButton().click();
notExist(this.snackBar.getMessage()); notExist(this.snackBar.getMessage());
exist(this.benutzerListPage.getList());
} }
public saveBenutzer(): void { public saveBenutzer(): void {
this.benutzerPage.getSaveButton().click(); this.benutzerPage.getSaveButton().click();
} }
public deleteBenutzer(): void {
this.benutzerPage.getDeleteButton().click();
exist(this.benutzerDeleteDialog.getDeleteButton());
this.benutzerDeleteDialog.getDeleteButton().click();
exist(this.benutzerListPage.getList());
}
} }
...@@ -17,32 +17,45 @@ export class E2EBenutzerHelper { ...@@ -17,32 +17,45 @@ export class E2EBenutzerHelper {
public addBenutzerAndSave(user: AdminUserE2E): void { public addBenutzerAndSave(user: AdminUserE2E): void {
this.addBenutzer(user); this.addBenutzer(user);
this.executer.saveAndCloseSnackbar(); this.saveAndCloseSnackbar();
} }
public addBenutzer(user: AdminUserE2E): void { public addBenutzer(user: AdminUserE2E): void {
this.executer.modifyBenutzer(user); this.modifyBenutzer(user);
}
public openBenutzerPage(userName: string): void {
this.navigator.openBenutzerPage(userName);
} }
public editBenutzerAndSave(user: AdminUserE2E): void { public editBenutzerAndSave(user: AdminUserE2E): void {
this.editBenutzer(user); this.editBenutzer(user);
this.executer.saveAndCloseSnackbar(); this.saveAndCloseSnackbar();
} }
public editBenutzer(user: AdminUserE2E): void { public editBenutzer(user: AdminUserE2E): void {
this.modifyBenutzer(user);
}
private modifyBenutzer(user: AdminUserE2E): void {
this.executer.modifyBenutzer(user); this.executer.modifyBenutzer(user);
} }
public editOrganisationsEinheitenAndSave(organisationsEinheiten: OrganisationsEinheitE2E[]): void { public editOrganisationsEinheitenAndSave(organisationsEinheiten: OrganisationsEinheitE2E[]): void {
this.executer.modifyOrganisationsEinheiten(organisationsEinheiten); this.executer.modifyOrganisationsEinheiten(organisationsEinheiten);
this.saveAndCloseSnackbar();
}
private saveAndCloseSnackbar(): void {
this.executer.saveAndCloseSnackbar(); this.executer.saveAndCloseSnackbar();
} }
public saveBenutzer(): void { public saveBenutzer(): void {
this.executer.saveBenutzer(); this.executer.saveBenutzer();
} }
public deleteBenutzer(userName: string): void {
this.openBenutzerPage(userName);
this.executer.deleteBenutzer();
}
public openBenutzerPage(userName: string): void {
this.navigator.openBenutzerPage(userName);
}
} }
...@@ -4,7 +4,7 @@ import { ...@@ -4,7 +4,7 @@ import {
BenutzerListItemE2EComponent, BenutzerListItemE2EComponent,
} from '../../components/benutzer/benutzer.e2e.component'; } from '../../components/benutzer/benutzer.e2e.component';
import { AdminUserE2E } from '../../model/util'; import { AdminUserE2E } from '../../model/util';
import { contains, exist } from '../../support/cypress.util'; import { contains, exist, notExist } from '../../support/cypress.util';
import { AlfaRollen } from '../../support/user-util'; import { AlfaRollen } from '../../support/user-util';
export class E2EBenutzerVerifier { export class E2EBenutzerVerifier {
...@@ -41,6 +41,10 @@ export class E2EBenutzerVerifier { ...@@ -41,6 +41,10 @@ export class E2EBenutzerVerifier {
if (user.isAdmin) contains(benutzer.getRoles(), AlfaRollen.ADMIN); if (user.isAdmin) contains(benutzer.getRoles(), AlfaRollen.ADMIN);
} }
public verifyUserNotInList(userName: string): void {
notExist(this.getBenutzerItem(userName).getRoot());
}
private getBenutzerItem(userName: string): BenutzerListItemE2EComponent { private getBenutzerItem(userName: string): BenutzerListItemE2EComponent {
return this.benutzerListPage.getItem(userName); return this.benutzerListPage.getItem(userName);
} }
......
...@@ -49,15 +49,16 @@ describe('KeycloakResourceService', () => { ...@@ -49,15 +49,16 @@ describe('KeycloakResourceService', () => {
}); });
describe('getAll', () => { describe('getAll', () => {
const stateResource: StateResource<unknown> = createStateResource([]);
beforeEach(() => { beforeEach(() => {
service.handleChanges = jest.fn(); service.handleChanges = jest.fn().mockReturnValue(singleCold(stateResource));
}); });
it('should return stateResource as observable', (done) => { it('should return stateResource', () => {
service.getAll().subscribe((stateResource) => { const stateResource$: Observable<StateResource<unknown[]>> = service.getAll();
expect(stateResource).toBe(service.stateResource.value);
done(); expect(stateResource$).toBeObservable(singleCold(stateResource));
});
}); });
it('should call handleChanges ', fakeAsync(() => { it('should call handleChanges ', fakeAsync(() => {
...@@ -68,12 +69,25 @@ describe('KeycloakResourceService', () => { ...@@ -68,12 +69,25 @@ describe('KeycloakResourceService', () => {
}); });
describe('handleChanges', () => { describe('handleChanges', () => {
it('should call doIfLoadingRequired', () => { let doIfLoadingRequiredSpy: jest.SpyInstance<boolean>;
const doIfLoadingRequired: jest.SpyInstance<boolean> = jest.spyOn(ResourceUtil, 'doIfLoadingRequired');
beforeEach(() => {
doIfLoadingRequiredSpy = jest.spyOn(ResourceUtil, 'doIfLoadingRequired').mockImplementation();
});
it('should call doIfLoadingRequired', () => {
service.handleChanges(emptyStateResource); service.handleChanges(emptyStateResource);
expect(doIfLoadingRequired).toHaveBeenCalled(); expect(doIfLoadingRequiredSpy).toHaveBeenCalled();
});
it('should return stateResource', (done) => {
service.stateResource.next(createStateResource([]));
service.handleChanges(emptyStateResource).subscribe((stateResource: StateResource<[]>) => {
expect(stateResource).toEqual(createStateResource([]));
done();
});
}); });
}); });
......
...@@ -22,22 +22,20 @@ ...@@ -22,22 +22,20 @@
* unter der Lizenz sind dem Lizenztext zu entnehmen. * unter der Lizenz sind dem Lizenztext zu entnehmen.
*/ */
import { createEmptyStateResource, createStateResource, doIfLoadingRequired, StateResource } from '@alfa-client/tech-shared'; import { createEmptyStateResource, createStateResource, doIfLoadingRequired, StateResource } from '@alfa-client/tech-shared';
import { BehaviorSubject, first, map, Observable, startWith, tap } from 'rxjs'; import { BehaviorSubject, first, map, Observable, startWith, switchMap, tap } from 'rxjs';
export abstract class KeycloakResourceService<T> { export abstract class KeycloakResourceService<T> {
readonly stateResource: BehaviorSubject<StateResource<T[]>> = new BehaviorSubject({ readonly stateResource: BehaviorSubject<StateResource<T[]>> = new BehaviorSubject(createEmptyStateResource());
...createStateResource<T[]>([]),
loaded: false,
});
public getAll(): Observable<StateResource<T[]>> { public getAll(): Observable<StateResource<T[]>> {
return this.stateResource return this.stateResource
.asObservable() .asObservable()
.pipe(tap((stateResource: StateResource<T[]>): void => this.handleChanges(stateResource))); .pipe(switchMap((stateResource: StateResource<T[]>) => this.handleChanges(stateResource)));
} }
handleChanges(stateResource: StateResource<T[]>): void { handleChanges(stateResource: StateResource<T[]>): Observable<StateResource<T[]>> {
doIfLoadingRequired(stateResource, (): void => this.loadResource()); doIfLoadingRequired(stateResource, (): void => this.loadResource());
return this.stateResource.asObservable();
} }
loadResource(): void { loadResource(): void {
......
...@@ -26,8 +26,13 @@ import { ROUTES } from '@admin-client/shared'; ...@@ -26,8 +26,13 @@ import { ROUTES } from '@admin-client/shared';
import { User, UserService } from '@admin-client/user-shared'; import { User, UserService } from '@admin-client/user-shared';
import { PatchConfig } from '@admin/keycloak-shared'; import { PatchConfig } from '@admin/keycloak-shared';
import { NavigationService } from '@alfa-client/navigation-shared'; import { NavigationService } from '@alfa-client/navigation-shared';
import { createEmptyStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared'; import {
import { Mock, mock } from '@alfa-client/test-utils'; createEmptyStateResource,
createLoadingStateResource,
createStateResource,
StateResource,
} from '@alfa-client/tech-shared';
import { Mock, mock, mockWindowError } from '@alfa-client/test-utils';
import { SnackBarService } from '@alfa-client/ui'; import { SnackBarService } from '@alfa-client/ui';
import { fakeAsync, TestBed, tick } from '@angular/core/testing'; import { fakeAsync, TestBed, tick } from '@angular/core/testing';
import { AbstractControl, FormControl, FormGroup, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { AbstractControl, FormControl, FormGroup, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
...@@ -159,7 +164,13 @@ describe('UserFormService', () => { ...@@ -159,7 +164,13 @@ describe('UserFormService', () => {
}); });
describe('initOrganisationsEinheiten', () => { describe('initOrganisationsEinheiten', () => {
beforeEach(() => {
formService._addOrganisationsEinheitenToForm = jest.fn();
});
it('should call adminOrganisationsEinheitService getAll', () => { it('should call adminOrganisationsEinheitService getAll', () => {
formService._initOrganisationsEinheiten();
expect(adminOrganisationsEinheitService.getAll).toHaveBeenCalled(); expect(adminOrganisationsEinheitService.getAll).toHaveBeenCalled();
}); });
...@@ -170,8 +181,6 @@ describe('UserFormService', () => { ...@@ -170,8 +181,6 @@ describe('UserFormService', () => {
}); });
it('should call addOrganisationsEinheitenToForm ', fakeAsync(() => { it('should call addOrganisationsEinheitenToForm ', fakeAsync(() => {
formService._addOrganisationsEinheitenToForm = jest.fn();
formService._initOrganisationsEinheiten().subscribe(); formService._initOrganisationsEinheiten().subscribe();
tick(); tick();
...@@ -189,6 +198,15 @@ describe('UserFormService', () => { ...@@ -189,6 +198,15 @@ describe('UserFormService', () => {
it('should set initOrganisationsEinheiten$', () => { it('should set initOrganisationsEinheiten$', () => {
expect(formService['_initOrganisationsEinheiten$']).toBeDefined(); expect(formService['_initOrganisationsEinheiten$']).toBeDefined();
}); });
it('should not throw any exception on loading state resource', () => {
adminOrganisationsEinheitService.getAll.mockReturnValue(of(createLoadingStateResource()));
const errorMock: any = mockWindowError();
formService._initOrganisationsEinheiten();
expect(errorMock).not.toHaveBeenCalled();
});
}); });
describe('addOrganisationsEinheitenToForm', () => { describe('addOrganisationsEinheitenToForm', () => {
......
...@@ -26,7 +26,7 @@ import { ROUTES } from '@admin-client/shared'; ...@@ -26,7 +26,7 @@ import { ROUTES } from '@admin-client/shared';
import { User, UserService } from '@admin-client/user-shared'; import { User, UserService } from '@admin-client/user-shared';
import { KeycloakFormService, PatchConfig } from '@admin/keycloak-shared'; import { KeycloakFormService, PatchConfig } from '@admin/keycloak-shared';
import { NavigationService } from '@alfa-client/navigation-shared'; import { NavigationService } from '@alfa-client/navigation-shared';
import { createEmptyStateResource, EMPTY_STRING, mapToResource, StateResource } from '@alfa-client/tech-shared'; import { createEmptyStateResource, EMPTY_STRING, isLoaded, mapToResource, StateResource } from '@alfa-client/tech-shared';
import { SnackBarService } from '@alfa-client/ui'; import { SnackBarService } from '@alfa-client/ui';
import { Injectable, OnDestroy } from '@angular/core'; import { Injectable, OnDestroy } from '@angular/core';
import { import {
...@@ -39,7 +39,7 @@ import { ...@@ -39,7 +39,7 @@ import {
Validators, Validators,
} from '@angular/forms'; } from '@angular/forms';
import { UrlSegment } from '@angular/router'; import { UrlSegment } from '@angular/router';
import { catchError, Observable, of, Subscription, tap } from 'rxjs'; import { catchError, filter, Observable, of, Subscription, tap } from 'rxjs';
@Injectable() @Injectable()
export class UserFormService extends KeycloakFormService<User> implements OnDestroy { export class UserFormService extends KeycloakFormService<User> implements OnDestroy {
...@@ -137,6 +137,7 @@ export class UserFormService extends KeycloakFormService<User> implements OnDest ...@@ -137,6 +137,7 @@ export class UserFormService extends KeycloakFormService<User> implements OnDest
_initOrganisationsEinheiten(): Observable<AdminOrganisationsEinheit[]> { _initOrganisationsEinheiten(): Observable<AdminOrganisationsEinheit[]> {
const organisationsEinheitenGroup: UntypedFormGroup = this.getOrganisationsEinheitenGroup(); const organisationsEinheitenGroup: UntypedFormGroup = this.getOrganisationsEinheitenGroup();
return this.adminOrganisationsEinheitService.getAll().pipe( return this.adminOrganisationsEinheitService.getAll().pipe(
filter(isLoaded),
mapToResource<AdminOrganisationsEinheit[]>(), mapToResource<AdminOrganisationsEinheit[]>(),
tap((organisationsEinheiten: AdminOrganisationsEinheit[]): void => { tap((organisationsEinheiten: AdminOrganisationsEinheit[]): void => {
this.setOrganisationsEinheitenIdsInMap(organisationsEinheiten); this.setOrganisationsEinheitenIdsInMap(organisationsEinheiten);
......
...@@ -20,6 +20,7 @@ describe('UserListContainerComponent', () => { ...@@ -20,6 +20,7 @@ describe('UserListContainerComponent', () => {
userService = { userService = {
...mock(UserService), ...mock(UserService),
getAll: jest.fn().mockReturnValue(usersStateResource$), getAll: jest.fn().mockReturnValue(usersStateResource$),
refresh: jest.fn(),
}; };
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
...@@ -55,4 +56,12 @@ describe('UserListContainerComponent', () => { ...@@ -55,4 +56,12 @@ describe('UserListContainerComponent', () => {
expect(userList.usersStateResource).toBe(usersStateResource); expect(userList.usersStateResource).toBe(usersStateResource);
}); });
}); });
describe('on destroy', () => {
it('should call service to refresh list', () => {
component.ngOnDestroy();
expect(userService.refresh).toHaveBeenCalled();
});
});
}); });
import { User, UserService } from '@admin-client/user-shared'; import { User, UserService } from '@admin-client/user-shared';
import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared'; import { StateResource } from '@alfa-client/tech-shared';
import { AsyncPipe } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { Component, inject, OnInit } from '@angular/core'; import { Component, inject, OnDestroy, OnInit } from '@angular/core';
import { Observable, of } from 'rxjs'; import { Observable } from 'rxjs';
import { UserListComponent } from './user-list/user-list.component'; import { UserListComponent } from './user-list/user-list.component';
@Component({ @Component({
...@@ -11,12 +11,16 @@ import { UserListComponent } from './user-list/user-list.component'; ...@@ -11,12 +11,16 @@ import { UserListComponent } from './user-list/user-list.component';
imports: [UserListComponent, AsyncPipe], imports: [UserListComponent, AsyncPipe],
templateUrl: './user-list-container.component.html', templateUrl: './user-list-container.component.html',
}) })
export class UserListContainerComponent implements OnInit { export class UserListContainerComponent implements OnInit, OnDestroy {
private userService = inject(UserService); private userService = inject(UserService);
public usersStateResource$: Observable<StateResource<User[]>> = of(createEmptyStateResource<User[]>()); public usersStateResource$: Observable<StateResource<User[]>>;
ngOnInit(): void { ngOnInit(): void {
this.usersStateResource$ = this.userService.getAll(); this.usersStateResource$ = this.userService.getAll();
} }
ngOnDestroy(): void {
this.userService.refresh();
}
} }
...@@ -25,8 +25,10 @@ ...@@ -25,8 +25,10 @@
--> -->
<h1 class="heading-1 mb-4" data-test-id="user-list-headline">Benutzer & Rollen</h1> <h1 class="heading-1 mb-4" data-test-id="user-list-headline">Benutzer & Rollen</h1>
<ods-routing-button [linkPath]="ROUTES.BENUTZER_NEU" text="Benutzer hinzufügen" class="mb-4 w-fit" dataTestId="add-user-button" /> <ods-routing-button [linkPath]="ROUTES.BENUTZER_NEU" text="Benutzer hinzufügen" class="mb-4 w-fit" dataTestId="add-user-button" />
<ods-list> <ods-spinner [stateResource]="usersStateResource">
<ods-list data-test-id="user-list">
@for (user of usersStateResource.resource; track $index) { @for (user of usersStateResource.resource; track $index) {
<admin-user [user]="user" class="block w-full" /> <admin-user [user]="user" class="block w-full" />
} }
</ods-list> </ods-list>
</ods-spinner>
...@@ -26,7 +26,7 @@ import { User } from '@admin-client/user-shared'; ...@@ -26,7 +26,7 @@ import { User } from '@admin-client/user-shared';
import { createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; import { createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared';
import { getMockComponent } from '@alfa-client/test-utils'; import { getMockComponent } from '@alfa-client/test-utils';
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RoutingButtonComponent } from '@ods/component'; import { RoutingButtonComponent, SpinnerComponent } from '@ods/component';
import { MockComponent } from 'ng-mocks'; import { MockComponent } from 'ng-mocks';
import { createUser } from '../../../../../user-shared/test/user'; import { createUser } from '../../../../../user-shared/test/user';
import { UserListComponent } from './user-list.component'; import { UserListComponent } from './user-list.component';
...@@ -38,8 +38,10 @@ describe('UsersListComponent', () => { ...@@ -38,8 +38,10 @@ describe('UsersListComponent', () => {
beforeEach(async () => { beforeEach(async () => {
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [UserListComponent], imports: [
declarations: [MockComponent(RoutingButtonComponent), MockComponent(UserComponent)], UserListComponent,
[MockComponent(RoutingButtonComponent), MockComponent(UserComponent), MockComponent(SpinnerComponent)],
],
}).compileComponents(); }).compileComponents();
fixture = TestBed.createComponent(UserListComponent); fixture = TestBed.createComponent(UserListComponent);
......
...@@ -26,7 +26,7 @@ import { User } from '@admin-client/user-shared'; ...@@ -26,7 +26,7 @@ import { User } from '@admin-client/user-shared';
import { StateResource } from '@alfa-client/tech-shared'; import { StateResource } from '@alfa-client/tech-shared';
import { AsyncPipe } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';
import { ButtonWithSpinnerComponent, RoutingButtonComponent } from '@ods/component'; import { ButtonWithSpinnerComponent, RoutingButtonComponent, SpinnerComponent } from '@ods/component';
import { ListComponent, ListItemComponent } from '@ods/system'; import { ListComponent, ListItemComponent } from '@ods/system';
import { UserComponent } from './user/user.component'; import { UserComponent } from './user/user.component';
...@@ -34,7 +34,15 @@ import { UserComponent } from './user/user.component'; ...@@ -34,7 +34,15 @@ import { UserComponent } from './user/user.component';
selector: 'admin-user-list', selector: 'admin-user-list',
templateUrl: './user-list.component.html', templateUrl: './user-list.component.html',
standalone: true, standalone: true,
imports: [ButtonWithSpinnerComponent, ListComponent, UserComponent, AsyncPipe, ListItemComponent, RoutingButtonComponent], imports: [
ButtonWithSpinnerComponent,
ListComponent,
UserComponent,
AsyncPipe,
ListItemComponent,
RoutingButtonComponent,
SpinnerComponent,
],
}) })
export class UserListComponent { export class UserListComponent {
@Input() usersStateResource: StateResource<User[]>; @Input() usersStateResource: StateResource<User[]>;
......
import { OzgCloudComponentFactory } from '@alfa-client/tech-shared'; import { OzgCloudComponentFactory } from '@alfa-client/tech-shared';
import { import { dispatchEventFromFixture, Mock, mock, MockEvent, mockGetValue } from '@alfa-client/test-utils';
createdClosedDialogRefMock,
dispatchEventFromFixture,
Mock,
mock,
MockEvent,
mockGetValue,
} from '@alfa-client/test-utils';
import { DIALOG_COMPONENT, OzgcloudDialogService } from '@alfa-client/ui'; import { DIALOG_COMPONENT, OzgcloudDialogService } from '@alfa-client/ui';
import { DIALOG_DATA } from '@angular/cdk/dialog'; import { DIALOG_DATA } from '@angular/cdk/dialog';
import { ComponentType } from '@angular/cdk/portal'; import { ComponentType } from '@angular/cdk/portal';
...@@ -96,21 +89,6 @@ describe('OpenDialogButtonComponent', () => { ...@@ -96,21 +89,6 @@ describe('OpenDialogButtonComponent', () => {
}); });
}); });
describe('open', () => {
beforeEach(() => {
component._createComponent = jest.fn().mockReturnValue(componentRef);
});
it('should emit close emitter on dialog close', () => {
component.close.emit = jest.fn();
dialogService.openInContext.mockReturnValue(createdClosedDialogRefMock());
component.open();
expect(component.close.emit).toHaveBeenCalled();
});
});
describe('create component', () => { describe('create component', () => {
it('should call component factory to create component', () => { it('should call component factory to create component', () => {
component.dialogData = dummyDialogData; component.dialogData = dummyDialogData;
......
...@@ -2,9 +2,8 @@ import { OzgCloudComponentFactory } from '@alfa-client/tech-shared'; ...@@ -2,9 +2,8 @@ import { OzgCloudComponentFactory } from '@alfa-client/tech-shared';
import { DIALOG_COMPONENT, OzgcloudDialogService } from '@alfa-client/ui'; import { DIALOG_COMPONENT, OzgcloudDialogService } from '@alfa-client/ui';
import { DIALOG_DATA } from '@angular/cdk/dialog'; import { DIALOG_DATA } from '@angular/cdk/dialog';
import { ComponentType } from '@angular/cdk/portal'; import { ComponentType } from '@angular/cdk/portal';
import { Component, ComponentRef, EventEmitter, inject, Injector, Input, Output, ViewContainerRef } from '@angular/core'; import { Component, ComponentRef, inject, Injector, Input, ViewContainerRef } from '@angular/core';
import { ButtonComponent, ButtonVariants } from '@ods/system'; import { ButtonComponent, ButtonVariants } from '@ods/system';
import { first } from 'rxjs';
@Component({ @Component({
selector: 'ods-open-dialog-button', selector: 'ods-open-dialog-button',
...@@ -38,13 +37,8 @@ export class OpenDialogButtonComponent { ...@@ -38,13 +37,8 @@ export class OpenDialogButtonComponent {
@Input() dialogData: any; @Input() dialogData: any;
@Input() size: ButtonVariants['size']; @Input() size: ButtonVariants['size'];
@Output() close: EventEmitter<void> = new EventEmitter();
public open(): void { public open(): void {
this.dialogService this.dialogService.openInContext(this._createComponent().instance.constructor, this.viewContainerRef);
.openInContext(this._createComponent().instance.constructor, this.viewContainerRef, this.dialogData)
.closed.pipe(first())
.subscribe(() => this.close.emit());
} }
_createComponent(): ComponentRef<any> { _createComponent(): ComponentRef<any> {
......
...@@ -53,3 +53,9 @@ export function mockGetValue(object: any, name: string, returnValue: any): void ...@@ -53,3 +53,9 @@ export function mockGetValue(object: any, name: string, returnValue: any): void
get: jest.fn(() => returnValue), get: jest.fn(() => returnValue),
}); });
} }
export function mockWindowError(): any {
const errorHandler = jest.fn();
window.onerror = errorHandler;
return errorHandler;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment