简体   繁体   中英

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

I am writing Mocha unit tests for Typescript code containing Jquery . I'm using jsdom for getting the document object. When I compile my TS code to JS and run the tests, it throws an error [ReferenceError: $ is not defined] .

My Typescript code is here

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

My unit test code is as follows:

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

When I run Mocha test it shows

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

Also tried using global.$ = require("jquery"); but does not work.

jQuery has to be available globally because your script gets it from the global space. If I modify your code so that var $ = require('jquery')(window); is replaced by:

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

then it works. Note the two calls: 1st to require jquery , then to build it by passing window . You could alternatively do:

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

If window is available globally, then there is no need to perform the double call as in the first snippet: jQuery just uses the globally available window .

You probably also want to define global.jQuery since some scripts count on its presence.

Here is a full example of a test file that runs:

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

The typings files are obtained the usual way using tsd . The file ./global.d.ts fixes the issue you may get with setting new values on global . It contains:

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

dummy.js was also modified like this:

declare var $: any;

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

You need to include jsdom and jQuery in Node first:

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

and then add this lines into your .js file where you are using jQuery

 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;

I found this question in 2020 and Louis got me pointing in the right direction. However, I found jsdom-global an easier alternative way of getting document working in Mocha. I installed jsdom-global following the instructions at jsdom-global

I used these lines to get jQuery and $ working as expected:

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

Then this test passed with flying colours:

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

If you can't or don't want to alter the global namespace type definition, you can still include jQuery, as following:

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

The full initialization of jQuery then becomes:

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

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

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