如何测试在窗口对象和打字稿中定义的函数

发布于 2025-02-11 18:43:54 字数 1756 浏览 0 评论 0 原文

我正在尝试测试对全局窗口对象上定义的函数的调用。我已经查看了多个示例,但仍然无法运行一个简单的测试用例。

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.t.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'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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

固执像三岁 2025-02-18 18:43:54

这里的问题是您的进口订单。

当您从“ ./api” 导入{api}时,您运行 const verifier = window.verifier; ,当时是 undefined << /代码>。

如果您更改导入和间谍的顺序,则应按预期工作:

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();
  });
});

您还可以直接考虑使用 window.verifier ,使测试有点清洁:

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 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();
  });
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文