使用 Mocha 使用 Typescript 进行单元测试 Jquery 时如何修复“$ is not defined”错误?

How to fix "$ is not defined" error when unit testing Jquery with Typescript using Mocha?

我正在为包含 JqueryTypescript 代码编写 Mocha 单元测试.我正在使用 jsdom 来获取文档对象。当我将我的 TS 代码编译为 JS 并 运行 测试时,它会抛出错误 [ReferenceError: $ is not defined].

我的 Typescript 代码在这里

export function hello(element) : void {
    $(element).toggleClass('abc');
};

我的单元测试代码如下:

import {hello} from '../src/dummy';

var expect = require('chai').expect;
var jsdom = require('jsdom');
var document = jsdom.jsdom();
var window = document.defaultView;

var $ = require('jquery')(window);

describe('TEST NAME', () => {

    it('should run', (done) => {
        hello($('div'));
        done();
    });
});

当我 运行 Mocha 测试时它显示

    <failure message="$ is not defined"><![CDATA[ReferenceError: $ is not defined ...
]]></failure>

也尝试使用 global.$ = require("jquery"); 但没有用。

如上所述,您应该正确导入 jQuery:import $ = require('jquery');

jQuery 必须全局可用,因为您的脚本从全局 space 获取它。如果我修改您的代码,将 var $ = require('jquery')(window); 替换为:

global.$ = require('jquery')(window);

然后就可以了。注意这两个调用:第一个要求 jquery,然后通过传递 window 来构建它。您也可以这样做:

global.window = window
global.$ = require('jquery');

如果 window 全局可用,则无需执行第一个代码段中的双重调用:jQuery 仅使用全局可用的 window.

您可能还想定义 global.jQuery,因为某些脚本依赖于它的存在。

这是运行的测试文件的完整示例:

/// <reference path="../typings/mocha/mocha.d.ts" />
/// <reference path="../typings/chai/chai.d.ts" />
/// <reference path="../typings/jsdom/jsdom.d.ts" />
/// <reference path="./global.d.ts" />

import {hello} from './dummy';

import chai = require('chai');
var expect = chai.expect;
import jsdom = require('jsdom');
var document = jsdom.jsdom("");
var window = document.defaultView;

global.window = window
global.$ = require('jquery');

describe('TEST NAME', () => {

    it('should run', (done) => {
        hello($('div'));
        done();
    });
});

typings 文件是使用 tsd 的通常方式获得的。文件 ./global.d.ts 修复了在 global 上设置新值时可能遇到的问题。它包含:

declare namespace NodeJS {
    interface Global {
      window: any;
      $: any;
    }
}

dummy.js也被修改成这样:

declare var $: any;

export function hello(element) : void {
    $(element).toggleClass('abc');
};

您需要先在 Node 中包含 jsdom 和 jQuery:

npm install jsdom --save-dev
npm install jquery --save-dev

然后将此行添加到您使用 jQuery

的 .js 文件中

const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const { window } = new JSDOM(`...`);
var jQuery = require('jquery')(window);

var example = (function($) {
 .....your jQuery code....
})(jQuery);

module.exports = example;

如果您不能或不想更改全局命名空间类型定义,您仍然可以包含 jQuery,如下所示:

const globalAny:any = global;
const $ = globalAny.$ = require('jquery')(window);

jQuery 的完整初始化变为:

const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const { window } = (new JSDOM());
const globalAny:any = global;
const $ = globalAny.$ = require('jquery')(window);

我在 2020 年发现了这个问题,路易斯让我指出了正确的方向。但是,我发现 jsdom-global 一种更简单的替代方法,可以让文档在 Mocha 中工作。 我按照 jsdom-global

中的说明安装了 jsdom-global

我使用这些行让 jQuery 和 $ 按预期工作:

require('jsdom-global')();
global.window = window;
global.$ = require('jquery');
global.jQuery = $;

那么这个测试就顺利通过了:

const assert = require("chai").assert;
function test(){
    return "test";
}
describe('Setting up global constants...', function () {
    describe('Libraries...', function () {
        it('jQuery and $ are present', () => {
            assert(jQuery !== undefined);
            assert($ !== undefined);
            assert($ === jQuery);
            assert($.isFunction(test));
        });
    });
});