Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I unit test downloading a file using Jasmine (Angular)?

I have an Angular 6 app that has an "export to CSV" button that when clicked, runs a method on the component that generates the CSV text to be downloaded. The file is then downloaded with the following code:

const tempLink = document.createElement('a');
tempLink.href = 'data:text/csv;charset=utf-8,' + encodeURI(csvContent);
tempLink.target = '_blank';
tempLink.download = 'export.csv';
tempLink.click();

How would I unit test clicking the "Export to CSV" button without triggering an actual download?

Would the only approach be to create the link in the HTML (not dynamically) and then have a Jasmine spy on the click event of the link?

like image 797
mprahl Avatar asked Aug 14 '18 16:08

mprahl


People also ask

How do you write unit test cases in Angular using Jasmine?

Create an Angular project with jasmine and karma By doing this, the jasmine and karma configuration is resolved for us. Install and create a new project with angular-cli: Install npm -g @angular/cli. Ng new angular-unit-testing angular unit-testing.

What is Jasmine testing framework and how do you use it for Angular unit testing?

Jasmine is a behavior development testing framework. Unit tests are written using Jasmine and are run to see if individual parts of an application are working correctly. As a result, unit tests will either pass or fail depending on if the code is working correctly or has a bug.


1 Answers

You can use the Jasmine spy functions (spyOn, spyOnProperty, jasmine.createSpy, jasmine.createSpyObj) in combination with the and methods to spy on and mock behavior.

In this case you can mock document.createElement() to return a spy object that you can use to verify that the correct properties get set and click() gets called.

Here is a working example:


example.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-example',
  template: '<div><button (click)="download()">Download Csv</button></div>'
})
export class ExampleComponent implements OnInit {

  constructor() { }

  ngOnInit() { }

  download() {
    const csvContent = this.generateCsv();
    const tempLink = document.createElement('a');
    tempLink.href = 'data:text/csv;charset=utf-8,' + encodeURI(csvContent);
    tempLink.target = '_blank';
    tempLink.download = 'export.csv';
    tempLink.click();
  }

  private generateCsv() {
    return 'ID,Name\n1,abc\n2,def\n';
  }

}

example.component.spec.ts

import { ExampleComponent } from './example.component';

describe('ExampleComponent', () => {

  it('should download the csv file', () => {
    // create spy object with a click() method
    const spyObj = jasmine.createSpyObj('a', ['click']);
    // spy on document.createElement() and return the spy object
    spyOn(document, 'createElement').and.returnValue(spyObj);

    const comp = new ExampleComponent();
    comp.download();

    expect(document.createElement).toHaveBeenCalledTimes(1);
    expect(document.createElement).toHaveBeenCalledWith('a');

    expect(spyObj.href).toBe('data:text/csv;charset=utf-8,ID,Name%0A1,abc%0A2,def%0A');
    expect(spyObj.target).toBe('_blank');
    expect(spyObj.download).toBe('export.csv');
    expect(spyObj.click).toHaveBeenCalledTimes(1);
    expect(spyObj.click).toHaveBeenCalledWith();
  });

});
like image 199
Brian Adams Avatar answered Sep 24 '22 23:09

Brian Adams