《手把手教你》系列技巧篇(三十八)-java+ selenium自动化测试-日历时间控件-下篇(详解教程)

简介: 【5月更文挑战第2天】在自动化测试过程中,经常会遇到处理日期控件的点击问题。宏哥之前分享过一种方法,但如果输入框是`readonly`属性,这种方法就无法奏效了。不过,通过修改元素属性,依然可以实现自动化填写日期。首先,定位到日期输入框并移除`readonly`属性,然后使用`sendKeys`方法输入日期。这样,即使输入框设置了`readonly`,也能成功处理日期控件。

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的调用做一下铺垫和入门。


每天学习一点,今后必成大神-

往期推荐(由于跳转参数丢失了,所有建议选中要访问的右键,在新标签页中打开链接即可访问):


Appium自动化系列,耗时80天打造的从搭建环境到实际应用精品教程测试

Python接口自动化测试教程,熬夜87天整理出这一份上万字的超全学习指南

Python+Selenium自动化系列,通宵700天从无到有搭建一个自动化测试框架

Java+Selenium自动化系列,仿照Python趁热打铁呕心沥血317天搭建价值好几K的自动化测试框架

Jmeter工具从基础->进阶->高级,费时2年多整理出这一份全网超详细的入门到精通教程

Fiddler工具从基础->进阶->高级,费时100多天吐血整理出这一份全网超详细的入门到精通教程

Pycharm工具基础使用教程

相关文章
|
6天前
|
Web App开发 Java 测试技术
《手把手教你》系列技巧篇(五十六)-java+ selenium自动化测试-下载文件-上篇(详细教程)
【5月更文挑战第20天】本文介绍了自动化测试中如何实现无弹窗下载文件,主要针对Firefox浏览器。作者指出,通常的下载操作包括点击下载按钮,但这里讨论的是避免下载弹窗直接保存文件的方法。文章详细讲解了通过设置Firefox参数(如`browser.download.dir`、`browser.helperApps.neverAsk.saveToDisk`等)来实现这一功能,并给出了Java Selenium的示例代码,展示了如何创建FirefoxProfile并进行相关设置,以及如何启动浏览器和执行下载操作。
23 0
《手把手教你》系列技巧篇(五十六)-java+ selenium自动化测试-下载文件-上篇(详细教程)
|
3天前
|
Java 测试技术 Python
《手把手教你》系列技巧篇(五十九)-java+ selenium自动化测试 - 截图三剑客 -上篇(详细教程)
【5月更文挑战第23天】本文介绍了使用Java和Selenium进行自动化测试时如何实现截图操作。原本计划讲解远程测试内容,但因服务器网络问题无法进行,因此转而分享Selenium的截图方法。文章分为三部分,首先简述背景,然后重点介绍了TakeScreenshout类,这是一个用于获取浏览器窗口内容的截图工具,不包含浏览器菜单和任务栏。接着,列举了一个测试场景:访问百度首页并截图保存。最后,提供了代码示例,展示了如何设计自动化测试代码以及截图保存到指定目录,并附有代码运行效果展示。
17 2
|
4天前
|
Java 测试技术 Python
《手把手教你》系列技巧篇(五十八)-java+ selenium自动化测试-分页测试(详细教程)
【5月更文挑战第22天】本文介绍了自动化测试分页的实现方法。首先,文章提出了测试分页时关注的三个关键点:总页数、当前页数和页码导航的可用性。接着,作者分享了一个实用网站([https://www.jq22.com/](https://www.jq22.com/))以找到示例进行实践。在代码部分,展示了使用Java和Selenium进行自动化测试的示例代码,包括获取总页数、遍历所有页面及判断当前页面等操作。最后,简要总结了分页自动化测试的实现过程。
18 1
|
5天前
|
Web App开发 Java 测试技术
《手把手教你》系列技巧篇(五十七)-java+ selenium自动化测试-下载文件-下篇(详细教程)
【5月更文挑战第21天】本文介绍了自动化测试中如何实现无弹窗下载文件,特别针对Chrome浏览器。通过设置`download.default_directory`和`profile.default_content_settings.popups`,可以避免下载弹窗并指定下载路径。示例代码展示了如何使用Java和Selenium实现这一功能,包括导入相关库、设置ChromeOptions和执行下载操作。最后,文章提到虽然没有介绍IE浏览器的下载方法,但已有Chrome和Firefox的方法已足够应对大多数需求。
23 0
|
18天前
|
数据采集 Web App开发 数据挖掘
利用Python和Selenium实现定时任务爬虫
利用Python和Selenium实现定时任务爬虫
|
18天前
|
JavaScript 前端开发 测试技术
Python Selenium基本用法
Python Selenium基本用法
39 2
|
18天前
|
Web App开发 数据采集 前端开发
基于Python的Selenium详解:从入门到实践
基于Python的Selenium详解:从入门到实践
147 0
|
13天前
|
Web App开发 负载均衡 前端开发
Python网络数据抓取(7):Selenium 模拟
Python网络数据抓取(7):Selenium 模拟
36 5
|
16天前
|
机器学习/深度学习 Java 数据挖掘
selenium的配置与基本使用(1),2024年最新网易Python面试必问
selenium的配置与基本使用(1),2024年最新网易Python面试必问
|
16天前
|
Web App开发 Ubuntu Linux
Linux无图形界面环境使用Python+Selenium实践
【5月更文挑战第1天】Linux无图形界面环境使用Python+Selenium实践
67 2
http://www.vxiaotou.com