Skip to content

Commit

Permalink
fix(upload): prevent error disappear when upload failed (#1057)
Browse files Browse the repository at this point in the history
* fix(upload): prevent error disappear when upload failed

* fix(upload): prevent error disappear when upload failed

* fix(upload): prevent error disappear when upload failed

* fix(upload): prevent error disappear when upload failed

* Update projects/ng-aquila/src/file-uploader/file-uploader.component.spec.ts

Co-authored-by: thilo-aschebrock <[email protected]>

Co-authored-by: thilo-aschebrock <[email protected]>
  • Loading branch information
2 people authored and GitHub Enterprise committed Oct 17, 2023
1 parent f87c95d commit cffaca6
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { HttpClientModule } from '@angular/common/http';
import { Component, Directive, Type, ViewChild } from '@angular/core';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { ChangeDetectorRef, Component, Directive, Type, ViewChild } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { FormBuilder, FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { NxErrorModule, NxLabelModule } from '@aposin/ng-aquila/base';
import { NxIconModule } from '@aposin/ng-aquila/icon';

import { NxFileUploader } from './file-uploader';
import { NxFileUploaderComponent } from './file-uploader.component';
import { FileItem } from './file-uploader.model';
import { NxFileUploaderModule } from './file-uploader.module';
Expand Down Expand Up @@ -33,6 +36,7 @@ describe('NxFileUploaderComponent', () => {
let hintElement: HTMLElement;
let inputElm: HTMLInputElement;
let labelElm: HTMLInputElement;
let httpTestingController: HttpTestingController;

function createTestComponent(component: Type<FileUploaderTest>) {
fixture = TestBed.createComponent(component);
Expand All @@ -55,9 +59,20 @@ describe('NxFileUploaderComponent', () => {

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [BasicFileUpload, ReactiveFileUpload, DynamicFileUpload, CustomItemTemplateFileUpload],
imports: [NxFileUploaderModule, NxLabelModule, NxIconModule, ReactiveFormsModule, FormsModule, NxErrorModule, HttpClientModule],
declarations: [BasicFileUpload, ReactiveFileUpload, DynamicFileUpload, CustomItemTemplateFileUpload, UploadFail],
imports: [
NxFileUploaderModule,
NxLabelModule,
NxIconModule,
ReactiveFormsModule,
FormsModule,
NxErrorModule,
HttpClientModule,
HttpClientTestingModule,
],
}).compileComponents();

httpTestingController = TestBed.inject(HttpTestingController);
}));

describe('basic', () => {
Expand Down Expand Up @@ -272,6 +287,37 @@ describe('NxFileUploaderComponent', () => {
expect(testInstance.form.controls.documents.hasError('required')).toBeTrue();
});

it('should remove failed upload file from the list and show error message', () => {
createTestComponent(UploadFail);
fixture.detectChanges();
let fakeFile = new File(['1'], 'fake file', { type: 'text/html' });
fakeFile = Object.defineProperty(fakeFile, 'size', { value: 12, writable: false });
const fileList = {
0: fakeFile,
length: 1,
item: () => fakeFile,
};

fileUploaderInstance._onFileChange({
type: 'change',
target: {
files: fileList,
},
});
fixture.detectChanges();
expect(fileUploaderInstance.value?.length).toBe(1);

const uploadButton = fixture.nativeElement.querySelector('#upload-trigger');

uploadButton.click();
fixture.detectChanges();

httpTestingController.expectOne('/file-upload-error').flush(null, { status: 404, statusText: 'error' });

expect(fileUploaderInstance.value?.length).toBe(0);
expect(testInstance.form?.get('documents')?.hasError('serverError')).toBeTruthy();
});

it('should list all files error in errors property', () => {
createTestComponent(ReactiveFileUpload);
testInstance.required = true;
Expand Down Expand Up @@ -796,3 +842,43 @@ class CustomItemTemplateFileUpload extends FileUploaderTest {
this.outputFile = value;
}
}
@Component({
template: `
<form [formGroup]="form">
<nx-file-uploader #documentUpload formControlName="documents" [uploader]="uploader" multiple>
<nx-label>Required file to upload</nx-label>
<span nxFileUploadHint>All files are accepted</span>
<button type="button" nxFileUploadButton>Add Files</button>
</nx-file-uploader>
<nx-error *ngIf="form.controls['documents'].hasError('serverError')" class="error-message"> An error occured while uploading. </nx-error>
<button id="upload-trigger" [nxFileUploadTriggerFor]="documentUpload" type="button">Upload files</button>
</form>
`,
})
class UploadFail extends FileUploaderTest {
fb: FormBuilder;
files!: null | FileItem[];
uploadConfig = {
requestUrl: '/file-upload-error',
options: {
reportProgress: true,
},
uploadSeparately: false,
};
uploader = new NxFileUploader(this.uploadConfig, this.http);

constructor(private readonly http: HttpClient, private cdr: ChangeDetectorRef) {
super();
this.uploader.response.pipe(takeUntilDestroyed()).subscribe(result => {
if (result.error) {
this.form.controls.documents.setErrors({
serverError: true,
});
}
});
this.fb = new FormBuilder();
this.form = this.fb.group({
documents: new FormControl([]),
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,6 @@ export class NxFileUploaderComponent implements ControlValueAccessor, AfterConte
this._filesSubscriptions = [];
}
}

this._resetValidators();
this._value = value;
this._subscribeToFileChanges();
}
Expand Down Expand Up @@ -539,14 +537,15 @@ export class NxFileUploaderComponent implements ControlValueAccessor, AfterConte
return;
}

// Remove latest upload failed from the list
if (this.uploader) {
this.uploader.response.pipe(take(1)).subscribe(res => {
const success = res.success?.files.filter(file => file.isUploaded);
const errorFiles = res.error?.files.filter(file => file.isError);
const successFiles = this.value?.filter(file => file.isUploaded && !file.isError);
const errorFiles = res.error?.files.filter(file => !file.isUploaded && file.isError);
if (errorFiles?.length) {
errorFiles?.forEach(file => this.setFileUploadError(file, 'An error occured while uploading'));
}
this.value = success;
this.value = successFiles;
});
this.uploader.uploadFiles(this.value!);
}
Expand Down

0 comments on commit cffaca6

Please sign in to comment.