我最近开始使用Jasmine进行JavaScript测试,但遇到了问题。我确定这里有人可以帮助我。
我有以下简单代码,发布在CodePen:
HTML:
<div class="container">
<button id="btnEraseDiv">Erase Div</button>
</div>
CSS:
.container{
display:flex;
flex-direction: column;
padding:20px;
background-color:#eef;
}
button{
padding:10px 0;
font-size: 1rem;
background-color:#fdd;
}
#toBeErased{
padding:10px;
border:1px solid #ffdddd;
background-color:#ffccdd;
margin-bottom:20px;
}
和JavaScript:
const eraseDiv = () => {
const myDiv = $('#toBeErased');
myDiv.children('p').fadeOut(300, () => {
myDiv.fadeOut(600, () => {
myDiv.remove();
});
})
}
const addMyDiv = () => {
const myDiv = $(`<div id="toBeErased">
<p>This div and all its content will be erased. <br />Click the button bellow to erase it.</p>
</div>`);
if (!document.querySelectorAll('#toBeErased').length) {
$('div.container').append(myDiv);
}
};
$(document).ready(() => {
$('button#btnEraseDiv').on('click', () => {
eraseDiv();
});
});
//here starts the test
describe("Erase button functionality", () => {
beforeEach( () => {
addMyDiv();
});
it('should erase the div when btnEraseDiv clicked - using async', async () => {
//this test here is the mistery
const btn = $('button#btnEraseDiv');
await btn.click();
expect($('div#toBeErased').length).toBeLessThan(1);
});
it('should erase the div when btnEraseDiv clicked - using done and timeout', (done) => {
//this is working, but i'm sure it is not the right usage
const btn = $('button#btnEraseDiv');
btn.click();
setTimeout( () => {
expect($('div#toBeErased').length).toBeLessThan(1);
done();
}, 2000);
});
});
阅读此测试所出的文档,但失败:
it('should erase the div when btnEraseDiv clicked - using async', async () => {
//this test here is the mistery
const btn = $('button#btnEraseDiv');
await btn.click();
expect($('div#toBeErased').length).toBeLessThan(1);
});
然后,我使另一个超时大于淡出时间,并且可以工作,但是感觉不正确。
it('should erase the div when btnEraseDiv clicked - using done and timeout', (done) => {
//this is working, but i'm sure it is not the right usage
const btn = $('button#btnEraseDiv');
btn.click();
setTimeout( () => {
expect($('div#toBeErased').length).toBeLessThan(1);
done();
}, 2000);
});
有人可以为我指出正确的方向,还是可以给我一个有关这种情况的示例?
谢谢您的时间!
[我认为您使用done
参数的“不当”解决方案实际上是一个不错的方法。您使用async
/ await
的第一个解决方案效果不佳,因为jQuery click()
方法未返回等待的类型(Promise或“ thenable”)。
如果您想使用async
/ await
解决方案,可以尝试以下方法:
// Add a reusable utility method for your tests.
const wait = async ms => new Promise(res => setTimeout(res, ms));
it('should erase the div when btnEraseDiv clicked - using async', async () => {
$('button#btnEraseDiv').click();
await wait(2000); // Wait for animations to complete.
expect($('div#toBeErased').length).toBeLessThan(1);
});
旁注
[您可能要考虑的另一件事,特别是如果要编写和维护大量UI测试时,正在使用E2E / UI测试库,例如Nightwatch,Puppeteer,Selenium,Cypress,或Protractor(如果您使用的是Angular)。
这些库将使您可以编写与实现代码分开存在的测试。您可以在普通浏览器或无头浏览器实例中运行它们。它们都内置了“驱动程序” API函数,使您可以“等待”某些DOM条件。例如Nightwatch的waitForElementPresent()
或Puppeteer的waitForSelector()
。还有许多可用的API方法可帮助您轻松编写可维护的E2E / UI测试。