0

I am developing a Javascript SDK and I am using an external library defined on the window object

  private getFromATS(): string {
    return window.ats.retrieveEnvelope(function (envelope: string) {
      console.log('Located ATS.js');
      return JSON.parse(envelope).envelope;
    });
  }

Now I am developing some unit tests and I am trying to mock this library. So far I have tried the following which have not worked

// Method 1
spyOn(window.ats, 'retrieveEnvelope').and.returnValue(function (
      callback: Callback<String>
    ) {
      return callback('{"envelope":"asdfasdfasdf"}');
    });

// Method 2
    spyOn(window, 'ats').and.returnValue({
      retrieveEnvelope: function (callback: Callback<String>) {
        return callback('{"envelope":"asdfasdfasdf"}');
      },
    });

// Method 3
    window = Object.create(window);
    Object.defineProperty(window, 'ats', {
      value: {
        retrieveEnvelope: function (callback: Callback<String>) {
          return callback('{"envelope":"asdfasdfasdf"}');
        },
      },
      writable: true,
    });

// Method 4
const windowStud = {
      ats: {
        retrieveEnvelope: function (callback: Callback<String>) {
          return callback('{"envelope":"asdfasdfasdf"}');
        },
      },
    } as Window & typeof globalThis;

None of these work. How can I mock an "external" property of the window object using Jasmine?

// EDIT

This is a great solution using dependency injection but is there a way to avoid changing that main code to achieve that?

Niko
  • 616
  • 4
  • 20

1 Answers1

0

You can try defining it on a beforeEach/beforeAll and set it back to undefined in an afterEach/afterAll for the other test suites.

beforeEach(() => {
  // set the property
  window.ats = {
      retrieveEnvelope: function (callback: Callback<String>) {
        return callback('{"envelope":"asdfasdfasdf"}');
      },
   };
});

afterEach(() => {
  // reset back to undefined
  window.ats = undefined;
});
AliF50
  • 16,947
  • 1
  • 21
  • 37