diff --git a/alfa-client/apps/admin/src/app/app.component.spec.ts b/alfa-client/apps/admin/src/app/app.component.spec.ts index f062db31f82f5052a760630ad38da8e7e52edbf5..7789cebe72549c662115feb3c1162c5346b5e4a0 100644 --- a/alfa-client/apps/admin/src/app/app.component.spec.ts +++ b/alfa-client/apps/admin/src/app/app.component.spec.ts @@ -22,6 +22,7 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { ConfigurationLinkRel, ConfigurationResource, ConfigurationService } from '@admin-client/configuration-shared'; +import { KeycloakTokenService } from '@admin/keycloak-shared'; import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared'; import { BuildInfoComponent } from '@alfa-client/common'; import { HasLinkPipe, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; @@ -39,7 +40,6 @@ import { } from '@ods/system'; import { createConfigurationResource } from 'libs/admin/configuration-shared/test/configuration'; import { MenuContainerComponent } from 'libs/admin/configuration/src/lib/menu-container/menu-container.component'; -import { KeycloakTokenService } from 'libs/admin/shared/src/lib/keycloak/keycloak-token.service'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { MockComponent, MockDirective } from 'ng-mocks'; diff --git a/alfa-client/apps/admin/src/app/app.component.ts b/alfa-client/apps/admin/src/app/app.component.ts index 7959078d1e435db1870485a5da0430c0464fdfb1..a523590d12806227b1aad8f7b1fca8b4d0a996eb 100644 --- a/alfa-client/apps/admin/src/app/app.component.ts +++ b/alfa-client/apps/admin/src/app/app.component.ts @@ -24,6 +24,7 @@ import { MenuContainerComponent } from '@admin-client/configuration'; import { ConfigurationLinkRel, ConfigurationResource, ConfigurationService } from '@admin-client/configuration-shared'; import { ROUTES } from '@admin-client/shared'; +import { KeycloakTokenService } from '@admin/keycloak-shared'; import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared'; import { BuildInfoComponent } from '@alfa-client/common'; import { isLoaded, isNotUndefined, mapToResource, StateResource, TechSharedModule } from '@alfa-client/tech-shared'; @@ -40,7 +41,6 @@ import { UsersIconComponent, } from '@ods/system'; import { filter, Observable, Subscription } from 'rxjs'; -import { KeycloakTokenService } from '../../../../libs/admin/shared/src/lib/keycloak/keycloak-token.service'; import { UserProfileButtonContainerComponent } from '../common/user-profile-button-container/user-profile.button-container.component'; import { UnavailablePageComponent } from '../pages/unavailable/unavailable-page/unavailable-page.component'; diff --git a/alfa-client/libs/admin/keycloak-shared/.eslintrc.json b/alfa-client/libs/admin/keycloak-shared/.eslintrc.json new file mode 100644 index 0000000000000000000000000000000000000000..b10f9813a8f5c59432cf245301dc4d01a8031fd1 --- /dev/null +++ b/alfa-client/libs/admin/keycloak-shared/.eslintrc.json @@ -0,0 +1,33 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "lib", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "lib", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/alfa-client/libs/admin/keycloak-shared/README.md b/alfa-client/libs/admin/keycloak-shared/README.md new file mode 100644 index 0000000000000000000000000000000000000000..64e0f40f766db575830e3690582b8139409be0b8 --- /dev/null +++ b/alfa-client/libs/admin/keycloak-shared/README.md @@ -0,0 +1,7 @@ +# admin-keycloak + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test admin-keycloak` to execute the unit tests. diff --git a/alfa-client/libs/admin/keycloak-shared/jest.config.ts b/alfa-client/libs/admin/keycloak-shared/jest.config.ts new file mode 100644 index 0000000000000000000000000000000000000000..71e242bbaf2095da5c4bab0ce9af18f3bd7a3440 --- /dev/null +++ b/alfa-client/libs/admin/keycloak-shared/jest.config.ts @@ -0,0 +1,22 @@ +const esModules = ['@keycloak/keycloak-admin-client', 'url-join', 'url-template', 'camelize-ts']; +export default { + displayName: 'admin-keycloak-shared', + preset: '../../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + coverageDirectory: '../../../coverage/libs/admin/keycloak', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: [`node_modules/(?!.pnpm|.*\\.mjs$|${esModules.join('|')})`], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/alfa-client/libs/admin/keycloak-shared/project.json b/alfa-client/libs/admin/keycloak-shared/project.json new file mode 100644 index 0000000000000000000000000000000000000000..e3966576f9425d7599fad9a0bfb08f9fbc64697e --- /dev/null +++ b/alfa-client/libs/admin/keycloak-shared/project.json @@ -0,0 +1,20 @@ +{ + "name": "admin-keycloak-shared", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/admin/keycloak-shared/src", + "prefix": "lib", + "projectType": "library", + "tags": [], + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/admin/keycloak-shared/jest.config.ts" + } + }, + "lint": { + "executor": "@nx/eslint:lint" + } + } +} diff --git a/alfa-client/libs/admin/keycloak-shared/src/index.ts b/alfa-client/libs/admin/keycloak-shared/src/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..b0e24572b79fae2fa13d859fc348d5319e8229e1 --- /dev/null +++ b/alfa-client/libs/admin/keycloak-shared/src/index.ts @@ -0,0 +1,3 @@ +export * from './lib/keycloak-token.service'; +export * from './lib/organisations-einheit.repository'; +export * from './lib/user.repository'; diff --git a/alfa-client/libs/admin/shared/src/lib/keycloak/keycloak-token.service.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-token.service.spec.ts similarity index 100% rename from alfa-client/libs/admin/shared/src/lib/keycloak/keycloak-token.service.spec.ts rename to alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-token.service.spec.ts diff --git a/alfa-client/libs/admin/shared/src/lib/keycloak/keycloak-token.service.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-token.service.ts similarity index 100% rename from alfa-client/libs/admin/shared/src/lib/keycloak/keycloak-token.service.ts rename to alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-token.service.ts diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.repository.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts similarity index 95% rename from alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.repository.spec.ts rename to alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts index d4b38346168e17dd3db1bb9f2ed2b2df1aed6c61..001f591f358f74c4fda4ea438e40e06268c6b162 100644 --- a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.repository.spec.ts +++ b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts @@ -3,7 +3,7 @@ import { mock, Mock } from '@alfa-client/test-utils'; import { TestBed } from '@angular/core/testing'; import KcAdminClient from '@keycloak/keycloak-admin-client'; import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation'; -import { createGroupRep } from '../test/organisations-einheit'; +import { createGroupRep } from '../../../organisations-einheit-shared/src/test/organisations-einheit'; import { AdminOrganisationsEinheitRepository } from './organisations-einheit.repository'; describe('AdminOrganisationsEinheitRepository', () => { diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.repository.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.ts similarity index 100% rename from alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.repository.ts rename to alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.ts diff --git a/alfa-client/libs/admin/user-shared/src/lib/user.repository.service.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts similarity index 98% rename from alfa-client/libs/admin/user-shared/src/lib/user.repository.service.spec.ts rename to alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts index 935fab4923c9e6d069b15768930a128de7c8c640..2c58c0f784361b21e27ca915453fb5b4748f632e 100644 --- a/alfa-client/libs/admin/user-shared/src/lib/user.repository.service.spec.ts +++ b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts @@ -21,6 +21,8 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ +import { User } from '@admin-client/user-shared'; +import { UserRepository } from '@admin/keycloak-shared'; import { Mock, mock } from '@alfa-client/test-utils'; import { TestBed, fakeAsync, tick } from '@angular/core/testing'; import { faker } from '@faker-js/faker'; @@ -30,10 +32,8 @@ import MappingsRepresentation from '@keycloak/keycloak-admin-client/lib/defs/map import { RoleMappingPayload } from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation'; import { cold } from 'jest-marbles'; import { throwError } from 'rxjs'; +import { createUser } from '../../../user-shared/test/user'; import { UserAddFormservice } from '../../../user/src/lib/users-roles/user-add-form/user-add.formservice'; -import { createUser } from '../../test/user'; -import { User } from './user.model'; -import { UserRepository } from './user.repository.service'; describe('UserRepository', () => { let repository: UserRepository; diff --git a/alfa-client/libs/admin/user-shared/src/lib/user.repository.service.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts similarity index 98% rename from alfa-client/libs/admin/user-shared/src/lib/user.repository.service.ts rename to alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts index 83c95617065be3fa8ff877abea0ae014758424b5..3cc644b06842127a2d4d62a79137b13a4957b22e 100644 --- a/alfa-client/libs/admin/user-shared/src/lib/user.repository.service.ts +++ b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts @@ -21,6 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ +import { ClientMapping, ClientRoles, User } from '@admin-client/user-shared'; import { inject, Injectable } from '@angular/core'; import KcAdminClient from '@keycloak/keycloak-admin-client'; import ClientRepresentation from '@keycloak/keycloak-admin-client/lib/defs/clientRepresentation'; @@ -30,7 +31,6 @@ import RoleRepresentation, { RoleMappingPayload } from '@keycloak/keycloak-admin import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation'; import { isNil } from 'lodash-es'; import { catchError, concatMap, forkJoin, from, map, mergeMap, Observable, switchMap, tap, throwError } from 'rxjs'; -import { ClientMapping, ClientRoles, User } from './user.model'; @Injectable({ providedIn: 'root', diff --git a/alfa-client/libs/admin/keycloak-shared/src/test-setup.ts b/alfa-client/libs/admin/keycloak-shared/src/test-setup.ts new file mode 100644 index 0000000000000000000000000000000000000000..c408668266d2fec3a9803c0ec044bc163fb987fe --- /dev/null +++ b/alfa-client/libs/admin/keycloak-shared/src/test-setup.ts @@ -0,0 +1,12 @@ +import '@testing-library/jest-dom'; +import 'jest-preset-angular/setup-jest'; + +import { getTestBed } from '@angular/core/testing'; +import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; + +getTestBed().resetTestEnvironment(); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/admin/keycloak-shared/tsconfig.json b/alfa-client/libs/admin/keycloak-shared/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..8ca9ad312c2bd4dc364383853ddd91a2ed8f86fd --- /dev/null +++ b/alfa-client/libs/admin/keycloak-shared/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2022" + } +} diff --git a/alfa-client/libs/admin/keycloak-shared/tsconfig.lib.json b/alfa-client/libs/admin/keycloak-shared/tsconfig.lib.json new file mode 100644 index 0000000000000000000000000000000000000000..8441346f6e5858b2ef4235cb3c3160eda256f94a --- /dev/null +++ b/alfa-client/libs/admin/keycloak-shared/tsconfig.lib.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": ["src/**/*.spec.ts", "src/test-setup.ts", "jest.config.ts", "src/**/*.test.ts"], + "include": ["src/**/*.ts"] +} diff --git a/alfa-client/libs/admin/keycloak-shared/tsconfig.spec.json b/alfa-client/libs/admin/keycloak-shared/tsconfig.spec.json new file mode 100644 index 0000000000000000000000000000000000000000..723782fbd367969806c5992aea882773ab65af8b --- /dev/null +++ b/alfa-client/libs/admin/keycloak-shared/tsconfig.spec.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] +} diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.spec.ts b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.spec.ts index e1c23ad8873eda2ab82b28c8168ad8c0b575d16d..26aba0d2639fa0d8a0f629cf31ac1cd598b1e5bb 100644 --- a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.spec.ts +++ b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.spec.ts @@ -22,10 +22,10 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { AdminOrganisationsEinheit, AdminOrganisationsEinheitService } from '@admin-client/organisations-einheit-shared'; +import { AdminOrganisationsEinheitRepository } from '@admin/keycloak-shared'; import { Mock, mock } from '@alfa-client/test-utils'; import { TestBed } from '@angular/core/testing'; import { createAdminOrganisationsEinheit } from '../test/organisations-einheit'; -import { AdminOrganisationsEinheitRepository } from './organisations-einheit.repository'; describe('AdminOrganisationsEinheitService', () => { let service: AdminOrganisationsEinheitService; @@ -43,7 +43,7 @@ describe('AdminOrganisationsEinheitService', () => { describe('getItemsFromKeycloak', () => { it('should call repository getList', () => { - service.getItemsFromKeycloak(); + (service as any).getItemsFromKeycloak(); expect(repository.getList).toHaveBeenCalled(); }); }); @@ -51,7 +51,7 @@ describe('AdminOrganisationsEinheitService', () => { describe('createInKeycloak', () => { const organisationsEiheit: AdminOrganisationsEinheit = createAdminOrganisationsEinheit(); it('should call repository create', () => { - service.createInKeycloak(organisationsEiheit); + (service as any).createInKeycloak(organisationsEiheit); expect(repository.create).toHaveBeenCalledWith(organisationsEiheit); }); }); diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.ts b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.ts index 0c6bacf0c2c4baad9e971df9ccb5afec13a2dcba..ad2e0009e9a52c4a8970a4cdbe3f5b53cfe1d175 100644 --- a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.ts +++ b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.ts @@ -21,34 +21,31 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Injectable } from '@angular/core'; +import { AdminOrganisationsEinheitRepository } from '@admin/keycloak-shared'; +import { inject, Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { KeycloakResourceService } from '../../../user-shared/src/lib/keycloak.resource.service'; import { AdminOrganisationsEinheit } from './organisations-einheit.model'; -import { AdminOrganisationsEinheitRepository } from './organisations-einheit.repository'; @Injectable({ providedIn: 'root', }) export class AdminOrganisationsEinheitService extends KeycloakResourceService<AdminOrganisationsEinheit> { - //todo: test inject - constructor(private repository: AdminOrganisationsEinheitRepository) { - super(); - } + private readonly repository = inject(AdminOrganisationsEinheitRepository); - getItemsFromKeycloak(): Observable<AdminOrganisationsEinheit[]> { + protected getItemsFromKeycloak(): Observable<AdminOrganisationsEinheit[]> { return this.repository.getList(); } - createInKeycloak(organisationsEinheit: AdminOrganisationsEinheit): Observable<AdminOrganisationsEinheit> { + protected createInKeycloak(organisationsEinheit: AdminOrganisationsEinheit): Observable<AdminOrganisationsEinheit> { return this.repository.create(organisationsEinheit); } - saveInKeycloak(organisationsEinheit: AdminOrganisationsEinheit): Observable<void> { + protected saveInKeycloak(organisationsEinheit: AdminOrganisationsEinheit): Observable<void> { throw new Error('Method not implemented.'); } - deleteInKeycloak(id: string): Observable<void> { + protected deleteInKeycloak(id: string): Observable<void> { throw new Error('Method not implemented.'); } } diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts index 51cfb933dad24881ca93c4f50ca0f7722b1c90a3..aa95754e2879568e6f4c893a2b59615b6aa06ecf 100644 --- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts +++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts @@ -132,7 +132,7 @@ describe('OrganisationsEinheitContainerComponent', () => { it('should have organisationsEinheitResources', () => { const listComponent: OrganisationsEinheitListComponent = getMockComponent(fixture, OrganisationsEinheitListComponent); - expect(listComponent.organisationsEinheitListResource).toBeTruthy(); + expect(listComponent.organisationsEinheitList).toBeTruthy(); }); }); }); diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.html b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.html index 04f00bf619eff4e2eb832fc04ddac06b7b2a184a..2b55de16de82452e9f9baacdee1754ee356df7a8 100644 --- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.html +++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.html @@ -23,9 +23,9 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ods-list *ngIf="!isNil(organisationsEinheitListResource)" data-test-id="organisations-einheit-list"> +<ods-list *ngIf="!isNil(organisationsEinheitList)" data-test-id="organisations-einheit-list"> <ods-list-item - *ngFor="let organisationsEinheitResource of organisationsEinheitListResource" + *ngFor="let organisationsEinheitResource of organisationsEinheitList" data-test-id="organisations-einheit-list-item" > <dl class="flex-1 basis-3/4 font-semibold"> @@ -34,3 +34,4 @@ </dl> </ods-list-item> </ods-list> +ssda \ No newline at end of file diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.spec.ts b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.spec.ts index 7277b7aa52f9cfe72de727860ef905479679b69e..d80a3a54260b1f838767e1b54d127bfbad4106ff 100644 --- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.spec.ts +++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.spec.ts @@ -81,7 +81,7 @@ describe('OrganisationsEinheitListComponent', () => { createAdminOrganisationsEinheit(), ]; beforeEach(() => { - component.organisationsEinheitListResource = organisationsEinheiten; + component.organisationsEinheitList = organisationsEinheiten; fixture.detectChanges(); }); diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.ts b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.ts index 58d5a086bb989c8c28fb6075f4ff3568d25393dc..377768cc350898e054bd533113aa7e832e40a2d6 100644 --- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.ts +++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.ts @@ -35,7 +35,7 @@ import { isNil } from 'lodash-es'; imports: [CommonModule, ListComponent, ListItemComponent, ExclamationIconComponent, TooltipDirective, TechSharedModule], }) export class OrganisationsEinheitListComponent { - @Input() public organisationsEinheitListResource: AdminOrganisationsEinheit[]; + @Input() public organisationsEinheitList: AdminOrganisationsEinheit[]; protected readonly isNil = isNil; } diff --git a/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.spec.ts b/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.spec.ts index 228f1b0cfaec928f6c70ec566b92d5ae3250eb25..9855a20ebefe86e37ea51815ca5470249fd9c562 100644 --- a/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.spec.ts +++ b/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.spec.ts @@ -87,7 +87,7 @@ describe('KeycloakResourceService', () => { it('should update Resource', fakeAsync(() => { const dummyItems = [createDummy(), createDummy()]; - service.getItemsFromKeycloak = jest.fn().mockReturnValue(of(dummyItems)); + jest.spyOn(service, 'getItemsFromKeycloak' as any).mockReturnValue(of(dummyItems)); service.loadResource(); tick(); @@ -108,11 +108,11 @@ describe('KeycloakResourceService', () => { }); it('should call createInKeycloak', () => { - service.createInKeycloak = jest.fn().mockReturnValue(of({})); + const createInKeycloakSpy: jest.SpyInstance = jest.spyOn(service, 'createInKeycloak' as any).mockReturnValue(of({})); service.create(saveObject); - expect(service.createInKeycloak).toHaveBeenCalled(); + expect(createInKeycloakSpy).toHaveBeenCalled(); }); }); @@ -126,11 +126,11 @@ describe('KeycloakResourceService', () => { }); it('should call createInKeycloak', () => { - service.saveInKeycloak = jest.fn().mockReturnValue(of({})); + const saveInKeycloakSpy: jest.SpyInstance = jest.spyOn(service, 'saveInKeycloak' as any).mockReturnValue(of({})); service.save(dummyObject); - expect(service.saveInKeycloak).toHaveBeenCalled(); + expect(saveInKeycloakSpy).toHaveBeenCalled(); }); }); @@ -144,11 +144,11 @@ describe('KeycloakResourceService', () => { }); it('should call createInKeycloak', () => { - service.saveInKeycloak = jest.fn().mockReturnValue(of({})); + const saveInKeycloakSpy: jest.SpyInstance = jest.spyOn(service, 'saveInKeycloak' as any).mockReturnValue(of({})); service.save(id); - expect(service.saveInKeycloak).toHaveBeenCalled(); + expect(saveInKeycloakSpy).toHaveBeenCalled(); }); }); diff --git a/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.ts b/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.ts index b1fa837255e8816649e149ff2bbb60c4d5e97b7a..9dc055b4bc0d1084a6209ccff6cc0b3ceece14b0 100644 --- a/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.ts +++ b/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.ts @@ -43,7 +43,7 @@ export abstract class KeycloakResourceService<T> { .subscribe((items) => this.updateResource(items)); } - abstract getItemsFromKeycloak(): Observable<T[]>; + protected abstract getItemsFromKeycloak(): Observable<T[]>; private updateResource(items: T[]): void { this.stateResource.next(createStateResource(items)); @@ -53,19 +53,19 @@ export abstract class KeycloakResourceService<T> { return this.handleLoading(this.createInKeycloak(item)); } - abstract createInKeycloak(item: Partial<T>): Observable<T>; + protected abstract createInKeycloak(item: Partial<T>): Observable<T>; public save(item: T): Observable<boolean> { return this.handleLoading(this.saveInKeycloak(item)); } - abstract saveInKeycloak(item: T): Observable<void>; + protected abstract saveInKeycloak(item: T): Observable<void>; public delete(id: string): Observable<boolean> { return this.handleLoading(this.deleteInKeycloak(id)); } - abstract deleteInKeycloak(id: string): Observable<void>; + protected abstract deleteInKeycloak(id: string): Observable<void>; handleLoading(action: Observable<unknown>): Observable<boolean> { this.setLoading(); diff --git a/alfa-client/libs/admin/user-shared/src/lib/user.service.spec.ts b/alfa-client/libs/admin/user-shared/src/lib/user.service.spec.ts index c1148ee01e76d476ddf204eafee43060a936ad38..4769d32ed5c7629d3dc157426e8b581afedc346e 100644 --- a/alfa-client/libs/admin/user-shared/src/lib/user.service.spec.ts +++ b/alfa-client/libs/admin/user-shared/src/lib/user.service.spec.ts @@ -21,12 +21,12 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { mock, Mock, useFromMock } from '@alfa-client/test-utils'; -import { fakeAsync, tick } from '@angular/core/testing'; +import { UserRepository } from '@admin/keycloak-shared'; +import { mock, Mock } from '@alfa-client/test-utils'; +import { fakeAsync, TestBed, tick } from '@angular/core/testing'; import { of } from 'rxjs'; import { createUser } from '../../test/user'; import { User } from './user.model'; -import { UserRepository } from './user.repository.service'; import { UserService } from './user.service'; import * as UserUtil from './user.util'; @@ -38,12 +38,15 @@ describe('UserService', () => { beforeEach(() => { repository = { ...mock(UserRepository), getUsers: jest.fn().mockReturnValue(of([user])) }; - service = new UserService(useFromMock(repository)); + TestBed.configureTestingModule({ + providers: [{ provide: UserRepository, useValue: repository }], + }); + service = TestBed.inject(UserService); }); describe('getItemsFromKeycloak', () => { it('should call getUsers from userRepository', () => { - service.getItemsFromKeycloak(); + (service as any).getItemsFromKeycloak(); expect(repository.getUsers).toHaveBeenCalled(); }); @@ -51,7 +54,7 @@ describe('UserService', () => { it('should call sortUsersByLastName', fakeAsync(() => { const sortUsersByLastNameSpy: jest.SpyInstance<User[]> = jest.spyOn(UserUtil, 'sortUsersByLastName'); - service.getItemsFromKeycloak().subscribe(); + (service as any).getItemsFromKeycloak().subscribe(); tick(); expect(sortUsersByLastNameSpy).toHaveBeenCalled(); @@ -62,7 +65,7 @@ describe('UserService', () => { const user: User = createUser(); it('should call createInKeycloak from userRepository', () => { - service.createInKeycloak(user); + (service as any).createInKeycloak(user); expect(repository.createInKeycloak).toHaveBeenCalledWith(user); }); diff --git a/alfa-client/libs/admin/user-shared/src/lib/user.service.ts b/alfa-client/libs/admin/user-shared/src/lib/user.service.ts index 9cbe06b6009eb72145d4c3447940bd30f39fb7d3..76ef2e216284522871b00c7715f7cb1f8997ba43 100644 --- a/alfa-client/libs/admin/user-shared/src/lib/user.service.ts +++ b/alfa-client/libs/admin/user-shared/src/lib/user.service.ts @@ -21,35 +21,32 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Injectable } from '@angular/core'; +import { UserRepository } from '@admin/keycloak-shared'; +import { inject, Injectable } from '@angular/core'; import { map, Observable } from 'rxjs'; import { KeycloakResourceService } from './keycloak.resource.service'; import { User } from './user.model'; -import { UserRepository } from './user.repository.service'; import { sortUsersByLastName } from './user.util'; @Injectable({ providedIn: 'root', }) export class UserService extends KeycloakResourceService<User> { - // todo: test inject - constructor(private userRepository: UserRepository) { - super(); - } + private readonly userRepository = inject(UserRepository); - getItemsFromKeycloak(): Observable<User[]> { + protected getItemsFromKeycloak(): Observable<User[]> { return this.userRepository.getUsers().pipe(map(sortUsersByLastName)); } - createInKeycloak(user: Partial<User>): Observable<User> { + protected createInKeycloak(user: Partial<User>): Observable<User> { return this.userRepository.createInKeycloak(user); } - saveInKeycloak(user: User): Observable<void> { + protected saveInKeycloak(user: User): Observable<void> { throw new Error('Method not implemented.'); } - deleteInKeycloak(id: string): Observable<void> { + protected deleteInKeycloak(id: string): Observable<void> { throw new Error('Method not implemented.'); } } diff --git a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.spec.ts b/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.spec.ts index 93b68bb79ea62249b7864cd63bc3f5d706e0dfcf..f347f2a1a63692a3225c5824c19f2476af9855ef 100644 --- a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.spec.ts +++ b/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.spec.ts @@ -31,7 +31,6 @@ import { fakeAsync, TestBed, tick } from '@angular/core/testing'; import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { cold } from 'jest-marbles'; import { createUser } from 'libs/admin/user-shared/test/user'; -import { singleCold } from 'libs/tech-shared/test/marbles'; import { of, throwError } from 'rxjs'; import { UserAddFormservice } from './user-add.formservice'; import SpyInstance = jest.SpyInstance; @@ -47,7 +46,7 @@ describe('UserAddFormService', () => { let snackBarService: Mock<SnackBarService>; beforeEach(() => { - userService = { ...mock(UserService), refresh: jest.fn() }; + userService = { ...mock(UserService), refresh: jest.fn(), create: jest.fn() }; navigationService = mock(NavigationService); snackBarService = mock(SnackBarService); @@ -181,7 +180,7 @@ describe('UserAddFormService', () => { const user: User = createUser(); beforeEach(() => { - userService.createInKeycloak.mockReturnValue(of(user)); + userService.create.mockReturnValue(of(false)); }); it('should call createUser', () => { @@ -192,26 +191,30 @@ describe('UserAddFormService', () => { expect(createUserSpy).toHaveBeenCalled(); }); - it('should call userService createInKeycloak', () => { + it('should call userService create', () => { + jest.spyOn(formService as any, 'createUser').mockReturnValue(user); + formService.submit(); - expect(userService.createInKeycloak).toHaveBeenCalled(); + expect(userService.create).toHaveBeenCalledWith(user); }); - it('should return user as stateResource', fakeAsync(() => { - userService.createInKeycloak.mockReturnValue(singleCold(user, '-a')); + it('should return user as stateResource', () => { + userService.create.mockReturnValue(cold('-ab', { a: true, b: false })); + jest.spyOn(formService as any, 'createUser').mockReturnValue(user); const result = formService.submit(); expect(result).toBeObservable( - cold('ab', { + cold('abc', { a: createEmptyStateResource<User>(true), - b: createStateResource(user), + b: createStateResource(user, true), + c: createStateResource(user, false), }), ); - })); + }); - it('should call handleOnCreateUserSuccess', fakeAsync(() => { + it('should call handleOnCreateUserSuccess if not loading', fakeAsync(() => { const handleOnCreateUserSuccessSpy: SpyInstance = jest.spyOn(formService, 'handleOnCreateUserSuccess'); formService.submit().subscribe(); @@ -220,8 +223,18 @@ describe('UserAddFormService', () => { expect(handleOnCreateUserSuccessSpy).toHaveBeenCalled(); })); + it('should not call handleOnCreateUserSuccess if loading', fakeAsync(() => { + userService.create.mockReturnValue(of(true)); + const handleOnCreateUserSuccessSpy: SpyInstance = jest.spyOn(formService, 'handleOnCreateUserSuccess'); + + formService.submit().subscribe(); + tick(); + + expect(handleOnCreateUserSuccessSpy).not.toHaveBeenCalled(); + })); + it('should call handleSubmitError on error', fakeAsync(() => { - userService.createInKeycloak.mockReturnValue(throwError(() => new Error())); + userService.create.mockReturnValue(throwError(() => new Error())); const handleSubmitErrorSpy: SpyInstance = jest.spyOn(formService, 'handleSubmitError'); formService.submit().subscribe(); @@ -243,12 +256,6 @@ describe('UserAddFormService', () => { expect(navigationService.navigate).toHaveBeenCalledWith(ROUTES.BENUTZER_UND_ROLLEN); }); - - it('should refresh userList', () => { - formService.handleOnCreateUserSuccess(); - - expect(userService.refresh).toHaveBeenCalled(); - }); }); describe('handleSubmitError', () => { diff --git a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.ts b/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.ts index 5a6769f495ca2e04048c715bd878959a94486395..dd10a07fb294fc452d893af76750d33c5e7c4efc 100644 --- a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.ts +++ b/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.ts @@ -147,19 +147,22 @@ export class UserAddFormservice extends AbstractFormService<User> { } protected doSubmit(): Observable<StateResource<User>> { - const user: Partial<User> = this.createUser(); - return this.userService.createInKeycloak(user).pipe( - map((createdUser: User): StateResource<User> => createStateResource(createdUser)), - tap(() => this.handleOnCreateUserSuccess()), + const user: User = this.createUser(); + return this.userService.create(user).pipe( + tap((loading: boolean): void => this.executeIfNotLoading(loading, () => this.handleOnCreateUserSuccess())), + map((loading: boolean): StateResource<User> => createStateResource<User>(user, loading)), catchError((): Observable<StateResource<User>> => this.handleSubmitError()), startWith(createEmptyStateResource<User>(true)), ); } + private executeIfNotLoading(loading: boolean, func: () => void): void { + if (!loading) func(); + } + handleOnCreateUserSuccess(): void { this.snackBarService.showInfo('Der Benutzer wurde hinzugefügt.'); this.navigationService.navigate(ROUTES.BENUTZER_UND_ROLLEN); - this.userService.refresh(); } handleSubmitError(): Observable<StateResource<User>> { @@ -167,8 +170,9 @@ export class UserAddFormservice extends AbstractFormService<User> { return of(createEmptyStateResource<User>()); } - createUser(): Partial<User> { + createUser(): User { return { + id: EMPTY_STRING, email: this.form.get(UserAddFormservice.EMAIL).value, username: this.form.get(UserAddFormservice.BENUTZERNAME).value, firstName: this.form.get(UserAddFormservice.VORNAME).value, diff --git a/alfa-client/tsconfig.base.json b/alfa-client/tsconfig.base.json index 2014ad63b1ebdbf8c2b31b7259bcc0d77011dd4b..645b71e1ced60632f86bbe1484b8d0ba45b27c84 100644 --- a/alfa-client/tsconfig.base.json +++ b/alfa-client/tsconfig.base.json @@ -18,6 +18,7 @@ "paths": { "@admin-client/configuration": ["libs/admin/configuration/src/index.ts"], "@admin-client/configuration-shared": ["libs/admin/configuration-shared/src/index.ts"], + "@admin/keycloak-shared": ["libs/admin/keycloak-shared/src/index.ts"], "@admin-client/organisations-einheit": ["libs/admin/organisations-einheit/src/index.ts"], "@admin-client/organisations-einheit-shared": ["libs/admin/organisations-einheit-shared/src/index.ts"], "@admin-client/postfach": ["libs/admin/postfach/src/index.ts"], @@ -76,7 +77,7 @@ "@alfa-client/zustaendige-stelle-shared": ["libs/zustaendige-stelle-shared/src/index.ts"], "@authentication": ["libs/authentication/src/index.ts"], "@ods/component": ["libs/design-component/src/index.ts"], - "@ods/system": ["libs/design-system/src/index.ts"] + "@ods/system": ["libs/design-system/src/index.ts"], } }, "exclude": ["node_modules", "tmp"]