javascript - 如何自动化 ElectronJS 应用程序

标签 javascript automation electron puppeteer nightmare

我们正在寻求开发一个 ElectronJS 应用程序,用于在我们的办公室工作中实现特定的网站自动化,其中包括常见的任务,如登录、表单填写、报告下载等。

我们已经尝试了 ElectronJS、Spectron、NightmareJS、Puppeteer 等的基本教程,它们都可以单独工作,但是关于相互集成的文档非常少(尽管打开了 github 问题)。

我们希望实现以下目标:

  • 登录状态(session)不应在 ElectronJS 应用关闭时删除,并且应在应用重启时可用。
  • 在现有 browserWindow 上启动一些自动化任务(如下载、表单填写等)的菜单按钮很少

我们不需要 headless 自动化,在这种情况下,幕后会发生一些魔法。我们只需要当前页面上基于菜单/按钮点击的操作/任务。

NightmareJSPuppeteer 等似乎都启动了自己的网页实例(因为它们是为测试独立应用程序而构建的)但我们需要的是自动化现有的 BrowserWindows

puppeteernightmarejs 是实现此类目标的正确工具吗?如果是,有任何文件吗?

否则,我们是否应该在控制台中注入(inject)我们自己的原生 JS 事件,如 mouseclick 等事件来执行操作?

最佳答案

您可以使用puppeteer-corecore 版本默认不下载 Chromium,如果你想控制 Electron 应用程序则不需要它。

然后在测试中调用 launch 方法,将 electron 定义为可执行文件而不是 Chromium,如以下代码片段所示:

const electron = require("electron");
const puppeteer = require("puppeteer-core");

const delay = ms =>
  new Promise(resolve => {
    setTimeout(() => {
      resolve();
    }, ms);
  });

(async () => {
  try {
    const app = await puppeteer.launch({
      executablePath: electron,
      args: ["."],
      headless: false,
    });
    const pages = await app.pages();
    const [page] = pages;

    await page.setViewport({ width: 1200, height: 700 });
    await delay(5000);
    const image = await page.screenshot();
    console.log(image);
    await page.close();
    await delay(2000);
    await app.close();
  } catch (error) {
    console.error(error);
  }
})();

Electron 5.x.y 及更高版本的更新(目前最高为 7.x.y,我尚未在 8.x.y beta 上对其进行测试),其中使用 puppeteer.connect 而不是 启动方法:

// const assert = require("assert");
const electron = require("electron");
const kill = require("tree-kill");
const puppeteer = require("puppeteer-core");
const { spawn } = require("child_process");

let pid;

const run = async () => {
  const port = 9200; // Debugging port
  const startTime = Date.now();
  const timeout = 20000; // Timeout in miliseconds
  let app;

  // Start Electron with custom debugging port
  pid = spawn(electron, [".", `--remote-debugging-port=${port}`], {
    shell: true
  }).pid;

  // Wait for Puppeteer to connect
  while (!app) {
    try {
      app = await puppeteer.connect({
        browserURL: `http://localhost:${port}`,
        defaultViewport: { width: 1000, height: 600 } // Optional I think
      });
    } catch (error) {
      if (Date.now() > startTime + timeout) {
        throw error;
      }
    }
  }

  // Do something, e.g.:
  // const [page] = await app.pages();
  // await page.waitForSelector("#someid")// 
  // const text = await page.$eval("#someid", element => element.innerText);
  // assert(text === "Your expected text");
  // await page.close();
};

run()
  .then(() => {
    // Do something
  })
  .catch(error => {
    // Do something
    kill(pid, () => {
      process.exit(1);
    });
  });

获取pid 和使用kill 是可选的。对于在某些 CI 平台上运行脚本并不重要,但对于本地环境,您必须在每次尝试失败后手动关闭 Electron 应用程序。

简单的演示 repo : https://github.com/peterdanis/electron-puppeteer-demo

关于javascript - 如何自动化 ElectronJS 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51847667/

相关文章:

javascript - 将函数从 jQuery 转换为 Mootools

javascript - 如何使用 HtmlUnit 从 JavaScript html 页面获取结果?

java - 在有父元素的情况下查找子元素

javascript - electron-packager spawn ENOENT

javascript - 如何覆盖 JavaScript web api 通知对象

javascript - 在 UIWebView 中进行多项选择的 HTML 文件输入不适用于视频

javascript - 为什么这个 jquery each() 循环不对唯一类进行操作

php - 无法回显 Ajax 变量传递

python - 如果 RDC 最小化,Sikuli 脚本不会运行

electron - 在 Electron App 中使用 Ctrl+滚轮缩放?