@midscene/test 1.16.0 → 1.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/{1~77.mjs → 1~731.mjs} +9 -9
- package/dist/es/1~731.mjs.map +1 -0
- package/dist/es/cli/index.mjs +686 -167
- package/dist/es/cli/index.mjs.map +1 -1
- package/dist/es/index.mjs +45 -1
- package/dist/es/index.mjs.map +1 -1
- package/dist/es/test-cli.mjs +1863 -206
- package/dist/es/test-cli.mjs.map +1 -1
- package/dist/lib/cli/index.js +677 -155
- package/dist/lib/cli/index.js.map +1 -1
- package/dist/lib/index.js +45 -1
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/test-cli.js +1854 -203
- package/dist/lib/test-cli.js.map +1 -1
- package/dist/templates/test/android/.env.example +1 -1
- package/dist/templates/test/android/README.md +3 -1
- package/dist/templates/test/android/README.zh.md +3 -1
- package/dist/templates/test/android/midscene.config.ts +28 -31
- package/dist/templates/test/computer/.env.example +1 -1
- package/dist/templates/test/computer/README.md +3 -1
- package/dist/templates/test/computer/README.zh.md +3 -1
- package/dist/templates/test/computer/midscene.config.ts +31 -34
- package/dist/templates/test/harmony/.env.example +1 -1
- package/dist/templates/test/harmony/README.md +3 -1
- package/dist/templates/test/harmony/README.zh.md +3 -1
- package/dist/templates/test/harmony/midscene.config.ts +28 -31
- package/dist/templates/test/ios/.env.example +1 -1
- package/dist/templates/test/ios/README.md +3 -1
- package/dist/templates/test/ios/README.zh.md +3 -1
- package/dist/templates/test/ios/midscene.config.ts +28 -31
- package/dist/templates/test/web/.env.example +1 -1
- package/dist/templates/test/web/README.md +17 -1
- package/dist/templates/test/web/README.zh.md +17 -1
- package/dist/templates/test/web/cases/todo.yaml +2 -0
- package/dist/templates/test/web/midscene.config.ts +34 -12
- package/dist/types/cli/index.d.ts +107 -11
- package/dist/types/index.d.ts +6 -3
- package/package.json +14 -13
- package/dist/es/1~77.mjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Copy this file to .env before running tests.
|
|
2
2
|
# Do not commit .env to your repository. In CI, inject these values as environment variables instead.
|
|
3
3
|
# Choose a supported model and copy its four configuration values from:
|
|
4
|
-
# https://midscenejs.com/model-
|
|
4
|
+
# https://midscenejs.com/model-api-setup.html
|
|
5
5
|
# For the complete environment variable reference, see:
|
|
6
6
|
# https://midscenejs.com/model-config.html
|
|
7
7
|
# After configuring .env, verify model connectivity and Midscene compatibility from the project directory:
|
|
@@ -4,7 +4,7 @@ A Midscene Test project for Android, based on the TodoMVC case in `midscene-exam
|
|
|
4
4
|
|
|
5
5
|
If you skipped installation during creation, run `{{INSTALL_COMMAND}}`. The `postinstall` script automatically generates `midscene-node-spec.android.md` after each dependency installation. If lifecycle scripts are disabled, run `{{RUN_NODES_COMMAND}}` manually.
|
|
6
6
|
|
|
7
|
-
Copy `.env.example` to `.env`, then choose and configure a model using the [supported models and setup guide](https://midscenejs.com/model-
|
|
7
|
+
Copy `.env.example` to `.env`, then choose and configure a model using the [supported models and setup guide](https://midscenejs.com/model-api-setup.html). Do not commit `.env` to your repository; inject the model configuration as environment variables in CI.
|
|
8
8
|
|
|
9
9
|
After configuring `.env`, run `{{VERIFY_MODEL_COMMAND}}` from the project directory to check model connectivity and Midscene compatibility. This check does not require a browser or device. If it fails, see [Model debugging and observability](https://midscenejs.com/model-debugging-observability.html) before running tests.
|
|
10
10
|
|
|
@@ -17,3 +17,5 @@ Run tests with `{{TEST_COMMAND}}`. Read `midscene-node-spec.android.md` for the
|
|
|
17
17
|
After changing Node registrations in `midscene.config.ts`, run `{{RUN_NODES_COMMAND}}` to refresh the spec. This loads the configuration without connecting to a device or running tests. Extension factories must only acquire runtime resources inside Node execution.
|
|
18
18
|
|
|
19
19
|
Tests run serially and stop after the first failed case (`test.bail: 1`). Reports are saved and connections are released on failure. Reports are written to `midscene_run/report/`.
|
|
20
|
+
|
|
21
|
+
Each test file creates its own Agent through `fileSetup` and releases it afterward. The Project is limited to one file at a time because this starter connects to a single device or desktop. Before increasing the Project limit, provide independent devices/displays through your resource allocator.
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
这是参考 `midscene-example/android/vitest-demo` TodoMVC 用例的 Android 版 Midscene Test 项目。
|
|
4
4
|
|
|
5
|
-
如果创建时跳过安装,执行 `{{INSTALL_COMMAND}}`。安装后会自动生成 `midscene-node-spec.android.md`;若禁用了安装脚本,手动执行 `{{RUN_NODES_COMMAND}}`。复制 `.env.example` 为 `.env`,按[模型配置指南](https://midscenejs.com/model-
|
|
5
|
+
如果创建时跳过安装,执行 `{{INSTALL_COMMAND}}`。安装后会自动生成 `midscene-node-spec.android.md`;若禁用了安装脚本,手动执行 `{{RUN_NODES_COMMAND}}`。复制 `.env.example` 为 `.env`,按[模型配置指南](https://midscenejs.com/model-api-setup.html)配置模型。
|
|
6
6
|
|
|
7
7
|
配置后,在项目目录执行 `{{VERIFY_MODEL_COMMAND}}`,检查模型连接和 Midscene 兼容性。这一步不需要浏览器或设备;若检查失败,请先参考[模型调试与可观测性](https://midscenejs.com/model-debugging-observability.html)排查,再运行测试。
|
|
8
8
|
|
|
9
9
|
连接设备并用 `adb devices` 确认;可设置 `ANDROID_DEVICE_ID` 指定设备。`cases/todo.yaml` 打开在线 React TodoMVC,添加三个任务、删除一个、完成另一个、筛选已完成任务,并校验可见任务和未完成数量。设备需要能访问该网站;`beforeEach` 先执行 `midscene.config.ts` 中的 `todo.setup`,打开 All 视图并等待输入框加载,再由 `aiAssert` 确认列表为空(包含已完成任务)且没有遮挡弹窗。已有任务会保留;检查失败时,用例会在修改任务前停止。请切换到 All,删除全部任务(包括已完成任务),或仅清除 TodoMVC 网站的数据;关闭遮挡弹窗后重新运行。模型或连接异常应先按报告中的原因排查。AI 检查可能误判,失败时请结合报告确认页面状态。
|
|
10
10
|
|
|
11
11
|
执行 `{{TEST_COMMAND}}` 运行测试。Node 列表见 `midscene-node-spec.android.md`;修改配置中的 Node 后执行 `{{RUN_NODES_COMMAND}}` 刷新。用例串行运行,首次失败即停止后续用例(`test.bail: 1`);失败时仍会保存报告并释放连接。报告位于 `midscene_run/report/`。
|
|
12
|
+
|
|
13
|
+
每份测试文件通过 `fileSetup` 创建独立 Agent,结束后释放。此模板连接一台设备或一个桌面,因此 Project 的 `maxConcurrentFiles` 固定为 1;提高此上限前,需要通过资源分配脚本为并发文件提供独立设备或桌面。
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
import { fileURLToPath } from 'node:url';
|
|
2
2
|
import { AndroidAgent, agentFromAdbDevice } from '@midscene/android';
|
|
3
3
|
import { type NodeExecutionContext, defineNode, z } from '@midscene/test';
|
|
4
|
-
import {
|
|
4
|
+
import { defineFileSetup, defineTestProject } from '@midscene/test/config';
|
|
5
5
|
import { createMidsceneNodes } from '@midscene/test/midscene';
|
|
6
6
|
import { config as loadEnv } from 'dotenv';
|
|
7
7
|
|
|
8
8
|
loadEnv({ path: fileURLToPath(new URL('.env', import.meta.url)) });
|
|
9
9
|
|
|
10
|
-
interface
|
|
10
|
+
interface FileContext {
|
|
11
11
|
agent: AndroidAgent;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const getAgent = ({
|
|
15
|
-
context,
|
|
16
|
-
}: NodeExecutionContext<unknown, ProjectContext>) => {
|
|
14
|
+
const getAgent = ({ context }: NodeExecutionContext<unknown, FileContext>) => {
|
|
17
15
|
return context.agent;
|
|
18
16
|
};
|
|
19
17
|
|
|
20
|
-
const
|
|
18
|
+
const fileSetup = defineFileSetup<FileContext, undefined>({
|
|
21
19
|
name: 'android',
|
|
22
20
|
async setup({ env, onTeardown }) {
|
|
23
21
|
const agent = await agentFromAdbDevice(env.ANDROID_DEVICE_ID || undefined);
|
|
@@ -27,43 +25,42 @@ const setup = defineProjectSetup<ProjectContext>({
|
|
|
27
25
|
});
|
|
28
26
|
|
|
29
27
|
const todoSetupInputSchema = z.strictObject({});
|
|
30
|
-
const todoSetup = defineNode<typeof todoSetupInputSchema, void,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
};
|
|
49
|
-
},
|
|
28
|
+
const todoSetup = defineNode<typeof todoSetupInputSchema, void, FileContext>({
|
|
29
|
+
name: 'todo.setup',
|
|
30
|
+
title: 'Prepare TodoMVC for the initial-state check',
|
|
31
|
+
description:
|
|
32
|
+
'Open React TodoMVC in All view and wait for its input without changing existing tasks.',
|
|
33
|
+
inputSchema: todoSetupInputSchema,
|
|
34
|
+
async execute({ context, signal }) {
|
|
35
|
+
signal.throwIfAborted();
|
|
36
|
+
await context.agent.launch('https://todomvc.com/examples/react/dist/#/');
|
|
37
|
+
await context.agent.aiWaitFor(
|
|
38
|
+
'The React TodoMVC page has loaded and the "What needs to be done?" input is visible.',
|
|
39
|
+
{ timeoutMs: 30_000, abortSignal: signal },
|
|
40
|
+
);
|
|
41
|
+
signal.throwIfAborted();
|
|
42
|
+
return {
|
|
43
|
+
summary:
|
|
44
|
+
'Opened TodoMVC in All view; existing tasks were left unchanged.',
|
|
45
|
+
};
|
|
50
46
|
},
|
|
51
|
-
);
|
|
47
|
+
});
|
|
52
48
|
|
|
53
|
-
export default defineTestProject<
|
|
49
|
+
export default defineTestProject<FileContext, undefined>({
|
|
54
50
|
projects: [
|
|
55
51
|
{
|
|
56
52
|
name: 'android',
|
|
57
|
-
|
|
53
|
+
fileSetup,
|
|
54
|
+
maxConcurrentFiles: 1,
|
|
58
55
|
files: { include: ['cases/**/*.{yaml,yml}'] },
|
|
59
56
|
},
|
|
60
57
|
],
|
|
61
58
|
nodes: [
|
|
62
59
|
todoSetup,
|
|
63
|
-
...createMidsceneNodes<
|
|
60
|
+
...createMidsceneNodes<FileContext>({
|
|
64
61
|
agentClass: AndroidAgent,
|
|
65
62
|
getAgent,
|
|
66
63
|
}),
|
|
67
64
|
],
|
|
68
|
-
test: {
|
|
65
|
+
test: { maxConcurrentFiles: 1, bail: 1, testTimeout: 720_000 },
|
|
69
66
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Copy this file to .env before running tests.
|
|
2
2
|
# Do not commit .env to your repository. In CI, inject these values as environment variables instead.
|
|
3
3
|
# Choose a supported model and copy its four configuration values from:
|
|
4
|
-
# https://midscenejs.com/model-
|
|
4
|
+
# https://midscenejs.com/model-api-setup.html
|
|
5
5
|
# For the complete environment variable reference, see:
|
|
6
6
|
# https://midscenejs.com/model-config.html
|
|
7
7
|
# After configuring .env, verify model connectivity and Midscene compatibility from the project directory:
|
|
@@ -4,7 +4,7 @@ A Midscene Test project for Computer, based on the TodoMVC case in `midscene-exa
|
|
|
4
4
|
|
|
5
5
|
If you skipped installation during creation, run `{{INSTALL_COMMAND}}`. The `postinstall` script automatically generates `midscene-node-spec.computer.md` after each dependency installation. If lifecycle scripts are disabled, run `{{RUN_NODES_COMMAND}}` manually.
|
|
6
6
|
|
|
7
|
-
Copy `.env.example` to `.env`, then choose and configure a model using the [supported models and setup guide](https://midscenejs.com/model-
|
|
7
|
+
Copy `.env.example` to `.env`, then choose and configure a model using the [supported models and setup guide](https://midscenejs.com/model-api-setup.html). Do not commit `.env` to your repository; inject the model configuration as environment variables in CI.
|
|
8
8
|
|
|
9
9
|
After configuring `.env`, run `{{VERIFY_MODEL_COMMAND}}` from the project directory to check model connectivity and Midscene compatibility. This check does not require a browser or device. If it fails, see [Model debugging and observability](https://midscenejs.com/model-debugging-observability.html) before running tests.
|
|
10
10
|
|
|
@@ -17,3 +17,5 @@ Run tests with `{{TEST_COMMAND}}`. Read `midscene-node-spec.computer.md` for the
|
|
|
17
17
|
After changing Node registrations in `midscene.config.ts`, run `{{RUN_NODES_COMMAND}}` to refresh the spec. This loads the configuration without connecting to a device or running tests. Extension factories must only acquire runtime resources inside Node execution.
|
|
18
18
|
|
|
19
19
|
Tests run serially and stop after the first failed case (`test.bail: 1`). Reports are saved and connections are released on failure. Reports are written to `midscene_run/report/`.
|
|
20
|
+
|
|
21
|
+
Each test file creates its own Agent through `fileSetup` and releases it afterward. The Project is limited to one file at a time because this starter connects to a single device or desktop. Before increasing the Project limit, provide independent devices/displays through your resource allocator.
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
这是参考 `midscene-example/computer/vitest-demo` TodoMVC 用例的 Computer 版 Midscene Test 项目。
|
|
4
4
|
|
|
5
|
-
如果创建时跳过安装,执行 `{{INSTALL_COMMAND}}`。安装后会自动生成 `midscene-node-spec.computer.md`;若禁用了安装脚本,手动执行 `{{RUN_NODES_COMMAND}}`。复制 `.env.example` 为 `.env`,按[模型配置指南](https://midscenejs.com/model-
|
|
5
|
+
如果创建时跳过安装,执行 `{{INSTALL_COMMAND}}`。安装后会自动生成 `midscene-node-spec.computer.md`;若禁用了安装脚本,手动执行 `{{RUN_NODES_COMMAND}}`。复制 `.env.example` 为 `.env`,按[模型配置指南](https://midscenejs.com/model-api-setup.html)配置模型。
|
|
6
6
|
|
|
7
7
|
配置后,在项目目录执行 `{{VERIFY_MODEL_COMMAND}}`,检查模型连接和 Midscene 兼容性。这一步不需要浏览器或设备;若检查失败,请先参考[模型调试与可观测性](https://midscenejs.com/model-debugging-observability.html)排查,再运行测试。
|
|
8
8
|
|
|
9
9
|
按照[桌面环境指南](https://midscenejs.com/platforms/desktop.html)准备权限和依赖。可设置 `COMPUTER_DISPLAY_ID` 选择显示器;无头 Linux 需要 Xvfb 和 `MIDSCENE_COMPUTER_HEADLESS_LINUX`。`cases/todo.yaml` 在 macOS 使用 Safari、在 Windows/Linux 使用 Chrome 打开在线 React TodoMVC,添加三个任务、删除一个、完成另一个、筛选已完成任务,并校验任务名称及输入框占位文字。桌面需要能访问该网站;`beforeEach` 先执行 `midscene.config.ts` 中的 `todo.setup`,打开 All 视图并等待输入框加载,再由 `aiAssert` 确认列表为空(包含已完成任务)且没有遮挡弹窗。已有任务会保留;检查失败时,用例会在修改任务前停止。请切换到 All,删除全部任务(包括已完成任务),或仅清除 TodoMVC 网站的数据;关闭遮挡弹窗后重新运行。模型或连接异常应先按报告中的原因排查。AI 检查可能误判,失败时请结合报告确认页面状态。
|
|
10
10
|
|
|
11
11
|
执行 `{{TEST_COMMAND}}` 运行测试。Node 列表见 `midscene-node-spec.computer.md`;修改配置中的 Node 后执行 `{{RUN_NODES_COMMAND}}` 刷新。用例串行运行,首次失败即停止后续用例(`test.bail: 1`);失败时仍会保存报告并释放连接。报告位于 `midscene_run/report/`。
|
|
12
|
+
|
|
13
|
+
每份测试文件通过 `fileSetup` 创建独立 Agent,结束后释放。此模板连接一台设备或一个桌面,因此 Project 的 `maxConcurrentFiles` 固定为 1;提高此上限前,需要通过资源分配脚本为并发文件提供独立设备或桌面。
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
import { fileURLToPath } from 'node:url';
|
|
2
2
|
import { ComputerAgent, agentForComputer } from '@midscene/computer';
|
|
3
3
|
import { type NodeExecutionContext, defineNode, z } from '@midscene/test';
|
|
4
|
-
import {
|
|
4
|
+
import { defineFileSetup, defineTestProject } from '@midscene/test/config';
|
|
5
5
|
import { createMidsceneNodes } from '@midscene/test/midscene';
|
|
6
6
|
import { config as loadEnv } from 'dotenv';
|
|
7
7
|
|
|
8
8
|
loadEnv({ path: fileURLToPath(new URL('.env', import.meta.url)) });
|
|
9
9
|
|
|
10
|
-
interface
|
|
10
|
+
interface FileContext {
|
|
11
11
|
agent: ComputerAgent;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const getAgent = ({
|
|
15
|
-
context,
|
|
16
|
-
}: NodeExecutionContext<unknown, ProjectContext>) => {
|
|
14
|
+
const getAgent = ({ context }: NodeExecutionContext<unknown, FileContext>) => {
|
|
17
15
|
return context.agent;
|
|
18
16
|
};
|
|
19
17
|
|
|
20
|
-
const
|
|
18
|
+
const fileSetup = defineFileSetup<FileContext, undefined>({
|
|
21
19
|
name: 'computer',
|
|
22
20
|
async setup({ env, onTeardown }) {
|
|
23
21
|
const agent = await agentForComputer({
|
|
@@ -29,46 +27,45 @@ const setup = defineProjectSetup<ProjectContext>({
|
|
|
29
27
|
});
|
|
30
28
|
|
|
31
29
|
const todoSetupInputSchema = z.strictObject({});
|
|
32
|
-
const todoSetup = defineNode<typeof todoSetupInputSchema, void,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
};
|
|
54
|
-
},
|
|
30
|
+
const todoSetup = defineNode<typeof todoSetupInputSchema, void, FileContext>({
|
|
31
|
+
name: 'todo.setup',
|
|
32
|
+
title: 'Prepare TodoMVC for the initial-state check',
|
|
33
|
+
description:
|
|
34
|
+
'Open React TodoMVC in All view and wait for its input without changing existing tasks.',
|
|
35
|
+
inputSchema: todoSetupInputSchema,
|
|
36
|
+
async execute({ context, signal }) {
|
|
37
|
+
signal.throwIfAborted();
|
|
38
|
+
await context.agent.aiAct(
|
|
39
|
+
'Open a browser and navigate to https://todomvc.com/examples/react/dist/#/. On macOS use Safari with Cmd+Space and Cmd+L; on Windows or Linux use Chrome with the Windows key and Ctrl+L. Ensure the All filter is selected if filters are visible. Only navigate and select All; leave every Todo unchanged.',
|
|
40
|
+
{ abortSignal: signal },
|
|
41
|
+
);
|
|
42
|
+
await context.agent.aiWaitFor(
|
|
43
|
+
'The React TodoMVC page has loaded and the "What needs to be done?" input is visible.',
|
|
44
|
+
{ timeoutMs: 30_000, abortSignal: signal },
|
|
45
|
+
);
|
|
46
|
+
signal.throwIfAborted();
|
|
47
|
+
return {
|
|
48
|
+
summary:
|
|
49
|
+
'Opened TodoMVC in All view; existing tasks were left unchanged.',
|
|
50
|
+
};
|
|
55
51
|
},
|
|
56
|
-
);
|
|
52
|
+
});
|
|
57
53
|
|
|
58
|
-
export default defineTestProject<
|
|
54
|
+
export default defineTestProject<FileContext, undefined>({
|
|
59
55
|
projects: [
|
|
60
56
|
{
|
|
61
57
|
name: 'computer',
|
|
62
|
-
|
|
58
|
+
fileSetup,
|
|
59
|
+
maxConcurrentFiles: 1,
|
|
63
60
|
files: { include: ['cases/**/*.{yaml,yml}'] },
|
|
64
61
|
},
|
|
65
62
|
],
|
|
66
63
|
nodes: [
|
|
67
64
|
todoSetup,
|
|
68
|
-
...createMidsceneNodes<
|
|
65
|
+
...createMidsceneNodes<FileContext>({
|
|
69
66
|
agentClass: ComputerAgent,
|
|
70
67
|
getAgent,
|
|
71
68
|
}),
|
|
72
69
|
],
|
|
73
|
-
test: {
|
|
70
|
+
test: { maxConcurrentFiles: 1, bail: 1, testTimeout: 360_000 },
|
|
74
71
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Copy this file to .env before running tests.
|
|
2
2
|
# Do not commit .env to your repository. In CI, inject these values as environment variables instead.
|
|
3
3
|
# Choose a supported model and copy its four configuration values from:
|
|
4
|
-
# https://midscenejs.com/model-
|
|
4
|
+
# https://midscenejs.com/model-api-setup.html
|
|
5
5
|
# For the complete environment variable reference, see:
|
|
6
6
|
# https://midscenejs.com/model-config.html
|
|
7
7
|
# After configuring .env, verify model connectivity and Midscene compatibility from the project directory:
|
|
@@ -4,7 +4,7 @@ A Midscene Test project for HarmonyOS, based on the TodoMVC case in `midscene-ex
|
|
|
4
4
|
|
|
5
5
|
If you skipped installation during creation, run `{{INSTALL_COMMAND}}`. The `postinstall` script automatically generates `midscene-node-spec.harmony.md` after each dependency installation. If lifecycle scripts are disabled, run `{{RUN_NODES_COMMAND}}` manually.
|
|
6
6
|
|
|
7
|
-
Copy `.env.example` to `.env`, then choose and configure a model using the [supported models and setup guide](https://midscenejs.com/model-
|
|
7
|
+
Copy `.env.example` to `.env`, then choose and configure a model using the [supported models and setup guide](https://midscenejs.com/model-api-setup.html). Do not commit `.env` to your repository; inject the model configuration as environment variables in CI.
|
|
8
8
|
|
|
9
9
|
After configuring `.env`, run `{{VERIFY_MODEL_COMMAND}}` from the project directory to check model connectivity and Midscene compatibility. This check does not require a browser or device. If it fails, see [Model debugging and observability](https://midscenejs.com/model-debugging-observability.html) before running tests.
|
|
10
10
|
|
|
@@ -17,3 +17,5 @@ Run tests with `{{TEST_COMMAND}}`. Read `midscene-node-spec.harmony.md` for the
|
|
|
17
17
|
After changing Node registrations in `midscene.config.ts`, run `{{RUN_NODES_COMMAND}}` to refresh the spec. This loads the configuration without connecting to a device or running tests. Extension factories must only acquire runtime resources inside Node execution.
|
|
18
18
|
|
|
19
19
|
Tests run serially and stop after the first failed case (`test.bail: 1`). Reports are saved and connections are released on failure. Reports are written to `midscene_run/report/`.
|
|
20
|
+
|
|
21
|
+
Each test file creates its own Agent through `fileSetup` and releases it afterward. The Project is limited to one file at a time because this starter connects to a single device or desktop. Before increasing the Project limit, provide independent devices/displays through your resource allocator.
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
这是参考 `midscene-example/harmony/vitest-demo` TodoMVC 用例的 HarmonyOS 版 Midscene Test 项目。
|
|
4
4
|
|
|
5
|
-
如果创建时跳过安装,执行 `{{INSTALL_COMMAND}}`。安装后会自动生成 `midscene-node-spec.harmony.md`;若禁用了安装脚本,手动执行 `{{RUN_NODES_COMMAND}}`。复制 `.env.example` 为 `.env`,按[模型配置指南](https://midscenejs.com/model-
|
|
5
|
+
如果创建时跳过安装,执行 `{{INSTALL_COMMAND}}`。安装后会自动生成 `midscene-node-spec.harmony.md`;若禁用了安装脚本,手动执行 `{{RUN_NODES_COMMAND}}`。复制 `.env.example` 为 `.env`,按[模型配置指南](https://midscenejs.com/model-api-setup.html)配置模型。
|
|
6
6
|
|
|
7
7
|
配置后,在项目目录执行 `{{VERIFY_MODEL_COMMAND}}`,检查模型连接和 Midscene 兼容性。这一步不需要浏览器或设备;若检查失败,请先参考[模型调试与可观测性](https://midscenejs.com/model-debugging-observability.html)排查,再运行测试。
|
|
8
8
|
|
|
9
9
|
连接设备并用 `hdc list targets` 确认;可设置 `HARMONY_DEVICE_ID` 指定设备,必要时设置 `HDC_HOME`。`cases/todo.yaml` 在浏览器打开在线 React TodoMVC,添加三个任务、删除一个、完成另一个、筛选已完成任务,并校验可见任务和未完成数量。设备需要能访问该网站;`beforeEach` 先执行 `midscene.config.ts` 中的 `todo.setup`,打开 All 视图并等待输入框加载,再由 `aiAssert` 确认列表为空(包含已完成任务)且没有遮挡弹窗。已有任务会保留;检查失败时,用例会在修改任务前停止。请切换到 All,删除全部任务(包括已完成任务),或仅清除 TodoMVC 网站的数据;关闭遮挡弹窗后重新运行。模型或连接异常应先按报告中的原因排查。AI 检查可能误判,失败时请结合报告确认页面状态。
|
|
10
10
|
|
|
11
11
|
执行 `{{TEST_COMMAND}}` 运行测试。Node 列表见 `midscene-node-spec.harmony.md`;修改配置中的 Node 后执行 `{{RUN_NODES_COMMAND}}` 刷新。用例串行运行,首次失败即停止后续用例(`test.bail: 1`);失败时仍会保存报告并释放连接。报告位于 `midscene_run/report/`。
|
|
12
|
+
|
|
13
|
+
每份测试文件通过 `fileSetup` 创建独立 Agent,结束后释放。此模板连接一台设备或一个桌面,因此 Project 的 `maxConcurrentFiles` 固定为 1;提高此上限前,需要通过资源分配脚本为并发文件提供独立设备或桌面。
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
import { fileURLToPath } from 'node:url';
|
|
2
2
|
import { HarmonyAgent, agentFromHdcDevice } from '@midscene/harmony';
|
|
3
3
|
import { type NodeExecutionContext, defineNode, z } from '@midscene/test';
|
|
4
|
-
import {
|
|
4
|
+
import { defineFileSetup, defineTestProject } from '@midscene/test/config';
|
|
5
5
|
import { createMidsceneNodes } from '@midscene/test/midscene';
|
|
6
6
|
import { config as loadEnv } from 'dotenv';
|
|
7
7
|
|
|
8
8
|
loadEnv({ path: fileURLToPath(new URL('.env', import.meta.url)) });
|
|
9
9
|
|
|
10
|
-
interface
|
|
10
|
+
interface FileContext {
|
|
11
11
|
agent: HarmonyAgent;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const getAgent = ({
|
|
15
|
-
context,
|
|
16
|
-
}: NodeExecutionContext<unknown, ProjectContext>) => {
|
|
14
|
+
const getAgent = ({ context }: NodeExecutionContext<unknown, FileContext>) => {
|
|
17
15
|
return context.agent;
|
|
18
16
|
};
|
|
19
17
|
|
|
20
|
-
const
|
|
18
|
+
const fileSetup = defineFileSetup<FileContext, undefined>({
|
|
21
19
|
name: 'harmony',
|
|
22
20
|
async setup({ env, onTeardown }) {
|
|
23
21
|
const agent = await agentFromHdcDevice(env.HARMONY_DEVICE_ID || undefined);
|
|
@@ -27,43 +25,42 @@ const setup = defineProjectSetup<ProjectContext>({
|
|
|
27
25
|
});
|
|
28
26
|
|
|
29
27
|
const todoSetupInputSchema = z.strictObject({});
|
|
30
|
-
const todoSetup = defineNode<typeof todoSetupInputSchema, void,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
};
|
|
49
|
-
},
|
|
28
|
+
const todoSetup = defineNode<typeof todoSetupInputSchema, void, FileContext>({
|
|
29
|
+
name: 'todo.setup',
|
|
30
|
+
title: 'Prepare TodoMVC for the initial-state check',
|
|
31
|
+
description:
|
|
32
|
+
'Open React TodoMVC in All view and wait for its input without changing existing tasks.',
|
|
33
|
+
inputSchema: todoSetupInputSchema,
|
|
34
|
+
async execute({ context, signal }) {
|
|
35
|
+
signal.throwIfAborted();
|
|
36
|
+
await context.agent.launch('https://todomvc.com/examples/react/dist/#/');
|
|
37
|
+
await context.agent.aiWaitFor(
|
|
38
|
+
'The React TodoMVC page has loaded and the "What needs to be done?" input is visible.',
|
|
39
|
+
{ timeoutMs: 30_000, abortSignal: signal },
|
|
40
|
+
);
|
|
41
|
+
signal.throwIfAborted();
|
|
42
|
+
return {
|
|
43
|
+
summary:
|
|
44
|
+
'Opened TodoMVC in All view; existing tasks were left unchanged.',
|
|
45
|
+
};
|
|
50
46
|
},
|
|
51
|
-
);
|
|
47
|
+
});
|
|
52
48
|
|
|
53
|
-
export default defineTestProject<
|
|
49
|
+
export default defineTestProject<FileContext, undefined>({
|
|
54
50
|
projects: [
|
|
55
51
|
{
|
|
56
52
|
name: 'harmony',
|
|
57
|
-
|
|
53
|
+
fileSetup,
|
|
54
|
+
maxConcurrentFiles: 1,
|
|
58
55
|
files: { include: ['cases/**/*.{yaml,yml}'] },
|
|
59
56
|
},
|
|
60
57
|
],
|
|
61
58
|
nodes: [
|
|
62
59
|
todoSetup,
|
|
63
|
-
...createMidsceneNodes<
|
|
60
|
+
...createMidsceneNodes<FileContext>({
|
|
64
61
|
agentClass: HarmonyAgent,
|
|
65
62
|
getAgent,
|
|
66
63
|
}),
|
|
67
64
|
],
|
|
68
|
-
test: {
|
|
65
|
+
test: { maxConcurrentFiles: 1, bail: 1, testTimeout: 720_000 },
|
|
69
66
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Copy this file to .env before running tests.
|
|
2
2
|
# Do not commit .env to your repository. In CI, inject these values as environment variables instead.
|
|
3
3
|
# Choose a supported model and copy its four configuration values from:
|
|
4
|
-
# https://midscenejs.com/model-
|
|
4
|
+
# https://midscenejs.com/model-api-setup.html
|
|
5
5
|
# For the complete environment variable reference, see:
|
|
6
6
|
# https://midscenejs.com/model-config.html
|
|
7
7
|
# After configuring .env, verify model connectivity and Midscene compatibility from the project directory:
|
|
@@ -4,7 +4,7 @@ A Midscene Test project for iOS, based on the TodoMVC case in `midscene-example/
|
|
|
4
4
|
|
|
5
5
|
If you skipped installation during creation, run `{{INSTALL_COMMAND}}`. The `postinstall` script automatically generates `midscene-node-spec.ios.md` after each dependency installation. If lifecycle scripts are disabled, run `{{RUN_NODES_COMMAND}}` manually.
|
|
6
6
|
|
|
7
|
-
Copy `.env.example` to `.env`, then choose and configure a model using the [supported models and setup guide](https://midscenejs.com/model-
|
|
7
|
+
Copy `.env.example` to `.env`, then choose and configure a model using the [supported models and setup guide](https://midscenejs.com/model-api-setup.html). Do not commit `.env` to your repository; inject the model configuration as environment variables in CI.
|
|
8
8
|
|
|
9
9
|
After configuring `.env`, run `{{VERIFY_MODEL_COMMAND}}` from the project directory to check model connectivity and Midscene compatibility. This check does not require a browser or device. If it fails, see [Model debugging and observability](https://midscenejs.com/model-debugging-observability.html) before running tests.
|
|
10
10
|
|
|
@@ -17,3 +17,5 @@ Run tests with `{{TEST_COMMAND}}`. Read `midscene-node-spec.ios.md` for the avai
|
|
|
17
17
|
After changing Node registrations in `midscene.config.ts`, run `{{RUN_NODES_COMMAND}}` to refresh the spec. This loads the configuration without connecting to a device or running tests. Extension factories must only acquire runtime resources inside Node execution.
|
|
18
18
|
|
|
19
19
|
Tests run serially and stop after the first failed case (`test.bail: 1`). Reports are saved and connections are released on failure. Reports are written to `midscene_run/report/`.
|
|
20
|
+
|
|
21
|
+
Each test file creates its own Agent through `fileSetup` and releases it afterward. The Project is limited to one file at a time because this starter connects to a single device or desktop. Before increasing the Project limit, provide independent devices/displays through your resource allocator.
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
这是参考 `midscene-example/ios/vitest-demo` TodoMVC 用例的 iOS 版 Midscene Test 项目。
|
|
4
4
|
|
|
5
|
-
如果创建时跳过安装,执行 `{{INSTALL_COMMAND}}`。安装后会自动生成 `midscene-node-spec.ios.md`;若禁用了安装脚本,手动执行 `{{RUN_NODES_COMMAND}}`。复制 `.env.example` 为 `.env`,按[模型配置指南](https://midscenejs.com/model-
|
|
5
|
+
如果创建时跳过安装,执行 `{{INSTALL_COMMAND}}`。安装后会自动生成 `midscene-node-spec.ios.md`;若禁用了安装脚本,手动执行 `{{RUN_NODES_COMMAND}}`。复制 `.env.example` 为 `.env`,按[模型配置指南](https://midscenejs.com/model-api-setup.html)配置模型。
|
|
6
6
|
|
|
7
7
|
配置后,在项目目录执行 `{{VERIFY_MODEL_COMMAND}}`,检查模型连接和 Midscene 兼容性。这一步不需要浏览器或设备;若检查失败,请先参考[模型调试与可观测性](https://midscenejs.com/model-debugging-observability.html)排查,再运行测试。
|
|
8
8
|
|
|
9
9
|
启动 WebDriverAgent。可设置 `WDA_HOST` 和 `WDA_PORT`,或用 `WDA_BASE_URL` 指定带路径前缀的网关地址。远程 MJPEG 流可设置 `WDA_MJPEG_URL`,直连则可设置 `WDA_MJPEG_PORT`。`cases/todo.yaml` 打开在线 React TodoMVC,添加三个任务、删除一个、完成另一个、筛选已完成任务,并校验可见任务和未完成数量。设备需要能访问该网站;`beforeEach` 先执行 `midscene.config.ts` 中的 `todo.setup`,打开 All 视图并等待输入框加载,再由 `aiAssert` 确认列表为空(包含已完成任务)且没有遮挡弹窗。已有任务会保留;检查失败时,用例会在修改任务前停止。请切换到 All,删除全部任务(包括已完成任务),或仅清除 TodoMVC 网站的数据;关闭遮挡弹窗后重新运行。模型或连接异常应先按报告中的原因排查。AI 检查可能误判,失败时请结合报告确认页面状态。
|
|
10
10
|
|
|
11
11
|
执行 `{{TEST_COMMAND}}` 运行测试。Node 列表见 `midscene-node-spec.ios.md`;修改配置中的 Node 后执行 `{{RUN_NODES_COMMAND}}` 刷新。用例串行运行,首次失败即停止后续用例(`test.bail: 1`);失败时仍会保存报告并释放连接。报告位于 `midscene_run/report/`。
|
|
12
|
+
|
|
13
|
+
每份测试文件通过 `fileSetup` 创建独立 Agent,结束后释放。此模板连接一台设备或一个桌面,因此 Project 的 `maxConcurrentFiles` 固定为 1;提高此上限前,需要通过资源分配脚本为并发文件提供独立设备或桌面。
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
import { fileURLToPath } from 'node:url';
|
|
2
2
|
import { IOSAgent, agentFromWebDriverAgent } from '@midscene/ios';
|
|
3
3
|
import { type NodeExecutionContext, defineNode, z } from '@midscene/test';
|
|
4
|
-
import {
|
|
4
|
+
import { defineFileSetup, defineTestProject } from '@midscene/test/config';
|
|
5
5
|
import { createMidsceneNodes } from '@midscene/test/midscene';
|
|
6
6
|
import { config as loadEnv } from 'dotenv';
|
|
7
7
|
|
|
8
8
|
loadEnv({ path: fileURLToPath(new URL('.env', import.meta.url)) });
|
|
9
9
|
|
|
10
|
-
interface
|
|
10
|
+
interface FileContext {
|
|
11
11
|
agent: IOSAgent;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const getAgent = ({
|
|
15
|
-
context,
|
|
16
|
-
}: NodeExecutionContext<unknown, ProjectContext>) => {
|
|
14
|
+
const getAgent = ({ context }: NodeExecutionContext<unknown, FileContext>) => {
|
|
17
15
|
return context.agent;
|
|
18
16
|
};
|
|
19
17
|
|
|
20
|
-
const
|
|
18
|
+
const fileSetup = defineFileSetup<FileContext, undefined>({
|
|
21
19
|
name: 'ios',
|
|
22
20
|
async setup({ env, onTeardown }) {
|
|
23
21
|
const wdaBaseUrl = env.WDA_BASE_URL || undefined;
|
|
@@ -56,40 +54,39 @@ const setup = defineProjectSetup<ProjectContext>({
|
|
|
56
54
|
});
|
|
57
55
|
|
|
58
56
|
const todoSetupInputSchema = z.strictObject({});
|
|
59
|
-
const todoSetup = defineNode<typeof todoSetupInputSchema, void,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
};
|
|
78
|
-
},
|
|
57
|
+
const todoSetup = defineNode<typeof todoSetupInputSchema, void, FileContext>({
|
|
58
|
+
name: 'todo.setup',
|
|
59
|
+
title: 'Prepare TodoMVC for the initial-state check',
|
|
60
|
+
description:
|
|
61
|
+
'Open React TodoMVC in All view and wait for its input without changing existing tasks.',
|
|
62
|
+
inputSchema: todoSetupInputSchema,
|
|
63
|
+
async execute({ context, signal }) {
|
|
64
|
+
signal.throwIfAborted();
|
|
65
|
+
await context.agent.launch('https://todomvc.com/examples/react/dist/#/');
|
|
66
|
+
await context.agent.aiWaitFor(
|
|
67
|
+
'The React TodoMVC page has loaded and the "What needs to be done?" input is visible.',
|
|
68
|
+
{ timeoutMs: 30_000, abortSignal: signal },
|
|
69
|
+
);
|
|
70
|
+
signal.throwIfAborted();
|
|
71
|
+
return {
|
|
72
|
+
summary:
|
|
73
|
+
'Opened TodoMVC in All view; existing tasks were left unchanged.',
|
|
74
|
+
};
|
|
79
75
|
},
|
|
80
|
-
);
|
|
76
|
+
});
|
|
81
77
|
|
|
82
|
-
export default defineTestProject<
|
|
78
|
+
export default defineTestProject<FileContext, undefined>({
|
|
83
79
|
projects: [
|
|
84
80
|
{
|
|
85
81
|
name: 'ios',
|
|
86
|
-
|
|
82
|
+
fileSetup,
|
|
83
|
+
maxConcurrentFiles: 1,
|
|
87
84
|
files: { include: ['cases/**/*.{yaml,yml}'] },
|
|
88
85
|
},
|
|
89
86
|
],
|
|
90
87
|
nodes: [
|
|
91
88
|
todoSetup,
|
|
92
|
-
...createMidsceneNodes<
|
|
89
|
+
...createMidsceneNodes<FileContext>({ agentClass: IOSAgent, getAgent }),
|
|
93
90
|
],
|
|
94
|
-
test: {
|
|
91
|
+
test: { maxConcurrentFiles: 1, bail: 1, testTimeout: 720_000 },
|
|
95
92
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Copy this file to .env before running tests.
|
|
2
2
|
# Do not commit .env to your repository. In CI, inject these values as environment variables instead.
|
|
3
3
|
# Choose a supported model and copy its four configuration values from:
|
|
4
|
-
# https://midscenejs.com/model-
|
|
4
|
+
# https://midscenejs.com/model-api-setup.html
|
|
5
5
|
# For the complete environment variable reference, see:
|
|
6
6
|
# https://midscenejs.com/model-config.html
|
|
7
7
|
# After configuring .env, verify model connectivity and Midscene compatibility from the project directory:
|
|
@@ -4,7 +4,7 @@ A Midscene Test project for Web, based on the TodoMVC Test Runner example. For d
|
|
|
4
4
|
|
|
5
5
|
If you skipped installation during creation, run `{{INSTALL_COMMAND}}`. The `postinstall` script automatically generates `midscene-node-spec.web.md` after each dependency installation. If lifecycle scripts are disabled, run `{{RUN_NODES_COMMAND}}` manually.
|
|
6
6
|
|
|
7
|
-
Copy `.env.example` to `.env`, then choose and configure a model using the [supported models and setup guide](https://midscenejs.com/model-
|
|
7
|
+
Copy `.env.example` to `.env`, then choose and configure a model using the [supported models and setup guide](https://midscenejs.com/model-api-setup.html). Do not commit `.env` to your repository; inject the model configuration as environment variables in CI.
|
|
8
8
|
|
|
9
9
|
After configuring `.env`, run `{{VERIFY_MODEL_COMMAND}}` from the project directory to check model connectivity and Midscene compatibility. This check does not require a browser or device. If it fails, see [Model debugging and observability](https://midscenejs.com/model-debugging-observability.html) before running tests.
|
|
10
10
|
|
|
@@ -17,3 +17,19 @@ Run tests with `{{TEST_COMMAND}}`. Read `midscene-node-spec.web.md` for the avai
|
|
|
17
17
|
After changing Node registrations in `midscene.config.ts`, run `{{RUN_NODES_COMMAND}}` to refresh the spec. This loads the configuration without connecting to a device or running tests. Extension factories must only acquire runtime resources inside Node execution.
|
|
18
18
|
|
|
19
19
|
Tests run serially and stop after the first failed case (`test.bail: 1`). Reports are saved and the browser is closed on failure. Reports are written to `midscene_run/report/`.
|
|
20
|
+
|
|
21
|
+
## How preparation works
|
|
22
|
+
|
|
23
|
+
| Stage | Frequency | What this example does |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| `setup` (project configuration) | Once per project | Starts a shared Browser |
|
|
26
|
+
| `fileSetup` (project configuration) | Once per file | Creates a separate BrowserContext and Page; returns the Node `context` |
|
|
27
|
+
| `beforeAll` (YAML) | Once before the file's cases | Sets the viewport; the first `getAgent` call creates the Agent for later Nodes to reuse |
|
|
28
|
+
|
|
29
|
+
`fileSetup` applies to every file; each file declares its own `beforeAll`. The business Node `todo.setup` is unrelated to the `setup` configuration field.
|
|
30
|
+
|
|
31
|
+
## Usage notes
|
|
32
|
+
|
|
33
|
+
- Raise `test.maxConcurrentFiles` to run files concurrently. Cases within a file stay sequential.
|
|
34
|
+
- Retries do not repeat these three stages; `beforeEach` resets business state.
|
|
35
|
+
- File cleanup destroys the Agent and closes the BrowserContext. The Browser closes after all file cleanup. Isolate backend accounts and data separately.
|