Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 Unit Testing the code using window

I would like to test a code

public openAttachment(attachment: Attachment) {
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
        window.navigator.msSaveOrOpenBlob(attachment.getFile());
    }
    else {
        let objectUrl = URL.createObjectURL(attachment.getFile());
        window.open(objectUrl);
    }
}

I don't know how to get access to window or mock window in order to test it. I'm new to angular testing so it would be great if you could explain me in a detail please!

like image 698
Eugenia Kim Avatar asked Mar 16 '26 16:03

Eugenia Kim


1 Answers

You'll have access to the window object in your tests as well. So you can easily spy on them.

I've created a lightweight component with your particular usecase in mind.

Following is the component:

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

@Component({
  selector: 'app-attachment',
  templateUrl: './attachment.component.html',
  styleUrls: ['./attachment.component.css']
})
export class AttachmentComponent {

  public openAttachment(attachment) {
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
      window.navigator.msSaveOrOpenBlob(attachment.getFile());
    }
    else {
      let objectUrl = URL.createObjectURL(attachment.getFile());
      window.open(objectUrl);
    }
  }

}

Note that here I'm not sure what the Attachment type is. So I've removed that type annotation from the parameters to the openAttachment function.

And now this is how my tests should look:

import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { AttachmentComponent } from './attachment.component';

describe('AttachmentComponent', () => {
  let component: AttachmentComponent;
  let fixture: ComponentFixture<AttachmentComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ AttachmentComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AttachmentComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should be created', () => {
    expect(component).toBeTruthy();
  });

  describe('openAttachment', () => {
    let attachment;
    beforeEach(() => {
      attachment = { getFile: function() { return 'foo'; } };
    });

    it('should call `window.open` if `msSaveOrOpenBlob` is not a method present on the `window.navigator`', () => {

      // Since this will probably run on Chrome, Chrome Headless or PhantomJS, if won't have a `msSaveOrOpenBlob` method on it.
      // So this is the test for the else condition.
      let windowOpenSpy = spyOn(window, 'open');
      let returnValue = { foo: 'bar' };
      let urlCreateObjectSpy = spyOn(URL, 'createObjectURL').and.returnValue(returnValue);

      component.openAttachment(attachment);

      expect(urlCreateObjectSpy).toHaveBeenCalledWith('foo');
      expect(windowOpenSpy).toHaveBeenCalledWith(returnValue);

    });

    it('should call the `window.navigator.msSaveOrOpenBlob` if `msSaveOrOpenBlob` is present on the navigator object', () => {

      // To cover the if condition, we'll have to attach a `msSaveOrOpenBlob` method on the window.navigator object.
      // We can then spy on it and check whether that spy was called or not.
      // Our implementation will have to return a boolean because that's what is the return type of `msSaveOrOpenBlob`.
      window.navigator.msSaveOrOpenBlob = function() { return true; };
      let msSaveOrOpenBlobSpy = spyOn(window.navigator, 'msSaveOrOpenBlob');

      component.openAttachment(attachment);

      expect(msSaveOrOpenBlobSpy).toHaveBeenCalledWith('foo');

    });

  });

});

Again I'd like to emphasize on the fact that I'm not sure what the attachment type is going to be. So in the beforeEach block of my openAttachment describe block, I'm assigning it to an object that contains a key named getFile with value as a function that would eventually return a string foo.

Also since your tests would be running in Chrome by default, you won't get the msSaveOrOpenBlob function on the window.navigator object. So the first test in the openAttachment describe block would only cover the else block.

In the second test though, we've added msSaveOrOpenBlob as a function on the window.navigator object. So now it would be able to cover the if branch. So then you can create a spy on the msSaveOrOpenBlob function and expect this spy toHaveBeenCalledWith whatever is returned from the attachment.getFile() method(string foo in this case)

Hope this helps.

like image 163
SiddAjmera Avatar answered Mar 18 '26 05:03

SiddAjmera



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!