《手把手教你》系列技巧篇(三十八)-java+ selenium自动化测试-日历时间控件-下篇(详解教程)
1.简介
理想很丰满现实很骨感,在应用selenium实现web自动化时,经常会遇到处理日期控件点击问题,手工很简单,可以一个个点击日期控件选择需要的日期,但自动化执行过程中,完全复制手工这样的操作就有点难了。宏哥上一篇已经讲解了如何处理日历时间控件,但是对于第一种方法可能会遇到输入框是readonly的情况,那么第一种方法就不适用了,但是只要我们稍微的变通地处理一下,就又可以使用了。
2.问题
宏哥第一种方法地思路就是把它当做输入框,直接输入日期即可,想法是很美好的,但是有时候实行起来却不执行,这个时候我们就要仔细去看看前端的代码了,代码如下:
<div class="col-lg-3 form-input">
<input id="createTime" class="form-control" type="text" readonly="readonly" name="tatsudoDate" onclick="WdatePicker()" aria-required="true">
</div>
从上边的代码可以看出属性readonly人家根本不允许你输入,你就行不通了。
3.想法
既然这样了,我们就稍微变通一下,不要一条道走到黑。这个时候我们可以移除readonly的属性,问题就轻轻松松解决了,代码如下:
String js = "document.getElementById('createTime').removeAttribute('readonly')"; // 原生js,移除属性
((JavascriptExecutor)driver).executeScript(js); //将driver强制转换为JavascriptExecutor类型
driver.findElement(By.id("createTime")).sendKeys("2016-08-24"); //输入日期
4.注意
代码里面一定要记得导入这个方法(一般代码编辑器eclipse都会报错提示)虽然有提示,但是宏哥在这里还是提示一下,不要导错包了。:
import org.openqa.selenium.JavascriptExecutor;
5.项目实战
网上找了半天也没有找到这样的例子,以前12306的日历是这种。最近升级了,已经不是这种了。不找了索性宏哥自己在本地做一个这样的小demo给小伙伴或者童鞋们来演示一下。
注:本文演示的数据大家可以在公众号后台回复 宏哥38,在java+selenium->38 文件夹领取。
5.1代码准备
5.1.1前端HTML代码
前端HTML代码如下:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script src="dateJs.js"></script>
<link rel="stylesheet" type="text/css" href="date.css">
</head>
<body>
<div id="wrapper" style="position: relative;top: 100px;left:600px;">
<button class="button1"><a id="myAnchor" href="https://www.cnblogs.com/du-hong/">北京-宏哥</a></button></br>
<input type="text" id="Dateinput" readonly=""/>
<div class="calendar" id="calender" style="display: none;">
</div>
</div>
</body>
</html>
5.1.2CSS样式
HTML滑块CSS样式代码如下:
* {
margin: 0;
padding: 0;
}
body {
font-size: 13px;
}
.calendar {
width: 330px;
}
.calendar .title {
position: relative;
width: 100%;
height: 30px;
line-height: 30px;
background: #17a4eb;
}
.title div {
position: absolute;
}
.prev {
left: 10px;
}
.now {
left: 40%;
}
.next {
right: 10px;
}
input {
height: 30px;
width: 326px;
}
table {
width: 100%;
border-collapse: collapse;
}
table th {
border: 1px solid #ccc;
}
table td {
text-align: center;
border: 1px solid #ccc;
}
.red {
background-color: #a1cbdb;
}
.blue {
background-color: #e4e3e3;
}
.button1 {
background-color: #f44336;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 28px;
margin-bottom: 100px;
text-decoration: none;
color: white;
}
#myAnchor {
text-decoration: none;
color: white;
}
5.1.3日历JS
日历JS代码如下:
window.onload = function () {
//获取日期 输入框
var oInput = document.getElementById('Dateinput');
//获取日历
var oCalender = document.getElementById('calender');
//获取当前日期
var oDate = new Date();
//获取当年 年
var year = oDate.getFullYear();
//获取当前 月
var month = oDate.getMonth() + 1;
//日历框不能重复创建
var flag = false;
//日期输入框 获取焦点时 加载日历
oInput.onfocus = function () {
showDate(year, month);
}
//显示日历
function showDate(year, month) {
if (false == flag) {
//1.日历标题
var oTitle = document.createElement('div');
oTitle.className = 'title';
//1.1日历标题文本
var prevM = 0;
var nextM = 0;
prevM = month - 1;
nextM = month + 1;
//当月份为1时 上一个月为12
if (month == 1) {
prevM = 12;
}//当月份为12时 下一个月为1
else if (month == 12) {
nextM = 1;
}
var titleHtml = "";
titleHtml += '<div class="prev" id="prev"><span>';
titleHtml += prevM + '</span>月</div>';
titleHtml += '<div class="now">';
titleHtml += '<span class="span">';
titleHtml += year;
titleHtml += '</span>年';
titleHtml += '<span class="span">' + month;
titleHtml += '</span>月</div>';
titleHtml += '<div class="next" id="next"><span>';
titleHtml += nextM + '</span>月</div>';
oTitle.innerHTML = titleHtml;
//将日历标题 拼接到日历
oCalender.appendChild(oTitle);
//1.2获取日历 表头元素(以便添加事件)
var oSpans = oCalender.getElementsByTagName('span');
var prevMonth = oSpans[0];
var nextMonth = oSpans[3];
var nowMonth = oSpans[2];
var nowYear = oSpans[1];
//2.创建星期 表头
var otable = document.createElement('table');
var othead = document.createElement('thead');
var otr = document.createElement('tr');
//2.1表头内容填充
var arr = ['日', '一', '二', '三', '四', '五', '六'];
for (var i = 0; i < arr.length; i++) {
//创建th
var oth = document.createElement('th');
oth.innerHTML = arr[i];
otr.appendChild(oth);
}
//2.2将表头加入到日历
othead.appendChild(otr);
otable.appendChild(othead);
oCalender.appendChild(otable);
//3.添加 当前日历 全部日期
//3.1.先获得当期月 有多少天
var dayNum = 0;
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
dayNum = 31;
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
dayNum = 30;
} else if (month == 2 && isLeapYear(year)) {
dayNum = 29;
} else {
dayNum = 28;
}
//3.2.创建 6行7列 日期容器
var otbody = document.createElement('tbody');
for (var i = 0; i < 6; i++) {
var otr = document.createElement('tr');
for (var j = 0; j < 7; j++) {
var otd = document.createElement('td');
otr.appendChild(otd);
}
otbody.appendChild(otr);
}
otable.appendChild(otbody);
//3.3获得 1号对应的是星期几
//3.3.1.将当月1号赋值给日期变量
oDate.setFullYear(year);
//注意 js日期的月份是从0 开始计算
oDate.setMonth(month - 1);
oDate.setDate(1);
//3.3.2.计算1号在第一行日期容器中的位置,依次给日期容器填充内容
//注意 js中 getDay方法是获取当前日期是星期几
var week = oDate.getDay();
var otds = oCalender.getElementsByTagName('td');
for (var i = 0; i < dayNum; i++) {
otds[i + week].innerHTML = i + 1;
}
//让当前日期显示红色、后面的显示蓝色
showColor(otds);
//给左右月份绑定点击事件
monthEvent();
//判断最后一行是否全为空
lastTr(otds);
flag = true;
document.getElementById('calender').style.display = "block";
}
}
//判断是否是闰年
function isLeapYear(year) {
if (year % 100 == 0 && year % 400 == 0) {
return true;
} else if (year % 100 != 0 && year % 4 == 0) {
return true;
} else {
return false;
}
}
//判断日期容器最后一行是否有值
function lastTr(otds) {
var flag = true;
for (var i = 35; i < 42; i++) {
if (otds[i].innerHTML != '') {
flag = false;
}
}
//全是空的
if (flag) {
for (var i = 35; i < 42; i++) {
otds[i].style.display = 'none';
}
}
}
//当前日期显示红色、前面的显示灰色
function showColor(otds) {
//当前日期
var nowday = new Date().getDate();
var nowyear = new Date().getFullYear();
var nowmonth = new Date().getMonth();
var oCalendar = document.getElementById("calender");
ospans = oCalendar.getElementsByTagName('span');
var contralYear = ospans[1].innerHTML;
var contralMonth = ospans[2].innerHTML;
var oindex = 0;
for (var i = 0; i < otds.length; i++) {
if (nowday == otds[i].innerHTML && nowyear == contralYear && nowmonth + 1 == contralMonth) {
otds[i].className = 'red';
oindex = i;
}
}
}
//给左右月份绑定点击事件
function monthEvent() {
var oCalendar = document.getElementById("calender");
var prevDiv = document.getElementById("prev");
var nextDiv = document.getElementById("next");
var prevMonth = prevDiv.getElementsByTagName("span");
var nextMonth = nextDiv.getElementsByTagName("span");
prevDiv.onclick = function () {
flag = false;
oCalendar.innerHTML = '';
showDate(year, parseInt(prevMonth[0].innerHTML));
}
nextDiv.onclick = function () {
flag = false;
oCalendar.innerHTML = '';
showDate(year, parseInt(nextMonth[0].innerHTML));
}
}
}
6.自动化代码实现
6.1代码设计

6.2参考代码
package lessons; import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;//注意不要倒错包
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver; /**
* @author 北京-宏哥
*
* 《手把手教你》系列技巧篇(三十八)-java+ selenium自动化测试-日历时间控件-下篇(详解教程)
*
* 2021年10月31日
*/
public class calendar { public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", ".\\Tools\\chromedriver.exe");
WebDriver driver =new ChromeDriver();
driver.manage().window().maximize();
try {
driver.get("file:///C:/Users/DELL/Desktop/test/Calendar/Calendar.html");
Thread.sleep(5000);
//执行方式
JavascriptExecutor jsExecutor = (JavascriptExecutor) driver;
String js = "document.getElementById('Dateinput').removeAttribute('readonly')";
jsExecutor.executeScript(js);//执行js,将readonly属性去掉后就可以写入日期
driver.findElement(By.id("Dateinput")).clear();//写入前清除数据
driver.findElement(By.id("Dateinput")).sendKeys("2021-11-11");//写入期望日期
Thread.sleep(5000);
} catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println("执行结束,关闭浏览器!提前祝大家光棍节快乐!!!");
driver.quit();
}
}
}
6.3运行代码
1.运行代码,右键Run AS->Java Appliance,控制台输出,如下图所示:

2.运行代码后电脑端的浏览器的动作,如下小视频所示:
7.小结
好了,时间不早了,今天就分享到这里,感谢大家耐心的阅读,这两篇其实是为后边文章的JavaScript的调用做一下铺垫和入门。
《手把手教你》系列技巧篇(三十八)-java+ selenium自动化测试-日历时间控件-下篇(详解教程)的更多相关文章
- 《手把手教你》系列技巧篇(三十七)-java+ selenium自动化测试-日历时间控件-上篇(详解教程)
1.简介 我们在实际工作中,有可能遇到有些web产品,网页上有一些时间选择,然后支持按照不同时间段范围去筛选数据.网页上日历控件一般,是一个文本输入框,鼠标点击,就会弹出日历界面,可以选择具体日期.这 ...
- 《手把手教你》系列技巧篇(十)-java+ selenium自动化测试-元素定位大法之By class name(详细教程)
1.简介 按宏哥计划,本文继续介绍WebDriver关于元素定位大法,这篇介绍By ClassName.看到ID,NAME这些方法的讲解,小伙伴们和童鞋们应该知道,要做好Web自动化测试,最好是需要了 ...
- 《手把手教你》系列技巧篇(三十)-java+ selenium自动化测试- Actions的相关操作下篇(详解教程)
1.简介 本文主要介绍两个在测试过程中可能会用到的功能:Actions类中的拖拽操作和Actions类中的划取字段操作.例如:需要在一堆log字符中随机划取一段文字,然后右键选择摘取功能. 2.拖拽操 ...
- 《手把手教你》系列技巧篇(三十二)-java+ selenium自动化测试-select 下拉框(详解教程)
1.简介 在实际自动化测试过程中,我们也避免不了会遇到下拉选择的测试,因此宏哥在这里直接分享和介绍一下,希望小伙伴或者童鞋们在以后工作中遇到可以有所帮助. 2.select 下拉框 2.1Select ...
- 《手把手教你》系列技巧篇(二十八)-java+ selenium自动化测试-处理模态对话框弹窗(详解教程)
1.简介 在前边的文章中窗口句柄切换宏哥介绍了switchTo方法,这篇继续介绍switchTo中关于处理alert弹窗的问题.很多时候,我们进入一个网站,就会弹窗一个alert框,有些我们直接关闭, ...
- 《手把手教你》系列技巧篇(四十八)-java+ selenium自动化测试-判断元素是否可操作(详解教程)
1.简介 webdriver有三种判断元素状态的方法,分别是isEnabled,isSelected 和 isDisplayed,其中isSelected在前面的内容中已经简单的介绍了,isSelec ...
- 《手把手教你》系列技巧篇(十七)-java+ selenium自动化测试-元素定位大法之By css上卷(详细教程)
1.简介 CSS定位方式和xpath定位方式基本相同,只是CSS定位表达式有其自己的格式.CSS定位方式拥有比xpath定位速度快,且比CSS稳定的特性.下面详细介绍CSS定位方式的使用方法.xpat ...
- 《手把手教你》系列技巧篇(四十七)-java+ selenium自动化测试-判断元素是否显示(详解教程)
1.简介 webdriver有三种判断元素状态的方法,分别是isEnabled,isSelected 和 isDisplayed,其中isSelected在前面的内容中已经简单的介绍了,isSelec ...
- 《手把手教你》系列技巧篇(六)-java+ selenium自动化测试-阅读selenium源码(详细教程)
1.简介 前面几篇基础系列文章,足够你迈进了Selenium门槛,再不济你也至少知道如何写你第一个基于Java的Selenium自动化测试脚本.接下来宏哥介绍Selenium技巧篇,主要是介绍一些常用 ...
随机推荐
- centos 7 & 6 优化脚本
简单优化 ,未涉及安全优化,如有需求请自行修改脚本实现 1 #!/bin/bash 2 SysVer=`cat /etc/redhat-release | awk -F'release' '{prin ...
- 1.3redis小结--配置php reids拓展
1.执行php文件 输出phpinfo(); <?php phpinfo(); 2.根据PHPinfo的信息确定需要下载的 php_redis.dll , php_igbinary.dll 版 ...
- 新入手服务器不会玩?抢占式实例服务器教程,从零搭建tomcat超简流程
新入手服务器不会玩?抢占式实例服务器教程,从零搭建tomcat超简流程 相信很多新人入手Linux服务器后,一脸无奈,这黑框框究竟能干啥?忽觉巨亏血亏不是? 这里面门道可不是你想象中的那么点,简则服务 ...
- Hive语法及其进阶(二)
1.使用JDBC连接Hive 1 import java.sql.Connection; 2 import java.sql.DriverManager; 3 import java.sql.Prep ...
- 突破GD渲染的图片马
<?php /* The algorithm of injecting the payload into the JPG image, which will keep unchanged aft ...
- 最详细STL(一)vector
vector的本质还是数组,但是可以动态的增加和减少数组的容量(当数组空间内存不足时,都会执行: 分配新空间-复制元素-释放原空间),首先先讲讲vector和数组的具体区别 一.vector和数组的区 ...
- 记一次Kafka服务器宕机的真实经历!!
大家好,我是冰河~~ 估计节前前祭拜服务器不灵了,年后服务器总是或多或少的出现点问题.不知是人的问题,还是风水问题.昨天下班时,跟运维小伙伴交代了好几遍:如果使用Docker安装Kafka集群的话,也 ...
- mybatis 配置问题查找
mybatis配置问题记录 org.apache.ibatis.binding.BindingException: Type interface com.xx.dao.UserDao(自己项目的文件) ...
- [AGC023D] Go Home 题解
题目传送门 Solution 首先排除掉特殊情况:若 \(S\) 在两侧,肯定会顺序/逆序直接走完,答案就是边界减去出发点. 考虑到若 \(P_1\geq P_n\),那么显然 \(1\) 不到家 \ ...
- 洛谷3203 弹飞绵羊(LCT)
据说这个题当年的正解是分块qwq 根据题目所说,对于题目中的弹力系数,就相当于一条边,那么对于"跳出去"这个限制,我们可以选择建造一个新点\(n+1\)表示结束,那么每次,求一个点 ...