我被分配了一个繁琐的任务,就是要给100个相同的站点做同样的配置。曾经就有做过相同的事,那时还不会写脚本,全靠手动配置。机械的配置了两天的时间,身体感觉被掏空。所以这次我决定还是写一个脚本自动的进行配置。

一、了解Puppeteer

中文版资料:https://juejin.im/entry/59ad6c4f5188250f4850dccc

官方文档(英文):https://github.com/GoogleChrome/puppeteer

Puppeteer的API(英文):https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#

二、环境

只安装了node环境

三、开发阶段

3.1 初始化项目

引用了https://juejin.im/entry/59ad6c4f5188250f4850dccc

项目都是以创建文件夹开始。

  $ mkdir thal
$ cd thal

初始化 NPM,填入一些必要的信息。

  $ npm init

安装 Puppeteer。由于 Puppeteer 并不是稳定的版本而且每天都在更新,所以如果你想要最新的功能可以直接通过 GitHub 的仓库安装。

  $ npm i --save puppeteer

Puppeteer 包含了自己的 chrome / chromium 用以确保可以无界面地工作。因此每当你安装/更新 puppeteer 的时候,他都会下载指定的 chrome 版本。

3.2 编码

3.2.1 工程的目录结构

node_modeles中的内容是从git上拉下来的,src文件夹写得是我自己的代码,我执行的是addConfig里面的文件,common中是一些基础性配置,contentHub配置内容较多,所以我另建了一个contentHub文件夹。

3.2.2 common.js文件写的是常用的功能函数,这个是可以通用的。之前我不是说实现不了全选的功能吗,其实可以调用common中的setOption函数实现全选的功能

 const config = require('./config');

 //根据选择器sel选择id为val的子项
async function setOption(page, sel, val) {
await page.evaluate((sel, val) => {
document.querySelector(`${sel} > option[value="${val}"]`).selected = true;
element = document.querySelector(sel);
var event = new Event('change', { bubbles: true });
event.simulated = true;
element.dispatchEvent(event);
}, sel, val);
} //在id为sel的输入框中输入val
async function setTextVal(page, sel, val) {
await page.evaluate((sel, val) => {
document.querySelector(sel).value = val;
element = document.querySelector(sel);
var event = new Event('change', { bubbles: true });
event.simulated = true;
element.dispatchEvent(event);
}, sel, val);
} //判断选择器是否存在
async function isExist(page, selector) {
var is = await page.evaluate((sel) => {
const element = document.querySelector(sel);
if (!element) {
return false;
} else {
return true;
}
}, selector); return is;
} //导入单个配置
async function importSingleConfiguration(page, configType, configContent) {
const confirmBtn = 'input[value="Confirm"]';
const configTypeSel = '#edit-config-type';
await setOption(page, configTypeSel, configType);
await page.click('#edit-import');
await setTextVal(page, '#edit-import', configContent);
await page.click('#edit-submit');
await page.waitForNavigation(); const is = await isExist(page, confirmBtn);
if (is) {
await page.click(confirmBtn);
await page.waitForNavigation();
await page.waitFor(3 * config.stepWait);
}
} //设置checkbox中子项的值
async function setCheckBoxVal(page, sel, val) {
await page.evaluate((sel, val) => {
document.querySelector(sel).checked = val;
element = document.querySelector(sel);
var event = new Event('change', { bubbles: true });
event.simulated = true;
element.dispatchEvent(event);
}, sel, val);
} module.exports = {
setOption: setOption,
setTextVal: setTextVal,
importSingleConfiguration: importSingleConfiguration,
isExist: isExist,
selectAll: selectAll,
setCheckBoxVal: setCheckBoxVal, }

3.2.3 config.js文件中申明了许多基础性配置

我要跳转的网站url,登录的用户名和密码,站内页面跳转的路径等信息都配置在这个文件里面

const baseUrlArray = [
{
url: '',
langcode: '',
},
];
const baseUrl = baseUrlArray[0].url; const getUrl = (index) => {
const baseUrl = baseUrlArray[index].url;
return {
hubConnection: `${baseUrl}/example`,
};
} const getLangCode = (index) => {
return baseUrlArray[index].langcode;
} module.exports = {
secondWait: 1000,
stepWait: 5000,
username: '',
password: '',
credentials: {
username: '',
password: '',
},
baseUrl: baseUrl,
baseUrlArray: baseUrlArray,
urls: getUrl(0),
getUrl: getUrl,
getLangCode: getLangCode,
}

3.2.4 login.js

 const config = require('./config');

 async function login(page, url = null) {

   //fill authenticate user name and password
await page.authenticate(config.credentials); // goto login page
await page.goto(url ? url : config.urls.login);
const agreeButton = await page.$('#block-popup .btn');
await agreeButton.click(); //fill admin user name and password
await page.focus('#edit-name');
await page.keyboard.type(config.username);
await page.focus('#edit-pass');
await page.keyboard.type(config.password); const inputElement = await page.$('#edit-submit');
await inputElement.click(); await page.waitForNavigation();
} module.exports = login;

3.2.5 好了,登录成功了

四、收获

1.需要被其它页面引用的函数,常量必须要在module.exports={}中申明

2.headles: false是设置自动化操作是可视化的

3.在输入框中输入值并覆盖原有的值:

4.调用其他页面函数的声明:const common = require('./common');

五、疑惑

1.关于全选的功能,puppeteer并不支持全选,虽然官方文档上面说了linux和windows支持全选,但是我的linux系统没有任何反应,估计并不支持。补充一下,我这里说的是实现不了ctrl+A的全选功能。

Puppeteer——自动化脚本设计的更多相关文章

  1. Robot Framework测试框架用例脚本设计方法

    Robot Framework介绍 Robot Framework是一个通用的关键字驱动自动化测试框架.测试用例以HTML,纯文本或TSV(制表符分隔的一系列值)文件存储.通过测试库中实现的关键字驱动 ...

  2. 《手把手教你》系列基础篇(五)-java+ selenium自动化测试- 创建首个自动化脚本(详细教程)

    1.简介 前面几篇宏哥介绍了两种(java和maven)环境搭建和三大浏览器的启动方法,这篇文章宏哥将要介绍第一个自动化测试脚本.前边环境都搭建成功了,浏览器也驱动成功了,那么我们不着急学习其他内容, ...

  3. Automation Framework Design 自动化框架设计思想

    从2007年到2017年,十年内自动化测试工具层出不穷,各种工具在运用一段时间之后,各个公司都会有测试架构师对于目前的自动化测试工具进行框架定制设计. 从惠普2007年GDCC推出的的WebDrivi ...

  4. LoadRunner脚本设计、场景设计和结果分析

    本次笔记主要记录LoadRunner脚本设计.场景设计和结果分析   1. 脚本设计       录制模式            手工模式:插入步骤.手动编写       1.1  脚本增强:     ...

  5. Eclipse+Selenium自动化测试脚本设计V1.0

    Eclipse+Selenium自动化测试脚本设计V1.0 http://www.docin.com/p-803032251.html

  6. VS2010+Selenium测试脚本设计

    VS2010+Selenium测试脚本设计 http://www.docin.com/p-755903506.html

  7. CYQ.Data V5 分布式自动化缓存设计介绍(二)

    前言: 最近一段时间,开始了<IT连>创业,所以精力和写的文章多数是在分享创业的过程. 而关于本人三大框架CYQ.Data.Aries.Taurus.MVC的相关文章,基本都很少写了. 但 ...

  8. 自动化脚本中click()或sendKeys()没有反应

    前提: 排除xpath引用错误或元素的xpath每次都不同的情形. 问题描述 自动化脚本中click()方法和sendKeys()方法报错, 返回异常InvocationTargetException ...

  9. appium-desktop录制脚本二次开发,生成我司自动化脚本

    目的 通过对appium-desktop脚本录制功能进行二次开发,使录制的java脚本符合我司自动化框架要求. 实现步骤 1.增加元素名称的输入框 由于ATK(我司自动化测试框架)脚本中元素是以“ap ...

随机推荐

  1. Scala解析Json格式

    Scala解析Json格式 代码块 Scala原生包 导入包 import scala.util.parsing.json._ def main(args: Array[String]): Unit ...

  2. 免XML的SpringMVC配置

    Servlet 3.0以后,新增了一些注解,使得web.xml可以省略掉.这样配合Spring的JavaConfig就可以实现免xml的项目配置,这里简单搭建一个免XML的SpringMVC.Spri ...

  3. 在Myeclipse中拷贝一个web项目,但是tomcat文件夹中没有更新,需要进行修改才能更新。

    1.在Myeclipse中拷贝一个web项目,但是tocat文件夹中没有更新,需要进行修改才能更新. 2.方法:右键这个工程,然后Properties->MyEclipse->Projec ...

  4. 最小生成树 B - Networking

    You are assigned to design network connections between certain points in a wide area. You are given ...

  5. qt自己定义搜索框(超简单,带效果图)

    1. 什么也不要说.先上效果图: 2. 代码 头文件: #ifndef APPSEARCHLINE_H #define APPSEARCHLINE_H #include <QLineEdit&g ...

  6. CI session 类的用法

    最近使用codeingiter框架,发现默认的session 不是很好用,以下是用法总结:使用的是2.0.2的版本 1.扩展自带的session类:application/libraries/MY_s ...

  7. nodejs fs.open

    fs.open(path, flags, [mode], [callback(err, fd)])是 POSIX open 函数的封装,与 C 语言标准库中的 fopen 函数类似.它接受两个必选参数 ...

  8. ORACLE EM的删除与创建

    手动删除ORACLE 10G EM 使用emca可以手动配置em! 配置em的过程中有一个环节要特别主要: 不论使用dbca还是使用emca -deconfig dbcontrol db -repos ...

  9. ORA-00600: internal error code, arguments: [kkqtSetOp.1]

    新数据库从32升级到64位的11G 11 2 0 3 有条SQL 语句运行的时候会导致内部错误. 使用PL/SQL DEVELOPER 查询该语句的运行机会 按F5键 就激发了这个ORA600 单击此 ...

  10. 在项目开发中使用Git版本号控制工具以提高效率

    安装Git(linux centos平台) 源代码方式安装 1.装依赖 $ yum install curl-devel expat-devel gettext-devel openssl-devel ...