如何更改Jasmine中包含的Javascript文件中定义的全局变量?

时间:2017-08-24 23:28:34

标签: javascript node.js jasmine

背景

我花了最后几个小时试图找到答案,但这可能是因为我对require.js缺乏了解。

以下是我正在使用的内容:我有一个紧密耦合的遗留企业Web应用程序,它是在2001年编写的,当时使用的是IE 5特定的Javascript。名为Menu.js的Javascript文件具有使HTML表格像菜单一样的功能,其中表格单元格是菜单项,其中一些菜单项可以扩展子菜单,这是更多的表格单元格。 / p>

简而言之,代码很糟糕。但是,我必须提供一个创可贴,以使其与Chrome和Firefox兼容。解决方案是重写每个Javascript函数的内部以使用jQuery,这样它就可以跨浏览器兼容。

每个网页都包含Menu.js,每个网页都会自动生成,所以我不得不通过从Menu.js注入jQuery来包含jQuery,其中包含以下代码:

Menu.js

function injectQuery() {
  const script = document.createElement('script');
  script.src = 'https://code.jquery.com/jquery-3.2.1.min.js';
  document.getElementByTagName('head')[0].appendChild(script);
}

injectJQuery();

function getSubMenu(el) {
  return $(el).find('table')[0] || null;
}

// Other functions are defined here as well

if ( typeof module !=== 'undefined' && module.hasOwnProperty('exports') ) {
  module.exports.getSubMenu = getSubMenu;
}

在Jasmine中,在测试Menu.js时,如果没有出现未定义的错误,我无法使用$()函数。为了解决这个问题,我有以下代码:

menu.spec.js

const sut = require('../src/js/Menu.js');
const testMenu = require('./resources/test.menu').data();

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

global.$ = jQuery;

describe('getSubMenu()', () => {
  beforeEach(() => {
    document.querySelector('body').innerHTML = testMenu;
  });

  it('should return the nested sub-menu-3 table given the sub-menu-2 element', () => {
    const subMenu2 = $('#sub-menu-2');
    const result = sut.getSubMenu(subMenu2);

    expect(result.id).toBe('sub-menu-3');
  });
});

问题

每当我运行规范时,我都会收到以下错误:

const script = document.createElement('script');
                        ^
ReferenceError: document is not defined
    at injectJquery

因此,当Jasmine规范运行时,我不希望injectJquery()中定义的Menu.js方法运行。我尝试了以下方法:

尝试1 - 从Jasmine更改全局值

Menu.js

var isUnderTest = false;

...

if (!isUnderTest) {
  injectJquery();
}

...

if ( typeof module !=== 'undefined' && module.hasOwnProperty('exports') ) {
  ...
  module.exports.isUnderTest = isUnderTest;
}

menu.spec.js中,我尝试设置以下内容:

sut.isUnderTest = true;

但是,规范仍然试图执行injectJquery(),我收到了同样的错误。我尝试为isUnderTest变量定义一个setter函数并调用它,然后导出该函数,但我仍然收到同样的错误。

尝试2 - 使用Jasmine间谍强制该功能无效

我尝试使用Jasmine间谍通过以下代码使该功能无法执行任何操作:

spyOn(sut, 'injectJquery').and.callFake(() => null);

我确实从injectJquery()内导出Menu.js函数;但是,这也没有用。

尝试3 - 定义节点全局变量

我尝试在menu.spec.js中定义一个节点全局变量,如下所示:

global.isUnderTest = true;

但是,它仍然没有用。

最后的想法

来自Java世界并使用JUnit,我期望我在Jasmine中定义的测试对象下的系统行为与Java相似,但我知道Javascript文件Menu.js不是对象

我希望injectJquery()在浏览器中运行,但不在规范中。有没有办法抑制我没有看到的方法调用?

0 个答案:

没有答案