今天群里一位 Qian℡儭‖ 的伙伴问了一个非常好的问题,关于 web 页面中的提示消息如何处理,瞬间就来了兴趣,现在把今晚调试的成果放上来。
自动化有一个古老而经典的原则:
不要显式地使用 wait 这种固定时间的等待
强迫症表示,这个原则适用于提示消息场景吗? 试一试就知道了...
web 提示消息一般来说有两种实现方式:
以下 HTML 模拟了上述两种效果:
tip.tmpl
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>js弹框3秒后自动消失</title>
<link rel="stylesheet" type="text/css" href="/helper/css/bootstrap.css"/>
<link rel="stylesheet" type="text/css" href="/helper/css/demo.css"/>
</head>
<body>
<button id="alwaysExist" onclick="showModal()">点击弹出模态框-提示一直存在</button>
<button id="addAndDelete">点击出现模态框-新增删除消息Dom</button>
<div class='modal my-modal-alert' id='my-modal-alert'>
<div class='modal-dialog boxBodySmall'>
<div class='modal-content'>
<div class='modal-header boxHeader'>
<button type='button' class='close boxClose' data-dismiss='modal'>
<span aria-hidden='true'>×</span><span class='sr-only'>Close</span>
</button>
<h4 class='modal-title boxTitle' id='modal-title'>模态框</h4>
</div>
<div class='modal-body' id='modal-body-alert'>
<div id='modal_message'>js弹框自动消失案例</div>
<span id='num'></span>
</div>
<div class='modal-footer boxFooter' id='modal-footer'>
<button type='button' class='btn btn-default boxButton' data-dismiss='modal'>关闭</button>
<button type='button' class='btn btn-primary boxButton'>保存</button>
</div>
</div>
</div>
</div>
<script src="/helper/js/jquery-1.11.2.min.js"></script>
<script src="/helper/js/bootstrap.min.js"></script>
<script src="/helper/js/jquery-ui.min.js"></script>
<script>
var clearFlag = 0;
var count = 3;//设置3秒后自动消失
var showModal = function(){
$("#my-modal-alert").toggle();//显示模态框
$("#my-modal-alert").draggable({//设置模态框可拖动(需要引入jquery-ui.min.js)
handle: ".modal-header"
});
clearFlag = self.setInterval("autoClose()",1000);//每过一秒调用一次autoClose方法
}
var autoClose = function(){
if(count>0){
$("#num").html(count + "秒后窗口将自动关闭");
count--;
}else if(count<=0){
window.clearInterval(clearFlag);
$("#num").html("");
$("#my-modal-alert").fadeOut("slow");
count = 3;
$("#my-modal-alert").toggle();
}
}
</script>
<script>
$("#addAndDelete").click(function () {
var l = $("body>div").length;
if(l===1)
{
$("body").append(function () {
return '<div class="addAndDelete">\n' +
' <h4>我是提示消息,点击后会以新增的方式布局到HTML里,3秒后自动消失</h4>\n' +
'</div>'
});
setTimeout(function () {
$(".addAndDelete").remove();
}, 3000);
}
});
</script>
</body>
</html>
注:上面的 html 代码是用 go/gin 作为基础框架写的,其中的bootstrap
和jQuery
相关的库,都可以在网上下载到,实在不知道如何运行的可以在群里交流,需要的话,我会把源文件传到群里……唔,好像很啰嗦又不是很高端的样子.jpg
运行效果
点击第一个按钮,会出现第一张图的弹框,3 秒后消失;点击第二个按钮,出现第二张图的文本提示,同样 3 秒后消失
测试代码示例
测试以上两种情况下,提示信息有没有出现和提示信息有没有正常的消失,一共 4 个用例。
/// <reference types='Cypress' />
describe("百毒网站首页测试用例集", function() {
beforeEach(() => {
cy.visit("/");
});
it.skip("百度一下按钮文本检查", function() {
cy.get("#su").then($button_start_search => {
expect($button_start_search.attr("value")).to.eq("百度一下");
});
cy.url().should("include", "www.baidu.com"); // => true
cy.url().should($url => {
expect($url).to.contains("www.baidu.com");
console.log($url);
});
});
it("一直存在-点击后出现提示信息", function() {
cy.get("#my-modal-alert").then($alert => {
expect($alert).have.not.property("style");
cy.get("#alwaysExist")
.then($triggerButton => {
$triggerButton.click();
})
.then(() => {
expect($alert).have.attr("style", "display: block;");
});
});
});
it("一直存在-3秒后提示信息消失", function() {
cy.get("#my-modal-alert").then($alert => {
cy.get("#alwaysExist")
.trigger("click")
.then(() => {
cy.get("#my-modal-alert", { timeout: 4000 }).should("not.be.visible");
});
});
});
it("点击后新增然后自动消失-点击后出现提示信息", function() {
cy.get("#addAndDelete").click();
cy.get(".addAndDelete").then($tip => {
expect($tip).to.exist;
});
});
it("点击后新增然后自动消失-3秒后提示信息消失", function() {
cy.get("#addAndDelete").click();
cy.get(".addAndDelete").then($tip => {
expect($tip).to.exist;
});
cy.get(".addAndDelete", {timeout:4000}).should("not.exist");
});
});
运行过程中可以看到,提示信息消失时,我们的关于 “3 秒后提示信息消失” 的两个用例才会通过。
我们没有写任何关于 wait 的函数,一切的发生都尽可能的快,没有无畏的等待。这样的用例才是好的用例哦!should
判断会因get
传了timeout
参数而在超时时间内循环判断,直至成功或超时为止,参考官方Commands
关于 should 的描述。
遇到一个有趣的问题,为什么expect("xxx").to.exist
,xxx 好像随便传什么都能通过?~唔,留到明天研究下...~原来是这样,也就是说,Cypress 采用了包括 ChaiJS 在内的断言方式,而 ChaiJS 的断言是:对exist
的判断的话,如果判断的是字符串,那么只要此字符串不是null
或undefined
,结果都会是 pass,问题解决。
Cypress 入门系列:
注:目前官方团队正在开发 Python 版本,同样的 Free to use,对 JS 恐惧的同学不妨等一等,或者直接 JS 上手,非常简单,VSCode 装上之后,你会爱上 Cypress 和 JS,笔者会慢慢介绍各种 Web UI 自动化复杂场景下 Cypress 的强大应对,目前还没发现 Cypress 无法处理的问题!欢迎一起入坑!QQ 群:947886065.