How to write the unit testing for the file upload method in the Angular 7 (or 2+)

12,796

Solution 1

For the 100% code coverage of the mentioned section, I have added below 2 test cases. This works for me.

it('should upload the file - checkFileExist = true', () => {
    spyOn(component, 'checkFileExist').and.returnValue(true);
    spyOn(postalService,'importPostalCodes').and.callThrough();
    component.importFile();
    expect(postalService.importPostalCodes).toHaveBeenCalled();
});

it('should upload the file - checkFileExist = false', () => {
    spyOn(component, 'checkFileExist').and.returnValue(false);
    spyOn(postalService,'importPostalCodes').and.callThrough();
    component.importFile();
    expect(postalService.importPostalCodes).toHaveBeenCalledTimes(0);
});

Solution 2

A simple way to test file upload and check model value set.

.html

<input (change)="onFileSelected()" #fileInput type="file" id="file">

.ts

uploadedFile : any

onFileSelected() {
  const inputNode: any = document.querySelector('#file');
  this.uploadedFile  = inputNode.files[0];
}

spec.ts

it('should detect file input change and set uploadedFile  model', () => {
    const dataTransfer = new DataTransfer()
    dataTransfer.items.add(new File([''], 'test-file.pdf'))

    const inputDebugEl  = fixture.debugElement.query(By.css('input[type=file]'));
    inputDebugEl.nativeElement.files = dataTransfer.files;

    inputDebugEl.nativeElement.dispatchEvent(new InputEvent('change'));

    fixture.detectChanges();

    expect(component.uploadedFile).toBeTruthy()
    expect(component.uploadedFile).toBe('test-file.pdf')
    
});

it('file change event should arrive in handler', () => {
    const element = fixture.nativeElement;
    const input = element.querySelector('#file');
    spyOn(component, 'onFileSelected');
    input.dispatchEvent(new Event('change'));
    fixture.detectChanges();
    expect(component.onFileSelected).toHaveBeenCalled();
});
Share:
12,796
Helphin
Author by

Helphin

lazy ....

Updated on July 25, 2022

Comments

  • Helphin
    Helphin almost 2 years

    I'm trying to write the unit testing for the file upload method in the angular 7. Getting the below error in the testing window. I'm new for angular unit testing. Could someone help, How to add mock files to get the full code coverage?

    TypeError: Cannot set property 'value' of undefined

    Here is my unit test code (spec file),

    describe('ImportComponent', () => {
        let component: ImportComponent;
        let fixture: ComponentFixture<ImportComponent>;
        let element;
    
        beforeEach(
            async(() => {
                TestBed.configureTestingModule({
                    imports: [ HttpClientModule, RouterTestingModule ],
                    declarations: [ ImportComponent ]
                }).compileComponents();
            })
        );
    
        beforeEach(() => {
            fixture = TestBed.createComponent(ImportComponent);
            component = fixture.componentInstance;
            element = fixture.nativeElement;
            fixture.detectChanges();
        });
    
        it('should create', () => {
            expect(component).toBeTruthy();
        });
    
        it('should upload the file', () => {
            component.importFile();
            const inputEl = element.querySelector('#postal_file');
            const fileList = { 0: { name: 'foo', size: 500001 } };
            inputEl.value = {
                target: {
                    files: fileList
                }
            };
            inputEl.dispatchEvent(new Event('change'));     
        });
    });
    

    Method in the component

    importFile() {
            const inputEl: HTMLInputElement = this.el.nativeElement.querySelector('#postal_file');
            const fileCount: number = inputEl.files.length;
            const formData = new FormData();
            if (fileCount > 0) {
                formData.append(this.postalFileName, inputEl.files.item(0));
                this.postalService.importPostalCodes(formData).subscribe((data) => {
                    this.result = data;
                });
            }
        }
    

    and the HTML,

    <div class="file-import">
            <form action="" method="post" encType="multipart/form-data">
                <label for="postal_file">Choose File</label>
                <input type="file" name="postal_file" id="postal_file">
                <button type="button" (click)="importFile()">Import</button>
            </form>
        </div>
    

    The unit test is not covered all the code as shown in the below image, please help , how to ge the 100% code coverage.

    Code coverage image

  • Abhishek Singh
    Abhishek Singh almost 3 years
    Awesome..! really you answer worth 100 likes..!!
  • sharpshooter
    sharpshooter over 2 years
    Hello @adrita, your answer helped me a lot, but how can I pass an actual csv file with valid data to cover the other lines in main component code?