我正在尝试在单元测试中检查元素可见性状态是否已更改。我正在使用 .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 的交互而不是它的状态。我的意思是我可以验证对函数 toggle
、show
和 hide
的调用。这种方法有一个缺点,即它增加了复杂性,因为这需要我在测试中维护 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/