我被分配了一个繁琐的任务,就是要给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. mysql 5.5与5.6 timestamp 字段 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP的区别

    http://www.111cn.net/database/mysql/55392.htm 本文章来给各位同学介绍关于mysql 5.5与5.6 timestamp 字段 DEFAULT CURREN ...

  2. noip模拟赛 蒜头君的排序

    分析:其实就是求m个区间的逆序对个数,题目真的是明摆着让我们用莫队算法,套用树状数组就可以了. 具体怎么转移呢?如果移动R,那么对区间[l,r]有影响的是R左边的元素,我们只需要看有多少在R左边比a[ ...

  3. python——re模块(正则表达式)

    re 模块的使用: 1.使用compile()函数编译一个parttern对象, 例如:parttern=re.compile(r'\d+') 2.通过pattern对象提供的一系列属相和方法,对文本 ...

  4. sharepoint 2013安装--没安装成功--机器配置太低了

    油管上的sharepoint2013安装教程 https://www.youtube.com/watch?v=3lQVMGWJQho 下载脚本的网址 http://gallery.technet.mi ...

  5. Android 学习历程摘要(三)

    1.proguard混淆:对与Activity等不应进行混淆.否则系统将找不到生命周期函数:JSON字符串要考虑混淆之后是否会影响字段名:native方法也不混淆,否则调用不到 2.ListView的 ...

  6. linux sed 命令的用法

    原文  http://blog.chinaunix.net/uid-24426415-id-77244.html ------------------------------------------- ...

  7. HDU 2489 Minimal Ratio Tree (dfs+Prim最小生成树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2489 Problem Description For a tree, which nodes and ...

  8. JQuery之操作array

    1:split 函数将字符串按某个字符分割,将分割后的结果存入字符串数组中 function SplitUsersInformation(users) { var usersArray = users ...

  9. OpenCV2马拉松第25圈——直线拟合与RANSAC算法

    计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g/article/details/28118095 收入囊中 最小二乘法(least ...

  10. Cocos2d-x3.3RC0载入Android的WebView

    代码部分摘自http://www.fusijie.com/blog/2013/12/26/play-cocos2dx-33/ Cocos2d-x3.3RC0通过Jni嵌入Android的WebView ...