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

Merge branch 'OZG-5977-multi-file-upload-bescheid' into 'main'

OZG-5977 add multi file upload to bescheid wizard

See merge request !77
parents bb6df105 e58614cd
Branches
Tags
1 merge request!77OZG-5977 add multi file upload to bescheid wizard
Showing
with 162 additions and 691 deletions
......@@ -118,3 +118,5 @@ export function createInitialWizard(): Wizard {
bescheidCreated: false,
};
}
export const BESCHEID_UPLOADED_ATTACHMENTS: string = 'bescheid_uploaded_attachments';
\ No newline at end of file
......@@ -24,7 +24,7 @@
import { BinaryFileListLinkRel, BinaryFileListResource, BinaryFileResource, BinaryFileService, } from '@alfa-client/binary-file-shared';
import { CommandOrder, CommandResource, CommandResourceService, CommandService, CreateCommandProps, getEffectedResourceUrl, } from '@alfa-client/command-shared';
import { PostfachService } from '@alfa-client/postfach-shared';
import { createEmptyStateResource, createErrorStateResource, createLoadingStateResource, createStateResource, EMPTY_STRING, getEmbeddedResources, StateResource, } from '@alfa-client/tech-shared';
import { createEmptyStateResource, createErrorStateResource, createStateResource, EMPTY_STRING, getEmbeddedResources, StateResource, } from '@alfa-client/tech-shared';
import { Mock, mock } from '@alfa-client/test-utils';
import { VorgangCommandService, VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
import { TestBed } from '@angular/core/testing';
......@@ -39,12 +39,12 @@ import { createCommandErrorStateResource, createCommandResource, createCommandSt
import { ResourceRepository } from '../../../tech-shared/src/lib/resource/resource.repository';
import { createFile } from '../../../tech-shared/test/file';
import { singleCold, singleColdCompleted } from '../../../tech-shared/test/marbles';
import { createBescheid, createBescheidAttachments, createBescheidDocument, createBescheidResource } from '../test/bescheid';
import { createBescheid, createBescheidDocument, createBescheidResource } from '../test/bescheid';
import { createDocumentResource } from '../test/document';
import { BescheidFacade } from './+state/bescheid.facade';
import { BescheidResourceService } from './bescheid-resource-service';
import { BescheidLinkRel } from './bescheid.linkrel';
import { Bescheid, BescheidAttachments, BescheidDocument, BescheidResource, BescheidWizardStep, createEmptyBescheidAttachments, createEmptyBescheidDocument, createEmptyUploadInProgress, createInitialWizard, } from './bescheid.model';
import { Bescheid, BESCHEID_UPLOADED_ATTACHMENTS, BescheidDocument, BescheidResource, BescheidWizardStep, createEmptyBescheidDocument, createEmptyUploadInProgress, createInitialWizard, } from './bescheid.model';
import { BescheidService2 } from './bescheid2.service';
import { DocumentLinkRel } from './document.linkrel';
import { DocumentResource } from './document.model';
......@@ -115,16 +115,25 @@ describe('BescheidService', () => {
expect(service.getActiveStep()).toBeObservable(singleCold(BescheidWizardStep.AntragBescheiden));
expect(service.getBescheidCreated()).toBeObservable(singleCold(false));
expect(service.getBescheidDocument()).toBeObservable(singleCold(createEmptyBescheidDocument()));
expect(service.getAttachments()).toBeObservable(singleCold(createEmptyBescheidAttachments()));
});
});
describe('exit', () => {
beforeEach(() => {
service._clearUploadedFiles = jest.fn();
});
it('should reload postfach list', () => {
service.exit();
expect(postfachService.setPostfachMailOnReload).toHaveBeenCalled();
});
it('should clear uploaded files', () => {
service.exit();
expect(service._clearUploadedFiles).toHaveBeenCalled();
});
});
describe('skipBescheidCreation', () => {
......@@ -441,113 +450,16 @@ describe('BescheidService', () => {
expect(binaryFileService.getFiles).not.toHaveBeenCalled();
});
it('should emit attachments state', () => {
it('should add files', () => {
const binaryFileListStateResource: StateResource<BinaryFileListResource> =
createStateResource(createBinaryFileListResource());
binaryFileService.getFiles.mockReturnValue(of(binaryFileListStateResource));
service.loadAttachments(bescheidResourceWithAttachments);
expect(binaryFileService.getFiles).toHaveBeenCalledWith(bescheidResourceWithAttachments, BescheidLinkRel.ATTACHMENTS);
expect(service.getAttachments()).toBeObservable(
singleCold({
...createEmptyBescheidAttachments(),
items: getEmbeddedResources(binaryFileListStateResource, BinaryFileListLinkRel.FILE_LIST),
}),
);
});
});
describe('uploadAttachment', () => {
const attachment: File = createFile();
beforeEach(() => {
binaryFileService.uploadFile.mockReturnValue(EMPTY);
service.handleAttachmentUpload = jest.fn();
});
it('should emit upload loading', () => {
service.uploadAttachment(attachment, bescheidResource);
expect(service.getAttachments()).toBeObservable(
singleCold({
...createEmptyBescheidAttachments(),
upload: { fileName: attachment.name, loading: true },
uploadStateResource: createLoadingStateResource(),
} as BescheidAttachments),
);
});
it('should call binary file service', () => {
service.uploadAttachment(attachment, bescheidResource);
expect(binaryFileService.uploadFile).toHaveBeenCalledWith(
bescheidResource,
BescheidLinkRel.UPLOAD_ATTACHMENT,
attachment,
false,
);
});
it('should handle attachment upload', () => {
const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource(createBinaryFileResource());
binaryFileService.uploadFile.mockReturnValue(of(binaryFileStateResource));
service.uploadAttachment(attachment, bescheidResource);
expect(service.handleAttachmentUpload).toHaveBeenCalledWith(binaryFileStateResource);
});
});
describe('handleAttachmentUpload', () => {
it('should emit state on success', () => {
const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource(createBinaryFileResource());
service.handleAttachmentUpload(binaryFileStateResource);
expect(service.getAttachments()).toBeObservable(
singleCold({
...createEmptyBescheidAttachments(),
items: [binaryFileStateResource.resource],
uploadStateResource: binaryFileStateResource,
upload: {
...createEmptyUploadInProgress(),
error: binaryFileStateResource.error,
loading: binaryFileStateResource.loading,
},
} as BescheidAttachments),
);
});
it('should emit state on error', () => {
const binaryFileStateResource: StateResource<BinaryFileResource> = createErrorStateResource(createProblemDetail());
service.handleAttachmentUpload(binaryFileStateResource);
expect(service.getAttachments()).toBeObservable(
singleCold({
...createEmptyBescheidAttachments(),
items: [],
uploadStateResource: binaryFileStateResource,
upload: {
...createEmptyUploadInProgress(),
error: binaryFileStateResource.error,
loading: binaryFileStateResource.loading,
},
}),
);
});
});
describe('deleteAttachment', () => {
it('should delete', () => {
const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource(createBinaryFileResource());
service.handleAttachmentUpload(binaryFileStateResource);
service.deleteAttachment(binaryFileStateResource.resource);
service.loadAttachments(bescheidResourceWithAttachments);
expect(service.getAttachments()).toBeObservable(
singleCold({ ...createEmptyBescheidAttachments(), uploadStateResource: binaryFileStateResource } as BescheidAttachments),
expect(binaryFileService.addFiles).toHaveBeenCalledWith(
BESCHEID_UPLOADED_ATTACHMENTS,
getEmbeddedResources(binaryFileListStateResource, BinaryFileListLinkRel.FILE_LIST),
);
});
});
......@@ -885,11 +797,21 @@ describe('BescheidService', () => {
});
describe('setActiveStep', () => {
beforeEach(() => {
service._clearUploadedFiles = jest.fn();
});
it('should emit changed active step', () => {
service.setActiveStep(BescheidWizardStep.DokumenteHochladen);
expect(service.getActiveStep()).toBeObservable(singleCold(BescheidWizardStep.DokumenteHochladen));
});
it('should clear uploaded files', () => {
service.setActiveStep(BescheidWizardStep.DokumenteHochladen);
expect(service._clearUploadedFiles).toHaveBeenCalled();
});
});
describe('getBescheidDraft', () => {
......@@ -939,23 +861,6 @@ describe('BescheidService', () => {
});
});
describe('finishAddingAttachments', () => {
it('should update state', () => {
const attachments: BescheidAttachments = createBescheidAttachments();
service._attachments$.next(attachments);
service.finishAddingAttachments();
expect(service.getAttachments()).toBeObservable(
singleCold({
...attachments,
upload: createEmptyUploadInProgress(),
uploadStateResource: createEmptyStateResource(),
} as BescheidAttachments),
);
});
});
describe('finishAddingBescheidDocument', () => {
it('should update state', () => {
const bescheidDocument: BescheidDocument = createBescheidDocument();
......@@ -972,4 +877,12 @@ describe('BescheidService', () => {
);
});
});
describe('clear uploaded files', () => {
it('should call binary files service', () => {
service._clearUploadedFiles();
expect(binaryFileService.clearUploadedFiles).toHaveBeenCalledWith(BESCHEID_UPLOADED_ATTACHMENTS);
});
});
});
import {
Bescheid,
BescheidAttachments,
BESCHEID_UPLOADED_ATTACHMENTS,
BescheidDocument,
BescheidLinkRel,
BescheidResource,
......@@ -11,7 +11,6 @@ import {
buildCreateBescheidDocumentFromFileProps,
buildSendBescheidCommandProps,
buildUpdateBescheidCommandProps,
createEmptyBescheidAttachments,
createEmptyBescheidDocument,
createEmptyUploadInProgress,
createInitialWizard,
......@@ -35,7 +34,6 @@ import {
import { PostfachService } from '@alfa-client/postfach-shared';
import {
createEmptyStateResource,
createLoadingStateResource,
filterIsLoadedOrHasError,
getEmbeddedResources,
hasStateResourceError,
......@@ -63,17 +61,16 @@ export class BescheidService2 {
private readonly bescheidResourceService = inject(BescheidResourceService);
readonly _bescheidDocument$: BehaviorSubject<BescheidDocument> = new BehaviorSubject(createEmptyBescheidDocument());
readonly _attachments$: BehaviorSubject<BescheidAttachments> = new BehaviorSubject(createEmptyBescheidAttachments());
readonly _wizard$: BehaviorSubject<Wizard> = new BehaviorSubject(createInitialWizard());
public init(): void {
this._wizard$.next(createInitialWizard());
this._bescheidDocument$.next(createEmptyBescheidDocument());
this._attachments$.next(createEmptyBescheidAttachments());
}
public exit(): void {
this.postfachService.setPostfachMailOnReload();
this._clearUploadedFiles();
}
public skipBescheidCreation(
......@@ -173,50 +170,10 @@ export class BescheidService2 {
getEmbeddedResources<BinaryFileResource>(stateResource, BinaryFileListLinkRel.FILE_LIST),
),
)
.subscribe((files: BinaryFileResource[]) => this._attachments$.next({ ...this._attachments$.value, items: files }));
.subscribe((files: BinaryFileResource[]) => this.binaryFileService.addFiles(BESCHEID_UPLOADED_ATTACHMENTS, files));
}
}
public uploadAttachment(attachment: File, bescheidResource: BescheidResource): void {
this._attachments$.next({
...this._attachments$.value,
upload: { fileName: attachment.name, loading: true },
uploadStateResource: createLoadingStateResource(),
});
this.binaryFileService
.uploadFile(bescheidResource, BescheidLinkRel.UPLOAD_ATTACHMENT, attachment, false)
.pipe(filterIsLoadedOrHasError(), first())
.subscribe((binaryFileStateResource: StateResource<BinaryFileResource>) =>
this.handleAttachmentUpload(binaryFileStateResource),
);
}
handleAttachmentUpload(binaryFileStateResource: StateResource<BinaryFileResource>) {
const value: BescheidAttachments = this._attachments$.value;
if (hasStateResourceError(binaryFileStateResource)) {
this._attachments$.next({
...value,
uploadStateResource: binaryFileStateResource,
upload: { ...value.upload, error: binaryFileStateResource.error, loading: binaryFileStateResource.loading },
});
} else {
this._attachments$.next({
...value,
uploadStateResource: binaryFileStateResource,
items: [...value.items, binaryFileStateResource.resource],
upload: { ...value.upload, error: binaryFileStateResource.error, loading: binaryFileStateResource.loading },
});
}
}
public deleteAttachment(attachment: BinaryFileResource): void {
const value: BescheidAttachments = this._attachments$.value;
this._attachments$.next({
...value,
items: value.items.filter((each: BinaryFileResource) => getUrl(each) !== getUrl(attachment)),
});
}
public uploadBescheidDocument(document: File, bescheid: BescheidResource): void {
this._bescheidDocument$.next({ ...this._bescheidDocument$.value, upload: { fileName: document.name, loading: true } });
this.binaryFileService
......@@ -321,10 +278,6 @@ export class BescheidService2 {
return this.bescheidResourceService.get();
}
public getAttachments(): Observable<BescheidAttachments> {
return this._attachments$.asObservable();
}
public getBescheidDocument(): Observable<BescheidDocument> {
return this._bescheidDocument$.asObservable();
}
......@@ -338,6 +291,7 @@ export class BescheidService2 {
}
public setActiveStep(step: BescheidWizardStep): void {
this._clearUploadedFiles();
this._wizard$.next({ ...this._wizard$.value, activeStep: step });
}
......@@ -369,14 +323,6 @@ export class BescheidService2 {
this._wizard$.next({ ...this._wizard$.value, canBeSend: true });
}
public finishAddingAttachments(): void {
this._attachments$.next({
...this._attachments$.value,
upload: createEmptyUploadInProgress(),
uploadStateResource: createEmptyStateResource(),
});
}
public finishAddingBescheidDocument(): void {
this._bescheidDocument$.next({
...this._bescheidDocument$.value,
......@@ -384,4 +330,8 @@ export class BescheidService2 {
create: createEmptyStateResource(),
});
}
_clearUploadedFiles(): void {
this.binaryFileService.clearUploadedFiles(BESCHEID_UPLOADED_ATTACHMENTS);
}
}
<ods-attachment-wrapper>
@for (attachment of attachments; track $index) {
<alfa-binary-file2-container
[file]="attachment"
[deletable]="deletable"
(startDelete)="delete.emit($event)"
[attr.data-test-id]="(attachment.name | convertForDataTest) + '-file2-container'"
>
</alfa-binary-file2-container>
}
@if (upload.loading || upload.error) {
<ods-attachment
[loadingCaption]="upload.fileName"
errorCaption="Fehler beim Hochladen"
[errorMessages]="upload.error | convertProblemDetailToErrorMessages"
description="Anhang wird hochgeladen"
[isLoading]="upload.loading"
data-test-id="attachment-upload-in-progress"
></ods-attachment>
}
</ods-attachment-wrapper>
import { BescheidAttachments, createEmptyBescheidAttachments, createEmptyUploadInProgress } from '@alfa-client/bescheid-shared';
import { BinaryFile2ContainerComponent } from '@alfa-client/binary-file';
import { ConvertForDataTestPipe, ConvertProblemDetailToErrorMessagesPipe, ProblemDetail } from '@alfa-client/tech-shared';
import {
existsAsHtmlElement,
getElementComponentFromFixtureByCss,
notExistsAsHtmlElement,
triggerEvent,
} from '@alfa-client/test-utils';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AttachmentComponent, AttachmentWrapperComponent } from '@ods/system';
import { MockComponent } from 'ng-mocks';
import { createBescheidAttachments } from '../../../../../../../bescheid-shared/src/test/bescheid';
import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
import { createProblemDetail } from '../../../../../../../tech-shared/test/error';
import { BescheidWizardAttachmentFilesComponent } from './bescheid-wizard-attachment-files.component';
describe('BescheidWizardAttachmentFileComponent', () => {
let component: BescheidWizardAttachmentFilesComponent;
let fixture: ComponentFixture<BescheidWizardAttachmentFilesComponent>;
const convertForDataTest: ConvertForDataTestPipe = new ConvertForDataTestPipe();
const convertProblemDetailsToErrorMessage: ConvertProblemDetailToErrorMessagesPipe =
new ConvertProblemDetailToErrorMessagesPipe();
const attachments: BescheidAttachments = createBescheidAttachments();
const binaryFileContainerTestId: string = getDataTestIdOf(
convertForDataTest.transform(attachments.items[0].name) + '-file2-container',
);
const attachmentUploadTestId: string = getDataTestIdOf('attachment-upload-in-progress');
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [
BescheidWizardAttachmentFilesComponent,
MockComponent(BinaryFile2ContainerComponent),
MockComponent(AttachmentComponent),
MockComponent(AttachmentWrapperComponent),
ConvertForDataTestPipe,
ConvertProblemDetailToErrorMessagesPipe,
],
}).compileComponents();
fixture = TestBed.createComponent(BescheidWizardAttachmentFilesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
describe('component', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
it('should set initial values', () => {
expect(component.upload).toEqual(createEmptyUploadInProgress());
expect(component.attachments).toEqual(createEmptyBescheidAttachments().items);
});
describe('set attachments', () => {
it('should set attachments', () => {
component.attachments = attachments;
expect(component.attachments).toEqual(attachments.items);
});
it('should set upload', () => {
component.attachments = attachments;
expect(component.upload).toEqual(attachments.upload);
});
});
});
describe('template', () => {
describe('attachment binary file container', () => {
it('should exists', () => {
component.attachments = attachments;
fixture.detectChanges();
existsAsHtmlElement(fixture, binaryFileContainerTestId);
});
it('should have been called with inputs', () => {
component.attachments = attachments;
fixture.detectChanges();
const binaryFileComponent: BinaryFile2ContainerComponent =
getElementComponentFromFixtureByCss<BinaryFile2ContainerComponent>(fixture, binaryFileContainerTestId);
expect(binaryFileComponent.file).toEqual(attachments.items[0]);
expect(binaryFileComponent.deletable).toEqual(component.deletable);
});
describe('output', () => {
describe('startDelete', () => {
it('should emit', () => {
component.attachments = attachments;
component.delete.emit = jest.fn();
fixture.detectChanges();
triggerEvent({
fixture,
elementSelector: binaryFileContainerTestId,
name: 'startDelete',
data: attachments.items[0],
});
expect(component.delete.emit).toHaveBeenCalledWith(attachments.items[0]);
});
});
});
});
describe('upload attachment', () => {
it('should exists on loading', () => {
component.attachments = { ...attachments, upload: { ...attachments.upload, loading: true, error: null } };
fixture.detectChanges();
existsAsHtmlElement(fixture, attachmentUploadTestId);
});
it('should exists on error', () => {
component.attachments = {
...attachments,
upload: { ...attachments.upload, loading: false, error: createProblemDetail() },
};
fixture.detectChanges();
existsAsHtmlElement(fixture, attachmentUploadTestId);
});
it('should NOT exists', () => {
component.attachments = {
...attachments,
upload: { ...attachments.upload, loading: false, error: null },
};
fixture.detectChanges();
notExistsAsHtmlElement(fixture, attachmentUploadTestId);
});
it('should have been called with inputs', () => {
component.attachments = attachments;
fixture.detectChanges();
const attachmentComponent: AttachmentComponent = getElementComponentFromFixtureByCss<AttachmentComponent>(
fixture,
attachmentUploadTestId,
);
expect(attachmentComponent.loadingCaption).toEqual(attachments.upload.fileName);
expect(attachmentComponent.errorMessages).toEqual(
convertProblemDetailsToErrorMessage.transform(attachments.upload.error as ProblemDetail),
);
expect(attachmentComponent.isLoading).toEqual(attachments.upload.loading);
});
});
});
});
import {
BescheidAttachments,
createEmptyBescheidAttachments,
createEmptyUploadInProgress,
UploadFileInProgress,
} from '@alfa-client/bescheid-shared';
import { BinaryFileResource } from '@alfa-client/binary-file-shared';
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'alfa-bescheid-wizard-attachment-files',
templateUrl: './bescheid-wizard-attachment-files.component.html',
})
export class BescheidWizardAttachmentFilesComponent {
@Input() set attachments(value: BescheidAttachments) {
this._attachments = value;
this.upload = value.upload;
}
get attachments(): BinaryFileResource[] {
return this._attachments.items;
}
@Input() deletable: boolean;
@Output() delete: EventEmitter<BinaryFileResource> = new EventEmitter();
public upload: UploadFileInProgress = createEmptyUploadInProgress();
private _attachments: BescheidAttachments = createEmptyBescheidAttachments();
}
<alfa-bescheid-wizard-attachment-files
[attachments]="attachments$ | async"
[deletable]="(activeStep$ | async) === bescheidWizardStep.DokumenteHochladen"
(delete)="deleteAttachment($event)"
data-test-id="bescheid-attachments"
></alfa-bescheid-wizard-attachment-files>
import { BescheidAttachments, BescheidWizardStep } from '@alfa-client/bescheid-shared';
import { BinaryFileResource } from '@alfa-client/binary-file-shared';
import { existsAsHtmlElement, getElementComponentFromFixtureByCss, mock, Mock, triggerEvent } from '@alfa-client/test-utils';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MockComponent } from 'ng-mocks';
import { of } from 'rxjs';
import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
import { createBescheidAttachments } from '../../../../../../bescheid-shared/src/test/bescheid';
import { createBinaryFileResource } from '../../../../../../binary-file-shared/test/binary-file';
import { getDataTestIdOf } from '../../../../../../tech-shared/test/data-test';
import { singleColdCompleted } from '../../../../../../tech-shared/test/marbles';
import { BescheidWizardAttachmentFilesComponent } from './attachment-files/bescheid-wizard-attachment-files.component';
import { BescheidWizardAttachmentFilesContainerComponent } from './bescheid-wizard-attachment-files-container.component';
describe('BescheidWizardAttachmentFileContainerComponent', () => {
let component: BescheidWizardAttachmentFilesContainerComponent;
let fixture: ComponentFixture<BescheidWizardAttachmentFilesContainerComponent>;
const attachmentsFilesTestId: string = getDataTestIdOf('bescheid-attachments');
const attachments: BescheidAttachments = createBescheidAttachments();
let bescheidService: Mock<BescheidService2>;
beforeEach(() => {
bescheidService = mock(BescheidService2);
});
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [BescheidWizardAttachmentFilesContainerComponent, MockComponent(BescheidWizardAttachmentFilesComponent)],
providers: [{ provide: BescheidService2, useValue: bescheidService }],
}).compileComponents();
fixture = TestBed.createComponent(BescheidWizardAttachmentFilesContainerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
describe('component', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
describe('ngOnInit', () => {
it('should set attachments', () => {
bescheidService.getAttachments.mockReturnValue(of(attachments));
component.ngOnInit();
expect(component.attachments$).toBeObservable(singleColdCompleted(attachments));
});
it('should set active step', () => {
bescheidService.getActiveStep.mockReturnValue(of(BescheidWizardStep.BescheidVersenden));
component.ngOnInit();
expect(component.activeStep$).toBeObservable(singleColdCompleted(BescheidWizardStep.BescheidVersenden));
});
});
describe('deleteAttachment', () => {
it('should call service', () => {
component.deleteAttachment = jest.fn();
const binaryFileResource: BinaryFileResource = createBinaryFileResource();
component.deleteAttachment(binaryFileResource);
expect(component.deleteAttachment).toHaveBeenCalledWith(binaryFileResource);
});
});
});
describe('template', () => {
describe('attachment files', () => {
function getComponent(): BescheidWizardAttachmentFilesComponent {
return getElementComponentFromFixtureByCss<BescheidWizardAttachmentFilesComponent>(fixture, attachmentsFilesTestId);
}
it('should exists', () => {
existsAsHtmlElement(fixture, attachmentsFilesTestId);
});
it('should have been called with attachments', () => {
component.attachments$ = of(attachments);
fixture.detectChanges();
expect(getComponent().attachments).toEqual(attachments);
});
it('should have been called with deletable true', () => {
component.activeStep$ = of(BescheidWizardStep.DokumenteHochladen);
fixture.detectChanges();
expect(getComponent().deletable).toEqual(true);
});
it('should have been called with deletable false', () => {
component.activeStep$ = of(BescheidWizardStep.BescheidVersenden);
fixture.detectChanges();
expect(getComponent().deletable).toEqual(false);
});
describe('output', () => {
describe('delete', () => {
it('should call handler', () => {
const binaryFileResource: BinaryFileResource = createBinaryFileResource();
component.deleteAttachment = jest.fn();
triggerEvent({ fixture, elementSelector: attachmentsFilesTestId, name: 'delete', data: binaryFileResource });
expect(component.deleteAttachment).toHaveBeenCalledWith(binaryFileResource);
});
});
});
});
});
});
import { BescheidAttachments, BescheidWizardStep } from '@alfa-client/bescheid-shared';
import { BinaryFileResource } from '@alfa-client/binary-file-shared';
import { Component, inject, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { BescheidService2 } from '../../../../../../bescheid-shared/src/lib/bescheid2.service';
@Component({
selector: 'alfa-bescheid-wizard-attachment-files-container',
templateUrl: './bescheid-wizard-attachment-files-container.component.html',
})
export class BescheidWizardAttachmentFilesContainerComponent implements OnInit {
public readonly bescheidService = inject(BescheidService2);
public attachments$: Observable<BescheidAttachments>;
public activeStep$: Observable<BescheidWizardStep>;
public readonly bescheidWizardStep = BescheidWizardStep;
ngOnInit(): void {
this.attachments$ = this.bescheidService.getAttachments();
this.activeStep$ = this.bescheidService.getActiveStep();
}
public deleteAttachment(binaryFileResource: BinaryFileResource): void {
this.bescheidService.deleteAttachment(binaryFileResource);
}
}
......@@ -26,13 +26,20 @@
</ods-textarea-editor>
</div>
<alfa-bescheid-wizard-dokumente-hochladen-summary
[isBescheidDocumentMissing]="false"
data-test-id="bescheid-versenden-dokumente"
></alfa-bescheid-wizard-dokumente-hochladen-summary>
<alfa-bescheid-wizard-document-file-container data-test-id="bescheid-document-file">
</alfa-bescheid-wizard-document-file-container>
@if (bescheidResource | hasLink: BescheidLinkRel.ATTACHMENTS) {
<alfa-binary-file-list-container
[resource]="bescheidResource"
[linkRel]="BescheidLinkRel.ATTACHMENTS"
[listOrientation]="BinaryFileListOrientation.VERTICAL"
data-test-id="bescheid-attachments"
></alfa-binary-file-list-container>
}
</div>
@if (
(bescheidResource | hasLink: bescheidLinkRel.UPDATE) || (bescheidResource | hasLink: bescheidLinkRel.BESCHEIDEN_UND_SENDEN)
(bescheidResource | hasLink: BescheidLinkRel.UPDATE) || (bescheidResource | hasLink: BescheidLinkRel.BESCHEIDEN_UND_SENDEN)
) {
<ods-button-with-spinner
class="self-end"
......
import { BescheidLinkRel, BescheidWizardDialogResult } from '@alfa-client/bescheid-shared';
import { CommandResource } from '@alfa-client/command-shared';
import { BinaryFileListContainerComponent } from '@alfa-client/binary-file';
import {
createEmptyStateResource,
createErrorStateResource,
createLoadingStateResource,
HasLinkPipe,
StateResource,
} from '@alfa-client/tech-shared';
import {
existsAsHtmlElement,
getElementComponentFromFixtureByCss,
mock,
Mock,
notExistsAsHtmlElement,
triggerEvent,
useFromMock,
} from '@alfa-client/test-utils';
import { existsAsHtmlElement, mock, Mock, notExistsAsHtmlElement, useFromMock } from '@alfa-client/test-utils';
import { DialogRef } from '@angular/cdk/dialog';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
......@@ -26,19 +17,18 @@ import { EMPTY, of } from 'rxjs';
import { BescheidService2 } from '../../../../../../../../bescheid-shared/src/lib/bescheid2.service';
import { createBescheidResource, createWizard } from '../../../../../../../../bescheid-shared/src/test/bescheid';
import { createSuccessfullyDoneCommandStateResource } from '../../../../../../../../command-shared/test/command';
import { getDataTestIdAttributeOf, getDataTestIdOf } from '../../../../../../../../tech-shared/test/data-test';
import { getDataTestIdOf } from '../../../../../../../../tech-shared/test/data-test';
import { createProblemDetail } from '../../../../../../../../tech-shared/test/error';
import { singleColdCompleted } from '../../../../../../../../tech-shared/test/marbles';
import { BescheidFormService } from '../../../../bescheid.formservice';
import { BescheidWizardDokumenteHochladenSummaryComponent } from '../../../dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component';
import { BescheidWizardDocumentFileContainerComponent } from '../../../document-file-container/bescheid-wizard-document-file-container.component';
import { BescheidWizardBescheidVersendenSendenComponent } from './bescheid-wizard-bescheid-versenden-senden.component';
describe('BescheidWizardBescheidVersendenSendenComponent', () => {
let component: BescheidWizardBescheidVersendenSendenComponent;
let fixture: ComponentFixture<BescheidWizardBescheidVersendenSendenComponent>;
const dokumenteTestsId: string = getDataTestIdOf('bescheid-versenden-dokumente');
const submitButtonTestId: string = getDataTestIdAttributeOf('send-button');
const attachmentsTestId: string = getDataTestIdOf('bescheid-attachments');
const empfaengerTestId: string = getDataTestIdOf('bescheid-nachricht-empfaenger');
let bescheidService: Mock<BescheidService2>;
......@@ -56,10 +46,11 @@ describe('BescheidWizardBescheidVersendenSendenComponent', () => {
await TestBed.configureTestingModule({
declarations: [
BescheidWizardBescheidVersendenSendenComponent,
MockComponent(BescheidWizardDokumenteHochladenSummaryComponent),
MockComponent(ButtonWithSpinnerComponent),
MockComponent(TextareaEditorComponent),
MockComponent(TextEditorComponent),
MockComponent(BinaryFileListContainerComponent),
MockComponent(BescheidWizardDocumentFileContainerComponent),
HasLinkPipe,
ReactiveFormsModule,
],
......@@ -246,68 +237,21 @@ describe('BescheidWizardBescheidVersendenSendenComponent', () => {
});
});
describe('dokumente hochladen summary', () => {
describe('attachment list', () => {
it('should exists', () => {
existsAsHtmlElement(fixture, dokumenteTestsId);
});
it('should have inputs', () => {
const dokumentComponent: BescheidWizardDokumenteHochladenSummaryComponent =
getElementComponentFromFixtureByCss<BescheidWizardDokumenteHochladenSummaryComponent>(fixture, dokumenteTestsId);
expect(dokumentComponent.isBescheidDocumentMissing).toBe(false);
});
describe('submit button', () => {
it('should exists with update link', () => {
component.bescheidResource = createBescheidResource([BescheidLinkRel.UPDATE]);
component.bescheidResource = createBescheidResource([BescheidLinkRel.ATTACHMENTS]);
fixture.detectChanges();
existsAsHtmlElement(fixture, dokumenteTestsId);
existsAsHtmlElement(fixture, attachmentsTestId);
});
it('should exists with bescheiden link', () => {
component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN_UND_SENDEN]);
fixture.detectChanges();
existsAsHtmlElement(fixture, dokumenteTestsId);
});
it('should NOT exists on missing links', () => {
it('should NOT exists', () => {
component.bescheidResource = createBescheidResource();
fixture.detectChanges();
notExistsAsHtmlElement(fixture, submitButtonTestId);
});
it('should have inputs', () => {
component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN_UND_SENDEN]);
const submitCommandStateResource: StateResource<CommandResource> = createSuccessfullyDoneCommandStateResource();
component.submitStateResource$ = of(submitCommandStateResource);
fixture.detectChanges();
const submitButtonComponent: ButtonWithSpinnerComponent =
getElementComponentFromFixtureByCss<ButtonWithSpinnerComponent>(fixture, submitButtonTestId);
expect(submitButtonComponent.stateResource).toEqual(submitCommandStateResource);
});
describe('output', () => {
describe('clickEmitter', () => {
it('should call handler', () => {
component.bescheidResource = createBescheidResource([BescheidLinkRel.BESCHEIDEN_UND_SENDEN]);
component.submit = jest.fn();
fixture.detectChanges();
triggerEvent({ fixture, elementSelector: submitButtonTestId, name: 'clickEmitter' });
expect(component.submit).toHaveBeenCalled();
});
});
});
notExistsAsHtmlElement(fixture, attachmentsTestId);
});
});
});
......
......@@ -4,6 +4,7 @@ import { createEmptyStateResource, StateResource } from '@alfa-client/tech-share
import { DialogRef } from '@angular/cdk/dialog';
import { Component, inject, Input } from '@angular/core';
import { Observable, of } from 'rxjs';
import { BinaryFileListOrientation } from '../../../../../../../../binary-file/src/lib/directive/binary-file-list-orientation/binary-file-list-orientation.directive';
import { BescheidFormService } from '../../../../bescheid.formservice';
@Component({
......@@ -22,8 +23,9 @@ export class BescheidWizardBescheidVersendenSendenComponent {
public focusBetreff: boolean = false;
public focusNachricht: boolean = false;
public readonly bescheidLinkRel = BescheidLinkRel;
public readonly BescheidLinkRel = BescheidLinkRel;
public readonly formServiceClass = BescheidFormService;
public readonly BinaryFileListOrientation = BinaryFileListOrientation;
public submit(): void {
this._resetFocus();
......
<div class="flex h-full flex-col justify-between">
<div>
<alfa-bescheid-wizard-antrag-bescheiden-summary></alfa-bescheid-wizard-antrag-bescheiden-summary>
<alfa-bescheid-wizard-dokumente-hochladen-summary
[isBescheidDocumentMissing]="false"
data-test-id="bescheid-versenden-dokumente"
></alfa-bescheid-wizard-dokumente-hochladen-summary>
<alfa-bescheid-wizard-document-file-container data-test-id="bescheid-document-file">
</alfa-bescheid-wizard-document-file-container>
@if (bescheidResource | hasLink: BescheidLinkRel.ATTACHMENTS) {
<alfa-binary-file-list-container
[resource]="bescheidResource"
[linkRel]="BescheidLinkRel.ATTACHMENTS"
[listOrientation]="BinaryFileListOrientation.VERTICAL"
data-test-id="bescheid-attachments"
></alfa-binary-file-list-container>
}
<p class="mb-8 text-base font-normal text-text">Der Bescheid muss manuell versendet werden.</p>
</div>
@if ((bescheidResource | hasLink: bescheidLinkRel.UPDATE) || (bescheidResource | hasLink: bescheidLinkRel.BESCHEIDEN)) {
@if ((bescheidResource | hasLink: BescheidLinkRel.UPDATE) || (bescheidResource | hasLink: BescheidLinkRel.BESCHEIDEN)) {
<ods-button-with-spinner
class="self-end"
[stateResource]="submitStateResource$ | async"
......
import { BescheidLinkRel, BescheidWizardDialogResult } from '@alfa-client/bescheid-shared';
import { BinaryFileListContainerComponent } from '@alfa-client/binary-file';
import { CommandResource } from '@alfa-client/command-shared';
import {
createEmptyStateResource,
......@@ -28,14 +29,14 @@ import { createProblemDetail } from '../../../../../../../../tech-shared/test/er
import { singleColdCompleted } from '../../../../../../../../tech-shared/test/marbles';
import { BescheidFormService } from '../../../../bescheid.formservice';
import { BescheidWizardAntragBescheidenSummaryComponent } from '../../../antrag-bescheiden/summary/bescheid-wizard-antrag-bescheiden-summary.component';
import { BescheidWizardDokumenteHochladenSummaryComponent } from '../../../dokumente-hochladen-container/summary/bescheid-wizard-dokumente-hochladen-summary.component';
import { BescheidWizardDocumentFileContainerComponent } from '../../../document-file-container/bescheid-wizard-document-file-container.component';
import { BescheidWizardBescheidVersendenSpeichernComponent } from './bescheid-wizard-bescheid-versenden-speichern.component';
describe('BescheidWizardBescheidVersendenSpeichernComponent', () => {
let component: BescheidWizardBescheidVersendenSpeichernComponent;
let fixture: ComponentFixture<BescheidWizardBescheidVersendenSpeichernComponent>;
const dokumenteTestsId: string = getDataTestIdOf('bescheid-versenden-dokumente');
const attachmentsTestId: string = getDataTestIdOf('bescheid-attachments');
const submitButtonTestId: string = getDataTestIdAttributeOf('confirm-and-save-button');
let formService: Mock<BescheidFormService>;
......@@ -52,7 +53,8 @@ describe('BescheidWizardBescheidVersendenSpeichernComponent', () => {
declarations: [
BescheidWizardBescheidVersendenSpeichernComponent,
MockComponent(BescheidWizardAntragBescheidenSummaryComponent),
MockComponent(BescheidWizardDokumenteHochladenSummaryComponent),
MockComponent(BinaryFileListContainerComponent),
MockComponent(BescheidWizardDocumentFileContainerComponent),
MockComponent(ButtonWithSpinnerComponent),
HasLinkPipe,
],
......@@ -118,16 +120,22 @@ describe('BescheidWizardBescheidVersendenSpeichernComponent', () => {
});
describe('template', () => {
describe('dokumente hochladen summary', () => {
describe('attachment list', () => {
it('should exists', () => {
existsAsHtmlElement(fixture, dokumenteTestsId);
component.bescheidResource = createBescheidResource([BescheidLinkRel.ATTACHMENTS]);
fixture.detectChanges();
existsAsHtmlElement(fixture, attachmentsTestId);
});
it('should have inputs', () => {
const dokumentComponent: BescheidWizardDokumenteHochladenSummaryComponent =
getElementComponentFromFixtureByCss<BescheidWizardDokumenteHochladenSummaryComponent>(fixture, dokumenteTestsId);
it('should NOT exists', () => {
component.bescheidResource = createBescheidResource();
expect(dokumentComponent.isBescheidDocumentMissing).toBe(false);
fixture.detectChanges();
notExistsAsHtmlElement(fixture, attachmentsTestId);
});
});
describe('submit button', () => {
......@@ -136,7 +144,7 @@ describe('BescheidWizardBescheidVersendenSpeichernComponent', () => {
fixture.detectChanges();
existsAsHtmlElement(fixture, dokumenteTestsId);
existsAsHtmlElement(fixture, submitButtonTestId);
});
it('should exists with bescheiden link', () => {
......@@ -144,7 +152,7 @@ describe('BescheidWizardBescheidVersendenSpeichernComponent', () => {
fixture.detectChanges();
existsAsHtmlElement(fixture, dokumenteTestsId);
existsAsHtmlElement(fixture, submitButtonTestId);
});
it('should NOT exists on missing links', () => {
......@@ -161,8 +169,10 @@ describe('BescheidWizardBescheidVersendenSpeichernComponent', () => {
component.submitStateResource$ = of(submitCommandStateResource);
fixture.detectChanges();
const submitButtonComponent: ButtonWithSpinnerComponent =
getElementComponentFromFixtureByCss<ButtonWithSpinnerComponent>(fixture, submitButtonTestId);
const submitButtonComponent: ButtonWithSpinnerComponent = getElementComponentFromFixtureByCss<ButtonWithSpinnerComponent>(
fixture,
submitButtonTestId,
);
expect(submitButtonComponent.stateResource).toEqual(submitCommandStateResource);
});
......@@ -183,4 +193,3 @@ describe('BescheidWizardBescheidVersendenSpeichernComponent', () => {
});
});
});
});
......@@ -4,6 +4,7 @@ import { createEmptyStateResource, StateResource } from '@alfa-client/tech-share
import { DialogRef } from '@angular/cdk/dialog';
import { Component, inject, Input } from '@angular/core';
import { Observable, of } from 'rxjs';
import { BinaryFileListOrientation } from '../../../../../../../../binary-file/src/lib/directive/binary-file-list-orientation/binary-file-list-orientation.directive';
import { BescheidFormService } from '../../../../bescheid.formservice';
@Component({
......@@ -18,7 +19,8 @@ export class BescheidWizardBescheidVersendenSpeichernComponent {
public submitStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>());
public readonly bescheidLinkRel = BescheidLinkRel;
public readonly BinaryFileListOrientation = BinaryFileListOrientation;
public readonly BescheidLinkRel = BescheidLinkRel;
public submit(): void {
this.submitStateResource$ = this.formService
......
......@@ -112,12 +112,6 @@ describe('BescheidWizardDokumenteHochladenComponent', () => {
});
describe('onWeiterClick', () => {
it('should finish adding attachments', () => {
component.onWeiterClick();
expect(bescheidService.finishAddingAttachments).toHaveBeenCalled();
});
it('should finish adding bescheid document', () => {
component.onWeiterClick();
......
......@@ -45,7 +45,6 @@ export class BescheidWizardDokumenteHochladenContainerComponent implements OnIni
}
public onWeiterClick(): void {
this.bescheidService.finishAddingAttachments();
this.bescheidService.finishAddingBescheidDocument();
this.bescheidService.setActiveStep(BescheidWizardStep.BescheidVersenden);
}
......
......@@ -34,6 +34,12 @@
</alfa-bescheid-wizard-document-file-container>
</div>
<div class="my-4">
<alfa-bescheid-wizard-attachment-files-container data-test-id="bescheid-attachment-files">
</alfa-bescheid-wizard-attachment-files-container>
<ods-file-upload-list-container
[parentFormArrayName]="BescheidFormService.FIELD_ATTACHMENTS"
[fileUploadType]="BESCHEID_UPLOADED_ATTACHMENTS"
[filesResource]="bescheidResource"
[filesLinkRel]="BescheidLinkRel.ATTACHMENTS"
[listOrientation]="BinaryFileListOrientation.VERTICAL"
data-test-id="bescheid-attachments"
></ods-file-upload-list-container>
</div>
......@@ -21,11 +21,11 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
import { FileUploadListContainerComponent } from '@alfa-client/binary-file';
import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MockComponent } from 'ng-mocks';
import { getDataTestIdOf } from '../../../../../../../tech-shared/test/data-test';
import { BescheidWizardAttachmentFilesContainerComponent } from '../../attachment-files-container/bescheid-wizard-attachment-files-container.component';
import { BescheidWizardDocumentFileContainerComponent } from '../../document-file-container/bescheid-wizard-document-file-container.component';
import { BescheidWizardDokumenteHochladenSummaryComponent } from './bescheid-wizard-dokumente-hochladen-summary.component';
......@@ -35,14 +35,14 @@ describe('BescheidWizardDokumenteHochladenSummaryComponent', () => {
const missingBescheidErrorMessageTestId: string = getDataTestIdOf('missing-bescheid-document-error-message');
const documentFileTestId: string = getDataTestIdOf('bescheid-document-file');
const attachmentFilesTestId: string = getDataTestIdOf('bescheid-attachment-files');
const attachmentFilesTestId: string = getDataTestIdOf('bescheid-attachments');
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [
BescheidWizardDokumenteHochladenSummaryComponent,
MockComponent(BescheidWizardDocumentFileContainerComponent),
MockComponent(BescheidWizardAttachmentFilesContainerComponent),
MockComponent(FileUploadListContainerComponent),
],
}).compileComponents();
......
......@@ -21,12 +21,21 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
import { BESCHEID_UPLOADED_ATTACHMENTS, BescheidLinkRel, BescheidResource } from '@alfa-client/bescheid-shared';
import { Component, Input } from '@angular/core';
import { BinaryFileListOrientation } from '../../../../../../../binary-file/src/lib/directive/binary-file-list-orientation/binary-file-list-orientation.directive';
import { BescheidFormService } from '../../../bescheid.formservice';
@Component({
selector: 'alfa-bescheid-wizard-dokumente-hochladen-summary',
templateUrl: './bescheid-wizard-dokumente-hochladen-summary.component.html',
})
export class BescheidWizardDokumenteHochladenSummaryComponent {
@Input() bescheidResource: BescheidResource;
@Input() isBescheidDocumentMissing: boolean;
public readonly BESCHEID_UPLOADED_ATTACHMENTS = BESCHEID_UPLOADED_ATTACHMENTS;
public readonly BescheidLinkRel = BescheidLinkRel;
public readonly BescheidFormService = BescheidFormService;
public readonly BinaryFileListOrientation = BinaryFileListOrientation;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment