Skip to content
Snippets Groups Projects
Select Git revision
  • 007c1ae8fedebcaa45e06817beb2f3c44043f916
  • master default protected
  • add-frequency-to-form
  • dev protected
  • ckan-2.11.0
  • add-package-custom-fields
  • fix-adding-datasets-for-users-and-editors
  • add-auth-subroute
  • 71-migrate-custom-fields-to-ckanext-scheming
  • add-author-maintainer-information
  • fix-inline-flex-btns
  • fix-known-spatial-uri-validation
  • py3
  • 47-aktuelle-resource-einer-collection-wird-nicht-mehr-gefunden
  • 10-eingabe-der-dct-accrualperiodicity-in-weboberflache
  • v1.3
  • 2.5.3
  • 2.5.2
  • 2.5.1
  • 2.5.0
  • 2.4.7
  • 2.4.6
  • 2.4.5
  • 2.4.4
  • 2.4.3
  • 2.4.2
  • 2.4.1
  • 2.4.0
  • 2.3.1
  • 2.3.0
  • 2.2.0
  • 2.1.0
  • 2.0.0
  • 1.4.3
  • 1.4.2
  • 1.4.1
36 results

test_validation.py

Blame
  • resource.service.spec.ts 18.04 KiB
    import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
    import { Observable, lastValueFrom, of, throwError } from 'rxjs';
    import { ResourceService } from './resource.service';
    import { ResourceRepository } from './resource.repository';
    import { LinkRelationName, ResourceServiceConfig, SaveResourceData } from './resource.model';
    import { Resource, getUrl } from '@ngxp/rest';
    import { createDummyResource } from 'libs/tech-shared/test/resource';
    import {
      StateResource,
      createEmptyStateResource,
      createErrorStateResource,
      createStateResource,
    } from './resource.util';
    import { fakeAsync, tick } from '@angular/core/testing';
    import { singleCold, singleHot } from './marbles';
    import { HttpErrorResponse } from '@angular/common/http';
    import { createProblemDetail } from 'libs/tech-shared/test/error';
    import { HttpError, ProblemDetail } from '../tech.model';
    import { cold } from 'jest-marbles';
    
    import * as ResourceUtil from './resource.util';
    
    describe('ResourceService', () => {
      let service: ResourceService<Resource, Resource>;
      let config: ResourceServiceConfig<Resource>;
    
      let repository: Mock<ResourceRepository>;
    
      const configResource: Resource = createDummyResource();
      const configStateResource: StateResource<Resource> = createStateResource(configResource);
      const configStateResource$: Observable<StateResource<Resource>> = of(configStateResource);
    
      const deleteLinkRel: string = 'dummyDeleteLinkRel';
      const editLinkRel: string = 'dummyEditLinkRel';
      const getLinkRel: LinkRelationName = 'dummyGetLinkRel';
    
      beforeEach(() => {
        config = {
          resource: configStateResource$,
          getLinkRel,
          deleteLinkRel,
          editLinkRel,
        };
        repository = mock(ResourceRepository);
    
        service = new ResourceService(config, useFromMock(repository));
      });
    
      it('should be created', () => {
        expect(service).toBeTruthy();
      });
    
      describe('get', () => {
        const stateResource: StateResource<Resource> = createStateResource(configResource);
    
        beforeEach(() => {
          service.stateResource.next(stateResource);
    
          service.handleNullConfigResource = jest.fn();
          service.handleConfigResource = jest.fn();
          service.handleConfigResourceChanged = jest.fn();
          service.shouldFilter = jest.fn().mockReturnValue(true);
        });
    
        it('should handle config resource changed', fakeAsync(() => {
          service.get().subscribe();
          tick();
    
          expect(service.handleConfigResourceChanged).toHaveBeenCalledWith(configResource);
        }));
    
        it('should handle null configresource', fakeAsync(() => {
          service.get().subscribe();
          tick();
    
          expect(service.handleNullConfigResource).toHaveBeenCalledWith(configResource);
        }));
    
        it('should handle configresource', fakeAsync(() => {
          service.get().subscribe();
          tick();
    
          expect(service.handleConfigResource).toHaveBeenCalledWith(stateResource, configResource);
        }));
    
        it('should call shouldFilter', fakeAsync(() => {
          service.get().subscribe();
          tick();
    
          expect(service.shouldFilter).toHaveBeenCalled();
        }));
    
        it('should return initial value', () => {
          service.stateResource.asObservable = jest
            .fn()
            .mockReturnValue(singleHot(stateResource, '-a'));
    
          const apiRootStateResource$: Observable<StateResource<Resource>> = service.get();
    
          expect(apiRootStateResource$).toBeObservable(
            cold('a', { a: createEmptyStateResource(true) }),
          );
        });
      });
    
      describe('handle config resource changed', () => {
        const changedConfigResource: Resource = createDummyResource();
    
        it('should update configresource if is different', () => {
          service.configResource = createDummyResource();
    
          service.handleConfigResourceChanged(changedConfigResource);
    
          expect(service.configResource).toBe(changedConfigResource);
        });
    
        it('should set stateresource reload', () => {
          service.configResource = createDummyResource();
    
          service.handleConfigResourceChanged(changedConfigResource);
    
          expect(service.stateResource.value.reload).toBeTruthy();
        });
      });
    
      describe('handle null config resource', () => {
        const resource: Resource = createDummyResource();
        const stateResource: StateResource<Resource> = createStateResource(resource);
    
        beforeEach(() => {
          service.shouldClearStateResource = jest.fn();
          service.stateResource.next(stateResource);
        });
        it('should call shouldClearStateResource', () => {
          service.handleNullConfigResource(null);
    
          expect(service.shouldClearStateResource).toHaveBeenCalledWith(null);
        });
    
        it('should clear stateresource if shouldClearStateResource is true', () => {
          service.shouldClearStateResource = jest.fn().mockReturnValue(true);
    
          service.handleNullConfigResource(null);
    
          expect(service.stateResource.value).toEqual(createEmptyStateResource());
        });
    
        it('should keep stateresource if shouldClearStateResource is false', () => {
          service.shouldClearStateResource = jest.fn().mockReturnValue(false);
    
          service.handleNullConfigResource(null);
    
          expect(service.stateResource.value).toBe(stateResource);
        });
      });
    
      describe('should clear stateresource', () => {
        const resource: Resource = createDummyResource();
        const stateResource: StateResource<Resource> = createStateResource(resource);
    
        it('should return true on null configresource and filled stateresource', () => {
          service.stateResource.next(stateResource);
    
          const shouldClear: boolean = service.shouldClearStateResource(null);
    
          expect(shouldClear).toBeTruthy();
        });
    
        it('should return false on null configresource and empty stateresource', () => {
          service.stateResource.next(createEmptyStateResource());
    
          const shouldClear: boolean = service.shouldClearStateResource(null);
    
          expect(shouldClear).toBeFalsy();
        });
      });
    
      describe('handle config resource', () => {
        const resource: Resource = createDummyResource();
        const stateResource: StateResource<Resource> = createStateResource(resource);
    
        it('should call shouldLoadResource', () => {
          service.shouldLoadResource = jest.fn();
    
          service.handleConfigResource(stateResource, configResource);
    
          expect(service.shouldLoadResource).toHaveBeenCalledWith(stateResource, configResource);
        });
    
        it('should load resource', () => {
          service.shouldLoadResource = jest.fn().mockReturnValue(true);
          service.loadResource = jest.fn();
    
          service.handleConfigResource(stateResource, configResource);
    
          expect(service.loadResource).toHaveBeenCalledWith(configResource);
        });
    
        it('should NOT load resource on shouldLoadResource false', () => {
          service.loadResource = jest.fn();
          service.shouldLoadResource = jest.fn().mockReturnValue(false);
    
          service.handleConfigResource(stateResource, configResource);
    
          expect(service.loadResource).not.toHaveBeenCalled();
        });
      });
    
      describe('should load resource', () => {
        const resource: Resource = createDummyResource();
        const stateResource: StateResource<Resource> = createStateResource(resource);
    
        let isLoadingRequiredSpy: jest.SpyInstance<boolean>;
    
        beforeEach(() => {
          isLoadingRequiredSpy = jest.spyOn(ResourceUtil, 'isLoadingRequired');
        });
    
        it('should return true on existing configresource and loading is required', () => {
          isLoadingRequiredSpy.mockReturnValue(true);
    
          const shouldLoad: boolean = service.shouldLoadResource(stateResource, configResource);
    
          expect(shouldLoad).toBeTruthy();
        });
    
        it('should call isLoadingRequired', () => {
          service.shouldLoadResource(stateResource, configResource);
    
          expect(isLoadingRequiredSpy).toBeCalledWith(stateResource);
        });
    
        it('should return false if configresource exists but loading is NOT required', () => {
          isLoadingRequiredSpy.mockReturnValue(false);
    
          const shouldLoad: boolean = service.shouldLoadResource(stateResource, configResource);
    
          expect(shouldLoad).toBeFalsy();
        });
      });
    
      describe('load resource', () => {
        const configResourceWithGetLinkRel: Resource = createDummyResource([getLinkRel]);
    
        it('should throw error if getLinkRel not exists', () => {
          expect(() => service.loadResource(configResource)).toThrowError(
            'No get link exists on configresource.',
          );
        });
    
        it('should set stateResource loading', () => {
          service.doLoadResource = jest.fn();
          service.setStateResourceLoading = jest.fn();
    
          service.loadResource(configResourceWithGetLinkRel);
    
          expect(service.setStateResourceLoading).toHaveBeenCalled();
        });
    
        it('should call do load resource', () => {
          service.doLoadResource = jest.fn();
    
          service.loadResource(configResourceWithGetLinkRel);
    
          expect(service.doLoadResource).toHaveBeenCalledWith(configResourceWithGetLinkRel);
        });
      });
    
      describe('set state resource loading', () => {
        it('should set loading true', () => {
          service.stateResource.next(createStateResource(createDummyResource()));
    
          service.setStateResourceLoading();
    
          expect(service.stateResource.value.loading).toBeTruthy();
        });
    
        it('should set reload false', () => {
          service.stateResource.next({ ...createStateResource(createDummyResource()), reload: true });
    
          service.setStateResourceLoading();
    
          expect(service.stateResource.value.reload).toBeFalsy();
        });
      });
    
      describe('do load resource', () => {
        const configResourceWithGetLinkRel: Resource = createDummyResource([getLinkRel]);
        const loadedResource: Resource = createDummyResource();
    
        beforeEach(() => {
          repository.getResource.mockReturnValue(of(loadedResource));
        });
    
        it('should call repository', () => {
          service.doLoadResource(configResourceWithGetLinkRel);
    
          expect(repository.getResource).toHaveBeenCalledWith(
            getUrl(configResourceWithGetLinkRel, getLinkRel),
          );
        });
    
        it('should update stateresource', () => {
          service.updateStateResource = jest.fn();
    
          service.doLoadResource(configResourceWithGetLinkRel);
    
          expect(service.updateStateResource).toHaveBeenCalledWith(loadedResource);
        });
      });
    
      describe('update stateresource', () => {
        const resourceToBeSet: Resource = createDummyResource();
    
        it('should set resource as stateresource', () => {
          service.stateResource.next(createEmptyStateResource());
    
          service.updateStateResource(resourceToBeSet);
    
          expect(service.stateResource.value).toEqual(createStateResource(resourceToBeSet));
        });
      });
    
      describe('should filter', () => {
        it('should return true if stateresource reload is true', () => {
          const shouldFilter: boolean = service.shouldFilter({
            ...createStateResource(createDummyResource()),
            reload: true,
          });
    
          expect(shouldFilter).toBeTruthy();
        });
    
        it('should return true on invalidCombination', () => {
          service.isInvalidResourceCombination = jest.fn().mockReturnValue(true);
    
          const shouldFilter: boolean = service.shouldFilter(
            createStateResource(createDummyResource()),
          );
    
          expect(shouldFilter).toBeTruthy();
        });
    
        it('should call isInvalidCombination', () => {
          const stateResource: StateResource<Resource> = createStateResource(createDummyResource());
          service.configResource = configResource;
          service.isInvalidResourceCombination = jest.fn();
    
          service.shouldFilter(stateResource);
    
          expect(service.isInvalidResourceCombination).toHaveBeenCalledWith(
            stateResource,
            configResource,
          );
        });
      });
    
      describe('is invalid resource combination', () => {
        it('should return true on loaded stateResource while configResource is null', () => {
          const stateResource: StateResource<Resource> = createStateResource(createDummyResource());
    
          const isInvalidCombination: boolean = service.isInvalidResourceCombination(
            stateResource,
            null,
          );
    
          expect(isInvalidCombination).toBeTruthy();
        });
    
        it('should return true on non loaded stateResource while configResource exists', () => {
          const stateResource: StateResource<Resource> = createEmptyStateResource();
          const configResource: Resource = createDummyResource();
    
          const isInvalidCombination: boolean = service.isInvalidResourceCombination(
            stateResource,
            configResource,
          );
    
          expect(isInvalidCombination).toBeTruthy();
        });
    
        it('should return false on loading stateResource', () => {
          const stateResource: StateResource<Resource> = {
            ...createStateResource(createDummyResource()),
            loading: true,
          };
          const configResource: Resource = createDummyResource();
    
          const isInvalidCombination: boolean = service.isInvalidResourceCombination(
            stateResource,
            configResource,
          );
    
          expect(isInvalidCombination).toBeFalsy();
        });
      });
    
      describe('save', () => {
        const dummyToSave: unknown = {};
        const loadedResource: Resource = createDummyResource();
    
        const resourceWithEditLinkRel: Resource = createDummyResource([editLinkRel]);
    
        it('should throw error if edit link not exists', () => {
          service.stateResource.next(createStateResource(createDummyResource()));
    
          expect(() => service.save(dummyToSave)).toThrowError(
            'No edit link exists on current stateresource.',
          );
        });
    
        it('should call repository', fakeAsync(() => {
          service.stateResource.next(createStateResource(resourceWithEditLinkRel));
          repository.save.mockReturnValue(of(loadedResource));
    
          service.save(dummyToSave).subscribe();
          tick();
    
          const expectedSaveResourceData: SaveResourceData<Resource> = {
            resource: resourceWithEditLinkRel,
            linkRel: editLinkRel,
            toSave: dummyToSave,
          };
          expect(repository.save).toHaveBeenCalledWith(expectedSaveResourceData);
        }));
    
        it('should return saved object', () => {
          service.stateResource.next(createStateResource(resourceWithEditLinkRel));
          repository.save.mockReturnValue(singleHot(loadedResource));
    
          const saved: Observable<StateResource<Resource | HttpError>> = service.save(dummyToSave);
    
          expect(saved).toBeObservable(singleCold(createStateResource(loadedResource)));
        });
    
        it('should call handleError', () => {
          service.stateResource.next(createStateResource(createDummyResource([config.editLinkRel])));
          const errorResponse: ProblemDetail = createProblemDetail();
          repository.save.mockReturnValue(throwError(() => errorResponse));
          service.handleError = jest.fn();
    
          service.save(<any>{}).subscribe();
    
          expect(service.handleError).toHaveBeenCalledWith(errorResponse);
        });
      });
    
      describe('handleError', () => {
        it('should return error stateresource on problem unprocessable entity', (done) => {
          const error: ProblemDetail = createProblemDetail();
    
          service
            .handleError(<HttpErrorResponse>(<any>error))
            .subscribe((responseError: StateResource<HttpError>) => {
              expect(responseError).toEqual(createErrorStateResource(error));
              done();
            });
        });
    
        it('should rethrow error', () => {
          const error: HttpErrorResponse = <HttpErrorResponse>{
            status: 500,
            statusText: 'Internal Server Error',
          };
    
          const thrownError$: Observable<StateResource<HttpError>> = service.handleError(error);
    
          expect.assertions(1);
          expect(lastValueFrom(thrownError$)).rejects.toThrowError('Internal Server Error');
        });
      });
    
      describe('refresh', () => {
        beforeEach(() => {
          service.loadResource = jest.fn();
        });
    
        it('should set reload true on statresource', () => {
          service.stateResource.next(createStateResource(createDummyResource()));
    
          service.refresh();
    
          expect(service.stateResource.value.reload).toBeTruthy();
        });
      });
    
      describe('can edit', () => {
        it('should return true if link is present', () => {
          const resource: StateResource<Resource> = createStateResource(
            createDummyResource([editLinkRel]),
          );
          service.stateResource.next(resource);
    
          const canEdit: boolean = service.canEdit();
    
          expect(canEdit).toBeTruthy();
        });
    
        it('should return false if link is NOT present', () => {
          const resource: StateResource<Resource> = createStateResource(createDummyResource());
          service.stateResource.next(resource);
    
          const canEdit: boolean = service.canEdit();
    
          expect(canEdit).toBeFalsy();
        });
      });
    
      describe('can delete', () => {
        it('should return true if link is present', () => {
          const resource: StateResource<Resource> = createStateResource(
            createDummyResource([deleteLinkRel]),
          );
          service.stateResource.next(resource);
    
          const canEdit: boolean = service.canDelete();
    
          expect(canEdit).toBeTruthy();
        });
    
        it('should return false if link is NOT present', () => {
          const resource: StateResource<Resource> = createStateResource(createDummyResource());
          service.stateResource.next(resource);
    
          const canEdit: boolean = service.canDelete();
    
          expect(canEdit).toBeFalsy();
        });
      });
    
      describe('delete', () => {
        const resourceWithDeleteLinkRel: Resource = createDummyResource([deleteLinkRel]);
        const stateResourceWithDeleteLink: StateResource<Resource> =
          createStateResource(resourceWithDeleteLinkRel);
    
        beforeEach(() => {
          service.stateResource.next(stateResourceWithDeleteLink);
        });
    
        it('should throw error if delete linkRel not exists on current stateresource', () => {
          service.stateResource.next(createStateResource(createDummyResource()));
    
          expect(() => service.delete()).toThrowError(
            'No delete link exists on current stateresource.',
          );
        });
    
        it('should call repository', () => {
          service.delete();
    
          expect(repository.delete).toHaveBeenCalledWith(resourceWithDeleteLinkRel, deleteLinkRel);
        });
    
        it('should return value', () => {
          const deleteResource: Resource = createDummyResource();
          repository.delete.mockReturnValue(singleHot(deleteResource));
    
          const deletedResource: Observable<Resource> = service.delete();
    
          expect(deletedResource).toBeObservable(singleCold(deleteResource));
        });
      });
    });