简体   繁体   中英

How to test function defined on window object in Jest and typescript

I'm trying to test a call to a function defined on the global window object. I have looked at multiple examples but am still not able to run a simple test case.

Api.ts

import "./global.d";
const verifier = window.Verifier;

export class Api {
  constructor(private readonly id: string) {}
  public fetchData() {
    return new Promise<object>((resolve, reject) => {
      verifier.request({
        request: {
          id: this.id
        },
        onSuccess: (data: object) => {
          resolve(data);
        },
        onFailure: () => {
          reject("Error!");
        }
      });
    });
  }
}

Api.test.ts

import { Api } from "./Api";

let windowSpy: any;

describe("Test Apis", () => {
  beforeEach(() => {
    windowSpy = jest.spyOn(window, "window", "get");
  });

  afterEach(() => {
    windowSpy.mockRestore();
  });
  it("should call the function", () => {
    const mockedReplace = jest.fn();
    windowSpy.mockImplementation(() => ({
      Verifier: {
        request: mockedReplace
      }
    }));
    const api = new Api("123");
    api.fetchData();
    expect(mockedReplace).toHaveBeenCalled();
  });
});

global.d.ts

import { Verifier } from "./verifier";

declare global {
  interface Window {
    Verifier: Verifier;
  }
}

verifier.d.ts

type RequestPayload = {
  request: {
    id: string;
  };
  onSuccess: (data: object) => void;
  onFailure: () => void;
};
type verifyCode = number;

export interface Verifier {
  request: (requestPayload: RequestPayload) => verifyCode;
}

I have also created a codesandbox example for easy reference https://codesandbox.io/s/cranky-mccarthy-2jj622?file=/src/verifier.d.ts

The problem here is your import order.

When you import { Api } from "./api"; , you run const verifier = window.Verifier; , which, at the time, is undefined .

If you change the order of the imports and spies it should work as expected:

import { RequestPayload } from "./verifier";

const mockRequest = jest
  .fn()
  .mockImplementation((requestPayload: RequestPayload) => 1);

jest.spyOn(window, "window", "get").mockImplementation(() => {
  return {
    Verifier: {
      request: mockRequest,
    },
  } as unknown as Window & typeof globalThis;
});

// // // // //

import { Api } from "./api";

// // // // //

describe("Test Apis", () => {
  let api: Api;

  beforeEach(() => {
    jest.clearAllMocks();
  });

  beforeEach(() => {
    api = new Api("123");
  });

  it("should have valid function", () => {
    expect(typeof api.fetchData).toBe("function");
  });

  it("should call the function", () => {
    api.fetchData();

    expect(mockRequest).toHaveBeenCalled();
  });
});

You could also think about using window.Verifier directly, making the tests a bit cleaner:

export class Api {
  constructor(private readonly id: string) {}
  public fetchData() {
    return new Promise<object>((resolve, reject) => {
      window.Verifier.request({
        request: {
          id: this.id,
        },
        onSuccess: (data: object) => {
          resolve(data);
        },
        onFailure: () => {
          reject("Error!");
        },
      });
    });
  }
}
describe("Test Apis", () => {
  let api: Api, mockRequest: jest.Mock;

  beforeEach(() => {
    jest.clearAllMocks();

    mockRequest = jest
      .fn()
      .mockImplementation((requestPayload: RequestPayload) => 1);

    jest.spyOn(global, "window", "get").mockImplementation(() => {
      return {
        Verifier: {
          request: mockRequest,
        },
      } as unknown as Window & typeof globalThis;
    });
  });

  beforeEach(() => {
    api = new Api("123");
  });

  it("should have valid function", () => {
    expect(typeof api.fetchData).toBe("function");
  });

  it("should call the function", () => {
    api.fetchData();

    expect(mockRequest).toHaveBeenCalled();
  });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM