Мокко: не удается вызвать методы модуля, использующие jQuery, из тестов мокко.

Итак, я использую Mocha/Chai для некоторого тестирования, и элемент, который я тестирую, зависит от jQuery. Я использую jsdom, чтобы помочь с этим. Как видно из приведенного ниже кода, у меня нет проблем с использованием jQuery из самого теста мокко. То, что я не могу понять, это просто вызов кода, использующего jQuery.

При запуске этого в браузере jQuery включается в тег скрипта до включения модуля ACE_GA, поэтому jQuery полностью работает там.

При изучении приведенного ниже фрагмента кода внутри функции done() есть две строки с комментариями. Первая строка с комментарием просто вызывает код из модуля ACE_GA, и он не работает. Вторая строка с комментарием воссоздает часть кода внутри модуля ACE_GA (который я пытался вызвать в первой строке), и все работает отлично.

Чтобы было ясно, строка, которая работает просто отлично:

var productItems = jQuery("[data-" + ACE_GA.VALID_PRODUCT_FIELDS.prefix + "]");

Просто копирует строку из метода модуля, который я пытаюсь вызвать, что вызывает у меня проблемы:

var productItems = ACE_GA.HELPERS.validateOptions(ACE_GA.VALID_PRODUCT_FIELDS.prefix);

Что мне нужно сделать, чтобы иметь возможность просто вызывать клиентскую библиотеку/модуль и работать с jQuery вместо того, чтобы копировать/вставлять фрагменты кода из модуля в тесты мокко?

var chai = require("chai");
var jsdom = require("jsdom");
var jQuery = require("jquery");
var fs = require("fs");
var ACE_GA = require("../main");

var bodyContent = fs.readFileSync(__dirname + "/../test/test.html", "utf8", "r");
global.document = jsdom.jsdom(bodyContent);
global.window = document.defaultView;
global.jQuery = jQuery;

describe("ACE_GA.HELPERS.validateOptions", function() {

    it("should select all items with a data-attribute of 'ace-ga-{something}'", function(done) {

        jsdom.env({
            html: bodyContent,
            src: jQuery,
            scripts: "http://www.asite.com/path/to/default/js/jquery-1.11.3.min.js",
            userAgent: "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36",
            done: function(err, window) {

                console.log("err", err);
                var jQuery = window.jQuery;

                //var productItems = ACE_GA.HELPERS.validateOptions(ACE_GA.VALID_PRODUCT_FIELDS.prefix);
                /** ^ that won't work and says jQuery requires a window with a document */

                var productItems = jQuery("[data-" + ACE_GA.VALID_PRODUCT_FIELDS.prefix + "]");
                /** ^ that works just fine and is copy/pasted from the non working method I'm trying to call above */

                chai.expect(productItems.length).to.equal(4);
                done();
            }
        });

    });

});

Для справки, вот точный вывод ошибки сбоя, которую я получаю

1) ACE_GA.HELPERS.validateOptions should select all items with a data-attribute of 'ace-ga-{something}':
 Uncaught Error: jQuery requires a window with a document
  at module.exports (C:\Path\To\Project\dev-files\node_modules\jquery\dist\jquery.js:29:12)
  at Object.validateOptions (main.js:144:15)
  at Object.done (test\gaecTest.js:89:39)
  at process.nextTick (C:\Path\To\Project\dev-files\node_modules\jsdom\lib\jsdom.js:320:18)
  at _combinedTickCallback (internal/process/next_tick.js:67:7)
  at process._tickCallback (internal/process/next_tick.js:98:9)

Из того, что я вижу, в самом включенном модуле (ACE_GA) возникает проблема с jQuery, работающей так, как я хочу, из этого контекста сама по себе (например, определение, а затем вызов jQuery() внутри mocha - это нормально, но определение jQuery() в mocha, а затем вызов его из модуля ACE_GA не работает так же).

Как указывалось ранее, при запуске этого в браузере я могу определить/включить jQuery до включения модуля ACE_GA.

Я пытаюсь сделать что-то подобное здесь, только не запуская его в браузере, а вместо этого запуская его с узла с мокко.


person Andrew B    schedule 28.11.2016    source источник


Ответы (1)


Непосредственная причина, по которой у вас возникают проблемы, заключается в том, что вы неправильно инициализируете экземпляр jQuery, который загружается непосредственно в узел (в отличие от того, который вы загружаете в экземпляре jsdom).

Когда вы делаете require('jquery'), jQuery проверяет, есть ли document в глобальной области видимости. Если это так, он устанавливает себя в глобальной области. В результате в браузере он устанавливается на window, как $ и jQuery. В Node.js нет document в глобальной области видимости по умолчанию. Это также имеет место в коде, который вы показываете. Когда document не определено, то, что вы получаете от require('jquery'), представляет собой фабрику, из которой вы можете создать экземпляр jQuery. Вы должны передать экземпляр Window на эту фабрику.

Вы можете изменить исходный код на:

var chai = require("chai");
var jsdom = require("jsdom");
var makeJQ = require("jquery"); // Load the factory.
var fs = require("fs");

var bodyContent = fs.readFileSync(__dirname + "/../test/test.html", "utf8", "r");
global.document = jsdom.jsdom(bodyContent);
global.window = document.defaultView;
global.$ = global.jQuery = makeJQ(window); // Actually make a jQuery instance.

// Load this after, since it depends on jQuery being in the global space.
var ACE_GA = require("../main");

Затем вам следует отказаться от второго окна, которое вы создаете с помощью jsdom в рамках теста, и просто использовать то, которое было настроено в начале вашего тестового файла. Вы можете повторно использовать его от теста к тесту, очищая дерево DOM между тестами.

person Louis    schedule 28.11.2016
comment
ВОТ ЭТО ДА! Большое спасибо!! - person Andrew B; 28.11.2016
comment
Я все еще вижу Error: jQuery requires a window with a document - person djKianoosh; 07.04.2017