javascript 在Playwright中直接在浏览器上下文中运行Assert

iovurdzv  于 2023-11-15  发布在  Java
关注(0)|答案(3)|浏览(136)

我想测试一些直接绑定到浏览器的API,不需要有UI表示。
最简单的测试是这样的:

import { test, expect } from "@playwright/test";

test("creates Image element", async ({ page }) => {
  await page.goto(`http://localhost:3333/e2e/assets/Dynamic.spec.html`);

  const img = new Image();
  const asset = new DynamicAsset(img);

  expect(asset.element()).toEqual(img);
});

字符串
当使用cypress时,所有的测试都在浏览器上下文中运行,这是可行的。
但在剧作家中出现以下错误:

ReferenceError: Image is not defined

    at file:///Users/tomche/development/frontendara/amandes/e2e/assets/Dynamic.spec.js:6:15


如果使用page.evaluate,如:

import { test, expect } from "@playwright/test";

test("creates Image element", async ({ page }) => {
  await page.goto(`http://localhost:3333/e2e/assets/Dynamic.spec.html`);

  await page.evaluate(() => {
    const img = new Image();
    const asset = new DynamicAsset(img);

    expect(asset.element()).toEqual(img);
  });
});


错误是:

page.evaluate: ReferenceError: expect is not defined


这是因为在浏览器上下文中评估的代码没有从上层作用域导入。
文档似乎只提到了可序列化的东西,但这段代码需要验证复杂的东西,这些东西在node或可序列化中并不是真正的mockable。
那么,有没有一种方法可以在浏览器中运行类似于cypress/karma等的Assert呢?

jdzmm42g

jdzmm42g1#

运行更新的完整测试代码,可以在evaluate()之外工作
(But注意我有一个不同的错误消息从原来的)

import { test, expect } from "@playwright/test";

test("creates Image element", async ({ page }) => {
  await page.goto(`http://localhost:3333/e2e/assets/Dynamic.spec.html`);

  const result = await page.evaluate(() => {
    const img = new Image();
    const asset = new DynamicAsset(img);
    return {img, asset}
  });

  expect(result.asset.element()).toEqual(result.img);
});

字符串

cgyqldqp

cgyqldqp2#

expect传递到page.evaluate()

import { test, expect } from "@playwright/test";

test("creates Image element", async ({ page }) => {
  await page.goto(`http://localhost:3333/e2e/assets/Dynamic.spec.html`);

  await page.evaluate((expect) => {
    const img = new Image();
    const asset = new DynamicAsset(img);

    expect(asset.element()).toEqual(img);
  }, expect);
});

字符串

sshcrbum

sshcrbum3#

Playwright、Puppeteer和其他基于后端的浏览器自动化库的黄金法则是:将浏览器的内容保存在浏览器中,将后端的内容保存在后端。在浏览器进程和后端进程之间来回移动数据的唯一方法是通过网络套接字进行序列化和非序列化(如果您喜欢,可以使用字符串化和反字符串化)。
对于OP的用例,现有的答案将不起作用,因为它们试图通过网络套接字将复杂的、不可序列化的对象作为字符串发送或返回。
在“将浏览器对象返回到Node”解决方案中,即使你可以序列化对象并在Node中重建它们,标识也不再匹配。即使标识匹配,测试的全部目的是处理浏览器中网站中运行的JS。如果这是一个可以使用Node对象执行的测试,使用Playwright没有什么意义,在纯Node中进行一个简单的Jest单元测试就可以了。
在“将PlaywrightAssert传递到浏览器”中,即使您可以序列化对象需要向Node报告错误的所有内容,但它并没有设计这样做。
对于当前的场景,正确的方法是在浏览器中执行相等性检查,对象所在的位置,然后返回一个简单的,可序列化的布尔值给Node进行Assert:

import {expect, test} from "@playwright/test"; // ^1.39.0

test("creates Image element", async ({page}) => {
  await page.goto("http://localhost:3333/e2e/assets/Dynamic.spec.html");

  const isAssetElementEqualToImg = await page.evaluate(() => {
    const img = new Image();
    const asset = new DynamicAsset(img);
    return asset.element() === img;
  });
  expect(isAssetElementEqualToImg).toBe(true);
});

字符串
自定义错误消息对于提高Assert失败消息的可读性非常有用:

test("creates Image element", async ({page}) => {
  await page.goto("http://localhost:3333/e2e/assets/Dynamic.spec.html");

  const eq = await page.evaluate(() => {
    const img = new Image();
    const asset = new DynamicAsset(img);
    return asset.element() === img;
  });
  expect(eq, "asset.element() === img was false").toBe(true);
});


这对于OP的特定场景来说很好,因为 predicate 可以同步确定,但是对于其他涉及实时异步工作的测试,您可能希望轮询或使用自定义匹配器来等待Assert通过。

相关问题