[microsoft/playwright]壮举:playwright-crx,剧作家的 chrome 扩展风格

2024-04-09 402 views
0

正如 #23514 中所讨论的,这是playwright-crx的 PR ,这是一个可以在 Chrome 扩展服务工作线程中运行的 playwright 版本。

为此,它依赖chrome.debugger.sendCommand/chrome.debugger.onEvent来实现ConnectionTransport接口。

应用程序编程接口

可以用作@playwright/experimental-crx库来创建新的 chrome 扩展。

这是使用playwright-crx的 chrome 扩展的后台服务工作者的简单示例:

import { _crx } from '@playwright/experimental-crx';

const crxPromise = _crx.start({ slowMo: 500 });

chrome.action.onClicked.addListener(async ({ id: tabId }) => {
  const crx = await crxPromise;

  // tries to connect to the active tab, or creates a new one
  const page = await crx.attach(tabId!).catch(() => crx.newPage());

  await page.goto('https://demo.playwright.dev/todomvc/#/');
  await page.getByPlaceholder('What needs to be done?').click();
  await page.getByPlaceholder('What needs to be done?').fill('Hello World!');
  await page.getByPlaceholder('What needs to be done?').press('Enter');

  // page stays open, but no longer controlled by playwright
  await crx.detach(page);
});

更完整的示例可以在 中找到example/todomvc-crx

API测试

大多数playwright-crx测试都在tests/crx/test-extension.它的后台 Service Worker 接收带有一些固定装置(当时有限,请参阅 参考资料crxFixtureRunner.ts)的序列化测试方法并运行它。

为了在模式下运行测试crx,我创建了一个新的 npm 脚本:npm run xtest

即使有一些限制(类似于page.evaluate),它已经通过了超过 1k 次测试。

然而,这是需要很大改进的地方:

  • 如果在测试函数之外声明函数或变量,测试将不会运行
  • 测试运行缓慢,因为它需要使用我们的测试 chrome 扩展为每个测试重新启动一个新的持久上下文
  • 目前固定装置非常有限
录音机

我决定将记录器 chrome 扩展集成到packages/recorder.

这样,该应用程序将继续像以前一样工作,但现在也可以作为 Chrome 扩展安装。

对原始应用程序的唯一更改只是一个内容脚本,用于在检测到扩展后台服务工作线程在 Chrome 扩展上下文中运行时与其进行通信。

在chrome扩展功能方面,它提供了:

这是一个更新的视频(我用来录制视频的应用程序存在鼠标位置错误):

https://github.com/microsoft/playwright/assets/1374559/3c67d830-3eb2-48f5-b409-28354c101b87

记录仪测试

在模式下,测试tests/library/inspector也会作为 chrome 扩展针对记录器运行crx

它使用我们的记录器 chrome 扩展启动持久上下文,然后使用 chrome 剧作家页面附加到其选项卡。

请注意,它使用 playwright chrome 风格而不是 crx 风格来自动化这些特定测试,但记录的指令由crx.请参阅inspectorTests.ts了解更多详情。

库包/需要

除剧作家捆绑包外,大部分requires 均已替换为相应的imports。对于这些,我创建了一个 vite 插件来替换BundleImpl编译时导入对应的需求

请参阅packages/playwright-crx/vite.config.ts了解更多详情。

垫片

为了编译和运行playwright-crx,我必须依赖 shims/polyfills。

以下是它使用的当前填充程序库的列表(在 中声明packages/playwright-crx/package.json):

我还在 下创建了一些垫片packages/playwright-crx/src/shims,主要带有noop函数。

参考文献:#23514

回答

6

“测试1”报告

3

@pavelfeldman,我还没有解决显式的 platformBundle 问题,因为我想在此时将代码更改保持在最低限度,并具有一些不错的代码覆盖率。

我注意到(困难的方式,CI 没有通过)你已经有了一个控制代码依赖关系的机制,也许我们可以扩展它来考虑节点库。尽管如此,这些更改总是具有很大的破坏性(拆分和移动代码),因此我认为这些更改应该出现在未来的 PR 中。

让我知道你的想法

6

同时,我正在做一个 vite 插件以避免utilsBundleRequire混乱,敬请期待。

9

vite插件完成。我还进行了重大变基并合并/删除了不再有意义的提交。

4

“测试1”报告

6

“测试1”报告

8

谢谢@pavelfeldman,我完全理解你的担忧。我的目标是避免使用任何节点垫片/填充,但这似乎比我最初想象的要难,所以这是我让事情正常工作和测试的第一个方法,以确保我不会破坏双方的任何东西,并且然后开始一步一步地解决这种脱钩问题。

但只是为了管理我的期望,如果值得付出努力,如果我找到一种仅依赖同构代码的干净方法,那么合并可以接受吗?

7

只是一个更新:我找到了一种使用树摇动来删除依赖项并使某些代码无法访问的方法。例如:

function writeFile(file: string, text: string) {
  if (process.env.PW_CRX) throw new Error(`Operation not allowed in CRX mode`);
  fs.writeFileSync(this._file, this._text);
}

fs.writeFileSync编译后将不包含该函数process.env.PW_CRX=1。我希望通过这种方式,代码更改将是最少的。

我刚刚做了这个httphttps模块,我不再需要那些https-browserifystream-http。其他大多数都更容易更换。

我还研究了utilsBundlezipBundle库,其中有几个是同构的,而不是在非常特定的地方使用的,所以类似的方法就可以了。

将是一个挑战的模块:

您认为包含这些库中的任何一个是可以接受的吗?例如,readable-stream来自NodeJS团队,其他一些(eventspath)是节点版本的副本。

1

删除 polyfill 依赖项的第一次迭代。

我还没有全部删除,但我已经实施了该策略:

  • 我为我们不想包含的节点模块创建了一个垫片生成器。它的想法是在 vite 编译库中清楚地标记正在调用这些模块(请参阅utils/crx/generate_node_shims.js
  • 我还创建了一个检查器,确保在最终编译的库中不会调用任何排除的节点模块(请参阅utils/crx/check_deps.js
  • 根据检查器的结果,我强制节点相关代码无法访问(请参阅我之前的评论https://github.com/microsoft/playwright/pull/24020#issuecomment-1626348338
  • 我还从现有捆绑包的 crx 版本中排除了非同构库

我试图对当前代码库进行尽可能小的更改。

9

关闭为不可诉

9

我确实使用了 ShareX 吗?