javascript - JQuery 在 Jest 测试中检查元素可见性

标签 javascript jquery node.js jestjs

我正在尝试在单元测试中检查元素可见性状态是否已更改。我正在使用 .is(":visible") 来执行此操作,并且在单元测试中它始终报告该元素已隐藏,但它在浏览器中运行良好。

代码就这么简单(参见完整的工作 example ):

html

<form>
      <div id="field">hi</div>
      <input type='checkbox' id="toggle">toggle</input>
      <input type='checkbox' id="show">show</input>
      <input type='checkbox' id="hide">hide</input>
</form>

javascript

$('form').on('change', 'input#toggle[type="checkbox"]', function() {
  target_row = $('#field');

  if (target_row.length) {
    target_row.toggle("fast");
  }
});

正如我所写,这在浏览器中运行良好,但在以下测试中不起作用:

jest.dontMock('jquery');
jest.dontMock('../toggle.js');

$ = jQuery = require('jquery');

describe('toggle.js', function() {
  var sut = require('../toggle.js');
  function givenFields(formFields) {
    document.documentElement.innerHTML = `
      <html><body><form>
      <div id="field">hi</div>
      ${formFields}
      </form></body></html>
    `;
    sut.initialize();
  }

  it('toggles the field', function() {
    givenFields(`<input type='checkbox' id="toggle">toggle</input>`);

    var initiallyVisible = $("#field").is(":visible");

    $('#toggle').click();

    // Checking that this is not jsdom rendering issue
    expect(document.hidden).toEqual(false);

    expect($("#field").is(":visible")).toEqual(!initiallyVisible);
  });

  it('shows the field', function() {
    givenFields(`<input type='checkbox' id="show">show</input>`);

    $('#show').click();

    expect($("#field").is(":visible")).toEqual(true);
  });
});

结果是:

  ● toggle.js › toggles the field

    expect(received).toEqual(expected)

    Expected: true
    Received: false

      26 |     expect(document.hidden).toEqual(false);
      27 |
    > 28 |     expect($("#field").is(":visible")).toEqual(!initiallyVisible);
         |                                        ^
      29 |   });
      30 |
      31 |   it('shows the field', function() {

      at Object.toEqual (src/__test__/toggle.spec.js:28:40)

  ● toggle.js › shows the field

    expect(received).toEqual(expected)

    Expected: true
    Received: false

      34 |     $('#show').click();
      35 |
    > 36 |     expect($("#field").is(":visible")).toEqual(true);
         |                                        ^
      37 |   });
      38 | });
      39 |

      at Object.toEqual (src/__test__/toggle.spec.js:36:40)

package.json 是:

{
  "name": "toggle",
  "devDependencies": {
    "jasmine": "3.2.0",
    "jest-cli": "24.1.0",
    "jquery": "3.3.1"
  },
  "scripts": {
    "test": "jest"
  }
}

任何想法可能是错误的,我该如何解决这个问题?

我不太喜欢的一个选项,因为它不是解决方案,而是一种解决方法,我可以检查与 DOM 的交互而不是它的状态。我的意思是我可以验证对函数 toggleshowhide 的调用。这种方法有一个缺点,即它增加了复杂性,因为这需要我在测试中维护 DOM 元素的状态并引入关于初始状态的假设。

最佳答案

我认为第一个问题是持续时间(在本例中为“快速”),toggle和显示功能不只是改变可见性:

When a duration, a plain object, or a single "complete" function is provided, .toggle() becomes an animation method. The .toggle() method animates the width, height, and opacity of the matched elements simultaneously. When these properties reach 0 after a hiding animation, the display style property is set to none to ensure that the element no longer affects the layout of the page.

所以您实际上想要检查元素的显示

下一个问题是 jquery 将显示设置为 none 需要 200 毫秒,因此我们需要考虑到这一点,这意味着我们可以这样写:

  it('toggles the field', function(done) {
    givenFields(`
      <div id="field">kuku</div>
      <input type='checkbox' id="toggle">toggle</input>
    `);

    var initialDisplay = $("#field").css('display');

    $('#toggle').click();

    // Checking that this is not jsdom rendering issue
    expect(document.hidden).toEqual(false);
    var expectedDisplay = initialDisplay === 'block' ? 'none' : 'block'
    setTimeout(function() {
      expect($("#field").css('display')).toEqual(expectedDisplay);
      done()
    }, 200)
  });

可能还有一种方法可以注入(inject) jest timer-mocks进入 jquery 这样你就可以避免 200ms 的等待。会很酷,但不确定是否可行。

编辑: jQuery.fx.off = true; 这很好用,给我们留下了:

jest.dontMock('jquery');
jest.dontMock('./toggle.js');

$ = jQuery = require('jquery');
jQuery.fx.off = true;

describe('toggle.js', function() {
  var sut = require('./toggle.js');
  function givenFields(formFields) {
    document.documentElement.innerHTML = `
      <html><body><form>${formFields}</form></body></html>
    `;
    sut.initialize();
  }

  it('toggles the field', function() {
    givenFields(`
      <div id="field">kuku</div>
      <input type='checkbox' id="toggle">toggle</input>
    `);

    var initialDisplay = $("#field").css('display');

    $('#toggle').click();

    // Checking that this is not jsdom rendering issue
    expect(document.hidden).toEqual(false);
    var expectedDisplay = initialDisplay === 'block' ? 'none' : 'block'
    expect($("#field").css('display')).toEqual(expectedDisplay);
  });

  it('shows the field', function() {
    givenFields(`
      <div id="field">kuku</div>
      <input type='checkbox' id="show">show</input>
    `);

    $('#show').click();

    expect($("#field").is(":visible")).toEqual(true);
  });

});

关于javascript - JQuery 在 Jest 测试中检查元素可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55591550/

相关文章:

javascript - 当另一个日期发生更改时,JQuery UI Datepicker 重新启动

javascript - Rails 在提交之前验证 form_for

javascript - 如何使用 JavaScript 显示从数据库正确检索的日期

javascript - 如何在不破坏链接的情况下替换部分网址?

javascript - 有没有办法在 JavaScript 中定期调用函数?

javascript - 网站上每个页面的不同计数器值

javascript - 查找对象中特定名称的值

jquery - 了解 jQuery 的工作原理

javascript - 在滚动上加载 Highchart 动画

javascript - Grunt 为生产构建?