# puppeteer 集成测试时所遇问题

# 问题  描述

我们很熟悉如下一种场景

<input type="file" name="uploadFile" id="uploadeFile" />上传文件
1

点击上传文件按钮时,浏览器会打开  你  系统里面的文件管理器,之后会让你选取你想  上传的文件。在你选取文件 ,点击确定按钮之后,浏览器会把你刚刚  选择的  相应文件上传到指定的服务器。

做前端开发的  大都使用很多框架或者小插件  来处理文件上传,很容易就可以搞定这件事。但这也往往造成了  前端开发人员  不太理解  前端文件上传的深层原理。这也引出  了  我下面的问题。

公司需要我使用 puppeteer 对公司的  的产品进行自动化集成测试。puppeteer 可以很容易  模拟人在真实浏览器中的  每一步操作,我  的思路也是按照现实的每一步动作进行  代码的书写。 总体步骤是:

  1. 获取元素 ①
  2. 元素点击、获取焦点 ②
  3. 输入数据 ③

可参考如下代码

//引入集成测试框架
var puppeteer = require('puppeteer');
//登录url
const loginUrl = 'URL';
puppeteer
  .launch({
    //false:在真实的浏览器中打开
    headless: false,
    //url不是https时需要设置
    ignoreHTTPSErrors: true,
  })
  .then(async (browser) => {
    var page = await browser.newPage();
    //设置页面大小
    page.setViewport({ width: 1920, height: 1080 });
    //打开页面
    try {
      console.log('正在打开页面……');
      await page.goto(loginUrl, { waitUntil: 'networkidle2' });
    } catch (e) {
      console.log('launch err:' + e);
    }

    /**1.登录 */
    try {
      console.log('正在登陆……');
      //获取用户名输入框        ①
      let userName = await page.$('#username');
      //点击用户名输入框        ②
      await userName.click();
      //输入用户名             ③
      await page.keyboard.type(account, { delay: 20 });
      //获取密码输入框
      let thePassword = await page.$('#password');
      //点击密码输入框
      await thePassword.click();
      //输入密码
      await page.keyboard.type(password, { delay: 20 });
      //获取登录按钮节点
      let loginBtn = await page.$('#login-button');
      //点击登录按钮
      await loginBtn.click();
      await timeout(3000);
      console.log('完成登录。');
    } catch (e) {
      console.log('login err:' + e);
    }
    //关闭browser
    browser.close();
  });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

但是, 怎么模拟文件上传功能呢?  前端文件上传功能:

  1. 点击上传 input 标签;
  2. 在系统文件管理器中选取要上传的文件
  3. 确定, 上传。

那如何  来模拟这  几个操作呢? 难道也要这样一步一步来吗? 可是 puppeteer 里面并没有处理打开系统文件管理器--选取文件--确定这一系列操作的接口。 怎  样才能解决呢?

# 解决方法

可能好多一开始使用 puppeteer 做集成测试的人都会犯上面的错误。我搜索了几乎能找到的 blog 都没有解决我的问题。最终还是在官网 github api 中窥到了解决问题的方法---.uploadFile()

elementHandle.uploadFile(...filePaths)
...filePaths <...string> Sets the value of the file input these paths. If some of the filePaths are relative paths, then they are resolved relative to current working directory.
returns: <Promise>
This method expects elementHandle to point to an input element.
1
2
3
4

可是这真的是解决我们问题的 api 吗? 试了之后才发现,真是!可是表单中的文件上传这么重要的功能竟然也没有一个例子。我也真实服了。 最终 puppeteer 文件上传  功能实现如下

try {
  console.log('文件上传中……');
  //获取上传文件按钮
  let uploadFile = await page.$('#uploadFile');
  //文件上传fileToUpload是文件所在的地址--可以是相对也可以是绝对路径
  await uploadFile.uploadFile(fileToUpload);
} catch (e) {
  console.log('文件上传错误:' + e);
}
1
2
3
4
5
6
7
8
9

# 忠告

  1. api 要写清楚功能,特别是重要的;
  2. 能  提供实例的最好  提供;
  3. English is REALLY important!
Last Updated: 2/8/2023, 2:30:06 AM