Node.js + electron-vue 使用selenium-webdriver 对浏览器进行操作

在使用electron-vue写自动化测试软件的时候,遇到了一些关于使用selenium-webdriver的坑,来记录一下
一、环境配置

由于vue并没有实际运行在node的运行时中,所以,在vue中引入selenium-webdriver会引发 no such module 的报错,这个错误当时困扰了我很久,因为确实没有意识到是不同运行时环境的问题。所以,基于这一点,我选择了在本地起一个node服务,通过访问node,来对selenium进行操作

const app = require('express')
const { Builder, By } = require('selenium-webdriver')

const server = app()

server.use((req, res, next) => {
  if (req.path !== '/' && !req.path.includes('.')) {
    res.set({
    // 由于vue启动时会自己占用一个端口,所以我们在服务端进行配置解决跨域问题
      'Access-Control-Allow-Credentials': true,
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Headers': 'X-Requested-With,Content-Type,access-token',
      'Access-Control-Allow-Methods': 'PUT,POST,GET,DELETE,OPTIONS',
      'Content-Type': 'application/json; charset=utf-8'
    })
  }
  req.method === 'OPTIONS' ? res.status(204).end() : next()
})

var port = 10099
var host = 'localhost'
server.listen(port, host, () => {
  console.log(`server running @ http://${host}:${port}`)
})

server.get('/openWeb', function (req, res) {
// 这个是对selenium进行操作的函数,会在稍后贴出
  jsOpenWeb()
})

这种解决方案的问题在于,需要通过命令行来启动本地的node服务,我这边使用electron可以在background.js中添加node child_process代码

// 命令行启动node服务,可以放在app.on('ready') 中
function startServer () {
  const cmdStr = 'node localServer.js'
  var exec = require('child_process').exec(cmdStr, function (error, stdout, stderr) {
    console.log(error)
    console.log(stdout)
  })
  exec.on('close', function (code) {
    console.log(code)
  })
}
二、操作浏览器

参考selenium文档

相关的代码可以参考以上文档,但是,在js的sdk中,几乎所有的操作均是异步执行,即所有的函数均返回Promise对象,这里是第二个卡住我的地方,因为我一开始并没有理解Promise是什么,直到和做前端的同学聊天时才得知,这是一个用于异步操作的对象,于是将原来的同步执行代码均换为异步执行

/**
*1.说明一下,中间注释的部分为之前在Chrome中测试网站会有弹窗,注释部分为滤除弹窗用的
*2.由于涉及到正在做抓取的网站,所以,我把域名换成百度了,都差不多,不过需要着重注意
   在一个页面有frame的时候,一定要将焦点通过switchTo函数切换到frame中,否则,
   无法获取网页元素。如果没有frame存在,直接摘掉switchTo().frame() 代码块即可操作
*/
function jsOpenWeb () {
  const broswer = new Builder().forBrowser('internet explorer').build()
  broswer.get('https://www.baidu.com')
  // broswer.wait(until.alertIsPresent()).then(() => {
    // broswer.switchTo().alert().accept().then(() => {
      //broswer.findElement(By.id('fraInterface')).then((value) => {
        console.log(value)
        broswer.switchTo().frame(value).then(() => {
        //下面两行代码效果一样的
        //通过元素id找到该元素并写入值
          broswer.findElement(By.id('kw')).sendKeys('搜索内容')
        //通过元素name找到该元素并写入值
          broswer.findElement(By.name('')).sendKeys('搜索内容')
        })
     // })
   // })
  // })
}
三、报错处理

1.记得把所有需要的浏览器驱动(IEDriverServer/ChromDriver)等等加入到环境变量中,Mac(usr/bin) Win(控制面板->系统与安全->系统->高级系统设置->高级->环境变量,将driver的路径填写进去就可以)

2.关于元素未找到的错误:
这个问题有网速相关,有frame嵌套的原因,但是在js的sdk中,更多的是没有异步执行的关系,比如你实际上并没有切入到frame中,就要去获取frame中的一个input是肯定不行的,所以,建议多打断点和log

3.IE下,input元素输入速率过慢:
如果出现了在给input写入值的时候,几秒钟才蹦出一个字符的这种现象时,请检查你的IEDriver,看看是否是32位的,如果不是,请换成32位

你可能感兴趣的:(Electron-Vue,javaScript)