feat: add error handling to CashboxExportDialog

This commit is contained in:
Bastian Wagner
2026-08-04 08:29:22 +02:00
parent 5c3ff52689
commit 11b70b9337
2 changed files with 38 additions and 5 deletions

View File

@@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { of } from 'rxjs'; import { of, throwError } from 'rxjs';
import { CashboxExportApi } from '../../../../core/team/cashbox-export-api'; import { CashboxExportApi } from '../../../../core/team/cashbox-export-api';
import { FileDownloadService } from '../../../../shared/file-download/file-download.service'; import { FileDownloadService } from '../../../../shared/file-download/file-download.service';
import { CashboxExportDialog } from './cashbox-export-dialog'; import { CashboxExportDialog } from './cashbox-export-dialog';
@@ -46,4 +46,26 @@ describe('CashboxExportDialog', () => {
expect(save).toHaveBeenCalledWith(expect.any(Blob), 'kassenbuch_2026-08-01_2026-08-31.csv'); expect(save).toHaveBeenCalledWith(expect.any(Blob), 'kassenbuch_2026-08-01_2026-08-31.csv');
expect(dialogRef.close).toHaveBeenCalled(); expect(dialogRef.close).toHaveBeenCalled();
}); });
it('displays error message and does not close dialog on export failure', () => {
exportCashbox = vi.fn(() => throwError(() => new Error('network error')));
TestBed.resetTestingModule();
TestBed.configureTestingModule({
imports: [CashboxExportDialog],
providers: [
{ provide: MAT_DIALOG_DATA, useValue: { teamId: 5 } },
{ provide: MatDialogRef, useValue: dialogRef },
{ provide: CashboxExportApi, useValue: { exportCashbox } },
{ provide: FileDownloadService, useValue: { save } },
],
});
fixture = TestBed.createComponent(CashboxExportDialog);
fixture.detectChanges();
fixture.componentInstance['form'].setValue({ from: '2026-08-01', to: '2026-08-31', format: 'csv' });
fixture.componentInstance['download']();
expect(dialogRef.close).not.toHaveBeenCalled();
expect(fixture.componentInstance['downloadError']()).toBe('Export konnte nicht heruntergeladen werden.');
});
}); });

View File

@@ -1,4 +1,4 @@
import { Component, inject } from '@angular/core'; import { Component, inject, signal } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, ValidationErrors, ValidatorFn, Validators } from '@angular/forms'; import { FormBuilder, ReactiveFormsModule, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
@@ -29,6 +29,9 @@ const rangeValid: ValidatorFn = (group): ValidationErrors | null => {
<h2 mat-dialog-title>Kassenbuch exportieren</h2> <h2 mat-dialog-title>Kassenbuch exportieren</h2>
<form [formGroup]="form" (ngSubmit)="download()"> <form [formGroup]="form" (ngSubmit)="download()">
<mat-dialog-content> <mat-dialog-content>
@if (downloadError()) {
<p class="error">{{ downloadError() }}</p>
}
<mat-form-field appearance="outline"> <mat-form-field appearance="outline">
<mat-label>Von</mat-label> <mat-label>Von</mat-label>
<input matInput formControlName="from" type="date" /> <input matInput formControlName="from" type="date" />
@@ -59,6 +62,8 @@ export class CashboxExportDialog {
private readonly api = inject(CashboxExportApi); private readonly api = inject(CashboxExportApi);
private readonly fileDownload = inject(FileDownloadService); private readonly fileDownload = inject(FileDownloadService);
protected readonly downloadError = signal<string | null>(null);
protected readonly form = this.formBuilder.nonNullable.group( protected readonly form = this.formBuilder.nonNullable.group(
{ {
from: ['', Validators.required], from: ['', Validators.required],
@@ -70,10 +75,16 @@ export class CashboxExportDialog {
protected download(): void { protected download(): void {
if (this.form.invalid) return; if (this.form.invalid) return;
this.downloadError.set(null);
const { from, to, format } = this.form.getRawValue(); const { from, to, format } = this.form.getRawValue();
this.api.exportCashbox(this.data.teamId, from, to, format).subscribe((blob) => { this.api.exportCashbox(this.data.teamId, from, to, format).subscribe({
next: (blob) => {
this.fileDownload.save(blob, `kassenbuch_${from}_${to}.${format}`); this.fileDownload.save(blob, `kassenbuch_${from}_${to}.${format}`);
this.dialogRef.close(); this.dialogRef.close();
},
error: () => {
this.downloadError.set('Export konnte nicht heruntergeladen werden.');
},
}); });
} }
} }