@allwright.dev/vitest (英语)
带有 Playwright 风格的全赖特装置 browser 财务报告和审定财务报表 page
注射,外加Android,iOS,macOS,以及Windows应用装置,用于本土测试和混合测试.
以 allwrightVitestConfig它在工人运行前开始一次,在测试完成后关闭一次。 现有的用户全局设置文件在Allwright启动后仍然支持并运行,然后在Allwright停止前拆出.
import { allwrightVitestConfig } from "@allwright.dev/vitest/config";
import { defineConfig } from "vitest/config";
export default allwrightVitestConfig(defineConfig({
test: {
globalSetup: ["./test/my-global-setup.ts"],
},
}));
安装 :
bun add -d vitest @allwright.dev/vitest
import { expect, test } from "@allwright.dev/vitest";
test("opens a page", async ({ page }) => {
await page.goto("https://themoderninternet.vercel.app");
await page.click(
"xpath=//div[contains(@class,'card')][.//h2[normalize-space()='Form Inputs']]//button[normalize-space()='Visit page']",
);
await expect(page.locator('xpath=//h1[text()="Form Inputs"]')).toHaveText("Form Inputs");
});
test("opens an Android app", async ({ androidApp }) => {
await androidApp.click('Id=com.example.airticket:id/bottom_nav_account');
});
test("opens an iOS app", async ({ iosApp }) => {
await iosApp.getByRole("button", { name: "Login", exact: true }).click();
});
test("opens a macOS app", async ({ macosApp }) => {
await macosApp.getByRole("button", { name: "New Document", exact: true }).click();
});
test("opens a Windows app", async ({ windowsApp }) => {
await windowsApp.getByRole("textbox").fill("Hello from Allwright");
});
检查的示例检查覆盖每个已执行的表面 :
网页, (中文(简体) ), 机器人, (中文(简体) ),
iOS系统, (中文(简体) ),
马科斯,以及
窗口。原生规格使用应用目标
配置到其表面 allwright.config.yaml 或者说
allwright.config.json。 。 。 .
固定套件读取共享的堆栈不可知配置格式 @allwright.dev/core。 。 。 .
使用 allwright.config.yaml 默认,或 allwright.config.json 如果你喜欢。 两者都遵循相同的根子计划 allwright.schema.json。 。 。 .
schemaVersion: 1
server:
addr: 127.0.0.1:50051
web:
browser:
name: firefox
binary: /Applications/Firefox.app/Contents/MacOS/firefox
expect:
timeoutMs: 7000
intervalMs: 100
suites:
smoke:
web:
browser:
name: chromium
Vitest 可以覆盖或从共享配置中选择,而不切换到 Vitest 特定文件 :
import { expect, test as base } from "@allwright.dev/vitest";
const test = base.extend({
allwright: async ({}, use) => {
await use({ suite: "smoke" });
}
});
Android 固定装置与网络固定装置同时提供:
import { expect, test as base } from "@allwright.dev/vitest";
const test = base.extend({
allwright: async ({}, use) => {
await use({
android: {
launchOptions: {
apkPath: "/absolute/path/to/app.apk",
appId: "com.example.airticket",
},
},
});
},
});
test("android only", async ({ androidApp }) => {
await androidApp.fill('xpath=//*[@text="Email"]', "[email protected]");
await expect(androidApp.locator('xpath=//*[@text="Email"]')).toHaveText("[email protected]");
});
test("hybrid web and android", async ({ page, androidApp }) => {
await page.goto("https://themoderninternet.vercel.app");
await androidApp.click('Id=com.example.airticket:id/bottom_nav_account');
});
iOS使用相同的应用程序和定位器形状. 配置本地代理端点 和捆绑标识符一次,然后将平台的靴子从测试机体中取出:
# allwright.config.yaml
mobile:
ios:
device: iPhone 17 Pro
app:
binary: https://allwright.dev/Flights-simulator.ipa
设定 ALLWRIGHT_IOS_AGENT_ENDPOINT 当代理无法到达时
http://127.0.0.1:8100。应用值也可能是本地的 .app, (中文(简体) ), .zip,或
.ipa; 需要时固定下载/取出, 安装在
选中的模拟器, 获取其捆绑标识符, 并启动它 。 覆盖
带它 ALLWRIGHT_IOS_APP_PATH。没有手工安装或投票
测试。 测试仅保留平台客户端代码 :
import { expect, test } from "@allwright.dev/vitest";
test("logs in", async ({ iosApp }) => {
await iosApp.getByRole("button", { name: "Login", exact: true }).click();
await iosApp.getByLabel("Email", { exact: true }).fill("[email protected]");
await expect(iosApp.getByText("Welcome back", { exact: true })).toBeVisible();
});
macOS应用程序使用已安装的应用程序捆绑标识符. 固定开始 捆绑的桌面 XCUI Test 运行器并发射配置的应用程序 :
# allwright.config.yaml
desktop:
mac:
app:
id: com.apple.TextEdit
import { expect, test } from "@allwright.dev/vitest";
test("opens a document window", async ({ macosApp }) => {
await macosApp.getByRole("button", { name: "New Document", exact: true }).click();
await expect(macosApp.getByRole("textField")).toBeVisible();
});
使用 ALLWRIGHT_MAC_AGENT_ENDPOINT 用于外部代理人或
ALLWRIGHT_MAC_APP_ID 以覆盖已配置的捆绑标识符.
Windows应用程序使用可执行路径,命令名,或被包-app AUMID. 这个 fixture 启动捆绑的 FlaUI UIA3 代理,并发射应用懒散:
# allwright.config.yaml
desktop:
windows:
app:
id: notepad.exe
import { expect, test } from "@allwright.dev/vitest";
test("edits a document", async ({ windowsApp }) => {
await windowsApp.getByRole("textbox").fill("Hello from Allwright");
await expect(windowsApp.getByRole("textbox")).toContainText("Hello");
});
使用 ALLWRIGHT_WINDOWS_AGENT_ENDPOINT 用于外部代理人或
ALLWRIGHT_WINDOWS_APP_ID 以覆盖已配置的应用程序标识符.
修饰品是懒惰的第一使用。 注入 browser, (中文(简体) ), page, (中文(简体) ), android, (中文(简体) ),
androidApp, (中文(简体) ), ios, (中文(简体) ), iosApp, (中文(简体) ), macos, (中文(简体) ), macosApp, (中文(简体) ), windows,或 windowsApp
不立即启动或连接;仅创建基础会话
当测试第一次通过固定执行动作时. 同步元数据
属性只有在懒惰的固定器被一个
先前等待的电话.
可用的固定装置 :
browser: 启用网页浏览器page: 初始网页android: 已连接的 Android 设备会话androidApp: 推出Android应用页面ios: 连接到 iOS 设备会话iosApp: 启用了 iOS 应用程序页面macos: 连接的 macOS 桌面会话macosApp: 启动的 macOS 应用页面windows: 连接的 Windows 桌面会话windowsApp: 启用了 Windows app页面
androidApp 导弹发射 allwright.android.launchOptions 首先,然后回到 config.mobile.android。 。 。 .
iosApp 与 allwright.ios.launchOptions 财务报告和审定财务报表 config.mobile.ios。 。 。 .
macosApp 与 allwright.macos.launchOptions 财务报告和审定财务报表 config.desktop.mac。 。 。 .
windowsApp 与 allwright.windows.launchOptions 财务报告和审定财务报表 config.desktop.windows。 。 。 .
Android, iOS, macOS, 以及Windows应用程序和定位器支持本地动作和
期望子集 : click, (中文(简体) ), count, (中文(简体) ), focus, (中文(简体) ), fill, (中文(简体) ), press, (中文(简体) ), textContent, (中文(简体) ), innerText, (中文(简体) ),
waitForSelector,以及 screenshot4. 流动预期 toHaveText, (中文(简体) ),
toContainText, (中文(简体) ), toHaveCount,以及 toBeVisible 使用相同的重试控件
作为网络固定装置。 紧紧靠并突出亮相仍只使用网络.
选入无障碍集成测试对公共页面进行固定, 被捆绑的原生取出,运行的引擎和动态加载的网络插件. 从这 创建软件包后, 运行 :
ALLWRIGHT_TEST_BROWSER=chromium bun run --cwd typescript/vitest vitest run tests/accessibility.spec.ts
ALLWRIGHT_TEST_BROWSER=firefox bun run --cwd typescript/vitest vitest run tests/accessibility.spec.ts
设定 ALLWRIGHT_TEST_LIVE_SITE=1 以复制窗体输入导航
公共实例网站. 默认固定为本地数据 URL. 使用
ALLWRIGHT_CLI_PATH 财务报告和审定财务报表 ALLWRIGHT_SERVER_ADDR 选择测试中的运行时间;
客户端、引擎和已安装的网络插件版本必须匹配.
被忽略的主张和地点排除
每个全赖特的页面/应用和定位匹配器都支持两个维特的 .not 表单
和可召唤者 .not() 别名。 使用
相同的超时和间隔选项:
await expect(page.getByRole('status')).not.toHaveText('Loading');
await expect(page.getByTestId('spinner')).not().toBeVisible();
await expect(page).not.toHaveCount('.error', 1);
await expect(androidApp.locator('text="Loading"')).not().toBeVisible();
当元素被隐藏或缺失时,负能见度成功. 选择器,
运输,而且会话错误仍然失败;它们不是隐形的证据.
否定文本的断言需要读取成功的文本。 匹配对象为
不可改变,还有一秒钟 .not 切换回积极的断言。 普通类
虚拟价值主张保留其原产地 .not 语法.
网络定位器也支持按元素身份进行排除,并进一步连锁:
const enabledActions = page.getByRole('button')
.not(page.getByRole('button', { disabled: true }));
await expect(enabledActions).not().toHaveCount(0);
两种定位器必须属于同一页. .not(other) 删除匹配的节点;
filter({ hasNot: other }) 删除包含匹配后人的候选人.
与 TypeScript/Java 一样,核心网络客户端中可提供相同的排除 API
.not(other)开始 .Not(other)粗鲁 .not(&other)和 Python 键 .not_(other)。 。 。 .
本作的Android定位器排除功能不被这个网络选择器API所曝光.
重试国家的期望
相对于页面或定位器,所以每次尝试读取新状态:
await expect(page).toHaveURL('https://example.com/dashboard');
await expect(page).toHaveURL(/\/dashboard(?:\?|$)/, { timeoutMs: 10_000 });
await expect(page.locator('input')).toHaveValue(/ready/i);
await expect(page.locator('select')).toHaveSelectedOptions(['a', 'b']);
await expect(page.locator('select')).toHaveSelectedOptions([{ value: 'a', label: /Alpha/ }]);
await expect(page.locator('textarea')).toHaveSelectedText('selected words');
await expect(page.locator('input[type=checkbox]')).toBeChecked();
await expect(page.locator('button[type=submit]')).toBeEnabled();
await expect(page.locator('input')).toBeEditable();
await expect(page.locator('input')).toBeFocused();
await expect(page.locator('.spinner')).toBeHidden();
await expect(page.locator('main')).toBeAttached();
await expect(page.locator('h1')).toHaveText('Welcome');
await expect(page.locator('a')).toHaveAttribute('href', /dashboard/);
await expect(page.locator('button')).toHaveBoundingBox({ width: 100, height: 40 });
await expect(page.locator('input[type=radio]')).not().toBeChecked();
每个元素匹配器也有一个页面/应用程序格式,例如 expect(page).toHaveValue('#name', 'Alice') 或者说 expect(androidApp).toBeEnabled('text="Continue"')。值、 检查状态、 属性、 边框、 附加/ 隐藏、 启用/ 损坏、 聚焦和可编辑的匹配者在网络、 Android、 iOS、 macOS 和 Windows 之间工作。 URL,所选择的选项和所选择的文本匹配者仍然只使用网络.
Allwright 页面/app/定位器的预期重试,直到匹配或超时结束,包括 .not 财务报告和审定财务报表 .not()。默认来自共享断言配置,返回到5秒和100毫秒间隔。 以 { timeoutMs, intervalMs }飞行中读取和嵌入的命令超时提示受剩余断言预算的约束; timeoutMs: 0 做一个观察,没有投票。 对已经捕获的数值的普通断言,例如 expect(await page.url()).toBe(...),使用标准Vitest行为,不重读页面.
字符串 URL 的预期完全匹配完整 URL; regex 的预期匹配当前每次尝试的 URL,而不修改 regex 的 lastIndex。数值、所选文本和属性也接受字符串或正则exs. null 表示缺少属性或不支持的文本框选择;空字符串是不同的。 所选选项数组按顺序匹配,并需要相同数量的选项. 条目可以是准确的值,值正则ex,也可以是指定值,标签,和/或索引的对象. b. 仅将所提供坐标/分数精确地与取景点CSS像素进行比较; null 期望没有可见的框. .not.toBeChecked() 等待一个不受控制的控制。 缺失元素和读取错误不能满足否定.