我正在尝试使用TypeScript,Jest和jQuery编写单元测试。我走得很远,但是运行测试时,出现“ jQuery需要带有文档的窗口”
显然,问题在于import * as $ from "jquery"
(see this question)也将初始化jQuery,但那时没有窗口。我需要的是jQuery模块的“惰性”版本,类似于$(document).ready(...)
通常的形式,只是$
符号本身。
背景:我已将jQuery安装为npm install @types/jquery
。我正在使用jsdom
创建一个假窗口。我正在使用ts-jest
将TS文件转换为jest
的JavaScript。使用npx jest --watch
或npm t
运行测试。
我想避免在Jest setupFile中使用global.$
,因为许多测试不需要开销。
答案 0 :(得分:0)
我有一个解决方案,但是您不能在测试的代码中使用$,因此它仅适用于您编写/可以更改的代码。
而不是直接使用$
,而是将其包装在提供程序中:
export class JQueryProvider {
constructor(public jq: any) {
// empty
}
get(selector: string): JQuery {
return this.jq(selector)
}
}
这样,我们可以隐藏$
来源的详细信息。即使输入get()
的类型为jq
,any
方法也会将结果转换为正确的类型。
此代码应进入共享实用程序模块。
测试应包括具有以下设置代码的模块:
import { JQueryProvider } from "./utils"
import { JSDOM } from "jsdom";
export type WithJQueryFunction = (jq: JQueryProvider) => void;
export function withJQuery(fn: WithJQueryFunction): void {
// Create window before loading jquery
const window = new JSDOM().window
// Create jQuery instance
const $ = require('jquery')(window);
// Create provider to avoid the global variable $
const jq = new JQueryProvider($)
fn(jq)
}
请注意,由于我不确定如何实现相同的效果,因此我使用的是require()
而不是import
。
测试现在看起来像这样:
withJQuery((jq) => {
describe('jQuery tests', () => {
it('empty div', () => {
const parent = jq.get('<div>')
expect(parent[0]).toMatchSnapshot()
})
it('empty div with class', () => {
const parent = jq.get('<div>').addClass('foo')
expect(parent[0]).toMatchSnapshot()
})
})
})
生产代码示例:
export class DivAppender implements Appender {
constructor(public jq: JQueryProvider, public parent: JQuery, public dateFormat = TIME_FORMAT) {
// empty
}
append(event: LogEvent): void {
const element = this.jq.get('<div>').addClass('event')
...
const appender = new DivAppender(new JQueryProvider($), $('body'))