Skip to content
Snippets Groups Projects
user.repository.spec.ts 11.3 KiB
Newer Older
  • Learn to ignore specific revisions
  • OZGCloud's avatar
    OZGCloud committed
    import { Mock, mock } from '@alfa-client/test-utils';
    
    OZGCloud's avatar
    OZGCloud committed
    import { TestBed, fakeAsync, tick } from '@angular/core/testing';
    
    OZGCloud's avatar
    OZGCloud committed
    import { faker } from '@faker-js/faker';
    
    import KcAdminClient, { NetworkError } from '@keycloak/keycloak-admin-client';
    
    OZGCloud's avatar
    OZGCloud committed
    import { TokenProvider } from '@keycloak/keycloak-admin-client/lib/client';
    import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation';
    import { Groups } from '@keycloak/keycloak-admin-client/lib/resources/groups';
    import { OAuthService } from 'angular-oauth2-oidc';
    
    OZGCloud's avatar
    OZGCloud committed
    import { Observable, OperatorFunction, catchError, firstValueFrom, of, throwError } from 'rxjs';
    
    import {
      createGroupRepresentation,
      createNetworkError,
    
      createOrganisationseinheit,
    
      createOrganisationseinheitError,
    
    } from '../../../test/user/user';
    
    import {
      Organisationseinheit,
      OrganisationseinheitError,
      OrganisationseinheitErrorType,
    } from './user.model';
    
    OZGCloud's avatar
    OZGCloud committed
    import { UserRepository } from './user.repository.service';
    
    describe('UserRepository', () => {
    
      const accessToken: string = faker.random.alphaNumeric(40);
    
      const error: OrganisationseinheitError = createOrganisationseinheitError();
    
      const networkError: NetworkError = createNetworkError(400, '');
    
    
      let repository: UserRepository;
    
      let kcAdminClient: Mock<KcAdminClient>;
    
      let oAuthService: Mock<OAuthService>;
    
      const mockGroupsFunc = (groupsKey: keyof Groups, implementation: jest.Mock) => {
        kcAdminClient.groups = <any>{
          [groupsKey]: implementation,
        };
      };
    
    
        kcAdminClient = mock(KcAdminClient);
    
        oAuthService = mock(OAuthService);
    
        TestBed.configureTestingModule({
          providers: [
    
            { provide: OAuthService, useValue: oAuthService },
    
            { provide: KcAdminClient, useValue: kcAdminClient },
    
        oAuthService.getAccessToken.mockReturnValue(accessToken);
    
        repository = TestBed.inject(UserRepository);
    
      });
    
      it('should be created', () => {
        expect(repository).toBeTruthy();
      });
    
      describe('registerTokenProvider', () => {
        it('should register token provider from oauth service', async () => {
          const tokenProvider: TokenProvider = kcAdminClient.registerTokenProvider.mock.calls[0][0];
          const token: string = await tokenProvider.getAccessToken();
          expect(token).toEqual(accessToken);
        });
    
      describe('map organisationseinheit representation', () => {
    
        let expectedOrganisationseinheit: Organisationseinheit = createOrganisationseinheit();
    
        it('should map field "id"', () => {
    
          const organisationseinheit: Organisationseinheit =
            repository.mapGroupRepresentationToOrganisationseinheit({
              id: expectedOrganisationseinheit.id,
            });
    
          expect(organisationseinheit.id).toEqual(expectedOrganisationseinheit.id);
    
        });
    
        it('should map field "name"', () => {
    
          const organisationseinheit: Organisationseinheit =
    
            repository.mapGroupRepresentationToOrganisationseinheit({
    
              name: expectedOrganisationseinheit.name,
    
          expect(organisationseinheit.name).toEqual(expectedOrganisationseinheit.name);
    
        });
    
        it('should map field "organisationseinheitIds"', () => {
    
          const organisationseinheit: Organisationseinheit =
    
            repository.mapGroupRepresentationToOrganisationseinheit({
    
              attributes: {
                organisationseinheitId: expectedOrganisationseinheit.organisationseinheitIds,
              },
    
          expect(organisationseinheit.organisationseinheitIds).toEqual(
            expectedOrganisationseinheit.organisationseinheitIds,
    
        it('should map missing organisationseinheitIds to empty list', () => {
    
          const organisationseinheit: Organisationseinheit =
    
            repository.mapGroupRepresentationToOrganisationseinheit({});
    
          expect(organisationseinheit.organisationseinheitIds).toEqual([]);
    
      describe('find organisationseinheitItems', () => {
    
        const organisationseinheitItems: Organisationseinheit[] = [
    
          createOrganisationseinheit(),
          createOrganisationseinheit(),
          createOrganisationseinheit(),
    
        const groupReps: GroupRepresentation[] =
          organisationseinheitItems.map(createGroupRepresentation);
    
        it('should return mapped organisationseinheit search result', async () => {
    
          const findMock: jest.Mock = jest.fn().mockReturnValue(Promise.resolve(groupReps));
    
          mockGroupsFunc('find', findMock);
    
          const groupsResult: Organisationseinheit[] = await firstValueFrom(
            repository.findOrganisationseinheitItems(),
          );
    
          expect(groupsResult).toEqual(groupsResult);
    
        it('should call with brief representation', fakeAsync(() => {
    
          const findMock: jest.Mock = jest.fn().mockReturnValue(Promise.resolve(groupReps));
    
          mockGroupsFunc('find', findMock);
    
          repository.findOrganisationseinheitItems().subscribe();
    
          expect(findMock).toHaveBeenCalledWith({ briefRepresentation: false });
        }));
    
      describe('save organisationseinheit', () => {
        const saveGroup: Organisationseinheit = createOrganisationseinheit();
    
        it('should call kcAdminClient.groups.save', async () => {
          const updateMock: jest.Mock = jest.fn(() => of(null));
          mockGroupsFunc('update', updateMock);
    
          await firstValueFrom(repository.saveOrganisationseinheit(saveGroup));
    
          expect(updateMock).toHaveBeenCalledWith(
            { id: saveGroup.id },
            {
              name: saveGroup.name,
              attributes: {
                organisationseinheitId: saveGroup.organisationseinheitIds,
    
        it('should return organisationseinheit save observable', async () => {
    
          const updateMock: jest.Mock = jest.fn(() => Promise.resolve(null));
          mockGroupsFunc('update', updateMock);
    
          const voidResult = await firstValueFrom(repository.saveOrganisationseinheit(saveGroup));
    
    
        it('should pipe rethrowMappedGroupsError', (done) => {
          const updateMock: jest.Mock = jest.fn(() => Promise.reject(networkError));
          mockGroupsFunc('update', updateMock);
          repository.rethrowMappedGroupsError = jest
            .fn()
            .mockReturnValue(catchError(() => throwError(() => error)));
    
    
          repository.saveOrganisationseinheit(saveGroup).subscribe({
    
            error: (err) => {
              expect(err).toBe(error);
              done();
            },
          });
        });
    
      describe('create organisationseinheit', () => {
        const newOrganisationseinheit: Organisationseinheit = createOrganisationseinheit();
    
        it('should call kcAdminClient.groups.create', async () => {
    
          const createMock: jest.Mock = jest.fn(() => of({ id: newOrganisationseinheit.id }));
    
          mockGroupsFunc('create', createMock);
    
          await firstValueFrom(
            repository.createOrganisationseinheit(
              newOrganisationseinheit.name,
              newOrganisationseinheit.organisationseinheitIds,
            ),
          );
    
          expect(createMock).toHaveBeenCalledWith({
    
            name: newOrganisationseinheit.name,
    
              organisationseinheitId: newOrganisationseinheit.organisationseinheitIds,
    
        it('should return mapped organisationseinheit result', async () => {
          const createMock: jest.Mock = jest.fn(() =>
            Promise.resolve({ id: newOrganisationseinheit.id }),
          );
    
          mockGroupsFunc('create', createMock);
    
          const newGroupResult: Organisationseinheit = await firstValueFrom(
            repository.createOrganisationseinheit(
              newOrganisationseinheit.name,
              newOrganisationseinheit.organisationseinheitIds,
            ),
    
          expect(newGroupResult).toEqual(newOrganisationseinheit);
    
        it('should pipe rethrowMappedGroupsError', (done) => {
          const createMock: jest.Mock = jest.fn(() => Promise.reject(networkError));
    
          mockGroupsFunc('create', createMock);
    
          repository.rethrowMappedGroupsError = jest
            .fn()
            .mockReturnValue(catchError(() => throwError(() => error)));
    
          repository
            .createOrganisationseinheit(
              newOrganisationseinheit.name,
              newOrganisationseinheit.organisationseinheitIds,
            )
            .subscribe({
              error: (err) => {
                expect(err).toBe(error);
                done();
              },
            });
    
        });
      });
    
      describe('rethrow mapped groups error', () => {
        let networkErrorObservable: Observable<never>;
    
        beforeEach(() => {
    
          repository.mapCreateGroupsNetworkError = jest.fn().mockReturnValue(error);
    
          networkErrorObservable = throwError(() => networkError);
        });
    
        it('should throw mapped error', (done) => {
          const rethrowOperator: OperatorFunction<never, never> = repository.rethrowMappedGroupsError();
    
          networkErrorObservable.pipe(rethrowOperator).subscribe({
    
            error: (err) => {
              expect(err).toBe(error);
              done();
            },
    
    
        it('should call mapCreateGroupsNetworkError', (done) => {
          const rethrowOperator: OperatorFunction<never, never> = repository.rethrowMappedGroupsError();
    
          networkErrorObservable.pipe(rethrowOperator).subscribe({
            error: () => {
              expect(repository.mapCreateGroupsNetworkError).toHaveBeenCalledWith(networkError);
              done();
            },
          });
        });
    
      describe('map create groups network error', () => {
        it('should interpret 409 status as name conflict', () => {
    
          const keycloakError: OrganisationseinheitError = createOrganisationseinheitError(
    
            OrganisationseinheitErrorType.NAME_CONFLICT,
    
          const networkError: NetworkError = createNetworkError(409, keycloakError.detail);
    
          const error: OrganisationseinheitError = repository.mapCreateGroupsNetworkError(networkError);
    
          expect(error).toEqual(keycloakError);
        });
    
        it('should interpret 400 status as name missing', () => {
    
          const keycloakError: OrganisationseinheitError = createOrganisationseinheitError(
    
            OrganisationseinheitErrorType.NAME_MISSING,
    
          const networkError: NetworkError = createNetworkError(400, keycloakError.detail);
    
          const error: OrganisationseinheitError = repository.mapCreateGroupsNetworkError(networkError);
    
          expect(error).toEqual(keycloakError);
        });
    
        it('should map missing errorMessage to empty string', () => {
          const networkError: NetworkError = createNetworkError(500, undefined);
    
          const error: OrganisationseinheitError = repository.mapCreateGroupsNetworkError(networkError);
    
          expect(error.detail).toEqual('');
    
      describe('delete organisationseinheit', () => {
        const deleteOrganisationseinheit: Organisationseinheit = createOrganisationseinheit();
    
    
        it('should call kcAdminClient.groups.del', async () => {
    
          const delMock: jest.Mock = jest.fn(() =>
            Promise.resolve({ id: deleteOrganisationseinheit.id }),
          );
    
          mockGroupsFunc('del', delMock);
    
          await firstValueFrom(repository.deleteOrganisationseinheit(deleteOrganisationseinheit.id));
    
    
          expect(delMock).toHaveBeenCalledWith({
    
            id: deleteOrganisationseinheit.id,
    
        it('should return void', async () => {
          mockGroupsFunc(
            'del',
            jest.fn(() => Promise.resolve(null)),
          );
    
          const voidResult = await firstValueFrom(
            repository.deleteOrganisationseinheit(deleteOrganisationseinheit.id),
          );
    
          expect(voidResult).toBeNull();