From d489288c8e7a35c3ca477bf03931ce3020291d80 Mon Sep 17 00:00:00 2001 From: liuwenxin <1009266660@qq.com> Date: Mon, 2 Nov 2026 09:06:40 +0800 Subject: [PATCH] =?UTF-8?q?test(=E5=BA=94=E7=94=A8=E4=B8=8E=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F):=20=E6=B7=BB=E5=8A=A0=E7=BB=84=E4=BB=B6=E9=AA=8C?= =?UTF-8?q?=E6=94=B6=E6=B5=81=E7=A8=8B=E4=B8=8E=E5=A4=8D=E6=B5=8B=E6=8A=A5?= =?UTF-8?q?=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 提供 13 组、74 个用例,覆盖 49 项可执行组件。 新增隔离运行、真实界面检查、结果汇总和安全安装脚本。 升级仅覆盖未修改的测试模板,并保留原文件备份。 为手动操作设置保护开关,保留修复前后验证证据。 验证:43 项相关检查、类型检查与构建通过。 --- README.md | 3 +- resources/test-flows/app-system/README.md | 106 + .../app-system/REPORT-before-fix.md | 153 ++ resources/test-flows/app-system/REPORT.md | 159 ++ .../test-flows/app-system/fixtures/tone.wav | Bin 0 -> 4844 bytes resources/test-flows/app-system/manifest.json | 851 ++++++ .../app-system/test_appsystem_01.json | 1776 ++++++++++++ .../app-system/test_appsystem_02.json | 2013 ++++++++++++++ .../app-system/test_appsystem_03.json | 2379 +++++++++++++++++ .../app-system/test_appsystem_04.json | 2041 ++++++++++++++ .../app-system/test_appsystem_05.json | 1629 +++++++++++ .../app-system/test_appsystem_06.json | 1507 +++++++++++ .../app-system/test_appsystem_07.json | 1128 ++++++++ .../app-system/test_appsystem_08.json | 897 +++++++ .../app-system/test_appsystem_09.json | 870 ++++++ .../app-system/test_appsystem_10.json | 455 ++++ .../app-system/test_appsystem_11.json | 1087 ++++++++ .../app-system/test_appsystem_12.json | 654 +++++ .../app-system/test_appsystem_13.json | 735 +++++ scripts/app-system-test-flows.mjs | 278 ++ scripts/app-system-tests.mjs | 390 +++ scripts/app-system-tests.test.mjs | 179 ++ 22 files changed, 19289 insertions(+), 1 deletion(-) create mode 100644 resources/test-flows/app-system/README.md create mode 100644 resources/test-flows/app-system/REPORT-before-fix.md create mode 100644 resources/test-flows/app-system/REPORT.md create mode 100644 resources/test-flows/app-system/fixtures/tone.wav create mode 100644 resources/test-flows/app-system/manifest.json create mode 100644 resources/test-flows/app-system/test_appsystem_01.json create mode 100644 resources/test-flows/app-system/test_appsystem_02.json create mode 100644 resources/test-flows/app-system/test_appsystem_03.json create mode 100644 resources/test-flows/app-system/test_appsystem_04.json create mode 100644 resources/test-flows/app-system/test_appsystem_05.json create mode 100644 resources/test-flows/app-system/test_appsystem_06.json create mode 100644 resources/test-flows/app-system/test_appsystem_07.json create mode 100644 resources/test-flows/app-system/test_appsystem_08.json create mode 100644 resources/test-flows/app-system/test_appsystem_09.json create mode 100644 resources/test-flows/app-system/test_appsystem_10.json create mode 100644 resources/test-flows/app-system/test_appsystem_11.json create mode 100644 resources/test-flows/app-system/test_appsystem_12.json create mode 100644 resources/test-flows/app-system/test_appsystem_13.json create mode 100644 scripts/app-system-test-flows.mjs create mode 100644 scripts/app-system-tests.mjs create mode 100644 scripts/app-system-tests.test.mjs diff --git a/README.md b/README.md index ac5c83d..5a71376 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ ### 质量与测试 -- 全量测试 167 项(能力注册冒烟、流程运行集成、Word/Excel/PDF/桌面桥真实设备测试) +- 全量测试 206 项(能力注册冒烟、流程运行集成、组件缺陷回归、测试流程包与安装保护、Word/Excel/PDF/桌面桥真实设备测试) - 本地演示站(`127.0.0.1:17863`):网页订单页 + 网页元素演练场(表单/下拉/勾选/密码/禁用按钮/悬停/长页面) - 内置 3 个网页自动化测试任务(浏览器导航、元素读写、滚动与 Cookie)+ 6 条固定示例任务 - 打包冒烟测试:跳过单实例锁隔离启动,验证产物可用性 @@ -79,6 +79,7 @@ docs 现状分析、实施方案 ## 文档 +- [应用与系统 49 项组件测试任务](resources/test-flows/app-system/README.md):13 组可安装任务、使用步骤、覆盖清单及实际验收报告。 - [现状分析与可行性](docs/01-现状分析与可行性.md) - [实施方案(三天)](docs/02-实施方案.md) diff --git a/resources/test-flows/app-system/README.md b/resources/test-flows/app-system/README.md new file mode 100644 index 0000000..b07b38e --- /dev/null +++ b/resources/test-flows/app-system/README.md @@ -0,0 +1,106 @@ +# 应用与系统组件测试 + +本流程包覆盖“可执行 → 应用与系统”的 **49 个组件 ID**,分为 13 个任务、74 个用例。同名组件的不同版本分别统计。11 个待接入组件不计入验收。 + +测试发现的 PID 空结果、类型判断/转换、毫秒等待、按模式校验参数、命令行编码及 BAT 路径问题现已修复。绿色运行状态仅表示引擎没有抛出异常;本流程还会核对实际值、返回类型、进程状态和等待耗时。 + +## 在当前应用中使用 + +1. 返回左侧“编排”首页,点击任务列表右上角的刷新按钮。 +2. 搜索“组件测试”,打开所需任务并点击“编辑流程”。 +3. 先使用 01~07 组。运行后打开底部“运行日志”,搜索“用例结果”或查看末尾的“本组汇总”。 +4. 每条用例结果依次为:`[用例编号, 组件 ID, 状态, 输入, 预期, 实际]`。 +5. 状态 `PASS` 是通过,`FAIL` 是失败,`BLOCKED` 是缺少条件或无法校验,`MANUAL` 是待人工确认。有任一未通过项目,任务最终显示“失败”,详细原因以用例结果为准。 + +01~07 组现可自动验证;类型选项使用明确的语义值,07 组只填写当前命令模式需要的参数。实际结果见本包的最新报告,修复前的失败证据另行保留。 + +## 分组与预期 + +| 组 | 测试目标 | 关键输入与验收条件 | +|---|---|---| +| 01 · 应用与 PID | 5 个组件,8 个用例 | 生成唯一 `rpatest_` 程序,启动两个实例;返回 PID 与列表应匹配;两个关闭组件各关闭一个实例;无匹配时应返回 `null` / `[]`。 | +| 02 · 数据转换 | 6 个组件,10 个用例 | `"123.5" → 123.5`、`"-42.25" → -42.25`、`-3.9 → -3`、真假布尔值、`42 → "42"`;通用转换分别检查数值、整数、布尔和文本。 | +| 03 · 数据判断 | 6 个组件,12 个用例 | 对象与数组、数字与中文、`null` / 空文本 / `0`、真实数组与文本 `"[]"`;“判断数据类型”按目录契约应返回布尔值。 | +| 04 · 变量与配置 | 7 个组件,10 个用例 | 中文变量、整数和列表、深复制内容及引用独立、当前流程 ID、自定义配置命中与未命中、计数 `10 → 12 → 14`。 | +| 05 · 等待与随机数 | 5 个组件,7 个用例 | 三个等待组件按独立毫秒时钟测量;毫秒版本设置 `3000`,预期 `2800~6500 ms`;随机整数包含 `min=max=7` 与负数范围,小数应处于 `[0,1)`。 | +| 06 · 系统路径与环境变量 | 5 个组件,7 个用例 | 与 Windows 独立查询的临时、用户、桌面路径比较;只读写专用变量 `RPA_APP_SYSTEM_TEST_VALUE`,结束恢复原先读到的值。 | +| 07 · 命令行 | 2 个组件,5 个用例 | PowerShell 中文固定输出;DOS、BAT、PowerShell 三种 V1 模式;非零退出码应报错。只校验当前模式的参数,另有含中文和空格 BAT 路径的回归测试。 | +| 08 · Windows 凭据【手动】 | 3 个组件,3 个用例 | 仅操作唯一新建测试目标。缺少安全的秘密输入机制,默认阻塞,不能把真实密码填进流程。 | +| 09 · 输入法【手动】 | 2 个组件,3 个用例 | 读取、切换到 `en-US`、尝试恢复原状态;必须人工核对前台窗口与任务栏,子进程返回成功不算通过。 | +| 10 · 音频【手动】 | 1 个组件,1 个用例 | 使用自制 0.3 秒、440 Hz 低音量 WAV;人工确认确实听到声音。 | +| 11 · 屏保【手动】 | 3 个组件,4 个用例 | 两个开启版本分别配对关闭,需观察实际屏保;V1 按 Windows 已有屏保设置运行,已去掉未实现的自定义文字、效果和密码参数。 | +| 12 · 锁屏与解锁【手动】 | 2 个组件,2 个用例 | 锁屏仍要求账户等参数,该组保持阻塞。原“屏幕解锁”已明确标为“唤醒屏幕(非登录解锁)”,无需账号密码,不支持 Windows 登录解锁。 | +| 13 · 远程桌面【手动】 | 2 个组件,2 个用例 | 填写自己的测试地址,人工完成登录并验证目标;`tsdiscon` 可能断开当前会话,关闭操作有独立开关。 | + +## 手动测试的执行开关 + +08~13 组不会由自动脚本执行。任务中名为“手动执行开关”的初始化节点,默认值是布尔 `false`。 + +只有确认该组的运行环境、影响和恢复方式后,才把该节点的“值”改为 `${true}`。恢复关闭使用 `${false}`。不要填写普通文本 `true` / `false`,保护条件只接受真正的布尔值。 + +- **08 组和 12 组的锁屏节点**:当前没有不会把秘密写入流程或 `run.json` 的输入途径,因此保持阻塞;不要填 Windows 登录密码,不创建、覆盖或删除已有业务凭据。“唤醒屏幕”本身已无需任何凭据,可在单独任务中测试。 +- **09 组**:先准备一个没有未保存内容的文本编辑窗口,人工记录原输入法,执行后核对是否真的切换并恢复。异常时人工切回原状态。 +- **10 组**:确认音量和输出设备后,只播放本包的短测试音。 +- **11 组**:需人在机器旁,有办法手动退出屏保;只调用 Windows 已配置的屏保,不设置自定义解锁密码。旧节点若保留 `set_password=1`,会在桌面操作前给出明确错误,可删除该旧节点后重新添加。 +- **12 组**:实际锁屏须先明确确认影响和恢复方式,人在机器旁并能正常用 Windows 登录;不能测试自动输入登录密码。 +- **13 组**:先设置“填写用户自己的测试远程地址”。连接成功须人工确认,启动 `mstsc` 不算已经登录。断连还要求“断连单独开关”为 `${true}`,必须另行确认操作的是哪个会话及如何重新连接。确认前保持 `${false}`。 + +人工项目即使组件返回成功,也继续显示 `MANUAL`,本工具不会自动写成通过。人工证据请附实际观察、时间和必要截图,不能仅记录返回标志。 + +## 安装、校验与报告命令 + +在项目根目录运行: + +```powershell +# 校验 13 组 / 49 项覆盖、连接关系及现有运行前校验 +node scripts/app-system-tests.mjs verify + +# 安装到当前用户:只新增;同 ID 已存在则跳过,保留用户修改 +node scripts/app-system-tests.mjs install --user-data "$env:APPDATA\rpa-studio" + +# 重建仓库里的流程 JSON;不会覆盖应用中已安装的任务 +node scripts/app-system-tests.mjs generate + +# 构建后,在全新的 Electron 用户目录运行非手动任务 +npm run build +node scripts/app-system-tests.mjs run-safe + +# 同时用临时可见的独立 Electron 窗口验证下拉选项、模式切换和唤醒提示 +node scripts/app-system-tests.mjs run-safe --ui-check + +# 从本次真实证据重新生成报告 +node scripts/app-system-tests.mjs report +``` + +安装默认使用 `%APPDATA%\rpa-studio`;非标准用户目录需要显式传入 `--user-data`。重复安装不会覆盖已有测试任务,也不改变用户原有任务。 + +`run-safe` 退出码:`0` 表示报告没有失败或阻塞,`2` 表示存在失败或阻塞(包含手动任务缺少前置条件),`1` 表示工具自身异常。报告和原始事件保存在项目的 `test-output/app-system/`,该目录已由现有 `.gitignore` 忽略。 + +每次自动运行保留独立 Electron 用户目录及 `runs//run.json`,测试不会占用当前日常实例,也不会把隔离验证结果伪装为用户任务列表中的运行历史。任务列表的新任务初始仍显示“尚未运行”。 + +## 边界与恢复 + +- 测试进程名称和可执行路径唯一,两个关闭组件只操作新建夹具 PID。常规异常后仍执行专用进程清理;中止流程可能跳过收尾,夹具会在 90 秒内自动退出。 +- 临时文件仅写入系统临时目录下的新建 `RPA-AppSystem-Tests` 子目录,保留供排查,不批量删除文件。 +- 环境变量组件只操作当前应用进程,不修改 Windows 用户/系统环境变量。本包恢复原读取值;原本不存在时只能恢复为空文本,当前组件不支持删除进程内变量,退出应用后消失。隔离运行预设原始值并验证恢复。 +- 凭据、输入法、屏保、锁屏、远程会话均未在自动验收中改变。 +- 缺少类型选项映射、真实桌面观察或测试远程主机时,状态保持阻塞或待人工确认。 + +## 修复结果与保留的限制 + +- PID:无匹配返回 `[]` / `null`,过滤空行、零和无效 PID。 +- 类型判断:按目标类型返回布尔值;数值类型与数字文本分开判断。 +- 类型转换:使用 `number`、`int`、`bool`、`string` 选项,输入无效时报错。历史默认值 `1` 兼容数值类型;其他数字别名为本项目明确规定的兼容值,前端统一使用语义值。 +- 等待:毫秒组件读取 `mileSecond`,其他秒制等待组件保持秒制;支持取消,拒绝超出计时器范围的值。 +- 关闭程序:PID/名称模式分别显示并校验参数;无效 PID 不会降级成按名称批量关闭。名称模式尊重“关闭所有会话”选项,并排除 RPA Studio 主进程。 +- 命令行:DOS/BAT/PowerShell 分别校验,修复中文输出编码和含空格、中文 BAT 路径的引号处理。 +- 屏保 V1:仅提供实际实现的系统屏保入口,不再要求自定义密码,也不展示未实现的自定义效果。 +- 原“屏幕解锁”:名称改为“唤醒屏幕(非登录解锁)”,不收集账号密码,返回 `loginUnlockSupported:false`;本人仍需完成 Windows 登录。 + +目录修正保存在 `resources/catalog-overrides.json`,重新生成目录也会应用;不会恢复错误的下拉选项或密码字段。 + +安装仍只新增、不覆盖已有任务。需要升级本包旧任务时,使用 `upgrade --baseline <升级前的模板目录>`;仅升级仍匹配旧模板的任务,并备份原文件,用户修改过的任务会跳过。 + +输入法、音频、屏保、锁屏和远程桌面仍需要人工证据或专门环境,不自动执行高影响操作。输入法子进程实现和 `tsdiscon` 会话语义不在本轮 9 项修复范围内。 + +最新逐用例证据见 [REPORT.md](REPORT.md),修复前证据见 [REPORT-before-fix.md](REPORT-before-fix.md)。 diff --git a/resources/test-flows/app-system/REPORT-before-fix.md b/resources/test-flows/app-system/REPORT-before-fix.md new file mode 100644 index 0000000..3abef2f --- /dev/null +++ b/resources/test-flows/app-system/REPORT-before-fix.md @@ -0,0 +1,153 @@ +# 应用与系统组件测试报告 + +记录时间:2026年10月30日 16:52:04(北京时间)。覆盖 49 项可执行组件,13 组任务。 + +按组件统计:通过 29,失败 4,阻塞 11,待人工确认 5,未运行 0。 + +状态依据是断言、前置校验和人工证据,节点执行成功不直接代表功能通过。未执行手动系统操作。 + +| 组 | 组件 ID | 名称 | 状态 | +|---|---|---|---| +| 01 | App_Run | 启动应用程序 | 通过 | +| 01 | App_GetPid | 获取一个匹配PID | 失败 | +| 01 | App_GetPids | 获取全部匹配PID | 失败 | +| 01 | App_Kill | 关闭应用程序 | 通过 | +| 01 | App_KillV1 | 关闭应用程序 | 通过 | +| 02 | Basic_StringToNum | 将文本转换为数字 | 通过 | +| 02 | Basic_ConvertNumber | 数据转为数值类型 | 通过 | +| 02 | Basic_ConvertInt | 数值转为整数类型 | 通过 | +| 02 | Basic_ConvertBool | 数据转为布尔类型 | 通过 | +| 02 | Basic_ConvertString | 将数字转换为文本 | 通过 | +| 02 | Basic_DataTypeConversion | 转换数据类型 | 阻塞 | +| 03 | Basic_IsDictionary | 判断数据是否为字典 | 通过 | +| 03 | Basic_IsNumber | 判断数据是否为数值 | 通过 | +| 03 | Basic_IsNull | 判断数据是否为空 | 通过 | +| 03 | Basic_IsArray | 判断数据是否为数组 | 通过 | +| 03 | Basic_Type | 获取数据类型 | 通过 | +| 03 | Basic_JudgeDataType | 判断数据类型 | 失败 | +| 04 | Basic_SetVariable | 设置变量 | 通过 | +| 04 | Basic_SetVariable_V1 | 设置变量 | 通过 | +| 04 | Basic_Clone | 复制数据 | 通过 | +| 04 | Basic_GetProcessInfo | 获取流程信息 | 通过 | +| 04 | Basic_DebugOutput | 调试输出 | 通过 | +| 04 | CustomConfig_GetConfig | 自定义配置 | 通过 | +| 04 | Basic_BusinessOrderCount | 业务办理计数 | 通过 | +| 05 | Basic_Delay_V2 | 等待 | 通过 | +| 05 | Basic_Delay_V1 | 等待 | 通过 | +| 05 | Basic_Delay | 流程延迟执行 | 失败 | +| 05 | Basic_RandomInt | 生成随机数 | 通过 | +| 05 | Basic_Rnd | 生成随机数 | 通过 | +| 06 | System_GetTempPath | 获取临时文件夹路径 | 通过 | +| 06 | System_GetHomePath | 获取用户文件夹路径 | 通过 | +| 06 | System_GetSystemPath | 获取系统文件夹路径 | 通过 | +| 06 | System_GetEnv | 获取环境变量 | 通过 | +| 06 | System_SetEnv | 设置环境变量 | 通过 | +| 07 | System_ExecuteCommand | 执行命令行 | 阻塞 | +| 07 | System_ExecuteCommandV1 | 执行命令行 | 阻塞 | +| 08 | System_AddCredential | 添加Windows凭据 | 阻塞 | +| 08 | System_ReadCredential | 获取Windows凭据 | 阻塞 | +| 08 | System_DeleteCredential | 删除Windows凭据 | 阻塞 | +| 09 | System_GetInputMethodState | 获取输入法状态 | 待人工确认 | +| 09 | System_SetInputMethodState | 设置输入法状态 | 待人工确认 | +| 10 | System_PlaySound | 播放音频 | 待人工确认 | +| 11 | System_ScreenSaverShow | 开启屏保 | 阻塞 | +| 11 | System_ScreenSaverShowV1 | 开启屏保 | 阻塞 | +| 11 | System_ScreenSaverStop | 关闭屏保 | 阻塞 | +| 12 | ScreenControl_Screenlock | 屏幕锁屏 | 阻塞 | +| 12 | ScreenControl_ScreenUnlock | 屏幕解锁 | 阻塞 | +| 13 | System_ConnectRemoteDesktop | 连接远程桌面 | 待人工确认 | +| 13 | System_CloseRemoteDesktop | 关闭远程连接 | 待人工确认 | + +## 用例证据 + +| 用例 | 组件 | 状态 | 预期 | 实际/原因 | +|---|---|---|---|---| +| 01-01 | App_Run | 通过 | 第一个测试进程 PID 大于 0 | 37796 | +| 01-02 | App_Run | 通过 | 第二个 PID 大于 0,且与第一个不同 | 48484 | +| 01-03 | App_GetPid | 通过 | 返回本次创建的任一 PID | 37796 | +| 01-04 | App_GetPids | 通过 | 列表恰含本次创建的两个 PID | [37796,48484] | +| 01-05 | App_Kill | 通过 | 结束第一个夹具 PID,第二个仍在运行 | [37796,false,true] | +| 01-06 | App_KillV1 | 通过 | 结束第二个夹具 PID | [48484,false] | +| 01-07 | App_GetPids | 失败 | 所有夹具结束后应返回空数组 [] | [0] | +| 01-08 | App_GetPid | 失败 | 无匹配时应返回 null | 0 | +| 02-01 | Basic_StringToNum | 通过 | 数字 123.5 | 123.5 | +| 02-02 | Basic_ConvertNumber | 通过 | 数字 -42.25 | -42.25 | +| 02-03 | Basic_ConvertInt | 通过 | 整数 -3(向零截断) | -3 | +| 02-04 | Basic_ConvertBool | 通过 | 布尔 true | true | +| 02-05 | Basic_ConvertBool | 通过 | 布尔 false | false | +| 02-06 | Basic_ConvertString | 通过 | 文本 "42" | "42" | +| 02-07 | Basic_DataTypeConversion | 阻塞 | 按目标类型转换;先确认目录中目标类型编号映射 | "42";目录没有目标类型选项映射,不能猜测编号;当前实现也未读取 into_type。 | +| 03-01 | Basic_IsDictionary | 通过 | true | true | +| 03-02 | Basic_IsDictionary | 通过 | false | false | +| 03-03 | Basic_IsNumber | 通过 | true | true | +| 03-04 | Basic_IsNumber | 通过 | false | false | +| 03-05 | Basic_IsNull | 通过 | true | true | +| 03-06 | Basic_IsNull | 通过 | true | true | +| 03-07 | Basic_IsNull | 通过 | false | false | +| 03-08 | Basic_IsArray | 通过 | true | true | +| 03-09 | Basic_IsArray | 通过 | false | false | +| 03-10 | Basic_Type | 通过 | "list" | "list" | +| 03-11 | Basic_Type | 通过 | "null" | "null" | +| 03-12 | Basic_JudgeDataType | 失败 | 返回布尔判定结果(true 或 false),不是类型名称 | "number" | +| 04-01 | Basic_SetVariable | 通过 | 原值及输出变量均保持中文文本 | "中文变量往返" | +| 04-02 | Basic_SetVariable_V1 | 通过 | 数字 42 | 42 | +| 04-03 | Basic_SetVariable_V1 | 通过 | 数组 [1,2] | [1,2] | +| 04-04 | Basic_Clone | 通过 | 深复制内容相同,外层和嵌套对象均不共用引用 | {"title":"中文","nested":{"n":1}} | +| 04-05 | Basic_GetProcessInfo | 通过 | 当前流程 ID、名称、运行 ID 和节点数一致 | {"id":"test_appsystem_04","name":"组件测试 04 · 变量与配置","description":"查看运行日志中的用例结果;有失败时任务最终显示失败,其他用例仍继续。","enabled":true,"trigger":{"type":"manual","label":"手动运行"},"version":"0.1.0","createdAt":"2026-10-30T00:00:00.000Z","updatedAt":"2026-10-30T00:00:00.000Z","nodeCount":99,"runId":"run_mvuqh8oe_gmpo"} | +| 04-06 | Basic_DebugOutput | 通过 | 日志及返回值为“中文日志测试:42” | "中文日志测试:42" | +| 04-07 | CustomConfig_GetConfig | 通过 | 数字 30 | 30 | +| 04-08 | CustomConfig_GetConfig | 通过 | 未命中返回 null | null | +| 04-09 | Basic_BusinessOrderCount | 通过 | 首次计数 12 | 12 | +| 04-10 | Basic_BusinessOrderCount | 通过 | 同一流程再次计数 14 | 14 | +| 05-01 | Basic_Delay_V2 | 通过 | 实际等待耗时 120~1800 ms | 161 | +| 05-02 | Basic_Delay_V2 | 通过 | 实际等待耗时 80~1800 ms | 186 | +| 05-03 | Basic_Delay_V1 | 通过 | 实际等待耗时 120~1800 ms | 156 | +| 05-04 | Basic_Delay | 失败 | 实际等待耗时 2800~6500 ms | 1013 | +| 05-05 | Basic_RandomInt | 通过 | 最小值等于最大值时返回整数 7 | 7 | +| 05-06 | Basic_RandomInt | 通过 | 返回 -2~2 的整数 | -2 | +| 05-07 | Basic_Rnd | 通过 | 随机小数满足 0 ≤ x < 1 | 0.6374054093586852 | +| 06-01 | System_GetTempPath | 通过 | 与系统临时目录一致(忽略尾部分隔符) | "C:\\Users\\Administrator\\AppData\\Local\\Temp" | +| 06-02 | System_GetHomePath | 通过 | 与 Windows 用户文件夹一致 | "C:\\Users\\Administrator" | +| 06-03 | System_GetSystemPath | 通过 | 与 Windows 实际桌面目录一致(包含重定向) | "C:\\Users\\Administrator\\Desktop" | +| 06-04 | System_GetEnv | 通过 | 读取测试专用变量的原始值,作为恢复依据 | "隔离环境原始值" | +| 06-05 | System_SetEnv | 通过 | 当前应用进程内设置成功 | "中文-测试-42" | +| 06-06 | System_GetEnv | 通过 | 能读回中文-测试-42 | "中文-测试-42" | +| 06-07 | System_SetEnv | 通过 | 恢复测试前读取值 | "隔离环境原始值" | +| 07-01 | System_ExecuteCommand | 阻塞 | RPA-PS-中文-OK | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 07-02 | System_ExecuteCommandV1 | 阻塞 | RPA-DOS-OK | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 07-03 | System_ExecuteCommandV1 | 阻塞 | RPA-PS-V1-OK | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 07-04 | System_ExecuteCommandV1 | 阻塞 | RPA-BAT-OK | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 07-05 | System_ExecuteCommand | 阻塞 | 非零退出码应抛出异常 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 08-01 | System_AddCredential | 阻塞 | 安全输入机制准备好后,在专用目标添加测试凭据 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 08-02 | System_ReadCredential | 阻塞 | 仅验证测试凭据存在,不读取或打印密码 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 08-03 | System_DeleteCredential | 阻塞 | 删除刚创建的测试目标,之后人工确认不存在 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 09-01 | System_GetInputMethodState | 待人工确认 | 读取前台窗口的真实输入法状态,人工对照任务栏 | 手动任务不纳入自动执行 | +| 09-02 | System_SetInputMethodState | 待人工确认 | 前台编辑器应切换到英文模式;仅子进程返回 set:true 不能算通过 | 手动任务不纳入自动执行 | +| 09-03 | System_SetInputMethodState | 待人工确认 | 恢复原输入法;人工确认前台窗口的实际状态 | 手动任务不纳入自动执行 | +| 10-01 | System_PlaySound | 待人工确认 | 听到一次短提示音;没有声音不能算通过 | 手动任务不纳入自动执行 | +| 11-01 | System_ScreenSaverShow | 阻塞 | 屏幕实际进入屏保;无配置时记录阻塞 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 11-02 | System_ScreenSaverStop | 阻塞 | 屏保实际关闭,可正常操作 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 11-03 | System_ScreenSaverShowV1 | 阻塞 | 未启用密码保护时无需密码也应能运行 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 11-04 | System_ScreenSaverStop | 阻塞 | 第二种屏保实际关闭 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 12-01 | ScreenControl_Screenlock | 阻塞 | 实际锁屏;需要人在机器旁用 Windows 登录凭据恢复,不改变账户密码 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 12-02 | ScreenControl_ScreenUnlock | 阻塞 | 核对 Windows 登录解锁;当前实现仅尝试唤醒屏幕,不能标记自动解锁通过 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 13-01 | System_ConnectRemoteDesktop | 待人工确认 | 人工完成登录,并确认已连接到正确测试机器;启动 mstsc 不等于连接成功 | 手动任务不纳入自动执行 | +| 13-02 | System_CloseRemoteDesktop | 待人工确认 | 确认目标会话及恢复方式后才能执行;当前实现会调用 tsdiscon | 手动任务不纳入自动执行 | + +## 运行前校验阻塞 + +- test_appsystem_07:「System_ExecuteCommandV1」缺少必填参数:BAT文件;「System_ExecuteCommandV1」缺少必填参数:PowerShell命令;「System_ExecuteCommandV1」缺少必填参数:DOS命令;「System_ExecuteCommandV1」缺少必填参数:BAT文件;「System_ExecuteCommandV1」缺少必填参数:DOS命令;「System_ExecuteCommandV1」缺少必填参数:PowerShell命令 +- test_appsystem_08:「System_AddCredential」缺少必填参数:用户名 +- test_appsystem_11:「System_ScreenSaverShowV1」缺少必填参数:password +- test_appsystem_12:「ScreenControl_Screenlock」缺少必填参数:用户名;「ScreenControl_Screenlock」缺少必填参数:密码;「ScreenControl_Screenlock」缺少必填参数:分辨率(宽);「ScreenControl_Screenlock」缺少必填参数:分辨率(高);「ScreenControl_ScreenUnlock」缺少必填参数:用户名;「ScreenControl_ScreenUnlock」缺少必填参数:密码 + +## 证据位置 + +隔离用户目录:D:\work\code\RPA-only-demo\test-output\app-system\isolated-I8utNv + +- test_appsystem_01:D:\work\code\RPA-only-demo\test-output\app-system\isolated-I8utNv\runs\run_mvuqh1m8_mpns\run.json +- test_appsystem_02:D:\work\code\RPA-only-demo\test-output\app-system\isolated-I8utNv\runs\run_mvuqh8fe_enbw\run.json +- test_appsystem_03:D:\work\code\RPA-only-demo\test-output\app-system\isolated-I8utNv\runs\run_mvuqh8lw_3nsu\run.json +- test_appsystem_04:D:\work\code\RPA-only-demo\test-output\app-system\isolated-I8utNv\runs\run_mvuqh8oe_gmpo\run.json +- test_appsystem_05:D:\work\code\RPA-only-demo\test-output\app-system\isolated-I8utNv\runs\run_mvuqh8sp_54xy\run.json +- test_appsystem_06:D:\work\code\RPA-only-demo\test-output\app-system\isolated-I8utNv\runs\run_mvuqha0h_4bfu\run.json diff --git a/resources/test-flows/app-system/REPORT.md b/resources/test-flows/app-system/REPORT.md new file mode 100644 index 0000000..930bccd --- /dev/null +++ b/resources/test-flows/app-system/REPORT.md @@ -0,0 +1,159 @@ +# 应用与系统组件测试报告 + +记录时间:2026年10月30日 18:50:29(北京时间)。覆盖 49 项可执行组件,13 组任务。 + +按组件统计:通过 36,失败 0,阻塞 5,待人工确认 8,未运行 0。 + +状态依据是断言、前置校验和人工证据,节点执行成功不直接代表功能通过。未执行手动系统操作。 + +| 组 | 组件 ID | 名称 | 状态 | +|---|---|---|---| +| 01 | App_Run | 启动应用程序 | 通过 | +| 01 | App_GetPid | 获取一个匹配PID | 通过 | +| 01 | App_GetPids | 获取全部匹配PID | 通过 | +| 01 | App_Kill | 关闭应用程序 | 通过 | +| 01 | App_KillV1 | 关闭应用程序 | 通过 | +| 02 | Basic_StringToNum | 将文本转换为数字 | 通过 | +| 02 | Basic_ConvertNumber | 数据转为数值类型 | 通过 | +| 02 | Basic_ConvertInt | 数值转为整数类型 | 通过 | +| 02 | Basic_ConvertBool | 数据转为布尔类型 | 通过 | +| 02 | Basic_ConvertString | 将数字转换为文本 | 通过 | +| 02 | Basic_DataTypeConversion | 转换数据类型 | 通过 | +| 03 | Basic_IsDictionary | 判断数据是否为字典 | 通过 | +| 03 | Basic_IsNumber | 判断数据是否为数值 | 通过 | +| 03 | Basic_IsNull | 判断数据是否为空 | 通过 | +| 03 | Basic_IsArray | 判断数据是否为数组 | 通过 | +| 03 | Basic_Type | 获取数据类型 | 通过 | +| 03 | Basic_JudgeDataType | 判断数据类型 | 通过 | +| 04 | Basic_SetVariable | 设置变量 | 通过 | +| 04 | Basic_SetVariable_V1 | 设置变量 | 通过 | +| 04 | Basic_Clone | 复制数据 | 通过 | +| 04 | Basic_GetProcessInfo | 获取流程信息 | 通过 | +| 04 | Basic_DebugOutput | 调试输出 | 通过 | +| 04 | CustomConfig_GetConfig | 自定义配置 | 通过 | +| 04 | Basic_BusinessOrderCount | 业务办理计数 | 通过 | +| 05 | Basic_Delay_V2 | 等待 | 通过 | +| 05 | Basic_Delay_V1 | 等待 | 通过 | +| 05 | Basic_Delay | 流程延迟执行 | 通过 | +| 05 | Basic_RandomInt | 生成随机数 | 通过 | +| 05 | Basic_Rnd | 生成随机数 | 通过 | +| 06 | System_GetTempPath | 获取临时文件夹路径 | 通过 | +| 06 | System_GetHomePath | 获取用户文件夹路径 | 通过 | +| 06 | System_GetSystemPath | 获取系统文件夹路径 | 通过 | +| 06 | System_GetEnv | 获取环境变量 | 通过 | +| 06 | System_SetEnv | 设置环境变量 | 通过 | +| 07 | System_ExecuteCommand | 执行命令行 | 通过 | +| 07 | System_ExecuteCommandV1 | 执行命令行 | 通过 | +| 08 | System_AddCredential | 添加Windows凭据 | 阻塞 | +| 08 | System_ReadCredential | 获取Windows凭据 | 阻塞 | +| 08 | System_DeleteCredential | 删除Windows凭据 | 阻塞 | +| 09 | System_GetInputMethodState | 获取输入法状态 | 待人工确认 | +| 09 | System_SetInputMethodState | 设置输入法状态 | 待人工确认 | +| 10 | System_PlaySound | 播放音频 | 待人工确认 | +| 11 | System_ScreenSaverShow | 开启屏保 | 待人工确认 | +| 11 | System_ScreenSaverShowV1 | 开启屏保 | 待人工确认 | +| 11 | System_ScreenSaverStop | 关闭屏保 | 待人工确认 | +| 12 | ScreenControl_Screenlock | 屏幕锁屏 | 阻塞 | +| 12 | ScreenControl_ScreenUnlock | 唤醒屏幕(非登录解锁) | 阻塞 | +| 13 | System_ConnectRemoteDesktop | 连接远程桌面 | 待人工确认 | +| 13 | System_CloseRemoteDesktop | 关闭远程连接 | 待人工确认 | + +## 真实界面验证 + +已通过独立 Electron 窗口检查:类型下拉选项、PID/名称参数切换、DOS/PowerShell 参数切换,以及唤醒组件不再索要账号密码。界面快照及 ui-check.json 保存在 test-output/app-system/。 + +## 用例证据 + +| 用例 | 组件 | 状态 | 预期 | 实际/原因 | +|---|---|---|---|---| +| 01-01 | App_Run | 通过 | 第一个测试进程 PID 大于 0 | 53688 | +| 01-02 | App_Run | 通过 | 第二个 PID 大于 0,且与第一个不同 | 47408 | +| 01-03 | App_GetPid | 通过 | 返回本次创建的任一 PID | 47408 | +| 01-04 | App_GetPids | 通过 | 列表恰含本次创建的两个 PID | [47408,53688] | +| 01-05 | App_Kill | 通过 | 结束第一个夹具 PID,第二个仍在运行 | [53688,false,true] | +| 01-06 | App_KillV1 | 通过 | 只填写 PID 即可结束第二个夹具进程 | [47408,false] | +| 01-07 | App_GetPids | 通过 | 所有夹具结束后应返回空数组 [] | [] | +| 01-08 | App_GetPid | 通过 | 无匹配时应返回 null | null | +| 02-01 | Basic_StringToNum | 通过 | 数字 123.5 | 123.5 | +| 02-02 | Basic_ConvertNumber | 通过 | 数字 -42.25 | -42.25 | +| 02-03 | Basic_ConvertInt | 通过 | 整数 -3(向零截断) | -3 | +| 02-04 | Basic_ConvertBool | 通过 | 布尔 true | true | +| 02-05 | Basic_ConvertBool | 通过 | 布尔 false | false | +| 02-06 | Basic_ConvertString | 通过 | 文本 "42" | "42" | +| 02-07 | Basic_DataTypeConversion | 通过 | 数值 42,严格区分文本和数值 | 42 | +| 02-08 | Basic_DataTypeConversion | 通过 | 整数 -3 | -3 | +| 02-09 | Basic_DataTypeConversion | 通过 | 布尔 false | false | +| 02-10 | Basic_DataTypeConversion | 通过 | 文本 "42" | "42" | +| 03-01 | Basic_IsDictionary | 通过 | true | true | +| 03-02 | Basic_IsDictionary | 通过 | false | false | +| 03-03 | Basic_IsNumber | 通过 | true | true | +| 03-04 | Basic_IsNumber | 通过 | false | false | +| 03-05 | Basic_IsNull | 通过 | true | true | +| 03-06 | Basic_IsNull | 通过 | true | true | +| 03-07 | Basic_IsNull | 通过 | false | false | +| 03-08 | Basic_IsArray | 通过 | true | true | +| 03-09 | Basic_IsArray | 通过 | false | false | +| 03-10 | Basic_Type | 通过 | "list" | "list" | +| 03-11 | Basic_Type | 通过 | "null" | "null" | +| 03-12 | Basic_JudgeDataType | 通过 | 数字 42 属于数值类型,返回布尔 true | true | +| 04-01 | Basic_SetVariable | 通过 | 原值及输出变量均保持中文文本 | "中文变量往返" | +| 04-02 | Basic_SetVariable_V1 | 通过 | 数字 42 | 42 | +| 04-03 | Basic_SetVariable_V1 | 通过 | 数组 [1,2] | [1,2] | +| 04-04 | Basic_Clone | 通过 | 深复制内容相同,外层和嵌套对象均不共用引用 | {"title":"中文","nested":{"n":1}} | +| 04-05 | Basic_GetProcessInfo | 通过 | 当前流程 ID、名称、运行 ID 和节点数一致 | {"id":"test_appsystem_04","name":"组件测试 04 · 变量与配置","description":"查看运行日志中的用例结果;有失败时任务最终显示失败,其他用例仍继续。","enabled":true,"trigger":{"type":"manual","label":"手动运行"},"version":"0.1.0","createdAt":"2026-10-30T00:00:00.000Z","updatedAt":"2026-10-30T00:00:00.000Z","nodeCount":99,"runId":"run_mvuupg9x_yifj"} | +| 04-06 | Basic_DebugOutput | 通过 | 日志及返回值为“中文日志测试:42” | "中文日志测试:42" | +| 04-07 | CustomConfig_GetConfig | 通过 | 数字 30 | 30 | +| 04-08 | CustomConfig_GetConfig | 通过 | 未命中返回 null | null | +| 04-09 | Basic_BusinessOrderCount | 通过 | 首次计数 12 | 12 | +| 04-10 | Basic_BusinessOrderCount | 通过 | 同一流程再次计数 14 | 14 | +| 05-01 | Basic_Delay_V2 | 通过 | 实际等待耗时 120~1800 ms | 165 | +| 05-02 | Basic_Delay_V2 | 通过 | 实际等待耗时 80~1800 ms | 122 | +| 05-03 | Basic_Delay_V1 | 通过 | 实际等待耗时 120~1800 ms | 154 | +| 05-04 | Basic_Delay | 通过 | 实际等待耗时 2800~6500 ms | 3011 | +| 05-05 | Basic_RandomInt | 通过 | 最小值等于最大值时返回整数 7 | 7 | +| 05-06 | Basic_RandomInt | 通过 | 返回 -2~2 的整数 | 2 | +| 05-07 | Basic_Rnd | 通过 | 随机小数满足 0 ≤ x < 1 | 0.18320588816502648 | +| 06-01 | System_GetTempPath | 通过 | 与系统临时目录一致(忽略尾部分隔符) | "C:\\Users\\Administrator\\AppData\\Local\\Temp" | +| 06-02 | System_GetHomePath | 通过 | 与 Windows 用户文件夹一致 | "C:\\Users\\Administrator" | +| 06-03 | System_GetSystemPath | 通过 | 与 Windows 实际桌面目录一致(包含重定向) | "C:\\Users\\Administrator\\Desktop" | +| 06-04 | System_GetEnv | 通过 | 读取测试专用变量的原始值,作为恢复依据 | "隔离环境原始值" | +| 06-05 | System_SetEnv | 通过 | 当前应用进程内设置成功 | "中文-测试-42" | +| 06-06 | System_GetEnv | 通过 | 能读回中文-测试-42 | "中文-测试-42" | +| 06-07 | System_SetEnv | 通过 | 恢复测试前读取值 | "隔离环境原始值" | +| 07-01 | System_ExecuteCommand | 通过 | RPA-PS-中文-OK | "RPA-PS-中文-OK" | +| 07-02 | System_ExecuteCommandV1 | 通过 | RPA-DOS-OK | "RPA-DOS-OK" | +| 07-03 | System_ExecuteCommandV1 | 通过 | RPA-PS-V1-OK | "RPA-PS-V1-OK" | +| 07-04 | System_ExecuteCommandV1 | 通过 | RPA-BAT-OK | "RPA-BAT-OK" | +| 07-05 | System_ExecuteCommand | 通过 | 非零退出码应抛出异常 | "桌面操作失败:Command failed: powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand JABQAHIAbwBnAHIAZQBzAHMAUAByAGUAZgBlAHIAZQBuAGMAZQA9ACcAUwBpAGwAZQBuAHQAbAB5AEMAbwBuAHQAaQBuAHUAZQAnADsAIABbAEMAbwBuAHMAbwBsAGUAXQA6ADoATwB1AHQAcAB1AHQARQBuAGMAbwBkAGkAbgBnAD0AWwBTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBVAFQARgA4AEUAbgBjAG8AZABpAG4AZwBdADoAOgBuAGUAdwAoACQAZgBhAGwAcwBlACkAOwAgACQATwB1AHQAcAB1AHQARQBuAGMAbwBkAGkAbgBnAD0AWwBDAG8AbgBzAG8AbABlAF0AOgA6AE8AdQB0AHAAdQB0AEUAbgBjAG8AZABpAG4AZwA7ACAAVwByAGkAdABlAC0ATwB1AHQAcAB1AHQAIAAnAFIAUABBAC0ARQBSAFIATwBSAC0AUABSAE8AQgBFACcAOwAgAGUAeABpAHQAIAA5AA==\n" | +| 08-01 | System_AddCredential | 阻塞 | 安全输入机制准备好后,在专用目标添加测试凭据 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 08-02 | System_ReadCredential | 阻塞 | 仅验证测试凭据存在,不读取或打印密码 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 08-03 | System_DeleteCredential | 阻塞 | 删除刚创建的测试目标,之后人工确认不存在 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 09-01 | System_GetInputMethodState | 待人工确认 | 读取前台窗口的真实输入法状态,人工对照任务栏 | 手动任务不纳入自动执行 | +| 09-02 | System_SetInputMethodState | 待人工确认 | 前台编辑器应切换到英文模式;仅子进程返回 set:true 不能算通过 | 手动任务不纳入自动执行 | +| 09-03 | System_SetInputMethodState | 待人工确认 | 恢复原输入法;人工确认前台窗口的实际状态 | 手动任务不纳入自动执行 | +| 10-01 | System_PlaySound | 待人工确认 | 听到一次短提示音;没有声音不能算通过 | 手动任务不纳入自动执行 | +| 11-01 | System_ScreenSaverShow | 待人工确认 | 屏幕实际进入屏保;无配置时记录阻塞 | 手动任务不纳入自动执行 | +| 11-02 | System_ScreenSaverStop | 待人工确认 | 屏保实际关闭,可正常操作 | 手动任务不纳入自动执行 | +| 11-03 | System_ScreenSaverShowV1 | 待人工确认 | 开启 Windows 已配置的屏保,不要求输入密码;人工确认屏幕实际变化 | 手动任务不纳入自动执行 | +| 11-04 | System_ScreenSaverStop | 待人工确认 | 第二种屏保实际关闭 | 手动任务不纳入自动执行 | +| 12-01 | ScreenControl_Screenlock | 阻塞 | 实际锁屏;需要人在机器旁用 Windows 登录凭据恢复,不改变账户密码 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 12-02 | ScreenControl_ScreenUnlock | 阻塞 | 仅尝试唤醒屏幕,loginUnlockSupported 必须为 false;Windows 登录仍需人工完成 | 运行前参数校验拦截,未绕过校验;详见校验问题 | +| 13-01 | System_ConnectRemoteDesktop | 待人工确认 | 人工完成登录,并确认已连接到正确测试机器;启动 mstsc 不等于连接成功 | 手动任务不纳入自动执行 | +| 13-02 | System_CloseRemoteDesktop | 待人工确认 | 确认目标会话及恢复方式后才能执行;当前实现会调用 tsdiscon | 手动任务不纳入自动执行 | + +## 运行前校验阻塞 + +- test_appsystem_08:「System_AddCredential」缺少必填参数:用户名 +- test_appsystem_12:「ScreenControl_Screenlock」缺少必填参数:用户名;「ScreenControl_Screenlock」缺少必填参数:密码;「ScreenControl_Screenlock」缺少必填参数:分辨率(宽);「ScreenControl_Screenlock」缺少必填参数:分辨率(高) + +## 证据位置 + +隔离用户目录:D:\work\code\RPA-only-demo\test-output\app-system\isolated-PN2R7C + +- test_appsystem_01:D:\work\code\RPA-only-demo\test-output\app-system\isolated-PN2R7C\runs\run_mvuuparb_ikwv\run.json +- test_appsystem_02:D:\work\code\RPA-only-demo\test-output\app-system\isolated-PN2R7C\runs\run_mvuupg4i_9qr9\run.json +- test_appsystem_03:D:\work\code\RPA-only-demo\test-output\app-system\isolated-PN2R7C\runs\run_mvuupg6q_6ij5\run.json +- test_appsystem_04:D:\work\code\RPA-only-demo\test-output\app-system\isolated-PN2R7C\runs\run_mvuupg9x_yifj\run.json +- test_appsystem_05:D:\work\code\RPA-only-demo\test-output\app-system\isolated-PN2R7C\runs\run_mvuupgcn_2wod\run.json +- test_appsystem_06:D:\work\code\RPA-only-demo\test-output\app-system\isolated-PN2R7C\runs\run_mvuupj2n_b65x\run.json +- test_appsystem_07:D:\work\code\RPA-only-demo\test-output\app-system\isolated-PN2R7C\runs\run_mvuupjiv_mh0i\run.json diff --git a/resources/test-flows/app-system/fixtures/tone.wav b/resources/test-flows/app-system/fixtures/tone.wav new file mode 100644 index 0000000000000000000000000000000000000000..a92822e103524d77d8446e9ea05fc658f9c10d1f GIT binary patch literal 4844 zcmYjVb(EG>(4V>S5=)1;fGn}dQj#K#Ah3iWUD6^F0*WiGfYL4?ASoi5_>Xj{8Yy`KG&3T6WUceaBh;@8VBWWOgPLpUIU7{>d2L`~mun-o&MCcA>AdPm?1nN#r={@?8rqCgZ zKq8ESwQv9q!g~0MH36j15K5$yRE%oU$E+zzi7xtWtcSvuFg?r*$3r}4;Z?S!u?>#IVb~BK!!US8 z{pn>`7(V4^QLrJ20475W_Q4-<2@b-1xB#-iFiHzkLW|HaB!v^9DOcr7mKlb-@F*_E z26&jW{S7@2qe7)nI3%*Zc-l{WAsvpz^Y|D~;$VCN@4+JSVQ?rAg3rtLUW5hI0z4$+ z1I#5HuEc^k2zF5h8W=K!Oa7sMI~)n0)0^-JrXq+pMS{4<(Jg{h%F8k@{Vu=XXAQGL zL&^!MtS5_TDO!k(Vho<-dX%NX;lBUT&-0gk_Yh0>X+Mm?SkYe$6V=3aK9I$sF^vwl z{5U_*ul1$Fov@dd!(c2R#)^gFWAP9xVr%G2)53NCsc-5>_!s`CFoV8^4_Ri8I3VVW zc+nTf!MC(L-1J?2Dc{8J^+Q8f>Ih9SuUH{&iKF6uu@rak`S>;5^R0YlU(iqTwL%Fh z3*|7I*eF0g7t_QQ&e2`E8eXuDr!LL4@+v$D0NFV9Eh1LN$-^R6l)}6qDMM)FQ{8bF z=YR8C!!h~??%@_uTGp3Vv=+Uw8I-0%p@~20R=WEx*$)Zd(JycsH;5Xtw=6BEixoHt z-lv+OjsL}scRO4&UnR7oWcUe}ibOdK1zVEv}FI#^v@eeO_wInVun< z$R#parkBM$F6Man7k~9$#r51)`GvoM!(y=;j+8FuDpLQETjN6MRj>Wg4!S-inBNx3eY)! z%*DIM_AU3HOCLJY0mvgt$g46=-H>HuK5-a25cz8^&YiIl_mkV}bJKYE7jw$%vWm*C z2FMRYR-8*^f^~)5E_=ZabVL2IP!G1@bCD{Wsv2soTqD}!W$F>~`2@GxZm^YHIX{}~ zF$&L!KV&EMp}H%die(rN3qoyQ$^Bp_T4(=pZ-#C34z3n^pv#J8Cos-s^zMc8Y$lvJE0&g@E^FDwuzl#ySRD20M{&0Op(3S9yM0& zlaob8{D`Cf+I?@|vOVl;?p=R8BtaI@S9Vo@s7*?$OX7XpMA^eCx7-%9RqbUl~P*>GosTys66T+w9Q_ zVW13+@VQ)Jd%!4r$(Hq(!Yb$?{*-^Jx;lqWR8i3!N6~Iy%aylV%tbTTUU6TCHV`LP z$pfmHuBOMUMsgLNBON| zXy0~c{7RaDRb{ejrH5;$?#T9HEG!JS-8j3!3^o6nG&|fkrAlZ;PxY>zuFL2$>L+mx zo`qt5qupsfG%04CjrUK&b=WGZs2X~S?xY8)bh0`&rvCn_J#N~WDV(E|ZdRBGAB%LV zm|myH>Fw%$IR}^04xiiIG0jaclVFFts^JYNAWp~_y-}~y&(%8ljO!5-n!AW?ZW@^T zrlh;#Pt)%>RsOBk>4UngcCwl13|+!>SIV|CWz1G{*?#3eqtCIi+^rVtRNX^2P;105 zuq|A4?QKt!-;6OcY=X~4`B2CyYMQ>sv3;wQ%#S%J-Y45(CYxz*n%GnB=dcHU7VXqf z{Y>xFXW8o!_z5NXgLan5XeyXYc9?4wxs{W^iq8tXn+ zxa_v5`8WEJnQW{2>eL$R%d_f~el4<5&sI-G8vGS*xCXYmxf-oz>f7t?ukakw#P@2e zj*nc>msDff7OT;levIv4E=6DAvo_K3%?ArbM>UgWjLxSQ$rSv7k~y-G=1TNs^oXhC z@`Un?vsYC=wv{{5T0fPs0^qLC>{gq9qSvC+%pJSUpP+kqLe|t-BgG>Vb!|07^nkjd zy-PJFdNSI@%(ESQAI8u~nL!)?$M#f~#)qp8s!jdC}*9tDJx-8lMEkzu;9Y9h)*j!=?o zb~k!FI>4mZv3@@7#AeWtw2&Gl#~@~Q#4U?fkZ&Ht;%8gnmtGdjck zZBw`&|KL$sS*MQ_=2KKnC5aCpF?4aaO~j-|`<+gk9DqaOGc{Mg z61k)wseW<{_M={Y6Q80d(flTA`n#r~JMa2I^@Z2Ht85?$IR>Q z8P_95T#)7TeMVZMw(>1e7UCKC4@?n8+H!NtF7OL!Esm4V)Nw{yAC4?pd<$d3GDdzq zM%s9@(!T3!)4Nz!ZdNN8Y2$Q~N)->`R&eeU+n)+E_OjQn;`TKp=nF|J$d z`Kq1VfMNOPI9iV$z!bP4$mQbMI63QYkghU)ZXDtU$uq(t}q-*h&i02O!{wCmOEo_ z+`wK>c4Mrxv39?Gz!*w^Ke37IqVB6(s(~u`fBpQT+hbq1h3tB}+m+>hJ_b=1QHRt; z)q%122%EyPP?SAtYTvL6?M(N?CsPIdS=^NK)o(n{d?8DUx$r!E=4-m)wzi$kb5V+a zhi*Vmu}Jn)n^j-+gY3?ou^#>EN4vGQgPm#HxG_HPEgLI3$*O9$>Z7*F??e%tPFcbs zcij%Lb8Rihb7p7=zhfS$)L`|2Ix6>w?wCsNhs-{f=b0t;4OiNa;(Cn4lj5jsuG**z z^0t_dMPNl}?OVD1c9V^F8GXaBlPcnPo{JJxU3FDzc^W^0|H2P`ntNmq+c@{Yy%L7f zJ*Xw#lSY8 zF+R41nLNuja`oM2&d`EzgA%ZjC@L4p4YG-xAckNyh=xD?OPAz2u}nXo6jsq4NH6Y* z&*d!EGhh6O1KI1?P{A*DL)cbFo{5uaB^<_$qP`p|-;t}uK3oQasD0?~&$!ucziaNx zgm>s;n1D$lmux31$<5*_o`H=tJFM~A?{H^aW1l9N|0WR>N6lV(37%ATOT5R$>bCxcp)yZh=1us6jZ$JZ`$b z>qmqdlnd^{0xTkWif$s8n24vC50;}5;kjS$*ZC)$>3DiT+n^8rhc!f9k)GMd9p>I$ zXhSF#F8JR$_D@50`klUk%J?hh5JfpZQ}6|E7ADcP&@L$EmN}UZOIlCeAp=guJ1E2r zoQM*;z)zHgCWdk$TPP8RhiI5dHJG7x#T2~4oOu*x#LwX@RiW*nGjry;VO&THUr~P8 z1m!Uqx8Zsmh%wA7pYYbKAq)52%W&y$(McVT-|u`8y>>5vJ=Q8wDfI!1@p z%;9^}-_)C}RluIu9~&d$JSYq+s50FM8^Y4CFKFH#oTEnYGo;7r*a*vE8gCEE!vX3{ zndkzu?$nTzWe!sr-h*6)oLCfd<87D+HJN*lqKYKwK`@~x^`_kv3!lJt_!kJC!)cfS z^>{b)BXyt>l#6+KHQubGP&#M{-@!h(2FByJ)xqkX%KwFo0ZYL!Kn$^;U?|i4bDUwOH*kDZ+RY4 zZr<{=f*#Ntx!?8c23{VIvLM?cQbyVQ|WChE+rb~2&PVt+{ io0&8cy!*%l`FTr}4|4PG2oQVuoWDG$mt@Hk(f 0) ? \"PASS\" : \"FAIL\", \"{\\\"executeable\\\":\\\"${fixture.exe}\\\"}\", \"第一个测试进程 PID 大于 0\", pid1]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t01_7", + "slot": "try_fn" + }, + { + "id": "t01_10", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_7", + "slot": "try_fn" + }, + { + "id": "t01_11", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_7", + "slot": "try_fn" + }, + { + "id": "t01_12", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"01-01\", \"App_Run\", \"FAIL\", \"{\\\"executeable\\\":\\\"${fixture.exe}\\\"}\", \"第一个测试进程 PID 大于 0\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t01_7", + "slot": "except_fn" + }, + { + "id": "t01_13", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_7", + "slot": "except_fn" + }, + { + "id": "t01_14", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_7", + "slot": "except_fn" + }, + { + "id": "t01_15", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1574 + }, + "values": { + "msg": "用例结果:${json(case_1)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_16", + "componentId": "logic_control_try_catch", + "label": "01-02 · App_Run", + "position": { + "x": 220, + "y": 1716 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_17", + "componentId": "App_Run", + "label": "App_Run", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "executeable": "${fixture.exe}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pid2" + }, + "parentId": "t01_16", + "slot": "try_fn" + }, + { + "id": "t01_18", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"01-02\", \"App_Run\", (pid2 > 0 && pid2 !== pid1) ? \"PASS\" : \"FAIL\", \"{\\\"executeable\\\":\\\"${fixture.exe}\\\"}\", \"第二个 PID 大于 0,且与第一个不同\", pid2]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t01_16", + "slot": "try_fn" + }, + { + "id": "t01_19", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_16", + "slot": "try_fn" + }, + { + "id": "t01_20", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_16", + "slot": "try_fn" + }, + { + "id": "t01_21", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"01-02\", \"App_Run\", \"FAIL\", \"{\\\"executeable\\\":\\\"${fixture.exe}\\\"}\", \"第二个 PID 大于 0,且与第一个不同\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t01_16", + "slot": "except_fn" + }, + { + "id": "t01_22", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_16", + "slot": "except_fn" + }, + { + "id": "t01_23", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_16", + "slot": "except_fn" + }, + { + "id": "t01_24", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2358 + }, + "values": { + "msg": "用例结果:${json(case_2)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_25", + "componentId": "logic_control_try_catch", + "label": "01-03 · App_GetPid", + "position": { + "x": 220, + "y": 2500 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_26", + "componentId": "App_GetPid", + "label": "App_GetPid", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "pattern": "${fixture.name}.exe" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_3" + }, + "parentId": "t01_25", + "slot": "try_fn" + }, + { + "id": "t01_27", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${[\"01-03\", \"App_GetPid\", (actual_3 === pid1 || actual_3 === pid2) ? \"PASS\" : \"FAIL\", \"{\\\"pattern\\\":\\\"${fixture.name}.exe\\\"}\", \"返回本次创建的任一 PID\", actual_3]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t01_25", + "slot": "try_fn" + }, + { + "id": "t01_28", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_25", + "slot": "try_fn" + }, + { + "id": "t01_29", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_25", + "slot": "try_fn" + }, + { + "id": "t01_30", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${[\"01-03\", \"App_GetPid\", \"FAIL\", \"{\\\"pattern\\\":\\\"${fixture.name}.exe\\\"}\", \"返回本次创建的任一 PID\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t01_25", + "slot": "except_fn" + }, + { + "id": "t01_31", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_25", + "slot": "except_fn" + }, + { + "id": "t01_32", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_25", + "slot": "except_fn" + }, + { + "id": "t01_33", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 3142 + }, + "values": { + "msg": "用例结果:${json(case_3)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_34", + "componentId": "logic_control_try_catch", + "label": "01-04 · App_GetPids", + "position": { + "x": 220, + "y": 3284 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_35", + "componentId": "App_GetPids", + "label": "App_GetPids", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "pattern": "${fixture.name}.exe" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_4" + }, + "parentId": "t01_34", + "slot": "try_fn" + }, + { + "id": "t01_36", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${[\"01-04\", \"App_GetPids\", (len(actual_4) === 2 && ((actual_4[0] === pid1 && actual_4[1] === pid2) || (actual_4[0] === pid2 && actual_4[1] === pid1))) ? \"PASS\" : \"FAIL\", \"{\\\"pattern\\\":\\\"${fixture.name}.exe\\\"}\", \"列表恰含本次创建的两个 PID\", actual_4]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t01_34", + "slot": "try_fn" + }, + { + "id": "t01_37", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_34", + "slot": "try_fn" + }, + { + "id": "t01_38", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_34", + "slot": "try_fn" + }, + { + "id": "t01_39", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${[\"01-04\", \"App_GetPids\", \"FAIL\", \"{\\\"pattern\\\":\\\"${fixture.name}.exe\\\"}\", \"列表恰含本次创建的两个 PID\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t01_34", + "slot": "except_fn" + }, + { + "id": "t01_40", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_34", + "slot": "except_fn" + }, + { + "id": "t01_41", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_34", + "slot": "except_fn" + }, + { + "id": "t01_42", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 3926 + }, + "values": { + "msg": "用例结果:${json(case_4)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_43", + "componentId": "logic_control_try_catch", + "label": "01-05 · App_Kill", + "position": { + "x": 220, + "y": 4068 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_44", + "componentId": "App_Kill", + "label": "App_Kill", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "pid": "${pid1}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_5" + }, + "parentId": "t01_43", + "slot": "try_fn" + }, + { + "id": "t01_45", + "componentId": "System_ExecuteCommand", + "label": "独立核对 PID 是否存活", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "action": "if (Get-Process -Id ${pid1} -ErrorAction SilentlyContinue) { 'true' } else { 'false' }" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "alive1" + }, + "parentId": "t01_43", + "slot": "try_fn" + }, + { + "id": "t01_46", + "componentId": "System_ExecuteCommand", + "label": "独立核对 PID 是否存活", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "action": "if (Get-Process -Id ${pid2} -ErrorAction SilentlyContinue) { 'true' } else { 'false' }" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "alive2" + }, + "parentId": "t01_43", + "slot": "try_fn" + }, + { + "id": "t01_47", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${[\"01-05\", \"App_Kill\", (parseJson(alive1) === false && parseJson(alive2) === true) ? \"PASS\" : \"FAIL\", \"{\\\"pid\\\":\\\"${pid1}\\\"}\", \"结束第一个夹具 PID,第二个仍在运行\", [actual_5, parseJson(alive1), parseJson(alive2)]]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t01_43", + "slot": "try_fn" + }, + { + "id": "t01_48", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_43", + "slot": "try_fn" + }, + { + "id": "t01_49", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_43", + "slot": "try_fn" + }, + { + "id": "t01_50", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${[\"01-05\", \"App_Kill\", \"FAIL\", \"{\\\"pid\\\":\\\"${pid1}\\\"}\", \"结束第一个夹具 PID,第二个仍在运行\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t01_43", + "slot": "except_fn" + }, + { + "id": "t01_51", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_43", + "slot": "except_fn" + }, + { + "id": "t01_52", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_43", + "slot": "except_fn" + }, + { + "id": "t01_53", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 4802 + }, + "values": { + "msg": "用例结果:${json(case_5)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_54", + "componentId": "logic_control_try_catch", + "label": "01-06 · App_KillV1", + "position": { + "x": 220, + "y": 4944 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_55", + "componentId": "App_KillV1", + "label": "App_KillV1", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "close_type": "id", + "pid": "${pid2}", + "kill_all": "0" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_6" + }, + "parentId": "t01_54", + "slot": "try_fn" + }, + { + "id": "t01_56", + "componentId": "System_ExecuteCommand", + "label": "独立核对 PID 是否存活", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "action": "if (Get-Process -Id ${pid2} -ErrorAction SilentlyContinue) { 'true' } else { 'false' }" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "aliveAfterV1" + }, + "parentId": "t01_54", + "slot": "try_fn" + }, + { + "id": "t01_57", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${[\"01-06\", \"App_KillV1\", (parseJson(aliveAfterV1) === false) ? \"PASS\" : \"FAIL\", \"{\\\"close_type\\\":\\\"id\\\",\\\"pid\\\":\\\"${pid2}\\\",\\\"kill_all\\\":\\\"0\\\"}\", \"只填写 PID 即可结束第二个夹具进程\", [actual_6, parseJson(aliveAfterV1)]]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_6" + }, + "parentId": "t01_54", + "slot": "try_fn" + }, + { + "id": "t01_58", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${failures + (case_6[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_54", + "slot": "try_fn" + }, + { + "id": "t01_59", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${pending + (case_6[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_54", + "slot": "try_fn" + }, + { + "id": "t01_60", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${[\"01-06\", \"App_KillV1\", \"FAIL\", \"{\\\"close_type\\\":\\\"id\\\",\\\"pid\\\":\\\"${pid2}\\\",\\\"kill_all\\\":\\\"0\\\"}\", \"只填写 PID 即可结束第二个夹具进程\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_6" + }, + "parentId": "t01_54", + "slot": "except_fn" + }, + { + "id": "t01_61", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${failures + (case_6[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_54", + "slot": "except_fn" + }, + { + "id": "t01_62", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${pending + (case_6[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_54", + "slot": "except_fn" + }, + { + "id": "t01_63", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 5632 + }, + "values": { + "msg": "用例结果:${json(case_6)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_64", + "componentId": "logic_control_try_catch", + "label": "01-07 · App_GetPids", + "position": { + "x": 220, + "y": 5774 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_65", + "componentId": "App_GetPids", + "label": "App_GetPids", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "pattern": "${fixture.name}.exe" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_7" + }, + "parentId": "t01_64", + "slot": "try_fn" + }, + { + "id": "t01_66", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${[\"01-07\", \"App_GetPids\", (len(actual_7) === 0) ? \"PASS\" : \"FAIL\", \"{\\\"pattern\\\":\\\"${fixture.name}.exe\\\"}\", \"所有夹具结束后应返回空数组 []\", actual_7]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_7" + }, + "parentId": "t01_64", + "slot": "try_fn" + }, + { + "id": "t01_67", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${failures + (case_7[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_64", + "slot": "try_fn" + }, + { + "id": "t01_68", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${pending + (case_7[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_64", + "slot": "try_fn" + }, + { + "id": "t01_69", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${[\"01-07\", \"App_GetPids\", \"FAIL\", \"{\\\"pattern\\\":\\\"${fixture.name}.exe\\\"}\", \"所有夹具结束后应返回空数组 []\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_7" + }, + "parentId": "t01_64", + "slot": "except_fn" + }, + { + "id": "t01_70", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${failures + (case_7[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_64", + "slot": "except_fn" + }, + { + "id": "t01_71", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${pending + (case_7[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_64", + "slot": "except_fn" + }, + { + "id": "t01_72", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 6416 + }, + "values": { + "msg": "用例结果:${json(case_7)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_73", + "componentId": "logic_control_try_catch", + "label": "01-08 · App_GetPid", + "position": { + "x": 220, + "y": 6558 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_74", + "componentId": "App_GetPid", + "label": "App_GetPid", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "pattern": "${fixture.name}.exe" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_8" + }, + "parentId": "t01_73", + "slot": "try_fn" + }, + { + "id": "t01_75", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${[\"01-08\", \"App_GetPid\", (actual_8 === null) ? \"PASS\" : \"FAIL\", \"{\\\"pattern\\\":\\\"${fixture.name}.exe\\\"}\", \"无匹配时应返回 null\", actual_8]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_8" + }, + "parentId": "t01_73", + "slot": "try_fn" + }, + { + "id": "t01_76", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${failures + (case_8[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_73", + "slot": "try_fn" + }, + { + "id": "t01_77", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${pending + (case_8[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_73", + "slot": "try_fn" + }, + { + "id": "t01_78", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${[\"01-08\", \"App_GetPid\", \"FAIL\", \"{\\\"pattern\\\":\\\"${fixture.name}.exe\\\"}\", \"无匹配时应返回 null\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_8" + }, + "parentId": "t01_73", + "slot": "except_fn" + }, + { + "id": "t01_79", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${failures + (case_8[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t01_73", + "slot": "except_fn" + }, + { + "id": "t01_80", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${pending + (case_8[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t01_73", + "slot": "except_fn" + }, + { + "id": "t01_81", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 7200 + }, + "values": { + "msg": "用例结果:${json(case_8)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_82", + "componentId": "System_ExecuteCommand", + "label": "收尾:仅清理本次专用测试进程", + "position": { + "x": 220, + "y": 7342 + }, + "values": { + "action": "$ErrorActionPreference='Stop'; $fixture='${fixture.exe}'; if ((Split-Path $fixture -Leaf) -notmatch '^rpatest_[0-9a-f]{12}\\.exe$') { throw '拒绝清理非测试进程' }; Get-Process -Name '${fixture.name}' -ErrorAction SilentlyContinue | Where-Object { $_.Path -eq $fixture } | Stop-Process -Force; '测试进程清理完成'" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "cleanupResult" + } + }, + { + "id": "t01_83", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 7484 + }, + "values": { + "msg": "本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_84", + "componentId": "logic_control_if_else", + "label": "汇总判定", + "position": { + "x": 220, + "y": 7626 + }, + "values": { + "condition": "${failures > 0 || pending > 0 || blocked > 0}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t01_85", + "componentId": "ExceptionUtil_Throws", + "label": "如实标记未通过", + "position": { + "x": 220, + "y": 4580 + }, + "values": { + "msg": "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t01_84", + "slot": "statement_if" + }, + { + "id": "t01_86", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 4580 + }, + "values": { + "msg": "本组全部通过。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t01_84", + "slot": "statement_else" + } + ], + "edges": [ + { + "id": "e_t01_2", + "source": "t01_1", + "target": "t01_2" + }, + { + "id": "e_t01_3", + "source": "t01_2", + "target": "t01_3" + }, + { + "id": "e_t01_4", + "source": "t01_3", + "target": "t01_4" + }, + { + "id": "e_t01_5", + "source": "t01_4", + "target": "t01_5" + }, + { + "id": "e_t01_6", + "source": "t01_5", + "target": "t01_6" + }, + { + "id": "e_t01_7", + "source": "t01_6", + "target": "t01_7" + }, + { + "id": "e_t01_15", + "source": "t01_7", + "target": "t01_15" + }, + { + "id": "e_t01_16", + "source": "t01_15", + "target": "t01_16" + }, + { + "id": "e_t01_24", + "source": "t01_16", + "target": "t01_24" + }, + { + "id": "e_t01_25", + "source": "t01_24", + "target": "t01_25" + }, + { + "id": "e_t01_33", + "source": "t01_25", + "target": "t01_33" + }, + { + "id": "e_t01_34", + "source": "t01_33", + "target": "t01_34" + }, + { + "id": "e_t01_42", + "source": "t01_34", + "target": "t01_42" + }, + { + "id": "e_t01_43", + "source": "t01_42", + "target": "t01_43" + }, + { + "id": "e_t01_53", + "source": "t01_43", + "target": "t01_53" + }, + { + "id": "e_t01_54", + "source": "t01_53", + "target": "t01_54" + }, + { + "id": "e_t01_63", + "source": "t01_54", + "target": "t01_63" + }, + { + "id": "e_t01_64", + "source": "t01_63", + "target": "t01_64" + }, + { + "id": "e_t01_72", + "source": "t01_64", + "target": "t01_72" + }, + { + "id": "e_t01_73", + "source": "t01_72", + "target": "t01_73" + }, + { + "id": "e_t01_81", + "source": "t01_73", + "target": "t01_81" + }, + { + "id": "e_t01_82", + "source": "t01_81", + "target": "t01_82" + }, + { + "id": "e_t01_83", + "source": "t01_82", + "target": "t01_83" + }, + { + "id": "e_t01_84", + "source": "t01_83", + "target": "t01_84" + } + ], + "meta": { + "createdAt": "2026-10-30T00:00:00.000Z", + "updatedAt": "2026-10-30T00:00:00.000Z", + "appVersion": "0.1.0" + } +} diff --git a/resources/test-flows/app-system/test_appsystem_02.json b/resources/test-flows/app-system/test_appsystem_02.json new file mode 100644 index 0000000..933c83f --- /dev/null +++ b/resources/test-flows/app-system/test_appsystem_02.json @@ -0,0 +1,2013 @@ +{ + "schemaVersion": 1, + "id": "test_appsystem_02", + "name": "组件测试 02 · 数据转换", + "description": "查看运行日志中的用例结果;有失败时任务最终显示失败,其他用例仍继续。", + "enabled": true, + "trigger": { + "type": "manual", + "label": "手动运行" + }, + "variables": [], + "nodes": [ + { + "id": "t02_1", + "componentId": "Trigger.Manual", + "label": "人工发起", + "position": { + "x": 220, + "y": 80 + }, + "values": { + "entryName": "开始组件测试" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_2", + "componentId": "Basic_SetVariable", + "label": "初始化失败计数", + "position": { + "x": 220, + "y": 222 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + } + }, + { + "id": "t02_3", + "componentId": "Basic_SetVariable", + "label": "初始化待确认计数", + "position": { + "x": 220, + "y": 364 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + } + }, + { + "id": "t02_4", + "componentId": "Basic_SetVariable", + "label": "初始化阻塞计数", + "position": { + "x": 220, + "y": 506 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "blocked" + } + }, + { + "id": "t02_5", + "componentId": "logic_control_try_catch", + "label": "02-01 · Basic_StringToNum", + "position": { + "x": 220, + "y": 648 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_6", + "componentId": "Basic_StringToNum", + "label": "Basic_StringToNum", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "val": "123.5" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_1" + }, + "parentId": "t02_5", + "slot": "try_fn" + }, + { + "id": "t02_7", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${[\"02-01\", \"Basic_StringToNum\", (actual_1 === 123.5) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":\\\"123.5\\\"}\", \"数字 123.5\", actual_1]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t02_5", + "slot": "try_fn" + }, + { + "id": "t02_8", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_5", + "slot": "try_fn" + }, + { + "id": "t02_9", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_5", + "slot": "try_fn" + }, + { + "id": "t02_10", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${[\"02-01\", \"Basic_StringToNum\", \"FAIL\", \"{\\\"val\\\":\\\"123.5\\\"}\", \"数字 123.5\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t02_5", + "slot": "except_fn" + }, + { + "id": "t02_11", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_5", + "slot": "except_fn" + }, + { + "id": "t02_12", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_5", + "slot": "except_fn" + }, + { + "id": "t02_13", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1290 + }, + "values": { + "msg": "用例结果:${json(case_1)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_14", + "componentId": "logic_control_try_catch", + "label": "02-02 · Basic_ConvertNumber", + "position": { + "x": 220, + "y": 1432 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_15", + "componentId": "Basic_ConvertNumber", + "label": "Basic_ConvertNumber", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "val": "-42.25" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_2" + }, + "parentId": "t02_14", + "slot": "try_fn" + }, + { + "id": "t02_16", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"02-02\", \"Basic_ConvertNumber\", (actual_2 === -42.25) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":\\\"-42.25\\\"}\", \"数字 -42.25\", actual_2]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t02_14", + "slot": "try_fn" + }, + { + "id": "t02_17", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_14", + "slot": "try_fn" + }, + { + "id": "t02_18", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_14", + "slot": "try_fn" + }, + { + "id": "t02_19", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"02-02\", \"Basic_ConvertNumber\", \"FAIL\", \"{\\\"val\\\":\\\"-42.25\\\"}\", \"数字 -42.25\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t02_14", + "slot": "except_fn" + }, + { + "id": "t02_20", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_14", + "slot": "except_fn" + }, + { + "id": "t02_21", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_14", + "slot": "except_fn" + }, + { + "id": "t02_22", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2074 + }, + "values": { + "msg": "用例结果:${json(case_2)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_23", + "componentId": "logic_control_try_catch", + "label": "02-03 · Basic_ConvertInt", + "position": { + "x": 220, + "y": 2216 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_24", + "componentId": "Basic_ConvertInt", + "label": "Basic_ConvertInt", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "val": -3.9 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_3" + }, + "parentId": "t02_23", + "slot": "try_fn" + }, + { + "id": "t02_25", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"02-03\", \"Basic_ConvertInt\", (actual_3 === -3) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":-3.9}\", \"整数 -3(向零截断)\", actual_3]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t02_23", + "slot": "try_fn" + }, + { + "id": "t02_26", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_23", + "slot": "try_fn" + }, + { + "id": "t02_27", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_23", + "slot": "try_fn" + }, + { + "id": "t02_28", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"02-03\", \"Basic_ConvertInt\", \"FAIL\", \"{\\\"val\\\":-3.9}\", \"整数 -3(向零截断)\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t02_23", + "slot": "except_fn" + }, + { + "id": "t02_29", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_23", + "slot": "except_fn" + }, + { + "id": "t02_30", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_23", + "slot": "except_fn" + }, + { + "id": "t02_31", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2858 + }, + "values": { + "msg": "用例结果:${json(case_3)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_32", + "componentId": "logic_control_try_catch", + "label": "02-04 · Basic_ConvertBool", + "position": { + "x": 220, + "y": 3000 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_33", + "componentId": "Basic_ConvertBool", + "label": "Basic_ConvertBool", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "val": "true" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_4" + }, + "parentId": "t02_32", + "slot": "try_fn" + }, + { + "id": "t02_34", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${[\"02-04\", \"Basic_ConvertBool\", (actual_4 === true) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":\\\"true\\\"}\", \"布尔 true\", actual_4]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t02_32", + "slot": "try_fn" + }, + { + "id": "t02_35", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_32", + "slot": "try_fn" + }, + { + "id": "t02_36", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_32", + "slot": "try_fn" + }, + { + "id": "t02_37", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${[\"02-04\", \"Basic_ConvertBool\", \"FAIL\", \"{\\\"val\\\":\\\"true\\\"}\", \"布尔 true\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t02_32", + "slot": "except_fn" + }, + { + "id": "t02_38", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_32", + "slot": "except_fn" + }, + { + "id": "t02_39", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_32", + "slot": "except_fn" + }, + { + "id": "t02_40", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 3642 + }, + "values": { + "msg": "用例结果:${json(case_4)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_41", + "componentId": "logic_control_try_catch", + "label": "02-05 · Basic_ConvertBool", + "position": { + "x": 220, + "y": 3784 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_42", + "componentId": "Basic_ConvertBool", + "label": "Basic_ConvertBool", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "val": "false" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_5" + }, + "parentId": "t02_41", + "slot": "try_fn" + }, + { + "id": "t02_43", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${[\"02-05\", \"Basic_ConvertBool\", (actual_5 === false) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":\\\"false\\\"}\", \"布尔 false\", actual_5]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t02_41", + "slot": "try_fn" + }, + { + "id": "t02_44", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_41", + "slot": "try_fn" + }, + { + "id": "t02_45", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_41", + "slot": "try_fn" + }, + { + "id": "t02_46", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${[\"02-05\", \"Basic_ConvertBool\", \"FAIL\", \"{\\\"val\\\":\\\"false\\\"}\", \"布尔 false\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t02_41", + "slot": "except_fn" + }, + { + "id": "t02_47", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_41", + "slot": "except_fn" + }, + { + "id": "t02_48", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_41", + "slot": "except_fn" + }, + { + "id": "t02_49", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 4426 + }, + "values": { + "msg": "用例结果:${json(case_5)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_50", + "componentId": "logic_control_try_catch", + "label": "02-06 · Basic_ConvertString", + "position": { + "x": 220, + "y": 4568 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_51", + "componentId": "Basic_ConvertString", + "label": "Basic_ConvertString", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "val": 42 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_6" + }, + "parentId": "t02_50", + "slot": "try_fn" + }, + { + "id": "t02_52", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${[\"02-06\", \"Basic_ConvertString\", (actual_6 === \"42\") ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":42}\", \"文本 \\\"42\\\"\", actual_6]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_6" + }, + "parentId": "t02_50", + "slot": "try_fn" + }, + { + "id": "t02_53", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${failures + (case_6[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_50", + "slot": "try_fn" + }, + { + "id": "t02_54", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${pending + (case_6[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_50", + "slot": "try_fn" + }, + { + "id": "t02_55", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${[\"02-06\", \"Basic_ConvertString\", \"FAIL\", \"{\\\"val\\\":42}\", \"文本 \\\"42\\\"\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_6" + }, + "parentId": "t02_50", + "slot": "except_fn" + }, + { + "id": "t02_56", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${failures + (case_6[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_50", + "slot": "except_fn" + }, + { + "id": "t02_57", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${pending + (case_6[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_50", + "slot": "except_fn" + }, + { + "id": "t02_58", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 5210 + }, + "values": { + "msg": "用例结果:${json(case_6)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_59", + "componentId": "logic_control_try_catch", + "label": "02-07 · Basic_DataTypeConversion", + "position": { + "x": 220, + "y": 5352 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_60", + "componentId": "Basic_DataTypeConversion", + "label": "Basic_DataTypeConversion", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "val": "42", + "into_type": "number" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_7" + }, + "parentId": "t02_59", + "slot": "try_fn" + }, + { + "id": "t02_61", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${[\"02-07\", \"Basic_DataTypeConversion\", (actual_7 === 42) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":\\\"42\\\",\\\"into_type\\\":\\\"number\\\"}\", \"数值 42,严格区分文本和数值\", actual_7]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_7" + }, + "parentId": "t02_59", + "slot": "try_fn" + }, + { + "id": "t02_62", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${failures + (case_7[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_59", + "slot": "try_fn" + }, + { + "id": "t02_63", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${pending + (case_7[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_59", + "slot": "try_fn" + }, + { + "id": "t02_64", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${[\"02-07\", \"Basic_DataTypeConversion\", \"FAIL\", \"{\\\"val\\\":\\\"42\\\",\\\"into_type\\\":\\\"number\\\"}\", \"数值 42,严格区分文本和数值\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_7" + }, + "parentId": "t02_59", + "slot": "except_fn" + }, + { + "id": "t02_65", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${failures + (case_7[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_59", + "slot": "except_fn" + }, + { + "id": "t02_66", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${pending + (case_7[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_59", + "slot": "except_fn" + }, + { + "id": "t02_67", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 5994 + }, + "values": { + "msg": "用例结果:${json(case_7)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_68", + "componentId": "logic_control_try_catch", + "label": "02-08 · Basic_DataTypeConversion", + "position": { + "x": 220, + "y": 6136 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_69", + "componentId": "Basic_DataTypeConversion", + "label": "Basic_DataTypeConversion", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "val": "-3.9", + "into_type": "int" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_8" + }, + "parentId": "t02_68", + "slot": "try_fn" + }, + { + "id": "t02_70", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${[\"02-08\", \"Basic_DataTypeConversion\", (actual_8 === -3) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":\\\"-3.9\\\",\\\"into_type\\\":\\\"int\\\"}\", \"整数 -3\", actual_8]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_8" + }, + "parentId": "t02_68", + "slot": "try_fn" + }, + { + "id": "t02_71", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${failures + (case_8[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_68", + "slot": "try_fn" + }, + { + "id": "t02_72", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${pending + (case_8[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_68", + "slot": "try_fn" + }, + { + "id": "t02_73", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${[\"02-08\", \"Basic_DataTypeConversion\", \"FAIL\", \"{\\\"val\\\":\\\"-3.9\\\",\\\"into_type\\\":\\\"int\\\"}\", \"整数 -3\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_8" + }, + "parentId": "t02_68", + "slot": "except_fn" + }, + { + "id": "t02_74", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${failures + (case_8[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_68", + "slot": "except_fn" + }, + { + "id": "t02_75", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${pending + (case_8[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_68", + "slot": "except_fn" + }, + { + "id": "t02_76", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 6778 + }, + "values": { + "msg": "用例结果:${json(case_8)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_77", + "componentId": "logic_control_try_catch", + "label": "02-09 · Basic_DataTypeConversion", + "position": { + "x": 220, + "y": 6920 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_78", + "componentId": "Basic_DataTypeConversion", + "label": "Basic_DataTypeConversion", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "val": "false", + "into_type": "bool" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_9" + }, + "parentId": "t02_77", + "slot": "try_fn" + }, + { + "id": "t02_79", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${[\"02-09\", \"Basic_DataTypeConversion\", (actual_9 === false) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":\\\"false\\\",\\\"into_type\\\":\\\"bool\\\"}\", \"布尔 false\", actual_9]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_9" + }, + "parentId": "t02_77", + "slot": "try_fn" + }, + { + "id": "t02_80", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${failures + (case_9[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_77", + "slot": "try_fn" + }, + { + "id": "t02_81", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${pending + (case_9[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_77", + "slot": "try_fn" + }, + { + "id": "t02_82", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${[\"02-09\", \"Basic_DataTypeConversion\", \"FAIL\", \"{\\\"val\\\":\\\"false\\\",\\\"into_type\\\":\\\"bool\\\"}\", \"布尔 false\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_9" + }, + "parentId": "t02_77", + "slot": "except_fn" + }, + { + "id": "t02_83", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${failures + (case_9[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_77", + "slot": "except_fn" + }, + { + "id": "t02_84", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${pending + (case_9[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_77", + "slot": "except_fn" + }, + { + "id": "t02_85", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 7562 + }, + "values": { + "msg": "用例结果:${json(case_9)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_86", + "componentId": "logic_control_try_catch", + "label": "02-10 · Basic_DataTypeConversion", + "position": { + "x": 220, + "y": 7704 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_87", + "componentId": "Basic_DataTypeConversion", + "label": "Basic_DataTypeConversion", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "val": 42, + "into_type": "string" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_10" + }, + "parentId": "t02_86", + "slot": "try_fn" + }, + { + "id": "t02_88", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "value": "${[\"02-10\", \"Basic_DataTypeConversion\", (actual_10 === \"42\") ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":42,\\\"into_type\\\":\\\"string\\\"}\", \"文本 \\\"42\\\"\", actual_10]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_10" + }, + "parentId": "t02_86", + "slot": "try_fn" + }, + { + "id": "t02_89", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "value": "${failures + (case_10[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_86", + "slot": "try_fn" + }, + { + "id": "t02_90", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "value": "${pending + (case_10[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_86", + "slot": "try_fn" + }, + { + "id": "t02_91", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "value": "${[\"02-10\", \"Basic_DataTypeConversion\", \"FAIL\", \"{\\\"val\\\":42,\\\"into_type\\\":\\\"string\\\"}\", \"文本 \\\"42\\\"\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_10" + }, + "parentId": "t02_86", + "slot": "except_fn" + }, + { + "id": "t02_92", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "value": "${failures + (case_10[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t02_86", + "slot": "except_fn" + }, + { + "id": "t02_93", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "value": "${pending + (case_10[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t02_86", + "slot": "except_fn" + }, + { + "id": "t02_94", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 8346 + }, + "values": { + "msg": "用例结果:${json(case_10)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_95", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 8488 + }, + "values": { + "msg": "本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_96", + "componentId": "logic_control_if_else", + "label": "汇总判定", + "position": { + "x": 220, + "y": 8630 + }, + "values": { + "condition": "${failures > 0 || pending > 0 || blocked > 0}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t02_97", + "componentId": "ExceptionUtil_Throws", + "label": "如实标记未通过", + "position": { + "x": 220, + "y": 4760 + }, + "values": { + "msg": "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t02_96", + "slot": "statement_if" + }, + { + "id": "t02_98", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 4760 + }, + "values": { + "msg": "本组全部通过。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t02_96", + "slot": "statement_else" + } + ], + "edges": [ + { + "id": "e_t02_2", + "source": "t02_1", + "target": "t02_2" + }, + { + "id": "e_t02_3", + "source": "t02_2", + "target": "t02_3" + }, + { + "id": "e_t02_4", + "source": "t02_3", + "target": "t02_4" + }, + { + "id": "e_t02_5", + "source": "t02_4", + "target": "t02_5" + }, + { + "id": "e_t02_13", + "source": "t02_5", + "target": "t02_13" + }, + { + "id": "e_t02_14", + "source": "t02_13", + "target": "t02_14" + }, + { + "id": "e_t02_22", + "source": "t02_14", + "target": "t02_22" + }, + { + "id": "e_t02_23", + "source": "t02_22", + "target": "t02_23" + }, + { + "id": "e_t02_31", + "source": "t02_23", + "target": "t02_31" + }, + { + "id": "e_t02_32", + "source": "t02_31", + "target": "t02_32" + }, + { + "id": "e_t02_40", + "source": "t02_32", + "target": "t02_40" + }, + { + "id": "e_t02_41", + "source": "t02_40", + "target": "t02_41" + }, + { + "id": "e_t02_49", + "source": "t02_41", + "target": "t02_49" + }, + { + "id": "e_t02_50", + "source": "t02_49", + "target": "t02_50" + }, + { + "id": "e_t02_58", + "source": "t02_50", + "target": "t02_58" + }, + { + "id": "e_t02_59", + "source": "t02_58", + "target": "t02_59" + }, + { + "id": "e_t02_67", + "source": "t02_59", + "target": "t02_67" + }, + { + "id": "e_t02_68", + "source": "t02_67", + "target": "t02_68" + }, + { + "id": "e_t02_76", + "source": "t02_68", + "target": "t02_76" + }, + { + "id": "e_t02_77", + "source": "t02_76", + "target": "t02_77" + }, + { + "id": "e_t02_85", + "source": "t02_77", + "target": "t02_85" + }, + { + "id": "e_t02_86", + "source": "t02_85", + "target": "t02_86" + }, + { + "id": "e_t02_94", + "source": "t02_86", + "target": "t02_94" + }, + { + "id": "e_t02_95", + "source": "t02_94", + "target": "t02_95" + }, + { + "id": "e_t02_96", + "source": "t02_95", + "target": "t02_96" + } + ], + "meta": { + "createdAt": "2026-10-30T00:00:00.000Z", + "updatedAt": "2026-10-30T00:00:00.000Z", + "appVersion": "0.1.0" + } +} diff --git a/resources/test-flows/app-system/test_appsystem_03.json b/resources/test-flows/app-system/test_appsystem_03.json new file mode 100644 index 0000000..d6b91c6 --- /dev/null +++ b/resources/test-flows/app-system/test_appsystem_03.json @@ -0,0 +1,2379 @@ +{ + "schemaVersion": 1, + "id": "test_appsystem_03", + "name": "组件测试 03 · 数据判断", + "description": "查看运行日志中的用例结果;有失败时任务最终显示失败,其他用例仍继续。", + "enabled": true, + "trigger": { + "type": "manual", + "label": "手动运行" + }, + "variables": [], + "nodes": [ + { + "id": "t03_1", + "componentId": "Trigger.Manual", + "label": "人工发起", + "position": { + "x": 220, + "y": 80 + }, + "values": { + "entryName": "开始组件测试" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_2", + "componentId": "Basic_SetVariable", + "label": "初始化失败计数", + "position": { + "x": 220, + "y": 222 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + } + }, + { + "id": "t03_3", + "componentId": "Basic_SetVariable", + "label": "初始化待确认计数", + "position": { + "x": 220, + "y": 364 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + } + }, + { + "id": "t03_4", + "componentId": "Basic_SetVariable", + "label": "初始化阻塞计数", + "position": { + "x": 220, + "y": 506 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "blocked" + } + }, + { + "id": "t03_5", + "componentId": "logic_control_try_catch", + "label": "03-01 · Basic_IsDictionary", + "position": { + "x": 220, + "y": 648 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_6", + "componentId": "Basic_IsDictionary", + "label": "Basic_IsDictionary", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "val": { + "name": "测试" + } + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_1" + }, + "parentId": "t03_5", + "slot": "try_fn" + }, + { + "id": "t03_7", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${[\"03-01\", \"Basic_IsDictionary\", (actual_1 === true) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":{\\\"name\\\":\\\"测试\\\"}}\", \"true\", actual_1]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t03_5", + "slot": "try_fn" + }, + { + "id": "t03_8", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_5", + "slot": "try_fn" + }, + { + "id": "t03_9", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_5", + "slot": "try_fn" + }, + { + "id": "t03_10", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${[\"03-01\", \"Basic_IsDictionary\", \"FAIL\", \"{\\\"val\\\":{\\\"name\\\":\\\"测试\\\"}}\", \"true\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t03_5", + "slot": "except_fn" + }, + { + "id": "t03_11", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_5", + "slot": "except_fn" + }, + { + "id": "t03_12", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_5", + "slot": "except_fn" + }, + { + "id": "t03_13", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1290 + }, + "values": { + "msg": "用例结果:${json(case_1)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_14", + "componentId": "logic_control_try_catch", + "label": "03-02 · Basic_IsDictionary", + "position": { + "x": 220, + "y": 1432 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_15", + "componentId": "Basic_IsDictionary", + "label": "Basic_IsDictionary", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "val": [] + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_2" + }, + "parentId": "t03_14", + "slot": "try_fn" + }, + { + "id": "t03_16", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"03-02\", \"Basic_IsDictionary\", (actual_2 === false) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":[]}\", \"false\", actual_2]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t03_14", + "slot": "try_fn" + }, + { + "id": "t03_17", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_14", + "slot": "try_fn" + }, + { + "id": "t03_18", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_14", + "slot": "try_fn" + }, + { + "id": "t03_19", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"03-02\", \"Basic_IsDictionary\", \"FAIL\", \"{\\\"val\\\":[]}\", \"false\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t03_14", + "slot": "except_fn" + }, + { + "id": "t03_20", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_14", + "slot": "except_fn" + }, + { + "id": "t03_21", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_14", + "slot": "except_fn" + }, + { + "id": "t03_22", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2074 + }, + "values": { + "msg": "用例结果:${json(case_2)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_23", + "componentId": "logic_control_try_catch", + "label": "03-03 · Basic_IsNumber", + "position": { + "x": 220, + "y": 2216 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_24", + "componentId": "Basic_IsNumber", + "label": "Basic_IsNumber", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "val": "12.5" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_3" + }, + "parentId": "t03_23", + "slot": "try_fn" + }, + { + "id": "t03_25", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"03-03\", \"Basic_IsNumber\", (actual_3 === true) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":\\\"12.5\\\"}\", \"true\", actual_3]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t03_23", + "slot": "try_fn" + }, + { + "id": "t03_26", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_23", + "slot": "try_fn" + }, + { + "id": "t03_27", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_23", + "slot": "try_fn" + }, + { + "id": "t03_28", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"03-03\", \"Basic_IsNumber\", \"FAIL\", \"{\\\"val\\\":\\\"12.5\\\"}\", \"true\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t03_23", + "slot": "except_fn" + }, + { + "id": "t03_29", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_23", + "slot": "except_fn" + }, + { + "id": "t03_30", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_23", + "slot": "except_fn" + }, + { + "id": "t03_31", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2858 + }, + "values": { + "msg": "用例结果:${json(case_3)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_32", + "componentId": "logic_control_try_catch", + "label": "03-04 · Basic_IsNumber", + "position": { + "x": 220, + "y": 3000 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_33", + "componentId": "Basic_IsNumber", + "label": "Basic_IsNumber", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "val": "中文" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_4" + }, + "parentId": "t03_32", + "slot": "try_fn" + }, + { + "id": "t03_34", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${[\"03-04\", \"Basic_IsNumber\", (actual_4 === false) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":\\\"中文\\\"}\", \"false\", actual_4]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t03_32", + "slot": "try_fn" + }, + { + "id": "t03_35", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_32", + "slot": "try_fn" + }, + { + "id": "t03_36", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_32", + "slot": "try_fn" + }, + { + "id": "t03_37", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${[\"03-04\", \"Basic_IsNumber\", \"FAIL\", \"{\\\"val\\\":\\\"中文\\\"}\", \"false\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t03_32", + "slot": "except_fn" + }, + { + "id": "t03_38", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_32", + "slot": "except_fn" + }, + { + "id": "t03_39", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_32", + "slot": "except_fn" + }, + { + "id": "t03_40", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 3642 + }, + "values": { + "msg": "用例结果:${json(case_4)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_41", + "componentId": "logic_control_try_catch", + "label": "03-05 · Basic_IsNull", + "position": { + "x": 220, + "y": 3784 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_42", + "componentId": "Basic_IsNull", + "label": "Basic_IsNull", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "val": null + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_5" + }, + "parentId": "t03_41", + "slot": "try_fn" + }, + { + "id": "t03_43", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${[\"03-05\", \"Basic_IsNull\", (actual_5 === true) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":null}\", \"true\", actual_5]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t03_41", + "slot": "try_fn" + }, + { + "id": "t03_44", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_41", + "slot": "try_fn" + }, + { + "id": "t03_45", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_41", + "slot": "try_fn" + }, + { + "id": "t03_46", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${[\"03-05\", \"Basic_IsNull\", \"FAIL\", \"{\\\"val\\\":null}\", \"true\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t03_41", + "slot": "except_fn" + }, + { + "id": "t03_47", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_41", + "slot": "except_fn" + }, + { + "id": "t03_48", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_41", + "slot": "except_fn" + }, + { + "id": "t03_49", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 4426 + }, + "values": { + "msg": "用例结果:${json(case_5)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_50", + "componentId": "logic_control_try_catch", + "label": "03-06 · Basic_IsNull", + "position": { + "x": 220, + "y": 4568 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_51", + "componentId": "Basic_IsNull", + "label": "Basic_IsNull", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "val": "" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_6" + }, + "parentId": "t03_50", + "slot": "try_fn" + }, + { + "id": "t03_52", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${[\"03-06\", \"Basic_IsNull\", (actual_6 === true) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":\\\"\\\"}\", \"true\", actual_6]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_6" + }, + "parentId": "t03_50", + "slot": "try_fn" + }, + { + "id": "t03_53", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${failures + (case_6[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_50", + "slot": "try_fn" + }, + { + "id": "t03_54", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${pending + (case_6[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_50", + "slot": "try_fn" + }, + { + "id": "t03_55", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${[\"03-06\", \"Basic_IsNull\", \"FAIL\", \"{\\\"val\\\":\\\"\\\"}\", \"true\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_6" + }, + "parentId": "t03_50", + "slot": "except_fn" + }, + { + "id": "t03_56", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${failures + (case_6[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_50", + "slot": "except_fn" + }, + { + "id": "t03_57", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${pending + (case_6[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_50", + "slot": "except_fn" + }, + { + "id": "t03_58", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 5210 + }, + "values": { + "msg": "用例结果:${json(case_6)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_59", + "componentId": "logic_control_try_catch", + "label": "03-07 · Basic_IsNull", + "position": { + "x": 220, + "y": 5352 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_60", + "componentId": "Basic_IsNull", + "label": "Basic_IsNull", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "val": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_7" + }, + "parentId": "t03_59", + "slot": "try_fn" + }, + { + "id": "t03_61", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${[\"03-07\", \"Basic_IsNull\", (actual_7 === false) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":0}\", \"false\", actual_7]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_7" + }, + "parentId": "t03_59", + "slot": "try_fn" + }, + { + "id": "t03_62", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${failures + (case_7[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_59", + "slot": "try_fn" + }, + { + "id": "t03_63", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${pending + (case_7[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_59", + "slot": "try_fn" + }, + { + "id": "t03_64", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${[\"03-07\", \"Basic_IsNull\", \"FAIL\", \"{\\\"val\\\":0}\", \"false\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_7" + }, + "parentId": "t03_59", + "slot": "except_fn" + }, + { + "id": "t03_65", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${failures + (case_7[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_59", + "slot": "except_fn" + }, + { + "id": "t03_66", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${pending + (case_7[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_59", + "slot": "except_fn" + }, + { + "id": "t03_67", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 5994 + }, + "values": { + "msg": "用例结果:${json(case_7)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_68", + "componentId": "logic_control_try_catch", + "label": "03-08 · Basic_IsArray", + "position": { + "x": 220, + "y": 6136 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_69", + "componentId": "Basic_IsArray", + "label": "Basic_IsArray", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "val": [] + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_8" + }, + "parentId": "t03_68", + "slot": "try_fn" + }, + { + "id": "t03_70", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${[\"03-08\", \"Basic_IsArray\", (actual_8 === true) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":[]}\", \"true\", actual_8]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_8" + }, + "parentId": "t03_68", + "slot": "try_fn" + }, + { + "id": "t03_71", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${failures + (case_8[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_68", + "slot": "try_fn" + }, + { + "id": "t03_72", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${pending + (case_8[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_68", + "slot": "try_fn" + }, + { + "id": "t03_73", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${[\"03-08\", \"Basic_IsArray\", \"FAIL\", \"{\\\"val\\\":[]}\", \"true\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_8" + }, + "parentId": "t03_68", + "slot": "except_fn" + }, + { + "id": "t03_74", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${failures + (case_8[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_68", + "slot": "except_fn" + }, + { + "id": "t03_75", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${pending + (case_8[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_68", + "slot": "except_fn" + }, + { + "id": "t03_76", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 6778 + }, + "values": { + "msg": "用例结果:${json(case_8)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_77", + "componentId": "logic_control_try_catch", + "label": "03-09 · Basic_IsArray", + "position": { + "x": 220, + "y": 6920 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_78", + "componentId": "Basic_IsArray", + "label": "Basic_IsArray", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "val": "[]" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_9" + }, + "parentId": "t03_77", + "slot": "try_fn" + }, + { + "id": "t03_79", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${[\"03-09\", \"Basic_IsArray\", (actual_9 === false) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":\\\"[]\\\"}\", \"false\", actual_9]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_9" + }, + "parentId": "t03_77", + "slot": "try_fn" + }, + { + "id": "t03_80", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${failures + (case_9[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_77", + "slot": "try_fn" + }, + { + "id": "t03_81", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${pending + (case_9[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_77", + "slot": "try_fn" + }, + { + "id": "t03_82", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${[\"03-09\", \"Basic_IsArray\", \"FAIL\", \"{\\\"val\\\":\\\"[]\\\"}\", \"false\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_9" + }, + "parentId": "t03_77", + "slot": "except_fn" + }, + { + "id": "t03_83", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${failures + (case_9[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_77", + "slot": "except_fn" + }, + { + "id": "t03_84", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3860 + }, + "values": { + "value": "${pending + (case_9[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_77", + "slot": "except_fn" + }, + { + "id": "t03_85", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 7562 + }, + "values": { + "msg": "用例结果:${json(case_9)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_86", + "componentId": "logic_control_try_catch", + "label": "03-10 · Basic_Type", + "position": { + "x": 220, + "y": 7704 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_87", + "componentId": "Basic_Type", + "label": "Basic_Type", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "val": [ + 1, + 2 + ] + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_10" + }, + "parentId": "t03_86", + "slot": "try_fn" + }, + { + "id": "t03_88", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "value": "${[\"03-10\", \"Basic_Type\", (actual_10 === \"list\") ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":[1,2]}\", \"\\\"list\\\"\", actual_10]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_10" + }, + "parentId": "t03_86", + "slot": "try_fn" + }, + { + "id": "t03_89", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "value": "${failures + (case_10[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_86", + "slot": "try_fn" + }, + { + "id": "t03_90", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "value": "${pending + (case_10[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_86", + "slot": "try_fn" + }, + { + "id": "t03_91", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "value": "${[\"03-10\", \"Basic_Type\", \"FAIL\", \"{\\\"val\\\":[1,2]}\", \"\\\"list\\\"\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_10" + }, + "parentId": "t03_86", + "slot": "except_fn" + }, + { + "id": "t03_92", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "value": "${failures + (case_10[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_86", + "slot": "except_fn" + }, + { + "id": "t03_93", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 4220 + }, + "values": { + "value": "${pending + (case_10[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_86", + "slot": "except_fn" + }, + { + "id": "t03_94", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 8346 + }, + "values": { + "msg": "用例结果:${json(case_10)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_95", + "componentId": "logic_control_try_catch", + "label": "03-11 · Basic_Type", + "position": { + "x": 220, + "y": 8488 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_96", + "componentId": "Basic_Type", + "label": "Basic_Type", + "position": { + "x": 220, + "y": 4580 + }, + "values": { + "val": null + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_11" + }, + "parentId": "t03_95", + "slot": "try_fn" + }, + { + "id": "t03_97", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 4580 + }, + "values": { + "value": "${[\"03-11\", \"Basic_Type\", (actual_11 === \"null\") ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":null}\", \"\\\"null\\\"\", actual_11]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_11" + }, + "parentId": "t03_95", + "slot": "try_fn" + }, + { + "id": "t03_98", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 4580 + }, + "values": { + "value": "${failures + (case_11[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_95", + "slot": "try_fn" + }, + { + "id": "t03_99", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 4580 + }, + "values": { + "value": "${pending + (case_11[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_95", + "slot": "try_fn" + }, + { + "id": "t03_100", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 4580 + }, + "values": { + "value": "${[\"03-11\", \"Basic_Type\", \"FAIL\", \"{\\\"val\\\":null}\", \"\\\"null\\\"\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_11" + }, + "parentId": "t03_95", + "slot": "except_fn" + }, + { + "id": "t03_101", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 4580 + }, + "values": { + "value": "${failures + (case_11[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_95", + "slot": "except_fn" + }, + { + "id": "t03_102", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 4580 + }, + "values": { + "value": "${pending + (case_11[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_95", + "slot": "except_fn" + }, + { + "id": "t03_103", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 9130 + }, + "values": { + "msg": "用例结果:${json(case_11)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_104", + "componentId": "logic_control_try_catch", + "label": "03-12 · Basic_JudgeDataType", + "position": { + "x": 220, + "y": 9272 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_105", + "componentId": "Basic_JudgeDataType", + "label": "Basic_JudgeDataType", + "position": { + "x": 220, + "y": 4940 + }, + "values": { + "val": 42, + "into_type": "number" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_12" + }, + "parentId": "t03_104", + "slot": "try_fn" + }, + { + "id": "t03_106", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 4940 + }, + "values": { + "value": "${[\"03-12\", \"Basic_JudgeDataType\", (actual_12 === true) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":42,\\\"into_type\\\":\\\"number\\\"}\", \"数字 42 属于数值类型,返回布尔 true\", actual_12]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_12" + }, + "parentId": "t03_104", + "slot": "try_fn" + }, + { + "id": "t03_107", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 4940 + }, + "values": { + "value": "${failures + (case_12[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_104", + "slot": "try_fn" + }, + { + "id": "t03_108", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 4940 + }, + "values": { + "value": "${pending + (case_12[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_104", + "slot": "try_fn" + }, + { + "id": "t03_109", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 4940 + }, + "values": { + "value": "${[\"03-12\", \"Basic_JudgeDataType\", \"FAIL\", \"{\\\"val\\\":42,\\\"into_type\\\":\\\"number\\\"}\", \"数字 42 属于数值类型,返回布尔 true\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_12" + }, + "parentId": "t03_104", + "slot": "except_fn" + }, + { + "id": "t03_110", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 4940 + }, + "values": { + "value": "${failures + (case_12[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t03_104", + "slot": "except_fn" + }, + { + "id": "t03_111", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 4940 + }, + "values": { + "value": "${pending + (case_12[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t03_104", + "slot": "except_fn" + }, + { + "id": "t03_112", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 9914 + }, + "values": { + "msg": "用例结果:${json(case_12)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_113", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 10056 + }, + "values": { + "msg": "本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_114", + "componentId": "logic_control_if_else", + "label": "汇总判定", + "position": { + "x": 220, + "y": 10198 + }, + "values": { + "condition": "${failures > 0 || pending > 0 || blocked > 0}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t03_115", + "componentId": "ExceptionUtil_Throws", + "label": "如实标记未通过", + "position": { + "x": 220, + "y": 5480 + }, + "values": { + "msg": "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t03_114", + "slot": "statement_if" + }, + { + "id": "t03_116", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 5480 + }, + "values": { + "msg": "本组全部通过。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t03_114", + "slot": "statement_else" + } + ], + "edges": [ + { + "id": "e_t03_2", + "source": "t03_1", + "target": "t03_2" + }, + { + "id": "e_t03_3", + "source": "t03_2", + "target": "t03_3" + }, + { + "id": "e_t03_4", + "source": "t03_3", + "target": "t03_4" + }, + { + "id": "e_t03_5", + "source": "t03_4", + "target": "t03_5" + }, + { + "id": "e_t03_13", + "source": "t03_5", + "target": "t03_13" + }, + { + "id": "e_t03_14", + "source": "t03_13", + "target": "t03_14" + }, + { + "id": "e_t03_22", + "source": "t03_14", + "target": "t03_22" + }, + { + "id": "e_t03_23", + "source": "t03_22", + "target": "t03_23" + }, + { + "id": "e_t03_31", + "source": "t03_23", + "target": "t03_31" + }, + { + "id": "e_t03_32", + "source": "t03_31", + "target": "t03_32" + }, + { + "id": "e_t03_40", + "source": "t03_32", + "target": "t03_40" + }, + { + "id": "e_t03_41", + "source": "t03_40", + "target": "t03_41" + }, + { + "id": "e_t03_49", + "source": "t03_41", + "target": "t03_49" + }, + { + "id": "e_t03_50", + "source": "t03_49", + "target": "t03_50" + }, + { + "id": "e_t03_58", + "source": "t03_50", + "target": "t03_58" + }, + { + "id": "e_t03_59", + "source": "t03_58", + "target": "t03_59" + }, + { + "id": "e_t03_67", + "source": "t03_59", + "target": "t03_67" + }, + { + "id": "e_t03_68", + "source": "t03_67", + "target": "t03_68" + }, + { + "id": "e_t03_76", + "source": "t03_68", + "target": "t03_76" + }, + { + "id": "e_t03_77", + "source": "t03_76", + "target": "t03_77" + }, + { + "id": "e_t03_85", + "source": "t03_77", + "target": "t03_85" + }, + { + "id": "e_t03_86", + "source": "t03_85", + "target": "t03_86" + }, + { + "id": "e_t03_94", + "source": "t03_86", + "target": "t03_94" + }, + { + "id": "e_t03_95", + "source": "t03_94", + "target": "t03_95" + }, + { + "id": "e_t03_103", + "source": "t03_95", + "target": "t03_103" + }, + { + "id": "e_t03_104", + "source": "t03_103", + "target": "t03_104" + }, + { + "id": "e_t03_112", + "source": "t03_104", + "target": "t03_112" + }, + { + "id": "e_t03_113", + "source": "t03_112", + "target": "t03_113" + }, + { + "id": "e_t03_114", + "source": "t03_113", + "target": "t03_114" + } + ], + "meta": { + "createdAt": "2026-10-30T00:00:00.000Z", + "updatedAt": "2026-10-30T00:00:00.000Z", + "appVersion": "0.1.0" + } +} diff --git a/resources/test-flows/app-system/test_appsystem_04.json b/resources/test-flows/app-system/test_appsystem_04.json new file mode 100644 index 0000000..a864442 --- /dev/null +++ b/resources/test-flows/app-system/test_appsystem_04.json @@ -0,0 +1,2041 @@ +{ + "schemaVersion": 1, + "id": "test_appsystem_04", + "name": "组件测试 04 · 变量与配置", + "description": "查看运行日志中的用例结果;有失败时任务最终显示失败,其他用例仍继续。", + "enabled": true, + "trigger": { + "type": "manual", + "label": "手动运行" + }, + "variables": [], + "nodes": [ + { + "id": "t04_1", + "componentId": "Trigger.Manual", + "label": "人工发起", + "position": { + "x": 220, + "y": 80 + }, + "values": { + "entryName": "开始组件测试" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_2", + "componentId": "Basic_SetVariable", + "label": "初始化失败计数", + "position": { + "x": 220, + "y": 222 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + } + }, + { + "id": "t04_3", + "componentId": "Basic_SetVariable", + "label": "初始化待确认计数", + "position": { + "x": 220, + "y": 364 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + } + }, + { + "id": "t04_4", + "componentId": "Basic_SetVariable", + "label": "初始化阻塞计数", + "position": { + "x": 220, + "y": 506 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "blocked" + } + }, + { + "id": "t04_5", + "componentId": "logic_control_try_catch", + "label": "04-01 · Basic_SetVariable", + "position": { + "x": 220, + "y": 648 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_6", + "componentId": "Basic_SetVariable", + "label": "Basic_SetVariable", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "中文变量往返" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_1" + }, + "parentId": "t04_5", + "slot": "try_fn" + }, + { + "id": "t04_7", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${[\"04-01\", \"Basic_SetVariable\", (actual_1 === \"中文变量往返\") ? \"PASS\" : \"FAIL\", \"{\\\"value\\\":\\\"中文变量往返\\\"}\", \"原值及输出变量均保持中文文本\", actual_1]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t04_5", + "slot": "try_fn" + }, + { + "id": "t04_8", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_5", + "slot": "try_fn" + }, + { + "id": "t04_9", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_5", + "slot": "try_fn" + }, + { + "id": "t04_10", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${[\"04-01\", \"Basic_SetVariable\", \"FAIL\", \"{\\\"value\\\":\\\"中文变量往返\\\"}\", \"原值及输出变量均保持中文文本\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t04_5", + "slot": "except_fn" + }, + { + "id": "t04_11", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_5", + "slot": "except_fn" + }, + { + "id": "t04_12", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_5", + "slot": "except_fn" + }, + { + "id": "t04_13", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1290 + }, + "values": { + "msg": "用例结果:${json(case_1)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_14", + "componentId": "logic_control_try_catch", + "label": "04-02 · Basic_SetVariable_V1", + "position": { + "x": 220, + "y": 1432 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_15", + "componentId": "Basic_SetVariable_V1", + "label": "Basic_SetVariable_V1", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "variableType": "rpa_int", + "value": "42" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_2" + }, + "parentId": "t04_14", + "slot": "try_fn" + }, + { + "id": "t04_16", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"04-02\", \"Basic_SetVariable_V1\", (actual_2 === 42) ? \"PASS\" : \"FAIL\", \"{\\\"variableType\\\":\\\"rpa_int\\\",\\\"value\\\":\\\"42\\\"}\", \"数字 42\", actual_2]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t04_14", + "slot": "try_fn" + }, + { + "id": "t04_17", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_14", + "slot": "try_fn" + }, + { + "id": "t04_18", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_14", + "slot": "try_fn" + }, + { + "id": "t04_19", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"04-02\", \"Basic_SetVariable_V1\", \"FAIL\", \"{\\\"variableType\\\":\\\"rpa_int\\\",\\\"value\\\":\\\"42\\\"}\", \"数字 42\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t04_14", + "slot": "except_fn" + }, + { + "id": "t04_20", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_14", + "slot": "except_fn" + }, + { + "id": "t04_21", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_14", + "slot": "except_fn" + }, + { + "id": "t04_22", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2074 + }, + "values": { + "msg": "用例结果:${json(case_2)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_23", + "componentId": "logic_control_try_catch", + "label": "04-03 · Basic_SetVariable_V1", + "position": { + "x": 220, + "y": 2216 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_24", + "componentId": "Basic_SetVariable_V1", + "label": "Basic_SetVariable_V1", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "variableType": "rpa_list", + "value": "[1,2]" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_3" + }, + "parentId": "t04_23", + "slot": "try_fn" + }, + { + "id": "t04_25", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"04-03\", \"Basic_SetVariable_V1\", (json(actual_3) === \"[1,2]\") ? \"PASS\" : \"FAIL\", \"{\\\"variableType\\\":\\\"rpa_list\\\",\\\"value\\\":\\\"[1,2]\\\"}\", \"数组 [1,2]\", actual_3]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t04_23", + "slot": "try_fn" + }, + { + "id": "t04_26", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_23", + "slot": "try_fn" + }, + { + "id": "t04_27", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_23", + "slot": "try_fn" + }, + { + "id": "t04_28", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"04-03\", \"Basic_SetVariable_V1\", \"FAIL\", \"{\\\"variableType\\\":\\\"rpa_list\\\",\\\"value\\\":\\\"[1,2]\\\"}\", \"数组 [1,2]\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t04_23", + "slot": "except_fn" + }, + { + "id": "t04_29", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_23", + "slot": "except_fn" + }, + { + "id": "t04_30", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_23", + "slot": "except_fn" + }, + { + "id": "t04_31", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2858 + }, + "values": { + "msg": "用例结果:${json(case_3)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_32", + "componentId": "Basic_SetVariable", + "label": "初始化复制源", + "position": { + "x": 220, + "y": 3000 + }, + "values": { + "value": { + "title": "中文", + "nested": { + "n": 1 + } + } + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "original" + } + }, + { + "id": "t04_33", + "componentId": "logic_control_try_catch", + "label": "04-04 · Basic_Clone", + "position": { + "x": 220, + "y": 3142 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_34", + "componentId": "Basic_Clone", + "label": "Basic_Clone", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "val": "${original}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_4" + }, + "parentId": "t04_33", + "slot": "try_fn" + }, + { + "id": "t04_35", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${[\"04-04\", \"Basic_Clone\", (json(actual_4) === json(original) && actual_4 !== original && actual_4.nested !== original.nested) ? \"PASS\" : \"FAIL\", \"{\\\"val\\\":\\\"${original}\\\"}\", \"深复制内容相同,外层和嵌套对象均不共用引用\", actual_4]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t04_33", + "slot": "try_fn" + }, + { + "id": "t04_36", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_33", + "slot": "try_fn" + }, + { + "id": "t04_37", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_33", + "slot": "try_fn" + }, + { + "id": "t04_38", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${[\"04-04\", \"Basic_Clone\", \"FAIL\", \"{\\\"val\\\":\\\"${original}\\\"}\", \"深复制内容相同,外层和嵌套对象均不共用引用\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t04_33", + "slot": "except_fn" + }, + { + "id": "t04_39", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_33", + "slot": "except_fn" + }, + { + "id": "t04_40", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_33", + "slot": "except_fn" + }, + { + "id": "t04_41", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 3784 + }, + "values": { + "msg": "用例结果:${json(case_4)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_42", + "componentId": "logic_control_try_catch", + "label": "04-05 · Basic_GetProcessInfo", + "position": { + "x": 220, + "y": 3926 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_43", + "componentId": "Basic_GetProcessInfo", + "label": "Basic_GetProcessInfo", + "position": { + "x": 220, + "y": 2600 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_5" + }, + "parentId": "t04_42", + "slot": "try_fn" + }, + { + "id": "t04_44", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "value": "${[\"04-05\", \"Basic_GetProcessInfo\", (actual_5.id === \"test_appsystem_04\" && actual_5.name === \"组件测试 04 · 变量与配置\" && len(actual_5.runId) > 0 && actual_5.nodeCount > 0) ? \"PASS\" : \"FAIL\", \"{}\", \"当前流程 ID、名称、运行 ID 和节点数一致\", actual_5]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t04_42", + "slot": "try_fn" + }, + { + "id": "t04_45", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_42", + "slot": "try_fn" + }, + { + "id": "t04_46", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_42", + "slot": "try_fn" + }, + { + "id": "t04_47", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "value": "${[\"04-05\", \"Basic_GetProcessInfo\", \"FAIL\", \"{}\", \"当前流程 ID、名称、运行 ID 和节点数一致\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t04_42", + "slot": "except_fn" + }, + { + "id": "t04_48", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_42", + "slot": "except_fn" + }, + { + "id": "t04_49", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_42", + "slot": "except_fn" + }, + { + "id": "t04_50", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 4568 + }, + "values": { + "msg": "用例结果:${json(case_5)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_51", + "componentId": "logic_control_try_catch", + "label": "04-06 · Basic_DebugOutput", + "position": { + "x": 220, + "y": 4710 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_52", + "componentId": "Basic_DebugOutput", + "label": "Basic_DebugOutput", + "position": { + "x": 220, + "y": 2960 + }, + "values": { + "msg": "中文日志测试:${actual_2}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_6" + }, + "parentId": "t04_51", + "slot": "try_fn" + }, + { + "id": "t04_53", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2960 + }, + "values": { + "value": "${[\"04-06\", \"Basic_DebugOutput\", (actual_6 === \"中文日志测试:42\") ? \"PASS\" : \"FAIL\", \"{\\\"msg\\\":\\\"中文日志测试:${actual_2}\\\"}\", \"日志及返回值为“中文日志测试:42”\", actual_6]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_6" + }, + "parentId": "t04_51", + "slot": "try_fn" + }, + { + "id": "t04_54", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2960 + }, + "values": { + "value": "${failures + (case_6[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_51", + "slot": "try_fn" + }, + { + "id": "t04_55", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2960 + }, + "values": { + "value": "${pending + (case_6[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_51", + "slot": "try_fn" + }, + { + "id": "t04_56", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2960 + }, + "values": { + "value": "${[\"04-06\", \"Basic_DebugOutput\", \"FAIL\", \"{\\\"msg\\\":\\\"中文日志测试:${actual_2}\\\"}\", \"日志及返回值为“中文日志测试:42”\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_6" + }, + "parentId": "t04_51", + "slot": "except_fn" + }, + { + "id": "t04_57", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2960 + }, + "values": { + "value": "${failures + (case_6[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_51", + "slot": "except_fn" + }, + { + "id": "t04_58", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2960 + }, + "values": { + "value": "${pending + (case_6[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_51", + "slot": "except_fn" + }, + { + "id": "t04_59", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 5352 + }, + "values": { + "msg": "用例结果:${json(case_6)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_60", + "componentId": "logic_control_try_catch", + "label": "04-07 · CustomConfig_GetConfig", + "position": { + "x": 220, + "y": 5494 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_61", + "componentId": "CustomConfig_GetConfig", + "label": "CustomConfig_GetConfig", + "position": { + "x": 220, + "y": 3320 + }, + "values": { + "jsonlist": "[{\"name\":\"timeout\",\"value\":30}]", + "configName": "timeout" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_7" + }, + "parentId": "t04_60", + "slot": "try_fn" + }, + { + "id": "t04_62", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3320 + }, + "values": { + "value": "${[\"04-07\", \"CustomConfig_GetConfig\", (actual_7 === 30) ? \"PASS\" : \"FAIL\", \"{\\\"jsonlist\\\":\\\"[{\\\\\\\"name\\\\\\\":\\\\\\\"timeout\\\\\\\",\\\\\\\"value\\\\\\\":30}]\\\",\\\"configName\\\":\\\"timeout\\\"}\", \"数字 30\", actual_7]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_7" + }, + "parentId": "t04_60", + "slot": "try_fn" + }, + { + "id": "t04_63", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3320 + }, + "values": { + "value": "${failures + (case_7[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_60", + "slot": "try_fn" + }, + { + "id": "t04_64", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3320 + }, + "values": { + "value": "${pending + (case_7[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_60", + "slot": "try_fn" + }, + { + "id": "t04_65", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3320 + }, + "values": { + "value": "${[\"04-07\", \"CustomConfig_GetConfig\", \"FAIL\", \"{\\\"jsonlist\\\":\\\"[{\\\\\\\"name\\\\\\\":\\\\\\\"timeout\\\\\\\",\\\\\\\"value\\\\\\\":30}]\\\",\\\"configName\\\":\\\"timeout\\\"}\", \"数字 30\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_7" + }, + "parentId": "t04_60", + "slot": "except_fn" + }, + { + "id": "t04_66", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3320 + }, + "values": { + "value": "${failures + (case_7[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_60", + "slot": "except_fn" + }, + { + "id": "t04_67", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3320 + }, + "values": { + "value": "${pending + (case_7[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_60", + "slot": "except_fn" + }, + { + "id": "t04_68", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 6136 + }, + "values": { + "msg": "用例结果:${json(case_7)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_69", + "componentId": "logic_control_try_catch", + "label": "04-08 · CustomConfig_GetConfig", + "position": { + "x": 220, + "y": 6278 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_70", + "componentId": "CustomConfig_GetConfig", + "label": "CustomConfig_GetConfig", + "position": { + "x": 220, + "y": 3680 + }, + "values": { + "jsonlist": "[]", + "configName": "missing" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_8" + }, + "parentId": "t04_69", + "slot": "try_fn" + }, + { + "id": "t04_71", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3680 + }, + "values": { + "value": "${[\"04-08\", \"CustomConfig_GetConfig\", (actual_8 === null) ? \"PASS\" : \"FAIL\", \"{\\\"jsonlist\\\":\\\"[]\\\",\\\"configName\\\":\\\"missing\\\"}\", \"未命中返回 null\", actual_8]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_8" + }, + "parentId": "t04_69", + "slot": "try_fn" + }, + { + "id": "t04_72", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3680 + }, + "values": { + "value": "${failures + (case_8[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_69", + "slot": "try_fn" + }, + { + "id": "t04_73", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3680 + }, + "values": { + "value": "${pending + (case_8[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_69", + "slot": "try_fn" + }, + { + "id": "t04_74", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3680 + }, + "values": { + "value": "${[\"04-08\", \"CustomConfig_GetConfig\", \"FAIL\", \"{\\\"jsonlist\\\":\\\"[]\\\",\\\"configName\\\":\\\"missing\\\"}\", \"未命中返回 null\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_8" + }, + "parentId": "t04_69", + "slot": "except_fn" + }, + { + "id": "t04_75", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3680 + }, + "values": { + "value": "${failures + (case_8[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_69", + "slot": "except_fn" + }, + { + "id": "t04_76", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3680 + }, + "values": { + "value": "${pending + (case_8[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_69", + "slot": "except_fn" + }, + { + "id": "t04_77", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 6920 + }, + "values": { + "msg": "用例结果:${json(case_8)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_78", + "componentId": "logic_control_try_catch", + "label": "04-09 · Basic_BusinessOrderCount", + "position": { + "x": 220, + "y": 7062 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_79", + "componentId": "Basic_BusinessOrderCount", + "label": "Basic_BusinessOrderCount", + "position": { + "x": 220, + "y": 4040 + }, + "values": { + "start_count": 10, + "count": 2 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_9" + }, + "parentId": "t04_78", + "slot": "try_fn" + }, + { + "id": "t04_80", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 4040 + }, + "values": { + "value": "${[\"04-09\", \"Basic_BusinessOrderCount\", (actual_9 === 12) ? \"PASS\" : \"FAIL\", \"{\\\"start_count\\\":10,\\\"count\\\":2}\", \"首次计数 12\", actual_9]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_9" + }, + "parentId": "t04_78", + "slot": "try_fn" + }, + { + "id": "t04_81", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 4040 + }, + "values": { + "value": "${failures + (case_9[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_78", + "slot": "try_fn" + }, + { + "id": "t04_82", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 4040 + }, + "values": { + "value": "${pending + (case_9[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_78", + "slot": "try_fn" + }, + { + "id": "t04_83", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 4040 + }, + "values": { + "value": "${[\"04-09\", \"Basic_BusinessOrderCount\", \"FAIL\", \"{\\\"start_count\\\":10,\\\"count\\\":2}\", \"首次计数 12\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_9" + }, + "parentId": "t04_78", + "slot": "except_fn" + }, + { + "id": "t04_84", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 4040 + }, + "values": { + "value": "${failures + (case_9[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_78", + "slot": "except_fn" + }, + { + "id": "t04_85", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 4040 + }, + "values": { + "value": "${pending + (case_9[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_78", + "slot": "except_fn" + }, + { + "id": "t04_86", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 7704 + }, + "values": { + "msg": "用例结果:${json(case_9)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_87", + "componentId": "logic_control_try_catch", + "label": "04-10 · Basic_BusinessOrderCount", + "position": { + "x": 220, + "y": 7846 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_88", + "componentId": "Basic_BusinessOrderCount", + "label": "Basic_BusinessOrderCount", + "position": { + "x": 220, + "y": 4400 + }, + "values": { + "start_count": 10, + "count": 2 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_10" + }, + "parentId": "t04_87", + "slot": "try_fn" + }, + { + "id": "t04_89", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 4400 + }, + "values": { + "value": "${[\"04-10\", \"Basic_BusinessOrderCount\", (actual_10 === 14) ? \"PASS\" : \"FAIL\", \"{\\\"start_count\\\":10,\\\"count\\\":2}\", \"同一流程再次计数 14\", actual_10]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_10" + }, + "parentId": "t04_87", + "slot": "try_fn" + }, + { + "id": "t04_90", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 4400 + }, + "values": { + "value": "${failures + (case_10[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_87", + "slot": "try_fn" + }, + { + "id": "t04_91", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 4400 + }, + "values": { + "value": "${pending + (case_10[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_87", + "slot": "try_fn" + }, + { + "id": "t04_92", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 4400 + }, + "values": { + "value": "${[\"04-10\", \"Basic_BusinessOrderCount\", \"FAIL\", \"{\\\"start_count\\\":10,\\\"count\\\":2}\", \"同一流程再次计数 14\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_10" + }, + "parentId": "t04_87", + "slot": "except_fn" + }, + { + "id": "t04_93", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 4400 + }, + "values": { + "value": "${failures + (case_10[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t04_87", + "slot": "except_fn" + }, + { + "id": "t04_94", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 4400 + }, + "values": { + "value": "${pending + (case_10[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t04_87", + "slot": "except_fn" + }, + { + "id": "t04_95", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 8488 + }, + "values": { + "msg": "用例结果:${json(case_10)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_96", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 8630 + }, + "values": { + "msg": "本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_97", + "componentId": "logic_control_if_else", + "label": "汇总判定", + "position": { + "x": 220, + "y": 8772 + }, + "values": { + "condition": "${failures > 0 || pending > 0 || blocked > 0}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t04_98", + "componentId": "ExceptionUtil_Throws", + "label": "如实标记未通过", + "position": { + "x": 220, + "y": 4940 + }, + "values": { + "msg": "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t04_97", + "slot": "statement_if" + }, + { + "id": "t04_99", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 4940 + }, + "values": { + "msg": "本组全部通过。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t04_97", + "slot": "statement_else" + } + ], + "edges": [ + { + "id": "e_t04_2", + "source": "t04_1", + "target": "t04_2" + }, + { + "id": "e_t04_3", + "source": "t04_2", + "target": "t04_3" + }, + { + "id": "e_t04_4", + "source": "t04_3", + "target": "t04_4" + }, + { + "id": "e_t04_5", + "source": "t04_4", + "target": "t04_5" + }, + { + "id": "e_t04_13", + "source": "t04_5", + "target": "t04_13" + }, + { + "id": "e_t04_14", + "source": "t04_13", + "target": "t04_14" + }, + { + "id": "e_t04_22", + "source": "t04_14", + "target": "t04_22" + }, + { + "id": "e_t04_23", + "source": "t04_22", + "target": "t04_23" + }, + { + "id": "e_t04_31", + "source": "t04_23", + "target": "t04_31" + }, + { + "id": "e_t04_32", + "source": "t04_31", + "target": "t04_32" + }, + { + "id": "e_t04_33", + "source": "t04_32", + "target": "t04_33" + }, + { + "id": "e_t04_41", + "source": "t04_33", + "target": "t04_41" + }, + { + "id": "e_t04_42", + "source": "t04_41", + "target": "t04_42" + }, + { + "id": "e_t04_50", + "source": "t04_42", + "target": "t04_50" + }, + { + "id": "e_t04_51", + "source": "t04_50", + "target": "t04_51" + }, + { + "id": "e_t04_59", + "source": "t04_51", + "target": "t04_59" + }, + { + "id": "e_t04_60", + "source": "t04_59", + "target": "t04_60" + }, + { + "id": "e_t04_68", + "source": "t04_60", + "target": "t04_68" + }, + { + "id": "e_t04_69", + "source": "t04_68", + "target": "t04_69" + }, + { + "id": "e_t04_77", + "source": "t04_69", + "target": "t04_77" + }, + { + "id": "e_t04_78", + "source": "t04_77", + "target": "t04_78" + }, + { + "id": "e_t04_86", + "source": "t04_78", + "target": "t04_86" + }, + { + "id": "e_t04_87", + "source": "t04_86", + "target": "t04_87" + }, + { + "id": "e_t04_95", + "source": "t04_87", + "target": "t04_95" + }, + { + "id": "e_t04_96", + "source": "t04_95", + "target": "t04_96" + }, + { + "id": "e_t04_97", + "source": "t04_96", + "target": "t04_97" + } + ], + "meta": { + "createdAt": "2026-10-30T00:00:00.000Z", + "updatedAt": "2026-10-30T00:00:00.000Z", + "appVersion": "0.1.0" + } +} diff --git a/resources/test-flows/app-system/test_appsystem_05.json b/resources/test-flows/app-system/test_appsystem_05.json new file mode 100644 index 0000000..5de4cea --- /dev/null +++ b/resources/test-flows/app-system/test_appsystem_05.json @@ -0,0 +1,1629 @@ +{ + "schemaVersion": 1, + "id": "test_appsystem_05", + "name": "组件测试 05 · 等待与随机数", + "description": "查看运行日志中的用例结果;有失败时任务最终显示失败,其他用例仍继续。", + "enabled": true, + "trigger": { + "type": "manual", + "label": "手动运行" + }, + "variables": [], + "nodes": [ + { + "id": "t05_1", + "componentId": "Trigger.Manual", + "label": "人工发起", + "position": { + "x": 220, + "y": 80 + }, + "values": { + "entryName": "开始组件测试" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_2", + "componentId": "Basic_SetVariable", + "label": "初始化失败计数", + "position": { + "x": 220, + "y": 222 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + } + }, + { + "id": "t05_3", + "componentId": "Basic_SetVariable", + "label": "初始化待确认计数", + "position": { + "x": 220, + "y": 364 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + } + }, + { + "id": "t05_4", + "componentId": "Basic_SetVariable", + "label": "初始化阻塞计数", + "position": { + "x": 220, + "y": 506 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "blocked" + } + }, + { + "id": "t05_5", + "componentId": "logic_control_try_catch", + "label": "05-01 · Basic_Delay_V2", + "position": { + "x": 220, + "y": 648 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_6", + "componentId": "Time_GetDatetimeObj", + "label": "独立采集毫秒时间", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "date_input": "${now()}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "startTime" + }, + "parentId": "t05_5", + "slot": "try_fn" + }, + { + "id": "t05_7", + "componentId": "Basic_Delay_V2", + "label": "Basic_Delay_V2", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "is_random": "0", + "second": "0.15", + "min_second": "0.1", + "max_second": "0.2" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_1" + }, + "parentId": "t05_5", + "slot": "try_fn" + }, + { + "id": "t05_8", + "componentId": "Time_GetDatetimeObj", + "label": "独立采集毫秒时间", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "date_input": "${now()}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "endTime" + }, + "parentId": "t05_5", + "slot": "try_fn" + }, + { + "id": "t05_9", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${[\"05-01\", \"Basic_Delay_V2\", (endTime.timestamp - startTime.timestamp >= 120 && endTime.timestamp - startTime.timestamp <= 1800) ? \"PASS\" : \"FAIL\", \"{\\\"is_random\\\":\\\"0\\\",\\\"second\\\":\\\"0.15\\\",\\\"min_second\\\":\\\"0.1\\\",\\\"max_second\\\":\\\"0.2\\\"}\", \"实际等待耗时 120~1800 ms\", endTime.timestamp - startTime.timestamp]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t05_5", + "slot": "try_fn" + }, + { + "id": "t05_10", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_5", + "slot": "try_fn" + }, + { + "id": "t05_11", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_5", + "slot": "try_fn" + }, + { + "id": "t05_12", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${[\"05-01\", \"Basic_Delay_V2\", \"FAIL\", \"{\\\"is_random\\\":\\\"0\\\",\\\"second\\\":\\\"0.15\\\",\\\"min_second\\\":\\\"0.1\\\",\\\"max_second\\\":\\\"0.2\\\"}\", \"实际等待耗时 120~1800 ms\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t05_5", + "slot": "except_fn" + }, + { + "id": "t05_13", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_5", + "slot": "except_fn" + }, + { + "id": "t05_14", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_5", + "slot": "except_fn" + }, + { + "id": "t05_15", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1382 + }, + "values": { + "msg": "用例结果:${json(case_1)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_16", + "componentId": "logic_control_try_catch", + "label": "05-02 · Basic_Delay_V2", + "position": { + "x": 220, + "y": 1524 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_17", + "componentId": "Time_GetDatetimeObj", + "label": "独立采集毫秒时间", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "date_input": "${now()}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "startTime" + }, + "parentId": "t05_16", + "slot": "try_fn" + }, + { + "id": "t05_18", + "componentId": "Basic_Delay_V2", + "label": "Basic_Delay_V2", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "is_random": "1", + "second": "0.15", + "min_second": "0.1", + "max_second": "0.2" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_2" + }, + "parentId": "t05_16", + "slot": "try_fn" + }, + { + "id": "t05_19", + "componentId": "Time_GetDatetimeObj", + "label": "独立采集毫秒时间", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "date_input": "${now()}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "endTime" + }, + "parentId": "t05_16", + "slot": "try_fn" + }, + { + "id": "t05_20", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"05-02\", \"Basic_Delay_V2\", (endTime.timestamp - startTime.timestamp >= 80 && endTime.timestamp - startTime.timestamp <= 1800) ? \"PASS\" : \"FAIL\", \"{\\\"is_random\\\":\\\"1\\\",\\\"second\\\":\\\"0.15\\\",\\\"min_second\\\":\\\"0.1\\\",\\\"max_second\\\":\\\"0.2\\\"}\", \"实际等待耗时 80~1800 ms\", endTime.timestamp - startTime.timestamp]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t05_16", + "slot": "try_fn" + }, + { + "id": "t05_21", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_16", + "slot": "try_fn" + }, + { + "id": "t05_22", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_16", + "slot": "try_fn" + }, + { + "id": "t05_23", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"05-02\", \"Basic_Delay_V2\", \"FAIL\", \"{\\\"is_random\\\":\\\"1\\\",\\\"second\\\":\\\"0.15\\\",\\\"min_second\\\":\\\"0.1\\\",\\\"max_second\\\":\\\"0.2\\\"}\", \"实际等待耗时 80~1800 ms\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t05_16", + "slot": "except_fn" + }, + { + "id": "t05_24", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_16", + "slot": "except_fn" + }, + { + "id": "t05_25", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_16", + "slot": "except_fn" + }, + { + "id": "t05_26", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2258 + }, + "values": { + "msg": "用例结果:${json(case_2)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_27", + "componentId": "logic_control_try_catch", + "label": "05-03 · Basic_Delay_V1", + "position": { + "x": 220, + "y": 2400 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_28", + "componentId": "Time_GetDatetimeObj", + "label": "独立采集毫秒时间", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "date_input": "${now()}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "startTime" + }, + "parentId": "t05_27", + "slot": "try_fn" + }, + { + "id": "t05_29", + "componentId": "Basic_Delay_V1", + "label": "Basic_Delay_V1", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "second": "0.15" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_3" + }, + "parentId": "t05_27", + "slot": "try_fn" + }, + { + "id": "t05_30", + "componentId": "Time_GetDatetimeObj", + "label": "独立采集毫秒时间", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "date_input": "${now()}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "endTime" + }, + "parentId": "t05_27", + "slot": "try_fn" + }, + { + "id": "t05_31", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"05-03\", \"Basic_Delay_V1\", (endTime.timestamp - startTime.timestamp >= 120 && endTime.timestamp - startTime.timestamp <= 1800) ? \"PASS\" : \"FAIL\", \"{\\\"second\\\":\\\"0.15\\\"}\", \"实际等待耗时 120~1800 ms\", endTime.timestamp - startTime.timestamp]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t05_27", + "slot": "try_fn" + }, + { + "id": "t05_32", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_27", + "slot": "try_fn" + }, + { + "id": "t05_33", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_27", + "slot": "try_fn" + }, + { + "id": "t05_34", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"05-03\", \"Basic_Delay_V1\", \"FAIL\", \"{\\\"second\\\":\\\"0.15\\\"}\", \"实际等待耗时 120~1800 ms\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t05_27", + "slot": "except_fn" + }, + { + "id": "t05_35", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_27", + "slot": "except_fn" + }, + { + "id": "t05_36", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_27", + "slot": "except_fn" + }, + { + "id": "t05_37", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 3134 + }, + "values": { + "msg": "用例结果:${json(case_3)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_38", + "componentId": "logic_control_try_catch", + "label": "05-04 · Basic_Delay", + "position": { + "x": 220, + "y": 3276 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_39", + "componentId": "Time_GetDatetimeObj", + "label": "独立采集毫秒时间", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "date_input": "${now()}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "startTime" + }, + "parentId": "t05_38", + "slot": "try_fn" + }, + { + "id": "t05_40", + "componentId": "Basic_Delay", + "label": "Basic_Delay", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "mileSecond": "3000" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_4" + }, + "parentId": "t05_38", + "slot": "try_fn" + }, + { + "id": "t05_41", + "componentId": "Time_GetDatetimeObj", + "label": "独立采集毫秒时间", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "date_input": "${now()}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "endTime" + }, + "parentId": "t05_38", + "slot": "try_fn" + }, + { + "id": "t05_42", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${[\"05-04\", \"Basic_Delay\", (endTime.timestamp - startTime.timestamp >= 2800 && endTime.timestamp - startTime.timestamp <= 6500) ? \"PASS\" : \"FAIL\", \"{\\\"mileSecond\\\":\\\"3000\\\"}\", \"实际等待耗时 2800~6500 ms\", endTime.timestamp - startTime.timestamp]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t05_38", + "slot": "try_fn" + }, + { + "id": "t05_43", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_38", + "slot": "try_fn" + }, + { + "id": "t05_44", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_38", + "slot": "try_fn" + }, + { + "id": "t05_45", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${[\"05-04\", \"Basic_Delay\", \"FAIL\", \"{\\\"mileSecond\\\":\\\"3000\\\"}\", \"实际等待耗时 2800~6500 ms\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t05_38", + "slot": "except_fn" + }, + { + "id": "t05_46", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_38", + "slot": "except_fn" + }, + { + "id": "t05_47", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_38", + "slot": "except_fn" + }, + { + "id": "t05_48", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 4010 + }, + "values": { + "msg": "用例结果:${json(case_4)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_49", + "componentId": "logic_control_try_catch", + "label": "05-05 · Basic_RandomInt", + "position": { + "x": 220, + "y": 4152 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_50", + "componentId": "Basic_RandomInt", + "label": "Basic_RandomInt", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "min": 7, + "max": 7 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_5" + }, + "parentId": "t05_49", + "slot": "try_fn" + }, + { + "id": "t05_51", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${[\"05-05\", \"Basic_RandomInt\", (actual_5 === 7) ? \"PASS\" : \"FAIL\", \"{\\\"min\\\":7,\\\"max\\\":7}\", \"最小值等于最大值时返回整数 7\", actual_5]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t05_49", + "slot": "try_fn" + }, + { + "id": "t05_52", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_49", + "slot": "try_fn" + }, + { + "id": "t05_53", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_49", + "slot": "try_fn" + }, + { + "id": "t05_54", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${[\"05-05\", \"Basic_RandomInt\", \"FAIL\", \"{\\\"min\\\":7,\\\"max\\\":7}\", \"最小值等于最大值时返回整数 7\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t05_49", + "slot": "except_fn" + }, + { + "id": "t05_55", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_49", + "slot": "except_fn" + }, + { + "id": "t05_56", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_49", + "slot": "except_fn" + }, + { + "id": "t05_57", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 4794 + }, + "values": { + "msg": "用例结果:${json(case_5)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_58", + "componentId": "logic_control_try_catch", + "label": "05-06 · Basic_RandomInt", + "position": { + "x": 220, + "y": 4936 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_59", + "componentId": "Basic_RandomInt", + "label": "Basic_RandomInt", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "min": -2, + "max": 2 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_6" + }, + "parentId": "t05_58", + "slot": "try_fn" + }, + { + "id": "t05_60", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${[\"05-06\", \"Basic_RandomInt\", (actual_6 >= -2 && actual_6 <= 2 && actual_6 % 1 === 0) ? \"PASS\" : \"FAIL\", \"{\\\"min\\\":-2,\\\"max\\\":2}\", \"返回 -2~2 的整数\", actual_6]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_6" + }, + "parentId": "t05_58", + "slot": "try_fn" + }, + { + "id": "t05_61", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${failures + (case_6[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_58", + "slot": "try_fn" + }, + { + "id": "t05_62", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${pending + (case_6[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_58", + "slot": "try_fn" + }, + { + "id": "t05_63", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${[\"05-06\", \"Basic_RandomInt\", \"FAIL\", \"{\\\"min\\\":-2,\\\"max\\\":2}\", \"返回 -2~2 的整数\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_6" + }, + "parentId": "t05_58", + "slot": "except_fn" + }, + { + "id": "t05_64", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${failures + (case_6[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_58", + "slot": "except_fn" + }, + { + "id": "t05_65", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${pending + (case_6[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_58", + "slot": "except_fn" + }, + { + "id": "t05_66", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 5578 + }, + "values": { + "msg": "用例结果:${json(case_6)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_67", + "componentId": "logic_control_try_catch", + "label": "05-07 · Basic_Rnd", + "position": { + "x": 220, + "y": 5720 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_68", + "componentId": "Basic_Rnd", + "label": "Basic_Rnd", + "position": { + "x": 220, + "y": 3140 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_7" + }, + "parentId": "t05_67", + "slot": "try_fn" + }, + { + "id": "t05_69", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${[\"05-07\", \"Basic_Rnd\", (actual_7 >= 0 && actual_7 < 1) ? \"PASS\" : \"FAIL\", \"{}\", \"随机小数满足 0 ≤ x < 1\", actual_7]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_7" + }, + "parentId": "t05_67", + "slot": "try_fn" + }, + { + "id": "t05_70", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${failures + (case_7[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_67", + "slot": "try_fn" + }, + { + "id": "t05_71", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${pending + (case_7[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_67", + "slot": "try_fn" + }, + { + "id": "t05_72", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${[\"05-07\", \"Basic_Rnd\", \"FAIL\", \"{}\", \"随机小数满足 0 ≤ x < 1\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_7" + }, + "parentId": "t05_67", + "slot": "except_fn" + }, + { + "id": "t05_73", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${failures + (case_7[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t05_67", + "slot": "except_fn" + }, + { + "id": "t05_74", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${pending + (case_7[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t05_67", + "slot": "except_fn" + }, + { + "id": "t05_75", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 6362 + }, + "values": { + "msg": "用例结果:${json(case_7)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_76", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 6504 + }, + "values": { + "msg": "本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_77", + "componentId": "logic_control_if_else", + "label": "汇总判定", + "position": { + "x": 220, + "y": 6646 + }, + "values": { + "condition": "${failures > 0 || pending > 0 || blocked > 0}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t05_78", + "componentId": "ExceptionUtil_Throws", + "label": "如实标记未通过", + "position": { + "x": 220, + "y": 3680 + }, + "values": { + "msg": "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t05_77", + "slot": "statement_if" + }, + { + "id": "t05_79", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 3680 + }, + "values": { + "msg": "本组全部通过。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t05_77", + "slot": "statement_else" + } + ], + "edges": [ + { + "id": "e_t05_2", + "source": "t05_1", + "target": "t05_2" + }, + { + "id": "e_t05_3", + "source": "t05_2", + "target": "t05_3" + }, + { + "id": "e_t05_4", + "source": "t05_3", + "target": "t05_4" + }, + { + "id": "e_t05_5", + "source": "t05_4", + "target": "t05_5" + }, + { + "id": "e_t05_15", + "source": "t05_5", + "target": "t05_15" + }, + { + "id": "e_t05_16", + "source": "t05_15", + "target": "t05_16" + }, + { + "id": "e_t05_26", + "source": "t05_16", + "target": "t05_26" + }, + { + "id": "e_t05_27", + "source": "t05_26", + "target": "t05_27" + }, + { + "id": "e_t05_37", + "source": "t05_27", + "target": "t05_37" + }, + { + "id": "e_t05_38", + "source": "t05_37", + "target": "t05_38" + }, + { + "id": "e_t05_48", + "source": "t05_38", + "target": "t05_48" + }, + { + "id": "e_t05_49", + "source": "t05_48", + "target": "t05_49" + }, + { + "id": "e_t05_57", + "source": "t05_49", + "target": "t05_57" + }, + { + "id": "e_t05_58", + "source": "t05_57", + "target": "t05_58" + }, + { + "id": "e_t05_66", + "source": "t05_58", + "target": "t05_66" + }, + { + "id": "e_t05_67", + "source": "t05_66", + "target": "t05_67" + }, + { + "id": "e_t05_75", + "source": "t05_67", + "target": "t05_75" + }, + { + "id": "e_t05_76", + "source": "t05_75", + "target": "t05_76" + }, + { + "id": "e_t05_77", + "source": "t05_76", + "target": "t05_77" + } + ], + "meta": { + "createdAt": "2026-10-30T00:00:00.000Z", + "updatedAt": "2026-10-30T00:00:00.000Z", + "appVersion": "0.1.0" + } +} diff --git a/resources/test-flows/app-system/test_appsystem_06.json b/resources/test-flows/app-system/test_appsystem_06.json new file mode 100644 index 0000000..094cb38 --- /dev/null +++ b/resources/test-flows/app-system/test_appsystem_06.json @@ -0,0 +1,1507 @@ +{ + "schemaVersion": 1, + "id": "test_appsystem_06", + "name": "组件测试 06 · 系统路径与环境变量", + "description": "查看运行日志中的用例结果;有失败时任务最终显示失败,其他用例仍继续。", + "enabled": true, + "trigger": { + "type": "manual", + "label": "手动运行" + }, + "variables": [], + "nodes": [ + { + "id": "t06_1", + "componentId": "Trigger.Manual", + "label": "人工发起", + "position": { + "x": 220, + "y": 80 + }, + "values": { + "entryName": "开始组件测试" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_2", + "componentId": "Basic_SetVariable", + "label": "初始化失败计数", + "position": { + "x": 220, + "y": 222 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + } + }, + { + "id": "t06_3", + "componentId": "Basic_SetVariable", + "label": "初始化待确认计数", + "position": { + "x": 220, + "y": 364 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + } + }, + { + "id": "t06_4", + "componentId": "Basic_SetVariable", + "label": "初始化阻塞计数", + "position": { + "x": 220, + "y": 506 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "blocked" + } + }, + { + "id": "t06_5", + "componentId": "System_ExecuteCommand", + "label": "独立读取 Windows 系统路径", + "position": { + "x": 220, + "y": 648 + }, + "values": { + "action": "@{temp=[IO.Path]::GetTempPath().TrimEnd('\\'); home=[Environment]::GetFolderPath('UserProfile'); desktop=[Environment]::GetFolderPath('Desktop')} | ConvertTo-Json -Compress" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pathOracle" + } + }, + { + "id": "t06_6", + "componentId": "Basic_SetVariable", + "label": "解析独立预期路径", + "position": { + "x": 220, + "y": 790 + }, + "values": { + "value": "${parseJson(pathOracle)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "paths" + } + }, + { + "id": "t06_7", + "componentId": "logic_control_try_catch", + "label": "06-01 · System_GetTempPath", + "position": { + "x": 220, + "y": 932 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_8", + "componentId": "System_GetTempPath", + "label": "System_GetTempPath", + "position": { + "x": 220, + "y": 1340 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_1" + }, + "parentId": "t06_7", + "slot": "try_fn" + }, + { + "id": "t06_9", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"06-01\", \"System_GetTempPath\", (actual_1 === paths.temp || actual_1 === paths.temp + \"\\\\\") ? \"PASS\" : \"FAIL\", \"{}\", \"与系统临时目录一致(忽略尾部分隔符)\", actual_1]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t06_7", + "slot": "try_fn" + }, + { + "id": "t06_10", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_7", + "slot": "try_fn" + }, + { + "id": "t06_11", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_7", + "slot": "try_fn" + }, + { + "id": "t06_12", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"06-01\", \"System_GetTempPath\", \"FAIL\", \"{}\", \"与系统临时目录一致(忽略尾部分隔符)\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t06_7", + "slot": "except_fn" + }, + { + "id": "t06_13", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_7", + "slot": "except_fn" + }, + { + "id": "t06_14", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_7", + "slot": "except_fn" + }, + { + "id": "t06_15", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1574 + }, + "values": { + "msg": "用例结果:${json(case_1)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_16", + "componentId": "logic_control_try_catch", + "label": "06-02 · System_GetHomePath", + "position": { + "x": 220, + "y": 1716 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_17", + "componentId": "System_GetHomePath", + "label": "System_GetHomePath", + "position": { + "x": 220, + "y": 1700 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_2" + }, + "parentId": "t06_16", + "slot": "try_fn" + }, + { + "id": "t06_18", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"06-02\", \"System_GetHomePath\", (actual_2 === paths.home) ? \"PASS\" : \"FAIL\", \"{}\", \"与 Windows 用户文件夹一致\", actual_2]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t06_16", + "slot": "try_fn" + }, + { + "id": "t06_19", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_16", + "slot": "try_fn" + }, + { + "id": "t06_20", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_16", + "slot": "try_fn" + }, + { + "id": "t06_21", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"06-02\", \"System_GetHomePath\", \"FAIL\", \"{}\", \"与 Windows 用户文件夹一致\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t06_16", + "slot": "except_fn" + }, + { + "id": "t06_22", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_16", + "slot": "except_fn" + }, + { + "id": "t06_23", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_16", + "slot": "except_fn" + }, + { + "id": "t06_24", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2358 + }, + "values": { + "msg": "用例结果:${json(case_2)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_25", + "componentId": "logic_control_try_catch", + "label": "06-03 · System_GetSystemPath", + "position": { + "x": 220, + "y": 2500 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_26", + "componentId": "System_GetSystemPath", + "label": "System_GetSystemPath", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "path_name": "desktop" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_3" + }, + "parentId": "t06_25", + "slot": "try_fn" + }, + { + "id": "t06_27", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${[\"06-03\", \"System_GetSystemPath\", (actual_3 === paths.desktop) ? \"PASS\" : \"FAIL\", \"{\\\"path_name\\\":\\\"desktop\\\"}\", \"与 Windows 实际桌面目录一致(包含重定向)\", actual_3]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t06_25", + "slot": "try_fn" + }, + { + "id": "t06_28", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_25", + "slot": "try_fn" + }, + { + "id": "t06_29", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_25", + "slot": "try_fn" + }, + { + "id": "t06_30", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${[\"06-03\", \"System_GetSystemPath\", \"FAIL\", \"{\\\"path_name\\\":\\\"desktop\\\"}\", \"与 Windows 实际桌面目录一致(包含重定向)\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t06_25", + "slot": "except_fn" + }, + { + "id": "t06_31", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_25", + "slot": "except_fn" + }, + { + "id": "t06_32", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_25", + "slot": "except_fn" + }, + { + "id": "t06_33", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 3142 + }, + "values": { + "msg": "用例结果:${json(case_3)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_34", + "componentId": "logic_control_try_catch", + "label": "06-04 · System_GetEnv", + "position": { + "x": 220, + "y": 3284 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_35", + "componentId": "System_GetEnv", + "label": "System_GetEnv", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "name": "RPA_APP_SYSTEM_TEST_VALUE" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "originalEnv" + }, + "parentId": "t06_34", + "slot": "try_fn" + }, + { + "id": "t06_36", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${[\"06-04\", \"System_GetEnv\", (true) ? \"PASS\" : \"FAIL\", \"{\\\"name\\\":\\\"RPA_APP_SYSTEM_TEST_VALUE\\\"}\", \"读取测试专用变量的原始值,作为恢复依据\", originalEnv]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t06_34", + "slot": "try_fn" + }, + { + "id": "t06_37", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_34", + "slot": "try_fn" + }, + { + "id": "t06_38", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_34", + "slot": "try_fn" + }, + { + "id": "t06_39", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${[\"06-04\", \"System_GetEnv\", \"FAIL\", \"{\\\"name\\\":\\\"RPA_APP_SYSTEM_TEST_VALUE\\\"}\", \"读取测试专用变量的原始值,作为恢复依据\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t06_34", + "slot": "except_fn" + }, + { + "id": "t06_40", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_34", + "slot": "except_fn" + }, + { + "id": "t06_41", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_34", + "slot": "except_fn" + }, + { + "id": "t06_42", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 3926 + }, + "values": { + "msg": "用例结果:${json(case_4)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_43", + "componentId": "logic_control_try_catch", + "label": "06-05 · System_SetEnv", + "position": { + "x": 220, + "y": 4068 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_44", + "componentId": "System_SetEnv", + "label": "System_SetEnv", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "name": "RPA_APP_SYSTEM_TEST_VALUE", + "value": "中文-测试-42" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_5" + }, + "parentId": "t06_43", + "slot": "try_fn" + }, + { + "id": "t06_45", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${[\"06-05\", \"System_SetEnv\", (actual_5 === \"中文-测试-42\") ? \"PASS\" : \"FAIL\", \"{\\\"name\\\":\\\"RPA_APP_SYSTEM_TEST_VALUE\\\",\\\"value\\\":\\\"中文-测试-42\\\"}\", \"当前应用进程内设置成功\", actual_5]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t06_43", + "slot": "try_fn" + }, + { + "id": "t06_46", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_43", + "slot": "try_fn" + }, + { + "id": "t06_47", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_43", + "slot": "try_fn" + }, + { + "id": "t06_48", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${[\"06-05\", \"System_SetEnv\", \"FAIL\", \"{\\\"name\\\":\\\"RPA_APP_SYSTEM_TEST_VALUE\\\",\\\"value\\\":\\\"中文-测试-42\\\"}\", \"当前应用进程内设置成功\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t06_43", + "slot": "except_fn" + }, + { + "id": "t06_49", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_43", + "slot": "except_fn" + }, + { + "id": "t06_50", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_43", + "slot": "except_fn" + }, + { + "id": "t06_51", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 4710 + }, + "values": { + "msg": "用例结果:${json(case_5)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_52", + "componentId": "logic_control_try_catch", + "label": "06-06 · System_GetEnv", + "position": { + "x": 220, + "y": 4852 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_53", + "componentId": "System_GetEnv", + "label": "System_GetEnv", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "name": "RPA_APP_SYSTEM_TEST_VALUE" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_6" + }, + "parentId": "t06_52", + "slot": "try_fn" + }, + { + "id": "t06_54", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${[\"06-06\", \"System_GetEnv\", (actual_6 === \"中文-测试-42\") ? \"PASS\" : \"FAIL\", \"{\\\"name\\\":\\\"RPA_APP_SYSTEM_TEST_VALUE\\\"}\", \"能读回中文-测试-42\", actual_6]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_6" + }, + "parentId": "t06_52", + "slot": "try_fn" + }, + { + "id": "t06_55", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${failures + (case_6[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_52", + "slot": "try_fn" + }, + { + "id": "t06_56", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${pending + (case_6[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_52", + "slot": "try_fn" + }, + { + "id": "t06_57", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${[\"06-06\", \"System_GetEnv\", \"FAIL\", \"{\\\"name\\\":\\\"RPA_APP_SYSTEM_TEST_VALUE\\\"}\", \"能读回中文-测试-42\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_6" + }, + "parentId": "t06_52", + "slot": "except_fn" + }, + { + "id": "t06_58", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${failures + (case_6[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_52", + "slot": "except_fn" + }, + { + "id": "t06_59", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "value": "${pending + (case_6[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_52", + "slot": "except_fn" + }, + { + "id": "t06_60", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 5494 + }, + "values": { + "msg": "用例结果:${json(case_6)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_61", + "componentId": "logic_control_try_catch", + "label": "06-07 · System_SetEnv", + "position": { + "x": 220, + "y": 5636 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_62", + "componentId": "System_SetEnv", + "label": "System_SetEnv", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "name": "RPA_APP_SYSTEM_TEST_VALUE", + "value": "${originalEnv}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_7" + }, + "parentId": "t06_61", + "slot": "try_fn" + }, + { + "id": "t06_63", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${[\"06-07\", \"System_SetEnv\", (actual_7 === originalEnv) ? \"PASS\" : \"FAIL\", \"{\\\"name\\\":\\\"RPA_APP_SYSTEM_TEST_VALUE\\\",\\\"value\\\":\\\"${originalEnv}\\\"}\", \"恢复测试前读取值\", actual_7]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_7" + }, + "parentId": "t06_61", + "slot": "try_fn" + }, + { + "id": "t06_64", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${failures + (case_7[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_61", + "slot": "try_fn" + }, + { + "id": "t06_65", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${pending + (case_7[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_61", + "slot": "try_fn" + }, + { + "id": "t06_66", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${[\"06-07\", \"System_SetEnv\", \"FAIL\", \"{\\\"name\\\":\\\"RPA_APP_SYSTEM_TEST_VALUE\\\",\\\"value\\\":\\\"${originalEnv}\\\"}\", \"恢复测试前读取值\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_7" + }, + "parentId": "t06_61", + "slot": "except_fn" + }, + { + "id": "t06_67", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${failures + (case_7[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t06_61", + "slot": "except_fn" + }, + { + "id": "t06_68", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 3500 + }, + "values": { + "value": "${pending + (case_7[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t06_61", + "slot": "except_fn" + }, + { + "id": "t06_69", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 6278 + }, + "values": { + "msg": "用例结果:${json(case_7)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_70", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 6420 + }, + "values": { + "msg": "本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_71", + "componentId": "logic_control_if_else", + "label": "汇总判定", + "position": { + "x": 220, + "y": 6562 + }, + "values": { + "condition": "${failures > 0 || pending > 0 || blocked > 0}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t06_72", + "componentId": "ExceptionUtil_Throws", + "label": "如实标记未通过", + "position": { + "x": 220, + "y": 4040 + }, + "values": { + "msg": "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t06_71", + "slot": "statement_if" + }, + { + "id": "t06_73", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 4040 + }, + "values": { + "msg": "本组全部通过。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t06_71", + "slot": "statement_else" + } + ], + "edges": [ + { + "id": "e_t06_2", + "source": "t06_1", + "target": "t06_2" + }, + { + "id": "e_t06_3", + "source": "t06_2", + "target": "t06_3" + }, + { + "id": "e_t06_4", + "source": "t06_3", + "target": "t06_4" + }, + { + "id": "e_t06_5", + "source": "t06_4", + "target": "t06_5" + }, + { + "id": "e_t06_6", + "source": "t06_5", + "target": "t06_6" + }, + { + "id": "e_t06_7", + "source": "t06_6", + "target": "t06_7" + }, + { + "id": "e_t06_15", + "source": "t06_7", + "target": "t06_15" + }, + { + "id": "e_t06_16", + "source": "t06_15", + "target": "t06_16" + }, + { + "id": "e_t06_24", + "source": "t06_16", + "target": "t06_24" + }, + { + "id": "e_t06_25", + "source": "t06_24", + "target": "t06_25" + }, + { + "id": "e_t06_33", + "source": "t06_25", + "target": "t06_33" + }, + { + "id": "e_t06_34", + "source": "t06_33", + "target": "t06_34" + }, + { + "id": "e_t06_42", + "source": "t06_34", + "target": "t06_42" + }, + { + "id": "e_t06_43", + "source": "t06_42", + "target": "t06_43" + }, + { + "id": "e_t06_51", + "source": "t06_43", + "target": "t06_51" + }, + { + "id": "e_t06_52", + "source": "t06_51", + "target": "t06_52" + }, + { + "id": "e_t06_60", + "source": "t06_52", + "target": "t06_60" + }, + { + "id": "e_t06_61", + "source": "t06_60", + "target": "t06_61" + }, + { + "id": "e_t06_69", + "source": "t06_61", + "target": "t06_69" + }, + { + "id": "e_t06_70", + "source": "t06_69", + "target": "t06_70" + }, + { + "id": "e_t06_71", + "source": "t06_70", + "target": "t06_71" + } + ], + "meta": { + "createdAt": "2026-10-30T00:00:00.000Z", + "updatedAt": "2026-10-30T00:00:00.000Z", + "appVersion": "0.1.0" + } +} diff --git a/resources/test-flows/app-system/test_appsystem_07.json b/resources/test-flows/app-system/test_appsystem_07.json new file mode 100644 index 0000000..9308689 --- /dev/null +++ b/resources/test-flows/app-system/test_appsystem_07.json @@ -0,0 +1,1128 @@ +{ + "schemaVersion": 1, + "id": "test_appsystem_07", + "name": "组件测试 07 · 命令行", + "description": "查看运行日志中的用例结果;有失败时任务最终显示失败,其他用例仍继续。", + "enabled": true, + "trigger": { + "type": "manual", + "label": "手动运行" + }, + "variables": [], + "nodes": [ + { + "id": "t07_1", + "componentId": "Trigger.Manual", + "label": "人工发起", + "position": { + "x": 220, + "y": 80 + }, + "values": { + "entryName": "开始组件测试" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t07_2", + "componentId": "Basic_SetVariable", + "label": "初始化失败计数", + "position": { + "x": 220, + "y": 222 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + } + }, + { + "id": "t07_3", + "componentId": "Basic_SetVariable", + "label": "初始化待确认计数", + "position": { + "x": 220, + "y": 364 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + } + }, + { + "id": "t07_4", + "componentId": "Basic_SetVariable", + "label": "初始化阻塞计数", + "position": { + "x": 220, + "y": 506 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "blocked" + } + }, + { + "id": "t07_5", + "componentId": "logic_control_try_catch", + "label": "07-01 · System_ExecuteCommand", + "position": { + "x": 220, + "y": 648 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t07_6", + "componentId": "System_ExecuteCommand", + "label": "System_ExecuteCommand", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "action": "Write-Output 'RPA-PS-中文-OK'" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_1" + }, + "parentId": "t07_5", + "slot": "try_fn" + }, + { + "id": "t07_7", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${[\"07-01\", \"System_ExecuteCommand\", (actual_1 === \"RPA-PS-中文-OK\") ? \"PASS\" : \"FAIL\", \"{\\\"action\\\":\\\"Write-Output 'RPA-PS-中文-OK'\\\"}\", \"RPA-PS-中文-OK\", actual_1]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t07_5", + "slot": "try_fn" + }, + { + "id": "t07_8", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t07_5", + "slot": "try_fn" + }, + { + "id": "t07_9", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t07_5", + "slot": "try_fn" + }, + { + "id": "t07_10", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${[\"07-01\", \"System_ExecuteCommand\", \"FAIL\", \"{\\\"action\\\":\\\"Write-Output 'RPA-PS-中文-OK'\\\"}\", \"RPA-PS-中文-OK\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t07_5", + "slot": "except_fn" + }, + { + "id": "t07_11", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t07_5", + "slot": "except_fn" + }, + { + "id": "t07_12", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 980 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t07_5", + "slot": "except_fn" + }, + { + "id": "t07_13", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1290 + }, + "values": { + "msg": "用例结果:${json(case_1)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t07_14", + "componentId": "logic_control_try_catch", + "label": "07-02 · System_ExecuteCommandV1", + "position": { + "x": 220, + "y": 1432 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t07_15", + "componentId": "System_ExecuteCommandV1", + "label": "System_ExecuteCommandV1", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "command_type": "1", + "dos_command": "echo RPA-DOS-OK", + "get_ret": "1" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_2" + }, + "parentId": "t07_14", + "slot": "try_fn" + }, + { + "id": "t07_16", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"07-02\", \"System_ExecuteCommandV1\", (actual_2 === \"RPA-DOS-OK\") ? \"PASS\" : \"FAIL\", \"{\\\"command_type\\\":\\\"1\\\",\\\"dos_command\\\":\\\"echo RPA-DOS-OK\\\",\\\"get_ret\\\":\\\"1\\\"}\", \"RPA-DOS-OK\", actual_2]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t07_14", + "slot": "try_fn" + }, + { + "id": "t07_17", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t07_14", + "slot": "try_fn" + }, + { + "id": "t07_18", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t07_14", + "slot": "try_fn" + }, + { + "id": "t07_19", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"07-02\", \"System_ExecuteCommandV1\", \"FAIL\", \"{\\\"command_type\\\":\\\"1\\\",\\\"dos_command\\\":\\\"echo RPA-DOS-OK\\\",\\\"get_ret\\\":\\\"1\\\"}\", \"RPA-DOS-OK\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t07_14", + "slot": "except_fn" + }, + { + "id": "t07_20", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t07_14", + "slot": "except_fn" + }, + { + "id": "t07_21", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t07_14", + "slot": "except_fn" + }, + { + "id": "t07_22", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2074 + }, + "values": { + "msg": "用例结果:${json(case_2)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t07_23", + "componentId": "logic_control_try_catch", + "label": "07-03 · System_ExecuteCommandV1", + "position": { + "x": 220, + "y": 2216 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t07_24", + "componentId": "System_ExecuteCommandV1", + "label": "System_ExecuteCommandV1", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "command_type": "3", + "ps_command": "Write-Output 'RPA-PS-V1-OK'", + "get_ret": "1" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_3" + }, + "parentId": "t07_23", + "slot": "try_fn" + }, + { + "id": "t07_25", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"07-03\", \"System_ExecuteCommandV1\", (actual_3 === \"RPA-PS-V1-OK\") ? \"PASS\" : \"FAIL\", \"{\\\"command_type\\\":\\\"3\\\",\\\"ps_command\\\":\\\"Write-Output 'RPA-PS-V1-OK'\\\",\\\"get_ret\\\":\\\"1\\\"}\", \"RPA-PS-V1-OK\", actual_3]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t07_23", + "slot": "try_fn" + }, + { + "id": "t07_26", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t07_23", + "slot": "try_fn" + }, + { + "id": "t07_27", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t07_23", + "slot": "try_fn" + }, + { + "id": "t07_28", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"07-03\", \"System_ExecuteCommandV1\", \"FAIL\", \"{\\\"command_type\\\":\\\"3\\\",\\\"ps_command\\\":\\\"Write-Output 'RPA-PS-V1-OK'\\\",\\\"get_ret\\\":\\\"1\\\"}\", \"RPA-PS-V1-OK\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t07_23", + "slot": "except_fn" + }, + { + "id": "t07_29", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t07_23", + "slot": "except_fn" + }, + { + "id": "t07_30", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t07_23", + "slot": "except_fn" + }, + { + "id": "t07_31", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2858 + }, + "values": { + "msg": "用例结果:${json(case_3)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t07_32", + "componentId": "System_ExecuteCommand", + "label": "创建仅输出标记的 BAT 夹具", + "position": { + "x": 220, + "y": 3000 + }, + "values": { + "action": "$dir=Join-Path ([IO.Path]::GetTempPath()) ('RPA-AppSystem-Tests\\'+[Guid]::NewGuid().ToString('N')); [IO.Directory]::CreateDirectory($dir) | Out-Null; $bat=Join-Path $dir 'echo-test.bat'; [IO.File]::WriteAllText($bat, '@echo RPA-BAT-OK', [Text.Encoding]::ASCII); $bat" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "batPath" + } + }, + { + "id": "t07_33", + "componentId": "logic_control_try_catch", + "label": "07-04 · System_ExecuteCommandV1", + "position": { + "x": 220, + "y": 3142 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t07_34", + "componentId": "System_ExecuteCommandV1", + "label": "System_ExecuteCommandV1", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "command_type": "2", + "bat_file": "${batPath}", + "get_ret": "1" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_4" + }, + "parentId": "t07_33", + "slot": "try_fn" + }, + { + "id": "t07_35", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${[\"07-04\", \"System_ExecuteCommandV1\", (actual_4 === \"RPA-BAT-OK\") ? \"PASS\" : \"FAIL\", \"{\\\"command_type\\\":\\\"2\\\",\\\"bat_file\\\":\\\"${batPath}\\\",\\\"get_ret\\\":\\\"1\\\"}\", \"RPA-BAT-OK\", actual_4]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t07_33", + "slot": "try_fn" + }, + { + "id": "t07_36", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t07_33", + "slot": "try_fn" + }, + { + "id": "t07_37", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t07_33", + "slot": "try_fn" + }, + { + "id": "t07_38", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${[\"07-04\", \"System_ExecuteCommandV1\", \"FAIL\", \"{\\\"command_type\\\":\\\"2\\\",\\\"bat_file\\\":\\\"${batPath}\\\",\\\"get_ret\\\":\\\"1\\\"}\", \"RPA-BAT-OK\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t07_33", + "slot": "except_fn" + }, + { + "id": "t07_39", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t07_33", + "slot": "except_fn" + }, + { + "id": "t07_40", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t07_33", + "slot": "except_fn" + }, + { + "id": "t07_41", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 3784 + }, + "values": { + "msg": "用例结果:${json(case_4)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t07_42", + "componentId": "logic_control_try_catch", + "label": "07-05 · 非零返回码检查", + "position": { + "x": 220, + "y": 3926 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t07_43", + "componentId": "System_ExecuteCommand", + "label": "非零返回码检查", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "action": "Write-Output 'RPA-ERROR-PROBE'; exit 9" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_5" + }, + "parentId": "t07_42", + "slot": "try_fn" + }, + { + "id": "t07_44", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "value": "${[\"07-05\", \"System_ExecuteCommand\", (false) ? \"PASS\" : \"FAIL\", \"{\\\"action\\\":\\\"Write-Output 'RPA-ERROR-PROBE'; exit 9\\\"}\", \"非零退出码应抛出异常\", actual_5]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t07_42", + "slot": "try_fn" + }, + { + "id": "t07_45", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t07_42", + "slot": "try_fn" + }, + { + "id": "t07_46", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t07_42", + "slot": "try_fn" + }, + { + "id": "t07_47", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "value": "${[\"07-05\", \"System_ExecuteCommand\", \"PASS\", \"{\\\"action\\\":\\\"Write-Output 'RPA-ERROR-PROBE'; exit 9\\\"}\", \"非零退出码应抛出异常\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_5" + }, + "parentId": "t07_42", + "slot": "except_fn" + }, + { + "id": "t07_48", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "value": "${failures + (case_5[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t07_42", + "slot": "except_fn" + }, + { + "id": "t07_49", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "value": "${pending + (case_5[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t07_42", + "slot": "except_fn" + }, + { + "id": "t07_50", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 4568 + }, + "values": { + "msg": "用例结果:${json(case_5)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t07_51", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 4710 + }, + "values": { + "msg": "本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t07_52", + "componentId": "logic_control_if_else", + "label": "汇总判定", + "position": { + "x": 220, + "y": 4852 + }, + "values": { + "condition": "${failures > 0 || pending > 0 || blocked > 0}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t07_53", + "componentId": "ExceptionUtil_Throws", + "label": "如实标记未通过", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "msg": "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t07_52", + "slot": "statement_if" + }, + { + "id": "t07_54", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 3140 + }, + "values": { + "msg": "本组全部通过。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t07_52", + "slot": "statement_else" + } + ], + "edges": [ + { + "id": "e_t07_2", + "source": "t07_1", + "target": "t07_2" + }, + { + "id": "e_t07_3", + "source": "t07_2", + "target": "t07_3" + }, + { + "id": "e_t07_4", + "source": "t07_3", + "target": "t07_4" + }, + { + "id": "e_t07_5", + "source": "t07_4", + "target": "t07_5" + }, + { + "id": "e_t07_13", + "source": "t07_5", + "target": "t07_13" + }, + { + "id": "e_t07_14", + "source": "t07_13", + "target": "t07_14" + }, + { + "id": "e_t07_22", + "source": "t07_14", + "target": "t07_22" + }, + { + "id": "e_t07_23", + "source": "t07_22", + "target": "t07_23" + }, + { + "id": "e_t07_31", + "source": "t07_23", + "target": "t07_31" + }, + { + "id": "e_t07_32", + "source": "t07_31", + "target": "t07_32" + }, + { + "id": "e_t07_33", + "source": "t07_32", + "target": "t07_33" + }, + { + "id": "e_t07_41", + "source": "t07_33", + "target": "t07_41" + }, + { + "id": "e_t07_42", + "source": "t07_41", + "target": "t07_42" + }, + { + "id": "e_t07_50", + "source": "t07_42", + "target": "t07_50" + }, + { + "id": "e_t07_51", + "source": "t07_50", + "target": "t07_51" + }, + { + "id": "e_t07_52", + "source": "t07_51", + "target": "t07_52" + } + ], + "meta": { + "createdAt": "2026-10-30T00:00:00.000Z", + "updatedAt": "2026-10-30T00:00:00.000Z", + "appVersion": "0.1.0" + } +} diff --git a/resources/test-flows/app-system/test_appsystem_08.json b/resources/test-flows/app-system/test_appsystem_08.json new file mode 100644 index 0000000..438cc33 --- /dev/null +++ b/resources/test-flows/app-system/test_appsystem_08.json @@ -0,0 +1,897 @@ +{ + "schemaVersion": 1, + "id": "test_appsystem_08", + "name": "组件测试 08 · Windows 凭据【手动】", + "description": "手动测试:先阅读测试说明。默认不开启执行开关,不能把组件返回成功当作功能通过。", + "enabled": true, + "trigger": { + "type": "manual", + "label": "手动运行" + }, + "variables": [], + "nodes": [ + { + "id": "t08_1", + "componentId": "Trigger.Manual", + "label": "人工发起", + "position": { + "x": 220, + "y": 80 + }, + "values": { + "entryName": "开始组件测试" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t08_2", + "componentId": "Basic_SetVariable", + "label": "初始化失败计数", + "position": { + "x": 220, + "y": 222 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + } + }, + { + "id": "t08_3", + "componentId": "Basic_SetVariable", + "label": "初始化待确认计数", + "position": { + "x": 220, + "y": 364 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + } + }, + { + "id": "t08_4", + "componentId": "Basic_SetVariable", + "label": "初始化阻塞计数", + "position": { + "x": 220, + "y": 506 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "blocked" + } + }, + { + "id": "t08_5", + "componentId": "Basic_SetVariable", + "label": "手动执行开关:确认环境后才可改为 true", + "position": { + "x": 220, + "y": 648 + }, + "values": { + "value": false + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "manualEnabled" + } + }, + { + "id": "t08_6", + "componentId": "Basic_SetVariable", + "label": "只允许使用新的测试凭据目标", + "position": { + "x": 220, + "y": 790 + }, + "values": { + "value": "RPA-AppSystem-Tests-${now()}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "credentialTarget" + } + }, + { + "id": "t08_7", + "componentId": "logic_control_try_catch", + "label": "08-01 · System_AddCredential", + "position": { + "x": 220, + "y": 932 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t08_8", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t08_7", + "slot": "try_fn" + }, + { + "id": "t08_9", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t08_8", + "slot": "statement_else" + }, + { + "id": "t08_10", + "componentId": "System_AddCredential", + "label": "System_AddCredential", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "application": "${credentialTarget}", + "name": "", + "password": "" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_1" + }, + "parentId": "t08_8", + "slot": "statement_if" + }, + { + "id": "t08_11", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"08-01\", \"System_AddCredential\", \"MANUAL\", \"{\\\"application\\\":\\\"${credentialTarget}\\\",\\\"name\\\":\\\"\\\",\\\"password\\\":\\\"\\\"}\", \"安全输入机制准备好后,在专用目标添加测试凭据\", actual_1]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t08_8", + "slot": "statement_if" + }, + { + "id": "t08_12", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t08_8", + "slot": "statement_if" + }, + { + "id": "t08_13", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t08_8", + "slot": "statement_if" + }, + { + "id": "t08_14", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"08-01\", \"System_AddCredential\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{\\\"application\\\":\\\"${credentialTarget}\\\",\\\"name\\\":\\\"\\\",\\\"password\\\":\\\"\\\"}\", \"安全输入机制准备好后,在专用目标添加测试凭据\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t08_7", + "slot": "except_fn" + }, + { + "id": "t08_15", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t08_7", + "slot": "except_fn" + }, + { + "id": "t08_16", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t08_7", + "slot": "except_fn" + }, + { + "id": "t08_17", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1436 + }, + "values": { + "msg": "用例结果:${json(case_1)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t08_18", + "componentId": "logic_control_try_catch", + "label": "08-02 · System_ReadCredential", + "position": { + "x": 220, + "y": 1578 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t08_19", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t08_18", + "slot": "try_fn" + }, + { + "id": "t08_20", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t08_19", + "slot": "statement_else" + }, + { + "id": "t08_21", + "componentId": "System_ReadCredential", + "label": "System_ReadCredential", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "application": "${credentialTarget}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_2" + }, + "parentId": "t08_19", + "slot": "statement_if" + }, + { + "id": "t08_22", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"08-02\", \"System_ReadCredential\", \"MANUAL\", \"{\\\"application\\\":\\\"${credentialTarget}\\\"}\", \"仅验证测试凭据存在,不读取或打印密码\", actual_2]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t08_19", + "slot": "statement_if" + }, + { + "id": "t08_23", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t08_19", + "slot": "statement_if" + }, + { + "id": "t08_24", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t08_19", + "slot": "statement_if" + }, + { + "id": "t08_25", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${[\"08-02\", \"System_ReadCredential\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{\\\"application\\\":\\\"${credentialTarget}\\\"}\", \"仅验证测试凭据存在,不读取或打印密码\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t08_18", + "slot": "except_fn" + }, + { + "id": "t08_26", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t08_18", + "slot": "except_fn" + }, + { + "id": "t08_27", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1700 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t08_18", + "slot": "except_fn" + }, + { + "id": "t08_28", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2082 + }, + "values": { + "msg": "用例结果:${json(case_2)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t08_29", + "componentId": "logic_control_try_catch", + "label": "08-03 · System_DeleteCredential", + "position": { + "x": 220, + "y": 2224 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t08_30", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t08_29", + "slot": "try_fn" + }, + { + "id": "t08_31", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t08_30", + "slot": "statement_else" + }, + { + "id": "t08_32", + "componentId": "System_DeleteCredential", + "label": "System_DeleteCredential", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "application": "${credentialTarget}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_3" + }, + "parentId": "t08_30", + "slot": "statement_if" + }, + { + "id": "t08_33", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${[\"08-03\", \"System_DeleteCredential\", \"MANUAL\", \"{\\\"application\\\":\\\"${credentialTarget}\\\"}\", \"删除刚创建的测试目标,之后人工确认不存在\", actual_3]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t08_30", + "slot": "statement_if" + }, + { + "id": "t08_34", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t08_30", + "slot": "statement_if" + }, + { + "id": "t08_35", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t08_30", + "slot": "statement_if" + }, + { + "id": "t08_36", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${[\"08-03\", \"System_DeleteCredential\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{\\\"application\\\":\\\"${credentialTarget}\\\"}\", \"删除刚创建的测试目标,之后人工确认不存在\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t08_29", + "slot": "except_fn" + }, + { + "id": "t08_37", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t08_29", + "slot": "except_fn" + }, + { + "id": "t08_38", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t08_29", + "slot": "except_fn" + }, + { + "id": "t08_39", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2728 + }, + "values": { + "msg": "用例结果:${json(case_3)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t08_40", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2870 + }, + "values": { + "msg": "本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t08_41", + "componentId": "logic_control_if_else", + "label": "汇总判定", + "position": { + "x": 220, + "y": 3012 + }, + "values": { + "condition": "${failures > 0 || pending > 0 || blocked > 0}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t08_42", + "componentId": "ExceptionUtil_Throws", + "label": "如实标记未通过", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "msg": "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t08_41", + "slot": "statement_if" + }, + { + "id": "t08_43", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2600 + }, + "values": { + "msg": "本组全部通过。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t08_41", + "slot": "statement_else" + } + ], + "edges": [ + { + "id": "e_t08_2", + "source": "t08_1", + "target": "t08_2" + }, + { + "id": "e_t08_3", + "source": "t08_2", + "target": "t08_3" + }, + { + "id": "e_t08_4", + "source": "t08_3", + "target": "t08_4" + }, + { + "id": "e_t08_5", + "source": "t08_4", + "target": "t08_5" + }, + { + "id": "e_t08_6", + "source": "t08_5", + "target": "t08_6" + }, + { + "id": "e_t08_7", + "source": "t08_6", + "target": "t08_7" + }, + { + "id": "e_t08_17", + "source": "t08_7", + "target": "t08_17" + }, + { + "id": "e_t08_18", + "source": "t08_17", + "target": "t08_18" + }, + { + "id": "e_t08_28", + "source": "t08_18", + "target": "t08_28" + }, + { + "id": "e_t08_29", + "source": "t08_28", + "target": "t08_29" + }, + { + "id": "e_t08_39", + "source": "t08_29", + "target": "t08_39" + }, + { + "id": "e_t08_40", + "source": "t08_39", + "target": "t08_40" + }, + { + "id": "e_t08_41", + "source": "t08_40", + "target": "t08_41" + } + ], + "meta": { + "createdAt": "2026-10-30T00:00:00.000Z", + "updatedAt": "2026-10-30T00:00:00.000Z", + "appVersion": "0.1.0" + } +} diff --git a/resources/test-flows/app-system/test_appsystem_09.json b/resources/test-flows/app-system/test_appsystem_09.json new file mode 100644 index 0000000..d2d90c0 --- /dev/null +++ b/resources/test-flows/app-system/test_appsystem_09.json @@ -0,0 +1,870 @@ +{ + "schemaVersion": 1, + "id": "test_appsystem_09", + "name": "组件测试 09 · 输入法【手动】", + "description": "手动测试:先阅读测试说明。默认不开启执行开关,不能把组件返回成功当作功能通过。", + "enabled": true, + "trigger": { + "type": "manual", + "label": "手动运行" + }, + "variables": [], + "nodes": [ + { + "id": "t09_1", + "componentId": "Trigger.Manual", + "label": "人工发起", + "position": { + "x": 220, + "y": 80 + }, + "values": { + "entryName": "开始组件测试" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t09_2", + "componentId": "Basic_SetVariable", + "label": "初始化失败计数", + "position": { + "x": 220, + "y": 222 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + } + }, + { + "id": "t09_3", + "componentId": "Basic_SetVariable", + "label": "初始化待确认计数", + "position": { + "x": 220, + "y": 364 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + } + }, + { + "id": "t09_4", + "componentId": "Basic_SetVariable", + "label": "初始化阻塞计数", + "position": { + "x": 220, + "y": 506 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "blocked" + } + }, + { + "id": "t09_5", + "componentId": "Basic_SetVariable", + "label": "手动执行开关:确认环境后才可改为 true", + "position": { + "x": 220, + "y": 648 + }, + "values": { + "value": false + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "manualEnabled" + } + }, + { + "id": "t09_6", + "componentId": "logic_control_try_catch", + "label": "09-01 · System_GetInputMethodState", + "position": { + "x": 220, + "y": 790 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t09_7", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t09_6", + "slot": "try_fn" + }, + { + "id": "t09_8", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t09_7", + "slot": "statement_else" + }, + { + "id": "t09_9", + "componentId": "System_GetInputMethodState", + "label": "System_GetInputMethodState", + "position": { + "x": 220, + "y": 1160 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "originalIme" + }, + "parentId": "t09_7", + "slot": "statement_if" + }, + { + "id": "t09_10", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${[\"09-01\", \"System_GetInputMethodState\", \"MANUAL\", \"{}\", \"读取前台窗口的真实输入法状态,人工对照任务栏\", originalIme]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t09_7", + "slot": "statement_if" + }, + { + "id": "t09_11", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t09_7", + "slot": "statement_if" + }, + { + "id": "t09_12", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t09_7", + "slot": "statement_if" + }, + { + "id": "t09_13", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${[\"09-01\", \"System_GetInputMethodState\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{}\", \"读取前台窗口的真实输入法状态,人工对照任务栏\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t09_6", + "slot": "except_fn" + }, + { + "id": "t09_14", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t09_6", + "slot": "except_fn" + }, + { + "id": "t09_15", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t09_6", + "slot": "except_fn" + }, + { + "id": "t09_16", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1294 + }, + "values": { + "msg": "用例结果:${json(case_1)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t09_17", + "componentId": "logic_control_try_catch", + "label": "09-02 · System_SetInputMethodState", + "position": { + "x": 220, + "y": 1436 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t09_18", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t09_17", + "slot": "try_fn" + }, + { + "id": "t09_19", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t09_18", + "slot": "statement_else" + }, + { + "id": "t09_20", + "componentId": "System_SetInputMethodState", + "label": "System_SetInputMethodState", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "mode": "en-US" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_2" + }, + "parentId": "t09_18", + "slot": "statement_if" + }, + { + "id": "t09_21", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${[\"09-02\", \"System_SetInputMethodState\", \"MANUAL\", \"{\\\"mode\\\":\\\"en-US\\\"}\", \"前台编辑器应切换到英文模式;仅子进程返回 set:true 不能算通过\", actual_2]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t09_18", + "slot": "statement_if" + }, + { + "id": "t09_22", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t09_18", + "slot": "statement_if" + }, + { + "id": "t09_23", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t09_18", + "slot": "statement_if" + }, + { + "id": "t09_24", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${[\"09-02\", \"System_SetInputMethodState\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{\\\"mode\\\":\\\"en-US\\\"}\", \"前台编辑器应切换到英文模式;仅子进程返回 set:true 不能算通过\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t09_17", + "slot": "except_fn" + }, + { + "id": "t09_25", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t09_17", + "slot": "except_fn" + }, + { + "id": "t09_26", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t09_17", + "slot": "except_fn" + }, + { + "id": "t09_27", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1940 + }, + "values": { + "msg": "用例结果:${json(case_2)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t09_28", + "componentId": "logic_control_try_catch", + "label": "09-03 · System_SetInputMethodState", + "position": { + "x": 220, + "y": 2082 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t09_29", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t09_28", + "slot": "try_fn" + }, + { + "id": "t09_30", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t09_29", + "slot": "statement_else" + }, + { + "id": "t09_31", + "componentId": "System_SetInputMethodState", + "label": "System_SetInputMethodState", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "mode": "${originalIme.culture}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_3" + }, + "parentId": "t09_29", + "slot": "statement_if" + }, + { + "id": "t09_32", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${[\"09-03\", \"System_SetInputMethodState\", \"MANUAL\", \"{\\\"mode\\\":\\\"${originalIme.culture}\\\"}\", \"恢复原输入法;人工确认前台窗口的实际状态\", actual_3]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t09_29", + "slot": "statement_if" + }, + { + "id": "t09_33", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t09_29", + "slot": "statement_if" + }, + { + "id": "t09_34", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t09_29", + "slot": "statement_if" + }, + { + "id": "t09_35", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${[\"09-03\", \"System_SetInputMethodState\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{\\\"mode\\\":\\\"${originalIme.culture}\\\"}\", \"恢复原输入法;人工确认前台窗口的实际状态\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t09_28", + "slot": "except_fn" + }, + { + "id": "t09_36", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t09_28", + "slot": "except_fn" + }, + { + "id": "t09_37", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t09_28", + "slot": "except_fn" + }, + { + "id": "t09_38", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2586 + }, + "values": { + "msg": "用例结果:${json(case_3)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t09_39", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2728 + }, + "values": { + "msg": "本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t09_40", + "componentId": "logic_control_if_else", + "label": "汇总判定", + "position": { + "x": 220, + "y": 2870 + }, + "values": { + "condition": "${failures > 0 || pending > 0 || blocked > 0}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t09_41", + "componentId": "ExceptionUtil_Throws", + "label": "如实标记未通过", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "msg": "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t09_40", + "slot": "statement_if" + }, + { + "id": "t09_42", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "msg": "本组全部通过。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t09_40", + "slot": "statement_else" + } + ], + "edges": [ + { + "id": "e_t09_2", + "source": "t09_1", + "target": "t09_2" + }, + { + "id": "e_t09_3", + "source": "t09_2", + "target": "t09_3" + }, + { + "id": "e_t09_4", + "source": "t09_3", + "target": "t09_4" + }, + { + "id": "e_t09_5", + "source": "t09_4", + "target": "t09_5" + }, + { + "id": "e_t09_6", + "source": "t09_5", + "target": "t09_6" + }, + { + "id": "e_t09_16", + "source": "t09_6", + "target": "t09_16" + }, + { + "id": "e_t09_17", + "source": "t09_16", + "target": "t09_17" + }, + { + "id": "e_t09_27", + "source": "t09_17", + "target": "t09_27" + }, + { + "id": "e_t09_28", + "source": "t09_27", + "target": "t09_28" + }, + { + "id": "e_t09_38", + "source": "t09_28", + "target": "t09_38" + }, + { + "id": "e_t09_39", + "source": "t09_38", + "target": "t09_39" + }, + { + "id": "e_t09_40", + "source": "t09_39", + "target": "t09_40" + } + ], + "meta": { + "createdAt": "2026-10-30T00:00:00.000Z", + "updatedAt": "2026-10-30T00:00:00.000Z", + "appVersion": "0.1.0" + } +} diff --git a/resources/test-flows/app-system/test_appsystem_10.json b/resources/test-flows/app-system/test_appsystem_10.json new file mode 100644 index 0000000..e57dba7 --- /dev/null +++ b/resources/test-flows/app-system/test_appsystem_10.json @@ -0,0 +1,455 @@ +{ + "schemaVersion": 1, + "id": "test_appsystem_10", + "name": "组件测试 10 · 音频【手动】", + "description": "手动测试:先阅读测试说明。默认不开启执行开关,不能把组件返回成功当作功能通过。", + "enabled": true, + "trigger": { + "type": "manual", + "label": "手动运行" + }, + "variables": [], + "nodes": [ + { + "id": "t10_1", + "componentId": "Trigger.Manual", + "label": "人工发起", + "position": { + "x": 220, + "y": 80 + }, + "values": { + "entryName": "开始组件测试" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t10_2", + "componentId": "Basic_SetVariable", + "label": "初始化失败计数", + "position": { + "x": 220, + "y": 222 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + } + }, + { + "id": "t10_3", + "componentId": "Basic_SetVariable", + "label": "初始化待确认计数", + "position": { + "x": 220, + "y": 364 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + } + }, + { + "id": "t10_4", + "componentId": "Basic_SetVariable", + "label": "初始化阻塞计数", + "position": { + "x": 220, + "y": 506 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "blocked" + } + }, + { + "id": "t10_5", + "componentId": "Basic_SetVariable", + "label": "手动执行开关:确认环境后才可改为 true", + "position": { + "x": 220, + "y": 648 + }, + "values": { + "value": false + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "manualEnabled" + } + }, + { + "id": "t10_6", + "componentId": "System_ExecuteCommand", + "label": "准备 0.3 秒低音量测试音", + "position": { + "x": 220, + "y": 790 + }, + "values": { + "action": "$dir=Join-Path ([IO.Path]::GetTempPath()) ('RPA-AppSystem-Tests\\'+[Guid]::NewGuid().ToString('N')); [IO.Directory]::CreateDirectory($dir) | Out-Null; $wav=Join-Path $dir 'tone.wav'; [IO.File]::WriteAllBytes($wav,[Convert]::FromBase64String('UklGRuQSAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YcASAAAAAAEAAwAFAAgACgALAAoABgABAPr/8v/r/+X/4//k/+n/8v/+/wsAGQAkAC0AMAAtACUAFwAFAPH/3v/N/8L/vf/B/8z/3//3/xEAKwBBAFAAVgBSAEQALAAPAO7/zv+z/6D/l/+c/6z/yP/r/xIAOABZAHEAewB3AGUARgAdAO//wv+b/3//cv91/4r/rf/b/w4AQgBvAJAAoACeAIkAYgAvAPX/u/+I/2L/Tv9P/2X/jv/G/wYARwCAAKwAxADFAK4AggBGAAAAuf94/0f/K/8n/z7/bP+t//n/RwCOAMUA5gDsANYApgBhAA8Au/9t/y//Cv8B/xb/SP+Q/+f/QgCXANsABgETAf4AzACAACQAwv9m/xv/6/7b/u3+If9w/9H/OQCcAO0AJAE4ASgB9ACiADwAzv9k/wv/z/62/sT++P5M/7b/KwCcAPsAPgFcAVEBHgHIAFkA3v9m///+tf6S/pr+zf4k/5f/GACXAAUBVgF/AXoBSQHwAHoA9P9u//j+oP5x/nH+of77/nT/AACNAAsBagGfAaMBdgEbAZ4ADgB6//X+jv5S/kn+dP7O/k7/5P9+AAsBegG8AcoBogFIAccALACL//b+gP42/iL+R/6g/iT/w/9rAAcBhQHWAfABzwF3AfIATwCh//3+d/4e/v79Gv5x/vf+nv9SAP0AjAHtARQC/AGoASABdgC8/wn/cv4J/tv97v1A/sj+df81AO8AjwEAAjUCKALZAVEBoQDc/xr/cv74/bz9w/0P/pb+Sf8TANwAjAEOAlMCUgIKAoQBzwAAADD/d/7s/Z/9mv3d/WL+Gf/s/8MAhAEZAm4CegI7ArgBAAEpAEv/gf7k/Yb9cv2s/S3+5v7B/6YAdwEeAoUCoAJsAu4BNAFVAGv/kf7h/XH9Tv18/ff9sf6T/4MAZQEeApgCxAKcAiQCawGGAJD/pv7j/WD9LP1N/cH9ef5g/1wATgEaAqcC5ALKAlsCpAG6ALn/wP7r/VT9Df0g/Yr9P/4q/zAAMQEQArACAAP2ApEC3gHyAOf/3/73/U398/z1/FT9BP7y/gAAEAEAArUCGQMfA8cCGQIsARoAA/8J/kr93PzN/B/9yf22/sz/6QDrAbUCLQNGA/sCVQJpAVAALf8h/k39yvyo/Oz8jP14/pT/vQDRAa8CPQNpAy0DkgKnAYoAW/8+/lb9vfyH/Lr8UP05/lj/jACxAaQCRwOIA14DzQLnAccAjv9h/mT9tfxq/Iv8Ff34/Rr/VwCMAZMCTQOjA4wDCAMpAgcBxf+I/nj9s/xR/F/82/y2/dj+HgBiAXwCTQO6A7YDQgNrAkkBAAC2/pH9tfw9/Db8ovx0/ZX+4f8yAWACRwPMA90DegOtAo4BPwDo/rD9vvwu/BH8a/wy/U/+oP/+AD4CPAPYAwAErwPuAtQBgQAe/9X9zPwk/PD7N/zx/Aj+XP/EABcCKgPfAx8E4gMvAxsCxwBa///94Pwf/NP7Bvyx/MH9Ff+HAOoBEwPhAzkEEQRvA2MCDwGZ/y/++/wh/Lz72Pty/Hn9zP5FALcB9gLcA04EPQSsA6sCWQHd/2T+G/0o/Kr7r/s2/DH9gf4AAIAB0wLSA10EZQTnA/MCpQEkAJ7+Qf02/J37ifv8++n8Nf63/0MBqgLBA2cEiAQfBDoD8gFuAN3+bP1J/Jb7afvG+6P85/1s/wIBfAKqA2sEpgRUBH8DQAK7ACD/nv1j/JX7TfuT+1/8mv0e/70ARwKOA2kEvwSFBMIDjQIKAWf/1f2D/Jv7N/tk+x38TP3N/nQADgJrA2AE0gSyBAME2wJbAbL/Ef6p/Kb7J/s6+937//x8/igA0AFCA1IE3wTaBEEEJwOuAQAAUv7V/Lj7HPsU+6H7s/wp/tj/jAETAz0E5wT9BHwEcwMBAlEAl/4H/dD7GPv0+mj7aPzW/YX/RAHeAiEE6AQaBbIEvANUAqUA4f4//e/7GvvZ+jT7IPyC/TH/+ACjAv8D4wQyBeUEAwSnAvoAL/98/RT8IvvE+gT72/sw/dv+qQBkAtcD1wREBRIFRwT5AlEBgP++/T/8Mvu1+tn6mfve/IP+VgAfAqkDxARQBTsFhwRKA6kB1f8F/nH8R/ut+rP6WvuO/Cv+AADWAXUDqwRVBV4FxASZAwECLABR/qj8ZPur+pP6IPtA/NP9qP+IAToDjARUBXsF/ATmA1kChQCg/uX8hvuv+nn66vr1+3v9Tv82AfsCZgRMBZIFLwUvBLEC4AD0/if9sPu7+mX6ufqt+yT98v7hALYCOQQ9BaMFXQV2BAcDPAFL/2793/vN+lj6jvpo+8/8lv6JAGwCBwQnBa0FhgW4BFsDmAGk/7r9Ffzm+lH6aPoo+3v8Ov4uAB4CzgMLBbAFqQX2BK0D9AEAAAv+UfwG+1H6SPrs+iv83v3R/8sBjwPoBK0FxQUwBfwDUAJeAF/+kvws+1j6L/q2+t37gv1z/3UBSwO+BKIF3AVkBUgEqwK9ALf+2fxZ+2b6HPqE+pP7KP0U/xsBAgOOBJEF6wWSBZAEBAMcARL/JP2M+3r6EPpZ+k370Py0/r8AtAJYBHkF9AW7BdQEWwN8AXD/dP3F+5b6Cvoz+gz7evxU/mAAYgIcBFoF9gXdBRMFrwPcAdD/yf0F/Ln6DPoU+s/6KPz1/QAADALaAzQF8AX5BU0FAQQ6AjEAIf5J/OL6Ffr7+Zj62PuX/Z7/sgGSAwcF5AUOBoEFTgSYApMAfP6T/BH7Jfrq+Wf6jfs6/Tz/VQFGA9QE0AUdBrAFlwTzAvUA2v7i/Ej7PPrf+Tv6Rvvh/Nr+9gD1ApsEtgUkBtgF2wRLA1cBO/81/YT7Wvrb+Rb6BPuJ/Hj+lACgAlwElQUkBvoFGwWhA7kBnf+M/cX7f/re+fj5yPo2/Bf+MgBHAhgEbQUdBhUGVQXzAxkCAADn/Q38qvrp+eD5kfrm+7f9zv/rAc4DPgUPBikGiQVBBHgCZABE/ln83Pr6+c/5X/qa+1r9av+MAX8DCQX6BTcGtwWKBNQCyACk/qn8FPsT+sb5NfpT+//8Bv8rAS0DzgTeBT0G3gXOBC0DKwEG//78Uvsz+sP5EPoR+6j8o/7IANYCjQS7BTsG/wUNBYMDjgFq/1f9lftZ+sj58/nV+lT8Qv5kAHsCRwSRBTMGGQZHBdUD7gHO/7P93vuG+tT53Pmf+gT84v0AAB4C/ANhBSQGLAZ6BSIETQIyABL+K/y5+uf5zflv+rn7hf2c/74BrAMrBQ0GOAanBWsEqQKWAHL+ffzz+gH6xflF+nP7Kv04/10BWAPvBPAFPQbNBa4EAgP6ANX+0/wy+yL6w/ki+jL70/zV/voAAQOtBMsFOgbtBewEVwNcATj/LP12+0n6yfkG+vf6gfx0/pYApgJmBKEFMQYGBiQFpwO8AZz/iP2/+3f61/nx+cL6MvwV/jIASQIaBG8FIAYXBlYF8wMZAgAA5/0N/Kv66/nj+ZP66Pu5/c7/6QHKAzgFCAYiBoEFOwR0AmMAR/5f/OX6Bvrc+Wv6pPtg/Wz/iAF3A/wE6gUlBqYFfATLAsUAqf61/CX7KPrc+Ur6ZfsL/Qr/JgEfA7oExQUhBsQFuAQeAyYBC/8N/Wn7UPrj+TD6LPu6/Kv+xADGAnMEmQUWBtsF7wRtA4QBbf9o/bL7f/ry+Rz6+fpu/E7+YgBpAigEaAUFBusFHgW3A98Bz//G/f/7s/oH+hD6zPom/PT9AAALAtgDMQXsBfQFRwX7AzcCMAAk/lH87foj+gr6pvrk+579oP+sAYYD9ATNBfYFagU7BIwCkACE/qX8LPtF+gz6h/qo+0z9Qf9MATADswSnBfAFhgV0BNwC7gDk/vz8cPtu+hX6b/py+/785f7sANgCbQR8BeQFmgWnBCcDSQFD/1X9uPuc+iT6XvpC+7X8i/6NAH4CIwRKBdEFqAXUBG4DoQGi/7D9BPzQ+jv6U/oY+3H8Nf4vACIC1QMUBbgFrwX6BK8D9QEAAAz+U/wK+1f6UPr1+jL84v3S/8YBhQPYBJgFrwUaBesDRgJcAGj+pfxI+3r6U/rZ+vn7lP13/2oBMQOYBHIFqAUzBSEEkgK1AMT++fyK+6P6XfrD+sf7Sv0f/w4B3AJTBEcFmwVFBVAE2QIMASD/T/3R+9H6bvq0+pr7Bf3K/rIAhQILBBYFhwVRBXoEGwNgAXv/p/0a/AT7hfqs+nT7xvx4/lgALQLAA+AEbQVVBZwEWAOvAdT///1n/Dz7ovqr+lX7i/wq/gAA1QFyA6YETQVTBbkEjwP7ASsAV/62/Hn7xfqw+jz7V/zh/ar/fQEiA2cEJwVLBc4EwQNCAoAAr/4H/bn77vq8+in7Kfyc/Vf/JQHQAiUE/AQ8Bd4E7AOEAtEABv9Z/f37G/vO+h37Afxd/Qj/zwB+AuADzAQnBeYEEQTBAh8BW/+s/UT8Tvvm+hj73/si/bz+ewAqApgDmAQMBegEMAT5AmkBr////Y38hPsD+xn7w/vt/HT+KADXAU0DXwTsBOQESAQrA64BAABS/tn8v/sm+yH7rvu+/DD+2P+EAQEDIwTGBNkEWgRXA+8BTgCl/iX9/ftO+y77oPuV/PL9jP8zAbQC4wOcBMkEZQR9AysCmQD2/nP9Pvx7+0H7l/ty/Ln9Q//iAGYCoQNtBLMEawSdA2IC4ABF/8D9gfys+1r7lftW/IT9/v6UABkCXQM6BJcEagS3A5QCIwGS/w7+xvzh+3j7mfs//Fb9vf5JAMsBFwMEBHcEYwTKA78CYgHc/1v+Df0Z/Jv7o/su/C39gP4AAH8BzwLKA1EEVgTYA+UCnAEjAKf+Vf1U/MP7svsk/Ar9Sf67/zQBhwKOAygERATfAwUD0QFnAPH+nf2R/O/7x/sf/O38Fv55/+sAPwJPA/oDLQThAyADAQKmADn/5f3R/B784fsh/Nb86f08/6QA+AEPA8kDEATcAzQDKwLiAH//LP4S/VH8APwo/MT8wv0C/2AAsQHOApUD7wPSA0IDUAIYAcH/cv5T/Yb8I/w0/Ln8oP3O/h8AawGMAl4DygPDA0sDbwJKAQAAt/6V/b78SvxG/LP8hP2e/uL/KAFKAiUDoQOvA00DiAJ4ATsA+f7X/fj8dPxd/LP8bf10/qn/5gAIAusCdQOWA0sDnAKfAXIAOf8Z/jP9ovx4/Ln8XP1P/nT/qADHAbACRgN5A0MDqgLCAaUAdv9Z/m790/yX/MP8Uf0v/kP/bACIAXQCFANYAzYDswLfAdMAsP+X/qv9Bf26/NP8S/0V/hf/NABKATcC4QIzAyQDtgL3Af0A5v/U/uf9Of3h/Of8S/0A/vD+AAAOAfwBrAILAw0DswIJAiEBGQAO/yL+b/0K/QD9UP3w/c/+0P/WAMEBdgLgAvMCrAIVAkABRwBG/1z+pf02/Rz9Wf3m/bL+pP+gAIcBPwKzAtQCoAIdAloBcAB6/5X+3P1k/Tz9aP3i/Zv+ff9tAE8BCQKEArICjwIfAm8BlQCr/8z+Ev6U/WD9e/3i/Yn+Wv8/ABoB0wFUAo4CegIcAn8BtQDX/wD/SP7F/Yb9kv3n/Xz+Pf8UAOcAngEjAmYCYQIUAokB0AAAADH/fP72/a79rf3y/XT+JP/t/7cAagHxAT0CRAIIAo4B5gAkAF//r/4n/tj9y/0A/nH+Ef/L/4sAOAHAARICJQL3AY4B9wBEAIr/4P5Y/gT+7P0T/nT+A/+u/2IACQGPAeYBAgLiAYkBAwFfALH/Dv+J/jH+EP4q/nv++f6V/z0A3ABgAbkB3gHKAYABCgF1ANT/Of+4/l7+Nv5E/ob+9f6C/xwAsgAyAYwBtwGuAXIBCwGGAPL/Yv/l/or+Xf5h/pb+9f5z/wAAjAAFAV8BjwGPAWABCAGSAAwAhv8Q/7f+hv6B/qr++/5p/+j/aQDcADMBZgFuAUsBAQGaACIAp/84/+L+r/6k/sL+Bf9k/9X/SgC0AAgBPAFKATEB9QCcADIAxP9e/wz/2P7I/tz+E/9k/8f/LwCQAN8AEwElARUB5QCaAD4A3P+A/zT/Av/t/vr+Jf9p/77/GQBwALgA6gD/APYA0QCTAEUA8f+f/1r/Kv8U/xr/O/9y/7n/BwBTAJQAwgDZANUAuQCIAEcAAAC6/37/Uv87/zz/VP+A/7n/+v86AHIAmwCxALIAngB4AEUACwDR/57/d/9i/2D/cP+R/77/8v8lAFMAdgCLAI4AgQBlAD4AEQDj/7r/m/+J/4X/j/+n/8j/7v8VADgAVABkAGkAYABNADIAEgDx/9T/vP+u/6r/sP+//9X/7/8JACEANAA/AEMAPgAzACIADwD7/+n/2//T/9D/0//c/+f/9f8CAA4AFwAcAB0AGwAVAA4ABgD///r/9v/1//b/+P/7//3///8=')); $wav" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "audioPath" + } + }, + { + "id": "t10_7", + "componentId": "logic_control_try_catch", + "label": "10-01 · System_PlaySound", + "position": { + "x": 220, + "y": 932 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t10_8", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t10_7", + "slot": "try_fn" + }, + { + "id": "t10_9", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t10_8", + "slot": "statement_else" + }, + { + "id": "t10_10", + "componentId": "System_PlaySound", + "label": "System_PlaySound", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "audio": "${audioPath}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_1" + }, + "parentId": "t10_8", + "slot": "statement_if" + }, + { + "id": "t10_11", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"10-01\", \"System_PlaySound\", \"MANUAL\", \"{\\\"audio\\\":\\\"${audioPath}\\\"}\", \"听到一次短提示音;没有声音不能算通过\", actual_1]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t10_8", + "slot": "statement_if" + }, + { + "id": "t10_12", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t10_8", + "slot": "statement_if" + }, + { + "id": "t10_13", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t10_8", + "slot": "statement_if" + }, + { + "id": "t10_14", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${[\"10-01\", \"System_PlaySound\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{\\\"audio\\\":\\\"${audioPath}\\\"}\", \"听到一次短提示音;没有声音不能算通过\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t10_7", + "slot": "except_fn" + }, + { + "id": "t10_15", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t10_7", + "slot": "except_fn" + }, + { + "id": "t10_16", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1340 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t10_7", + "slot": "except_fn" + }, + { + "id": "t10_17", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1436 + }, + "values": { + "msg": "用例结果:${json(case_1)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t10_18", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1578 + }, + "values": { + "msg": "本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t10_19", + "componentId": "logic_control_if_else", + "label": "汇总判定", + "position": { + "x": 220, + "y": 1720 + }, + "values": { + "condition": "${failures > 0 || pending > 0 || blocked > 0}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t10_20", + "componentId": "ExceptionUtil_Throws", + "label": "如实标记未通过", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "msg": "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t10_19", + "slot": "statement_if" + }, + { + "id": "t10_21", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "msg": "本组全部通过。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t10_19", + "slot": "statement_else" + } + ], + "edges": [ + { + "id": "e_t10_2", + "source": "t10_1", + "target": "t10_2" + }, + { + "id": "e_t10_3", + "source": "t10_2", + "target": "t10_3" + }, + { + "id": "e_t10_4", + "source": "t10_3", + "target": "t10_4" + }, + { + "id": "e_t10_5", + "source": "t10_4", + "target": "t10_5" + }, + { + "id": "e_t10_6", + "source": "t10_5", + "target": "t10_6" + }, + { + "id": "e_t10_7", + "source": "t10_6", + "target": "t10_7" + }, + { + "id": "e_t10_17", + "source": "t10_7", + "target": "t10_17" + }, + { + "id": "e_t10_18", + "source": "t10_17", + "target": "t10_18" + }, + { + "id": "e_t10_19", + "source": "t10_18", + "target": "t10_19" + } + ], + "meta": { + "createdAt": "2026-10-30T00:00:00.000Z", + "updatedAt": "2026-10-30T00:00:00.000Z", + "appVersion": "0.1.0" + } +} diff --git a/resources/test-flows/app-system/test_appsystem_11.json b/resources/test-flows/app-system/test_appsystem_11.json new file mode 100644 index 0000000..947a30f --- /dev/null +++ b/resources/test-flows/app-system/test_appsystem_11.json @@ -0,0 +1,1087 @@ +{ + "schemaVersion": 1, + "id": "test_appsystem_11", + "name": "组件测试 11 · 屏保【手动】", + "description": "手动测试:先阅读测试说明。默认不开启执行开关,不能把组件返回成功当作功能通过。", + "enabled": true, + "trigger": { + "type": "manual", + "label": "手动运行" + }, + "variables": [], + "nodes": [ + { + "id": "t11_1", + "componentId": "Trigger.Manual", + "label": "人工发起", + "position": { + "x": 220, + "y": 80 + }, + "values": { + "entryName": "开始组件测试" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t11_2", + "componentId": "Basic_SetVariable", + "label": "初始化失败计数", + "position": { + "x": 220, + "y": 222 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + } + }, + { + "id": "t11_3", + "componentId": "Basic_SetVariable", + "label": "初始化待确认计数", + "position": { + "x": 220, + "y": 364 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + } + }, + { + "id": "t11_4", + "componentId": "Basic_SetVariable", + "label": "初始化阻塞计数", + "position": { + "x": 220, + "y": 506 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "blocked" + } + }, + { + "id": "t11_5", + "componentId": "Basic_SetVariable", + "label": "手动执行开关:确认环境后才可改为 true", + "position": { + "x": 220, + "y": 648 + }, + "values": { + "value": false + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "manualEnabled" + } + }, + { + "id": "t11_6", + "componentId": "logic_control_try_catch", + "label": "11-01 · System_ScreenSaverShow", + "position": { + "x": 220, + "y": 790 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t11_7", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t11_6", + "slot": "try_fn" + }, + { + "id": "t11_8", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t11_7", + "slot": "statement_else" + }, + { + "id": "t11_9", + "componentId": "System_ScreenSaverShow", + "label": "System_ScreenSaverShow", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "text": "RPA 测试", + "status": "1" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_1" + }, + "parentId": "t11_7", + "slot": "statement_if" + }, + { + "id": "t11_10", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${[\"11-01\", \"System_ScreenSaverShow\", \"MANUAL\", \"{\\\"text\\\":\\\"RPA 测试\\\",\\\"status\\\":\\\"1\\\"}\", \"屏幕实际进入屏保;无配置时记录阻塞\", actual_1]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t11_7", + "slot": "statement_if" + }, + { + "id": "t11_11", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t11_7", + "slot": "statement_if" + }, + { + "id": "t11_12", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t11_7", + "slot": "statement_if" + }, + { + "id": "t11_13", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${[\"11-01\", \"System_ScreenSaverShow\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{\\\"text\\\":\\\"RPA 测试\\\",\\\"status\\\":\\\"1\\\"}\", \"屏幕实际进入屏保;无配置时记录阻塞\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t11_6", + "slot": "except_fn" + }, + { + "id": "t11_14", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t11_6", + "slot": "except_fn" + }, + { + "id": "t11_15", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t11_6", + "slot": "except_fn" + }, + { + "id": "t11_16", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1294 + }, + "values": { + "msg": "用例结果:${json(case_1)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t11_17", + "componentId": "logic_control_try_catch", + "label": "11-02 · System_ScreenSaverStop", + "position": { + "x": 220, + "y": 1436 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t11_18", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t11_17", + "slot": "try_fn" + }, + { + "id": "t11_19", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t11_18", + "slot": "statement_else" + }, + { + "id": "t11_20", + "componentId": "System_ScreenSaverStop", + "label": "System_ScreenSaverStop", + "position": { + "x": 220, + "y": 1520 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_2" + }, + "parentId": "t11_18", + "slot": "statement_if" + }, + { + "id": "t11_21", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${[\"11-02\", \"System_ScreenSaverStop\", \"MANUAL\", \"{}\", \"屏保实际关闭,可正常操作\", actual_2]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t11_18", + "slot": "statement_if" + }, + { + "id": "t11_22", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t11_18", + "slot": "statement_if" + }, + { + "id": "t11_23", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t11_18", + "slot": "statement_if" + }, + { + "id": "t11_24", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${[\"11-02\", \"System_ScreenSaverStop\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{}\", \"屏保实际关闭,可正常操作\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t11_17", + "slot": "except_fn" + }, + { + "id": "t11_25", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t11_17", + "slot": "except_fn" + }, + { + "id": "t11_26", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t11_17", + "slot": "except_fn" + }, + { + "id": "t11_27", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1940 + }, + "values": { + "msg": "用例结果:${json(case_2)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t11_28", + "componentId": "logic_control_try_catch", + "label": "11-03 · System_ScreenSaverShowV1", + "position": { + "x": 220, + "y": 2082 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t11_29", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t11_28", + "slot": "try_fn" + }, + { + "id": "t11_30", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t11_29", + "slot": "statement_else" + }, + { + "id": "t11_31", + "componentId": "System_ScreenSaverShowV1", + "label": "System_ScreenSaverShowV1", + "position": { + "x": 220, + "y": 1880 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_3" + }, + "parentId": "t11_29", + "slot": "statement_if" + }, + { + "id": "t11_32", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${[\"11-03\", \"System_ScreenSaverShowV1\", \"MANUAL\", \"{}\", \"开启 Windows 已配置的屏保,不要求输入密码;人工确认屏幕实际变化\", actual_3]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t11_29", + "slot": "statement_if" + }, + { + "id": "t11_33", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t11_29", + "slot": "statement_if" + }, + { + "id": "t11_34", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t11_29", + "slot": "statement_if" + }, + { + "id": "t11_35", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${[\"11-03\", \"System_ScreenSaverShowV1\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{}\", \"开启 Windows 已配置的屏保,不要求输入密码;人工确认屏幕实际变化\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_3" + }, + "parentId": "t11_28", + "slot": "except_fn" + }, + { + "id": "t11_36", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${failures + (case_3[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t11_28", + "slot": "except_fn" + }, + { + "id": "t11_37", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${pending + (case_3[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t11_28", + "slot": "except_fn" + }, + { + "id": "t11_38", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2586 + }, + "values": { + "msg": "用例结果:${json(case_3)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t11_39", + "componentId": "logic_control_try_catch", + "label": "11-04 · System_ScreenSaverStop", + "position": { + "x": 220, + "y": 2728 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t11_40", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t11_39", + "slot": "try_fn" + }, + { + "id": "t11_41", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t11_40", + "slot": "statement_else" + }, + { + "id": "t11_42", + "componentId": "System_ScreenSaverStop", + "label": "System_ScreenSaverStop", + "position": { + "x": 220, + "y": 2240 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_4" + }, + "parentId": "t11_40", + "slot": "statement_if" + }, + { + "id": "t11_43", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${[\"11-04\", \"System_ScreenSaverStop\", \"MANUAL\", \"{}\", \"第二种屏保实际关闭\", actual_4]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t11_40", + "slot": "statement_if" + }, + { + "id": "t11_44", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t11_40", + "slot": "statement_if" + }, + { + "id": "t11_45", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t11_40", + "slot": "statement_if" + }, + { + "id": "t11_46", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${[\"11-04\", \"System_ScreenSaverStop\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{}\", \"第二种屏保实际关闭\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_4" + }, + "parentId": "t11_39", + "slot": "except_fn" + }, + { + "id": "t11_47", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${failures + (case_4[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t11_39", + "slot": "except_fn" + }, + { + "id": "t11_48", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 2240 + }, + "values": { + "value": "${pending + (case_4[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t11_39", + "slot": "except_fn" + }, + { + "id": "t11_49", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 3232 + }, + "values": { + "msg": "用例结果:${json(case_4)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t11_50", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 3374 + }, + "values": { + "msg": "本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t11_51", + "componentId": "logic_control_if_else", + "label": "汇总判定", + "position": { + "x": 220, + "y": 3516 + }, + "values": { + "condition": "${failures > 0 || pending > 0 || blocked > 0}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t11_52", + "componentId": "ExceptionUtil_Throws", + "label": "如实标记未通过", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "msg": "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t11_51", + "slot": "statement_if" + }, + { + "id": "t11_53", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2780 + }, + "values": { + "msg": "本组全部通过。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t11_51", + "slot": "statement_else" + } + ], + "edges": [ + { + "id": "e_t11_2", + "source": "t11_1", + "target": "t11_2" + }, + { + "id": "e_t11_3", + "source": "t11_2", + "target": "t11_3" + }, + { + "id": "e_t11_4", + "source": "t11_3", + "target": "t11_4" + }, + { + "id": "e_t11_5", + "source": "t11_4", + "target": "t11_5" + }, + { + "id": "e_t11_6", + "source": "t11_5", + "target": "t11_6" + }, + { + "id": "e_t11_16", + "source": "t11_6", + "target": "t11_16" + }, + { + "id": "e_t11_17", + "source": "t11_16", + "target": "t11_17" + }, + { + "id": "e_t11_27", + "source": "t11_17", + "target": "t11_27" + }, + { + "id": "e_t11_28", + "source": "t11_27", + "target": "t11_28" + }, + { + "id": "e_t11_38", + "source": "t11_28", + "target": "t11_38" + }, + { + "id": "e_t11_39", + "source": "t11_38", + "target": "t11_39" + }, + { + "id": "e_t11_49", + "source": "t11_39", + "target": "t11_49" + }, + { + "id": "e_t11_50", + "source": "t11_49", + "target": "t11_50" + }, + { + "id": "e_t11_51", + "source": "t11_50", + "target": "t11_51" + } + ], + "meta": { + "createdAt": "2026-10-30T00:00:00.000Z", + "updatedAt": "2026-10-30T00:00:00.000Z", + "appVersion": "0.1.0" + } +} diff --git a/resources/test-flows/app-system/test_appsystem_12.json b/resources/test-flows/app-system/test_appsystem_12.json new file mode 100644 index 0000000..dbd15a1 --- /dev/null +++ b/resources/test-flows/app-system/test_appsystem_12.json @@ -0,0 +1,654 @@ +{ + "schemaVersion": 1, + "id": "test_appsystem_12", + "name": "组件测试 12 · 锁屏与解锁【手动】", + "description": "手动测试:先阅读测试说明。默认不开启执行开关,不能把组件返回成功当作功能通过。", + "enabled": true, + "trigger": { + "type": "manual", + "label": "手动运行" + }, + "variables": [], + "nodes": [ + { + "id": "t12_1", + "componentId": "Trigger.Manual", + "label": "人工发起", + "position": { + "x": 220, + "y": 80 + }, + "values": { + "entryName": "开始组件测试" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t12_2", + "componentId": "Basic_SetVariable", + "label": "初始化失败计数", + "position": { + "x": 220, + "y": 222 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + } + }, + { + "id": "t12_3", + "componentId": "Basic_SetVariable", + "label": "初始化待确认计数", + "position": { + "x": 220, + "y": 364 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + } + }, + { + "id": "t12_4", + "componentId": "Basic_SetVariable", + "label": "初始化阻塞计数", + "position": { + "x": 220, + "y": 506 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "blocked" + } + }, + { + "id": "t12_5", + "componentId": "Basic_SetVariable", + "label": "手动执行开关:确认环境后才可改为 true", + "position": { + "x": 220, + "y": 648 + }, + "values": { + "value": false + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "manualEnabled" + } + }, + { + "id": "t12_6", + "componentId": "logic_control_try_catch", + "label": "12-01 · ScreenControl_Screenlock", + "position": { + "x": 220, + "y": 790 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t12_7", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t12_6", + "slot": "try_fn" + }, + { + "id": "t12_8", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t12_7", + "slot": "statement_else" + }, + { + "id": "t12_9", + "componentId": "ScreenControl_Screenlock", + "label": "ScreenControl_Screenlock", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "username": "", + "pwd": "", + "width": "", + "height": "", + "scale_factor": "100" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_1" + }, + "parentId": "t12_7", + "slot": "statement_if" + }, + { + "id": "t12_10", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${[\"12-01\", \"ScreenControl_Screenlock\", \"MANUAL\", \"{\\\"username\\\":\\\"\\\",\\\"pwd\\\":\\\"\\\",\\\"width\\\":\\\"\\\",\\\"height\\\":\\\"\\\",\\\"scale_factor\\\":\\\"100\\\"}\", \"实际锁屏;需要人在机器旁用 Windows 登录凭据恢复,不改变账户密码\", actual_1]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t12_7", + "slot": "statement_if" + }, + { + "id": "t12_11", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t12_7", + "slot": "statement_if" + }, + { + "id": "t12_12", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t12_7", + "slot": "statement_if" + }, + { + "id": "t12_13", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${[\"12-01\", \"ScreenControl_Screenlock\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{\\\"username\\\":\\\"\\\",\\\"pwd\\\":\\\"\\\",\\\"width\\\":\\\"\\\",\\\"height\\\":\\\"\\\",\\\"scale_factor\\\":\\\"100\\\"}\", \"实际锁屏;需要人在机器旁用 Windows 登录凭据恢复,不改变账户密码\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t12_6", + "slot": "except_fn" + }, + { + "id": "t12_14", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t12_6", + "slot": "except_fn" + }, + { + "id": "t12_15", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1160 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t12_6", + "slot": "except_fn" + }, + { + "id": "t12_16", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1294 + }, + "values": { + "msg": "用例结果:${json(case_1)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t12_17", + "componentId": "logic_control_try_catch", + "label": "12-02 · ScreenControl_ScreenUnlock", + "position": { + "x": 220, + "y": 1436 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t12_18", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t12_17", + "slot": "try_fn" + }, + { + "id": "t12_19", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t12_18", + "slot": "statement_else" + }, + { + "id": "t12_20", + "componentId": "ScreenControl_ScreenUnlock", + "label": "ScreenControl_ScreenUnlock", + "position": { + "x": 220, + "y": 1520 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_2" + }, + "parentId": "t12_18", + "slot": "statement_if" + }, + { + "id": "t12_21", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${[\"12-02\", \"ScreenControl_ScreenUnlock\", \"MANUAL\", \"{}\", \"仅尝试唤醒屏幕,loginUnlockSupported 必须为 false;Windows 登录仍需人工完成\", actual_2]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t12_18", + "slot": "statement_if" + }, + { + "id": "t12_22", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t12_18", + "slot": "statement_if" + }, + { + "id": "t12_23", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t12_18", + "slot": "statement_if" + }, + { + "id": "t12_24", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${[\"12-02\", \"ScreenControl_ScreenUnlock\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{}\", \"仅尝试唤醒屏幕,loginUnlockSupported 必须为 false;Windows 登录仍需人工完成\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t12_17", + "slot": "except_fn" + }, + { + "id": "t12_25", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t12_17", + "slot": "except_fn" + }, + { + "id": "t12_26", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t12_17", + "slot": "except_fn" + }, + { + "id": "t12_27", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1940 + }, + "values": { + "msg": "用例结果:${json(case_2)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t12_28", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2082 + }, + "values": { + "msg": "本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t12_29", + "componentId": "logic_control_if_else", + "label": "汇总判定", + "position": { + "x": 220, + "y": 2224 + }, + "values": { + "condition": "${failures > 0 || pending > 0 || blocked > 0}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t12_30", + "componentId": "ExceptionUtil_Throws", + "label": "如实标记未通过", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "msg": "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t12_29", + "slot": "statement_if" + }, + { + "id": "t12_31", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "msg": "本组全部通过。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t12_29", + "slot": "statement_else" + } + ], + "edges": [ + { + "id": "e_t12_2", + "source": "t12_1", + "target": "t12_2" + }, + { + "id": "e_t12_3", + "source": "t12_2", + "target": "t12_3" + }, + { + "id": "e_t12_4", + "source": "t12_3", + "target": "t12_4" + }, + { + "id": "e_t12_5", + "source": "t12_4", + "target": "t12_5" + }, + { + "id": "e_t12_6", + "source": "t12_5", + "target": "t12_6" + }, + { + "id": "e_t12_16", + "source": "t12_6", + "target": "t12_16" + }, + { + "id": "e_t12_17", + "source": "t12_16", + "target": "t12_17" + }, + { + "id": "e_t12_27", + "source": "t12_17", + "target": "t12_27" + }, + { + "id": "e_t12_28", + "source": "t12_27", + "target": "t12_28" + }, + { + "id": "e_t12_29", + "source": "t12_28", + "target": "t12_29" + } + ], + "meta": { + "createdAt": "2026-10-30T00:00:00.000Z", + "updatedAt": "2026-10-30T00:00:00.000Z", + "appVersion": "0.1.0" + } +} diff --git a/resources/test-flows/app-system/test_appsystem_13.json b/resources/test-flows/app-system/test_appsystem_13.json new file mode 100644 index 0000000..380e3b1 --- /dev/null +++ b/resources/test-flows/app-system/test_appsystem_13.json @@ -0,0 +1,735 @@ +{ + "schemaVersion": 1, + "id": "test_appsystem_13", + "name": "组件测试 13 · 远程桌面【手动】", + "description": "手动测试:先阅读测试说明。默认不开启执行开关,不能把组件返回成功当作功能通过。", + "enabled": true, + "trigger": { + "type": "manual", + "label": "手动运行" + }, + "variables": [], + "nodes": [ + { + "id": "t13_1", + "componentId": "Trigger.Manual", + "label": "人工发起", + "position": { + "x": 220, + "y": 80 + }, + "values": { + "entryName": "开始组件测试" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t13_2", + "componentId": "Basic_SetVariable", + "label": "初始化失败计数", + "position": { + "x": 220, + "y": 222 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + } + }, + { + "id": "t13_3", + "componentId": "Basic_SetVariable", + "label": "初始化待确认计数", + "position": { + "x": 220, + "y": 364 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + } + }, + { + "id": "t13_4", + "componentId": "Basic_SetVariable", + "label": "初始化阻塞计数", + "position": { + "x": 220, + "y": 506 + }, + "values": { + "value": 0 + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "blocked" + } + }, + { + "id": "t13_5", + "componentId": "Basic_SetVariable", + "label": "手动执行开关:确认环境后才可改为 true", + "position": { + "x": 220, + "y": 648 + }, + "values": { + "value": false + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "manualEnabled" + } + }, + { + "id": "t13_6", + "componentId": "Basic_SetVariable", + "label": "填写用户自己的测试远程地址", + "position": { + "x": 220, + "y": 790 + }, + "values": { + "value": "" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "remoteAddress" + } + }, + { + "id": "t13_7", + "componentId": "Basic_SetVariable", + "label": "断连单独开关:可能断开当前 Windows 会话,必须另行确认", + "position": { + "x": 220, + "y": 932 + }, + "values": { + "value": false + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "allowDisconnect" + } + }, + { + "id": "t13_8", + "componentId": "logic_control_try_catch", + "label": "13-01 · System_ConnectRemoteDesktop", + "position": { + "x": 220, + "y": 1074 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t13_9", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t13_8", + "slot": "try_fn" + }, + { + "id": "t13_10", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t13_9", + "slot": "statement_else" + }, + { + "id": "t13_11", + "componentId": "System_ConnectRemoteDesktop", + "label": "System_ConnectRemoteDesktop", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "ip": "${remoteAddress}", + "port": "3389" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_1" + }, + "parentId": "t13_9", + "slot": "statement_if" + }, + { + "id": "t13_12", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${[\"13-01\", \"System_ConnectRemoteDesktop\", \"MANUAL\", \"{\\\"ip\\\":\\\"${remoteAddress}\\\",\\\"port\\\":\\\"3389\\\"}\", \"人工完成登录,并确认已连接到正确测试机器;启动 mstsc 不等于连接成功\", actual_1]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t13_9", + "slot": "statement_if" + }, + { + "id": "t13_13", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t13_9", + "slot": "statement_if" + }, + { + "id": "t13_14", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t13_9", + "slot": "statement_if" + }, + { + "id": "t13_15", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${[\"13-01\", \"System_ConnectRemoteDesktop\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{\\\"ip\\\":\\\"${remoteAddress}\\\",\\\"port\\\":\\\"3389\\\"}\", \"人工完成登录,并确认已连接到正确测试机器;启动 mstsc 不等于连接成功\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_1" + }, + "parentId": "t13_8", + "slot": "except_fn" + }, + { + "id": "t13_16", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${failures + (case_1[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t13_8", + "slot": "except_fn" + }, + { + "id": "t13_17", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1520 + }, + "values": { + "value": "${pending + (case_1[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t13_8", + "slot": "except_fn" + }, + { + "id": "t13_18", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 1578 + }, + "values": { + "msg": "用例结果:${json(case_1)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t13_19", + "componentId": "logic_control_try_catch", + "label": "13-02 · System_CloseRemoteDesktop", + "position": { + "x": 220, + "y": 1720 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t13_20", + "componentId": "logic_control_if_else", + "label": "手动执行保护", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "condition": "${manualEnabled === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t13_19", + "slot": "try_fn" + }, + { + "id": "t13_21", + "componentId": "ExceptionUtil_Throws", + "label": "默认不执行系统状态操作", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "msg": "待人工确认:执行开关未开启" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t13_20", + "slot": "statement_else" + }, + { + "id": "t13_30", + "componentId": "logic_control_if_else", + "label": "断连操作单独保护", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "condition": "${allowDisconnect === true}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t13_20", + "slot": "statement_if" + }, + { + "id": "t13_22", + "componentId": "System_CloseRemoteDesktop", + "label": "System_CloseRemoteDesktop", + "position": { + "x": 220, + "y": 1880 + }, + "values": {}, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "actual_2" + }, + "parentId": "t13_30", + "slot": "statement_if" + }, + { + "id": "t13_23", + "componentId": "Basic_SetVariable", + "label": "记录实际值与判定", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${[\"13-02\", \"System_CloseRemoteDesktop\", \"MANUAL\", \"{}\", \"确认目标会话及恢复方式后才能执行;当前实现会调用 tsdiscon\", actual_2]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t13_20", + "slot": "statement_if" + }, + { + "id": "t13_24", + "componentId": "Basic_SetVariable", + "label": "累计失败数", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t13_20", + "slot": "statement_if" + }, + { + "id": "t13_25", + "componentId": "Basic_SetVariable", + "label": "累计待人工确认数", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t13_20", + "slot": "statement_if" + }, + { + "id": "t13_26", + "componentId": "Basic_SetVariable", + "label": "记录异常结果", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${[\"13-02\", \"System_CloseRemoteDesktop\", manualEnabled === true ? \"FAIL\" : \"MANUAL\", \"{}\", \"确认目标会话及恢复方式后才能执行;当前实现会调用 tsdiscon\", error.reason]}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "case_2" + }, + "parentId": "t13_19", + "slot": "except_fn" + }, + { + "id": "t13_27", + "componentId": "Basic_SetVariable", + "label": "异常累计失败数", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${failures + (case_2[2] === \"FAIL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "failures" + }, + "parentId": "t13_19", + "slot": "except_fn" + }, + { + "id": "t13_28", + "componentId": "Basic_SetVariable", + "label": "异常累计待确认数", + "position": { + "x": 220, + "y": 1880 + }, + "values": { + "value": "${pending + (case_2[2] === \"MANUAL\" ? 1 : 0)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false, + "outputVar": "pending" + }, + "parentId": "t13_19", + "slot": "except_fn" + }, + { + "id": "t13_29", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2224 + }, + "values": { + "msg": "用例结果:${json(case_2)}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t13_31", + "componentId": "ExceptionUtil_Throws", + "label": "阻止未授权断连", + "position": { + "x": 220, + "y": 2060 + }, + "values": { + "msg": "阻塞:断连开关未开启;执行可能中断当前会话。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t13_30", + "slot": "statement_else" + }, + { + "id": "t13_32", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2366 + }, + "values": { + "msg": "本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t13_33", + "componentId": "logic_control_if_else", + "label": "汇总判定", + "position": { + "x": 220, + "y": 2508 + }, + "values": { + "condition": "${failures > 0 || pending > 0 || blocked > 0}" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + } + }, + { + "id": "t13_34", + "componentId": "ExceptionUtil_Throws", + "label": "如实标记未通过", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "msg": "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t13_33", + "slot": "statement_if" + }, + { + "id": "t13_35", + "componentId": "Log_Info", + "label": "输出测试结果", + "position": { + "x": 220, + "y": 2420 + }, + "values": { + "msg": "本组全部通过。" + }, + "options": { + "timeoutMs": 15000, + "retryCount": 0, + "logException": false + }, + "parentId": "t13_33", + "slot": "statement_else" + } + ], + "edges": [ + { + "id": "e_t13_2", + "source": "t13_1", + "target": "t13_2" + }, + { + "id": "e_t13_3", + "source": "t13_2", + "target": "t13_3" + }, + { + "id": "e_t13_4", + "source": "t13_3", + "target": "t13_4" + }, + { + "id": "e_t13_5", + "source": "t13_4", + "target": "t13_5" + }, + { + "id": "e_t13_6", + "source": "t13_5", + "target": "t13_6" + }, + { + "id": "e_t13_7", + "source": "t13_6", + "target": "t13_7" + }, + { + "id": "e_t13_8", + "source": "t13_7", + "target": "t13_8" + }, + { + "id": "e_t13_18", + "source": "t13_8", + "target": "t13_18" + }, + { + "id": "e_t13_19", + "source": "t13_18", + "target": "t13_19" + }, + { + "id": "e_t13_29", + "source": "t13_19", + "target": "t13_29" + }, + { + "id": "e_t13_32", + "source": "t13_29", + "target": "t13_32" + }, + { + "id": "e_t13_33", + "source": "t13_32", + "target": "t13_33" + } + ], + "meta": { + "createdAt": "2026-10-30T00:00:00.000Z", + "updatedAt": "2026-10-30T00:00:00.000Z", + "appVersion": "0.1.0" + } +} diff --git a/scripts/app-system-test-flows.mjs b/scripts/app-system-test-flows.mjs new file mode 100644 index 0000000..7511b18 --- /dev/null +++ b/scripts/app-system-test-flows.mjs @@ -0,0 +1,278 @@ +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +export const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +export const bundleRoot = path.join(projectRoot, "resources/test-flows/app-system"); +const ref = (expression) => `\${${expression}}`; +const literal = (value) => JSON.stringify(value); +const epoch = "2026-10-30T00:00:00.000Z"; + +// 只生成现有引擎支持的节点,不注册测试专用执行器。 +export class TestFlow { + constructor(number, title, components, manual = false) { + this.number = String(number).padStart(2, "0"); + this.flow = { + schemaVersion: 1, id: `test_appsystem_${this.number}`, + name: `组件测试 ${this.number} · ${title}${manual ? "【手动】" : ""}`, + description: manual ? "手动测试:先阅读测试说明。默认不开启执行开关,不能把组件返回成功当作功能通过。" : "查看运行日志中的用例结果;有失败时任务最终显示失败,其他用例仍继续。", + enabled: true, trigger: { type: "manual", label: "手动运行" }, variables: [], nodes: [], edges: [], + meta: { createdAt: epoch, updatedAt: epoch, appVersion: "0.1.0" } + }; + this.entry = { id: this.flow.id, file: `${this.flow.id}.json`, name: this.flow.name, manual, components, cases: [] }; + this.seq = 0; + this.top = []; + this.add("Trigger.Manual", { entryName: "开始组件测试" }, undefined, "人工发起"); + this.set("failures", 0, "初始化失败计数"); + this.set("pending", 0, "初始化待确认计数"); + this.set("blocked", 0, "初始化阻塞计数"); + if (manual) this.set("manualEnabled", false, "手动执行开关:确认环境后才可改为 true"); + } + + add(componentId, values = {}, outputVar, label, parent) { + const id = `t${this.number}_${++this.seq}`; + const node = { id, componentId, label: label || componentId, position: { x: 220, y: 80 + this.top.length * 180 }, values, + options: { timeoutMs: 15000, retryCount: 0, logException: false, ...(outputVar ? { outputVar } : {}) } }; + if (parent) { node.parentId = parent.id; node.slot = parent.slot; } + else { + if (this.top.length) this.flow.edges.push({ id: `e_${id}`, source: this.top.at(-1), target: id }); + this.top.push(id); + } + this.flow.nodes.push(node); + return node; + } + + set(name, value, label, parent) { return this.add("Basic_SetVariable", { value }, name, label, parent); } + log(message, parent) { return this.add("Log_Info", { msg: message }, undefined, "输出测试结果", parent); } + command(script, outputVar, label, parent) { return this.add("System_ExecuteCommand", { action: script }, outputVar, label, parent); } + + case(componentId, values, expected, predicate, options = {}) { + const index = this.entry.cases.length + 1; + const caseId = `${this.number}-${String(index).padStart(2, "0")}`; + const out = options.output || `actual_${index}`; + const result = `case_${index}`; + const container = this.add("logic_control_try_catch", {}, undefined, `${caseId} · ${options.title || componentId}`); + const run = { id: container.id, slot: "try_fn" }; + const caught = { id: container.id, slot: "except_fn" }; + let work = run; + if (this.entry.manual) { + const gate = this.add("logic_control_if_else", { condition: "${manualEnabled === true}" }, undefined, "手动执行保护", run); + work = { id: gate.id, slot: "statement_if" }; + this.add("ExceptionUtil_Throws", { msg: "待人工确认:执行开关未开启" }, undefined, "默认不执行系统状态操作", { id: gate.id, slot: "statement_else" }); + } + for (const step of options.before || []) this.add(step.componentId, step.values, step.output, step.label, work); + const target = this.add(componentId, values, out, options.title, work); + if (options.timeoutMs) target.options.timeoutMs = options.timeoutMs; + for (const step of options.after || []) this.add(step.componentId, step.values, step.output, step.label, work); + const actual = options.actual || out; + const manualResult = options.observe === true; + const status = options.blocked ? '"BLOCKED"' : manualResult ? '"MANUAL"' : `(${predicate}) ? "PASS" : "FAIL"`; + // 数组是表达式引擎原生支持的结构;对象交给 json/parseJson 处理。 + const prefix = [caseId, componentId]; + const input = options.input || JSON.stringify(values); + this.set(result, ref(`[${literal(prefix[0])}, ${literal(prefix[1])}, ${status}, ${literal(input)}, ${literal(expected)}, ${actual}]`), "记录实际值与判定", work); + this.set("failures", ref(`failures + (${result}[2] === "FAIL" ? 1 : 0)`), "累计失败数", work); + this.set("pending", ref(`pending + (${result}[2] === "MANUAL" ? 1 : 0)`), "累计待人工确认数", work); + if (options.blocked) this.set("blocked", ref("blocked + 1"), options.blocked, work); + const errorStatus = this.entry.manual ? 'manualEnabled === true ? "FAIL" : "MANUAL"' : '"FAIL"'; + this.set(result, ref(`[${literal(caseId)}, ${literal(componentId)}, ${errorStatus}, ${literal(input)}, ${literal(expected)}, error.reason]`), "记录异常结果", caught); + this.set("failures", ref(`failures + (${result}[2] === "FAIL" ? 1 : 0)`), "异常累计失败数", caught); + this.set("pending", ref(`pending + (${result}[2] === "MANUAL" ? 1 : 0)`), "异常累计待确认数", caught); + this.log(`用例结果:\${json(${result})}`); + this.entry.cases.push({ id: caseId, componentId, targetNodeId: target.id, resultVariable: result, input, expected, observe: manualResult, ...(options.blocked ? { blockedReason: options.blocked } : {}) }); + return out; + } + + finish() { + this.log("本组汇总:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。"); + const gate = this.add("logic_control_if_else", { condition: "${failures > 0 || pending > 0 || blocked > 0}" }, undefined, "汇总判定"); + this.add("ExceptionUtil_Throws", { msg: "组件测试未全部通过:失败 ${failures} 项,阻塞 ${blocked} 项,待人工确认 ${pending} 项。请查看日志。" }, undefined, "如实标记未通过", { id: gate.id, slot: "statement_if" }); + this.log("本组全部通过。", { id: gate.id, slot: "statement_else" }); + let y = 80; + for (const id of this.top) { + const node = this.flow.nodes.find(item => item.id === id); + node.position.y = y; + const children = this.flow.nodes.filter(item => item.parentId === id); + y += children.length ? 320 + children.length * 46 : 142; + } + return { flow: this.flow, entry: this.entry }; + } +} + +export function buildSuite() { + const groups = []; + groups.push(processFlow()); + const conversion = new TestFlow(2, "数据转换", ["Basic_StringToNum", "Basic_ConvertNumber", "Basic_ConvertInt", "Basic_ConvertBool", "Basic_ConvertString", "Basic_DataTypeConversion"]); + conversion.case("Basic_StringToNum", { val: "123.5" }, "数字 123.5", "actual_1 === 123.5"); + conversion.case("Basic_ConvertNumber", { val: "-42.25" }, "数字 -42.25", "actual_2 === -42.25"); + conversion.case("Basic_ConvertInt", { val: -3.9 }, "整数 -3(向零截断)", "actual_3 === -3"); + conversion.case("Basic_ConvertBool", { val: "true" }, "布尔 true", "actual_4 === true"); + conversion.case("Basic_ConvertBool", { val: "false" }, "布尔 false", "actual_5 === false"); + conversion.case("Basic_ConvertString", { val: 42 }, '文本 "42"', 'actual_6 === "42"'); + conversion.case("Basic_DataTypeConversion", { val: "42", into_type: "number" }, "数值 42,严格区分文本和数值", "actual_7 === 42"); + conversion.case("Basic_DataTypeConversion", { val: "-3.9", into_type: "int" }, "整数 -3", "actual_8 === -3"); + conversion.case("Basic_DataTypeConversion", { val: "false", into_type: "bool" }, "布尔 false", "actual_9 === false"); + conversion.case("Basic_DataTypeConversion", { val: 42, into_type: "string" }, '文本 "42"', 'actual_10 === "42"'); + groups.push(conversion.finish()); + const judge = new TestFlow(3, "数据判断", ["Basic_IsDictionary", "Basic_IsNumber", "Basic_IsNull", "Basic_IsArray", "Basic_Type", "Basic_JudgeDataType"]); + for (const [id, val, expected] of [ + ["Basic_IsDictionary", { name: "测试" }, true], ["Basic_IsDictionary", [], false], + ["Basic_IsNumber", "12.5", true], ["Basic_IsNumber", "中文", false], + ["Basic_IsNull", null, true], ["Basic_IsNull", "", true], ["Basic_IsNull", 0, false], + ["Basic_IsArray", [], true], ["Basic_IsArray", "[]", false], + ["Basic_Type", [1, 2], "list"], ["Basic_Type", null, "null"] + ]) { + const out = `actual_${judge.entry.cases.length + 1}`; + judge.case(id, { val }, JSON.stringify(expected), `${out} === ${literal(expected)}`); + } + judge.case("Basic_JudgeDataType", { val: 42, into_type: "number" }, "数字 42 属于数值类型,返回布尔 true", "actual_12 === true"); + groups.push(judge.finish()); + + const vars = new TestFlow(4, "变量与配置", ["Basic_SetVariable", "Basic_SetVariable_V1", "Basic_Clone", "Basic_GetProcessInfo", "Basic_DebugOutput", "CustomConfig_GetConfig", "Basic_BusinessOrderCount"]); + vars.case("Basic_SetVariable", { value: "中文变量往返" }, "原值及输出变量均保持中文文本", 'actual_1 === "中文变量往返"'); + vars.case("Basic_SetVariable_V1", { variableType: "rpa_int", value: "42" }, "数字 42", "actual_2 === 42"); + vars.case("Basic_SetVariable_V1", { variableType: "rpa_list", value: "[1,2]" }, "数组 [1,2]", 'json(actual_3) === "[1,2]"'); + vars.set("original", { title: "中文", nested: { n: 1 } }, "初始化复制源"); + vars.case("Basic_Clone", { val: "${original}" }, "深复制内容相同,外层和嵌套对象均不共用引用", "json(actual_4) === json(original) && actual_4 !== original && actual_4.nested !== original.nested"); + vars.case("Basic_GetProcessInfo", {}, "当前流程 ID、名称、运行 ID 和节点数一致", `actual_5.id === ${literal(vars.flow.id)} && actual_5.name === ${literal(vars.flow.name)} && len(actual_5.runId) > 0 && actual_5.nodeCount > 0`); + vars.case("Basic_DebugOutput", { msg: "中文日志测试:${actual_2}" }, '日志及返回值为“中文日志测试:42”', 'actual_6 === "中文日志测试:42"'); + vars.case("CustomConfig_GetConfig", { jsonlist: '[{"name":"timeout","value":30}]', configName: "timeout" }, "数字 30", "actual_7 === 30"); + vars.case("CustomConfig_GetConfig", { jsonlist: "[]", configName: "missing" }, "未命中返回 null", "actual_8 === null"); + vars.case("Basic_BusinessOrderCount", { start_count: 10, count: 2 }, "首次计数 12", "actual_9 === 12"); + vars.case("Basic_BusinessOrderCount", { start_count: 10, count: 2 }, "同一流程再次计数 14", "actual_10 === 14"); + groups.push(vars.finish()); + + groups.push(timingFlow()); + const system = new TestFlow(6, "系统路径与环境变量", ["System_GetTempPath", "System_GetHomePath", "System_GetSystemPath", "System_GetEnv", "System_SetEnv"]); + system.command("@{temp=[IO.Path]::GetTempPath().TrimEnd('\\'); home=[Environment]::GetFolderPath('UserProfile'); desktop=[Environment]::GetFolderPath('Desktop')} | ConvertTo-Json -Compress", "pathOracle", "独立读取 Windows 系统路径"); + system.set("paths", "${parseJson(pathOracle)}", "解析独立预期路径"); + system.case("System_GetTempPath", {}, "与系统临时目录一致(忽略尾部分隔符)", 'actual_1 === paths.temp || actual_1 === paths.temp + "\\\\"'); + system.case("System_GetHomePath", {}, "与 Windows 用户文件夹一致", "actual_2 === paths.home"); + system.case("System_GetSystemPath", { path_name: "desktop" }, "与 Windows 实际桌面目录一致(包含重定向)", "actual_3 === paths.desktop"); + system.case("System_GetEnv", { name: "RPA_APP_SYSTEM_TEST_VALUE" }, "读取测试专用变量的原始值,作为恢复依据", "true", { output: "originalEnv" }); + system.case("System_SetEnv", { name: "RPA_APP_SYSTEM_TEST_VALUE", value: "中文-测试-42" }, "当前应用进程内设置成功", 'actual_5 === "中文-测试-42"'); + system.case("System_GetEnv", { name: "RPA_APP_SYSTEM_TEST_VALUE" }, "能读回中文-测试-42", 'actual_6 === "中文-测试-42"'); + system.case("System_SetEnv", { name: "RPA_APP_SYSTEM_TEST_VALUE", value: "${originalEnv}" }, "恢复测试前读取值", "actual_7 === originalEnv"); + groups.push(system.finish()); + groups.push(commandFlow()); + groups.push(...manualFlows()); + return groups; +} + +function processFlow() { + const f = new TestFlow(1, "应用与 PID", ["App_Run", "App_GetPid", "App_GetPids", "App_Kill", "App_KillV1"]); + const csharp = "using System; using System.Threading; public static class RpaFixture { public static void Main() { Thread.Sleep(90000); } }"; + const setup = `$ErrorActionPreference='Stop'; $tag=[Guid]::NewGuid().ToString('N'); $dir=Join-Path ([IO.Path]::GetTempPath()) ('RPA-AppSystem-Tests\\'+$tag); [IO.Directory]::CreateDirectory($dir) | Out-Null; $name='rpatest_'+$tag.Substring(0,12); $exe=Join-Path $dir ($name+'.exe'); Add-Type -TypeDefinition '${csharp}' -OutputAssembly $exe -OutputType ConsoleApplication; @{folder=$dir;exe=$exe;name=$name} | ConvertTo-Json -Compress`; + f.command(setup, "fixtureJson", "准备唯一测试程序(90 秒自动退出)"); + f.set("fixture", "${parseJson(fixtureJson)}", "读取夹具路径与专用进程名"); + f.case("App_Run", { executeable: "${fixture.exe}" }, "第一个测试进程 PID 大于 0", "pid1 > 0", { output: "pid1" }); + f.case("App_Run", { executeable: "${fixture.exe}" }, "第二个 PID 大于 0,且与第一个不同", "pid2 > 0 && pid2 !== pid1", { output: "pid2" }); + f.case("App_GetPid", { pattern: "${fixture.name}.exe" }, "返回本次创建的任一 PID", "actual_3 === pid1 || actual_3 === pid2"); + f.case("App_GetPids", { pattern: "${fixture.name}.exe" }, "列表恰含本次创建的两个 PID", "len(actual_4) === 2 && ((actual_4[0] === pid1 && actual_4[1] === pid2) || (actual_4[0] === pid2 && actual_4[1] === pid1))"); + f.case("App_Kill", { pid: "${pid1}" }, "结束第一个夹具 PID,第二个仍在运行", "parseJson(alive1) === false && parseJson(alive2) === true", { + after: [processProbe("pid1", "alive1"), processProbe("pid2", "alive2")], actual: "[actual_5, parseJson(alive1), parseJson(alive2)]" + }); + f.case("App_KillV1", { close_type: "id", pid: "${pid2}", kill_all: "0" }, "只填写 PID 即可结束第二个夹具进程", "parseJson(aliveAfterV1) === false", { + after: [processProbe("pid2", "aliveAfterV1")], actual: "[actual_6, parseJson(aliveAfterV1)]" + }); + f.case("App_GetPids", { pattern: "${fixture.name}.exe" }, "所有夹具结束后应返回空数组 []", "len(actual_7) === 0"); + f.case("App_GetPid", { pattern: "${fixture.name}.exe" }, "无匹配时应返回 null", "actual_8 === null"); + const cleanup = "$ErrorActionPreference='Stop'; $fixture='${fixture.exe}'; if ((Split-Path $fixture -Leaf) -notmatch '^rpatest_[0-9a-f]{12}\\.exe$') { throw '拒绝清理非测试进程' }; Get-Process -Name '${fixture.name}' -ErrorAction SilentlyContinue | Where-Object { $_.Path -eq $fixture } | Stop-Process -Force; '测试进程清理完成'"; + f.command(cleanup, "cleanupResult", "收尾:仅清理本次专用测试进程"); + return f.finish(); +} + +function processProbe(pid, output) { + return { componentId: "System_ExecuteCommand", values: { action: `if (Get-Process -Id \${${pid}} -ErrorAction SilentlyContinue) { 'true' } else { 'false' }` }, output, label: "独立核对 PID 是否存活" }; +} + +function timingFlow() { + const f = new TestFlow(5, "等待与随机数", ["Basic_Delay_V2", "Basic_Delay_V1", "Basic_Delay", "Basic_RandomInt", "Basic_Rnd"]); + for (const [id, values, low, high] of [ + ["Basic_Delay_V2", { is_random: "0", second: "0.15", min_second: "0.1", max_second: "0.2" }, 120, 1800], + ["Basic_Delay_V2", { is_random: "1", second: "0.15", min_second: "0.1", max_second: "0.2" }, 80, 1800], + ["Basic_Delay_V1", { second: "0.15" }, 120, 1800], + ["Basic_Delay", { mileSecond: "3000" }, 2800, 6500] + ]) { + const step = (output) => ({ componentId: "Time_GetDatetimeObj", values: { date_input: "${now()}" }, output, label: "独立采集毫秒时间" }); + f.case(id, values, `实际等待耗时 ${low}~${high} ms`, `endTime.timestamp - startTime.timestamp >= ${low} && endTime.timestamp - startTime.timestamp <= ${high}`, { before: [step("startTime")], after: [step("endTime")], actual: "endTime.timestamp - startTime.timestamp" }); + } + f.case("Basic_RandomInt", { min: 7, max: 7 }, "最小值等于最大值时返回整数 7", "actual_5 === 7"); + f.case("Basic_RandomInt", { min: -2, max: 2 }, "返回 -2~2 的整数", "actual_6 >= -2 && actual_6 <= 2 && actual_6 % 1 === 0"); + f.case("Basic_Rnd", {}, "随机小数满足 0 ≤ x < 1", "actual_7 >= 0 && actual_7 < 1"); + return f.finish(); +} + +function commandFlow() { + const f = new TestFlow(7, "命令行", ["System_ExecuteCommand", "System_ExecuteCommandV1"]); + f.case("System_ExecuteCommand", { action: "Write-Output 'RPA-PS-中文-OK'" }, "RPA-PS-中文-OK", 'actual_1 === "RPA-PS-中文-OK"'); + f.case("System_ExecuteCommandV1", { command_type: "1", dos_command: "echo RPA-DOS-OK", get_ret: "1" }, "RPA-DOS-OK", 'actual_2 === "RPA-DOS-OK"'); + f.case("System_ExecuteCommandV1", { command_type: "3", ps_command: "Write-Output 'RPA-PS-V1-OK'", get_ret: "1" }, "RPA-PS-V1-OK", 'actual_3 === "RPA-PS-V1-OK"'); + f.command("$dir=Join-Path ([IO.Path]::GetTempPath()) ('RPA-AppSystem-Tests\\'+[Guid]::NewGuid().ToString('N')); [IO.Directory]::CreateDirectory($dir) | Out-Null; $bat=Join-Path $dir 'echo-test.bat'; [IO.File]::WriteAllText($bat, '@echo RPA-BAT-OK', [Text.Encoding]::ASCII); $bat", "batPath", "创建仅输出标记的 BAT 夹具"); + f.case("System_ExecuteCommandV1", { command_type: "2", bat_file: "${batPath}", get_ret: "1" }, "RPA-BAT-OK", 'actual_4 === "RPA-BAT-OK"'); + f.case("System_ExecuteCommand", { action: "Write-Output 'RPA-ERROR-PROBE'; exit 9" }, "非零退出码应抛出异常", "false", { title: "非零返回码检查" }); + // 最后一例是预期异常:由正常 Catch 记录 PASS,仍保留实际异常证据。 + const last = f.entry.cases.at(-1); + const caught = f.flow.nodes.find(node => node.options.outputVar === last.resultVariable && node.slot === "except_fn"); + caught.values.value = ref(`[${literal(last.id)}, ${literal(last.componentId)}, "PASS", ${literal(last.input)}, ${literal(last.expected)}, error.reason]`); + return f.finish(); +} + +function manualFlows() { + const result = []; + const credential = new TestFlow(8, "Windows 凭据", ["System_AddCredential", "System_ReadCredential", "System_DeleteCredential"], true); + credential.set("credentialTarget", "RPA-AppSystem-Tests-${now()}", "只允许使用新的测试凭据目标"); + credential.case("System_AddCredential", { application: "${credentialTarget}", name: "", password: "" }, "安全输入机制准备好后,在专用目标添加测试凭据", "false", { observe: true }); + credential.case("System_ReadCredential", { application: "${credentialTarget}" }, "仅验证测试凭据存在,不读取或打印密码", "false", { observe: true }); + credential.case("System_DeleteCredential", { application: "${credentialTarget}" }, "删除刚创建的测试目标,之后人工确认不存在", "false", { observe: true }); + result.push(credential.finish()); + + const ime = new TestFlow(9, "输入法", ["System_GetInputMethodState", "System_SetInputMethodState"], true); + ime.case("System_GetInputMethodState", {}, "读取前台窗口的真实输入法状态,人工对照任务栏", "false", { observe: true, output: "originalIme" }); + ime.case("System_SetInputMethodState", { mode: "en-US" }, "前台编辑器应切换到英文模式;仅子进程返回 set:true 不能算通过", "false", { observe: true }); + ime.case("System_SetInputMethodState", { mode: "${originalIme.culture}" }, "恢复原输入法;人工确认前台窗口的实际状态", "false", { observe: true }); + result.push(ime.finish()); + + const sound = new TestFlow(10, "音频", ["System_PlaySound"], true); + const wav = fs.readFileSync(path.join(bundleRoot, "fixtures/tone.wav")).toString("base64"); + sound.command(`$dir=Join-Path ([IO.Path]::GetTempPath()) ('RPA-AppSystem-Tests\\'+[Guid]::NewGuid().ToString('N')); [IO.Directory]::CreateDirectory($dir) | Out-Null; $wav=Join-Path $dir 'tone.wav'; [IO.File]::WriteAllBytes($wav,[Convert]::FromBase64String('${wav}')); $wav`, "audioPath", "准备 0.3 秒低音量测试音"); + sound.case("System_PlaySound", { audio: "${audioPath}" }, "听到一次短提示音;没有声音不能算通过", "false", { observe: true }); + result.push(sound.finish()); + + const saver = new TestFlow(11, "屏保", ["System_ScreenSaverShow", "System_ScreenSaverShowV1", "System_ScreenSaverStop"], true); + saver.case("System_ScreenSaverShow", { text: "RPA 测试", status: "1" }, "屏幕实际进入屏保;无配置时记录阻塞", "false", { observe: true }); + saver.case("System_ScreenSaverStop", {}, "屏保实际关闭,可正常操作", "false", { observe: true }); + saver.case("System_ScreenSaverShowV1", {}, "开启 Windows 已配置的屏保,不要求输入密码;人工确认屏幕实际变化", "false", { observe: true }); + saver.case("System_ScreenSaverStop", {}, "第二种屏保实际关闭", "false", { observe: true }); + result.push(saver.finish()); + + const lock = new TestFlow(12, "锁屏与解锁", ["ScreenControl_Screenlock", "ScreenControl_ScreenUnlock"], true); + lock.case("ScreenControl_Screenlock", { username: "", pwd: "", width: "", height: "", scale_factor: "100" }, "实际锁屏;需要人在机器旁用 Windows 登录凭据恢复,不改变账户密码", "false", { observe: true }); + lock.case("ScreenControl_ScreenUnlock", {}, "仅尝试唤醒屏幕,loginUnlockSupported 必须为 false;Windows 登录仍需人工完成", "false", { observe: true }); + result.push(lock.finish()); + + const remote = new TestFlow(13, "远程桌面", ["System_ConnectRemoteDesktop", "System_CloseRemoteDesktop"], true); + remote.set("remoteAddress", "", "填写用户自己的测试远程地址"); + remote.set("allowDisconnect", false, "断连单独开关:可能断开当前 Windows 会话,必须另行确认"); + remote.case("System_ConnectRemoteDesktop", { ip: "${remoteAddress}", port: "3389" }, "人工完成登录,并确认已连接到正确测试机器;启动 mstsc 不等于连接成功", "false", { observe: true }); + const disconnect = remote.case("System_CloseRemoteDesktop", {}, "确认目标会话及恢复方式后才能执行;当前实现会调用 tsdiscon", "false", { observe: true }); + const target = remote.flow.nodes.find(node => node.options.outputVar === disconnect); + const parent = { id: target.parentId, slot: target.slot }; + const guard = remote.add("logic_control_if_else", { condition: "${allowDisconnect === true}" }, undefined, "断连操作单独保护", parent); + // 子节点按数组顺序执行,保护节点必须在目标前。 + remote.flow.nodes.splice(remote.flow.nodes.indexOf(guard), 1); + remote.flow.nodes.splice(remote.flow.nodes.indexOf(target), 0, guard); + target.parentId = guard.id; target.slot = "statement_if"; + remote.add("ExceptionUtil_Throws", { msg: "阻塞:断连开关未开启;执行可能中断当前会话。" }, undefined, "阻止未授权断连", { id: guard.id, slot: "statement_else" }); + result.push(remote.finish()); + return result; +} + +export function writeSuite() { + const groups = buildSuite(); + fs.mkdirSync(bundleRoot, { recursive: true }); + for (const { flow, entry } of groups) fs.writeFileSync(path.join(bundleRoot, entry.file), JSON.stringify(flow, null, 2) + "\n"); + const manifest = { schemaVersion: 1, generatedAt: epoch, groups: groups.map(item => item.entry) }; + fs.writeFileSync(path.join(bundleRoot, "manifest.json"), JSON.stringify(manifest, null, 2) + "\n"); + return manifest; +} diff --git a/scripts/app-system-tests.mjs b/scripts/app-system-tests.mjs new file mode 100644 index 0000000..bf374b4 --- /dev/null +++ b/scripts/app-system-tests.mjs @@ -0,0 +1,390 @@ +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import net from "node:net"; +import { spawn, execFile } from "node:child_process"; +import { promisify } from "node:util"; +import { fileURLToPath } from "node:url"; +import ts from "typescript"; +import { projectRoot, bundleRoot, writeSuite } from "./app-system-test-flows.mjs"; + +const execFileAsync = promisify(execFile); +const pause = (ms) => new Promise(resolve => setTimeout(resolve, ms)); +const containers = new Set(["logic_control_if_else", "logic_control_count_for", "logic_control_array_for_v3", "logic_control_dictionary_for_v1", "logic_control_while", "infinite_loop", "logic_control_try_catch"]); +const statusNames = { PASS: "通过", FAIL: "失败", BLOCKED: "阻塞", MANUAL: "待人工确认", UNRUN: "未运行" }; + +export function readBundle() { + const manifest = JSON.parse(fs.readFileSync(path.join(bundleRoot, "manifest.json"), "utf8")); + return { manifest, groups: manifest.groups.map(entry => ({ entry, flow: JSON.parse(fs.readFileSync(path.join(bundleRoot, entry.file), "utf8")) })) }; +} + +// 静态清单供离线校验;真实运行前再与 Electron 返回的 implemented 清单逐项比较。 +export function staticCatalog() { + const registered = new Set(); + const directory = path.join(projectRoot, "src/main/capabilities"); + for (const name of fs.readdirSync(directory).filter(name => name.endsWith(".ts") && !name.endsWith(".test.ts"))) { + const source = ts.createSourceFile(name, fs.readFileSync(path.join(directory, name), "utf8"), ts.ScriptTarget.Latest, true); + const visit = node => { + if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "register") { + const first = node.arguments[0]; + if (first && ts.isStringLiteral(first)) registered.add(first.text); + if (first && ts.isArrayLiteralExpression(first)) for (const item of first.elements) if (ts.isStringLiteral(item)) registered.add(item.text); + } + ts.forEachChild(node, visit); + }; + visit(source); + } + const catalog = JSON.parse(fs.readFileSync(path.join(projectRoot, "resources/catalog.json"), "utf8")); + for (const c of catalog.components) c.implemented = containers.has(c.id) || registered.has(c.id) || registered.has(c.functionName); + return catalog; +} + +export async function validator() { + const source = fs.readFileSync(path.join(projectRoot, "src/renderer/src/validation/flowValidation.ts"), "utf8"); + const { outputText } = ts.transpileModule(source, { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext } }); + return (await import(`data:text/javascript;base64,${Buffer.from(outputText).toString("base64")}`)).validateFlow; +} + +export async function verifyBundle(catalog = staticCatalog()) { + const { manifest, groups } = readBundle(); + const expected = catalog.components.filter(c => c.group === "app" && c.implemented).map(c => c.id).sort(); + const actual = groups.flatMap(g => g.entry.components).sort(); + if (groups.length !== 13 || actual.length !== 49 || new Set(actual).size !== 49 || JSON.stringify(actual) !== JSON.stringify(expected)) throw new Error("流程包与当前 49 项可执行清单不一致,请重新生成并核对覆盖范围。"); + const validateFlow = await validator(); + const validation = {}; + for (const { flow, entry } of groups) { + const nodes = new Map(flow.nodes.map(n => [n.id, n])); + if (nodes.size !== flow.nodes.length || flow.nodes[0].componentId !== "Trigger.Manual") throw new Error(`${flow.id} 节点 ID 重复或缺少入口`); + const covered = new Set(entry.cases.map(c => c.componentId)); + if (entry.components.some(id => !covered.has(id)) || covered.size !== entry.components.length) throw new Error(`${flow.id} 用例覆盖不完整`); + for (const c of entry.cases) if (nodes.get(c.targetNodeId)?.componentId !== c.componentId) throw new Error(`${c.id} 目标节点不匹配`); + const reached = new Set([flow.nodes[0].id]); + for (let i = 0; i < nodes.size; i++) { + for (const edge of flow.edges) { + if (!nodes.has(edge.source) || !nodes.has(edge.target)) throw new Error(`${flow.id} 连线指向不存在的节点`); + if (reached.has(edge.source)) reached.add(edge.target); + } + for (const node of flow.nodes) if (reached.has(node.parentId)) reached.add(node.id); + } + if (reached.size !== nodes.size) throw new Error(`${flow.id} 存在断链或孤立节点`); + validation[entry.id] = validateFlow(flow, catalog); + const unexpected = validation[entry.id].filter(i => i.code !== "required"); + if (unexpected.length) throw new Error(`${flow.id} 存在意外校验问题:${JSON.stringify(unexpected)}`); + } + return { manifest, groups, validation, executableCount: expected.length }; +} + +export function installBundle(userData) { + const { groups } = readBundle(); + const directory = path.join(path.resolve(userData), "flows"); + fs.mkdirSync(directory, { recursive: true }); + const installed = [], skipped = []; + for (const { flow } of groups) { + const now = new Date().toISOString(); + const target = path.join(directory, `${flow.id}.json`); + try { + fs.writeFileSync(target, JSON.stringify({ ...flow, meta: { ...flow.meta, createdAt: now, updatedAt: now } }, null, 2) + "\n", { flag: "wx" }); + installed.push(flow.name); + } catch (error) { + if (error.code !== "EEXIST") throw error; + skipped.push(flow.name); + } + } + return { userData: path.resolve(userData), installed, skipped }; +} + +/** 仅升级仍与指定旧模板一致的测试任务;用户修改过的内容保持原样。 */ +export function upgradeBundle(userData, baselineDirectory, backupDirectory) { + const { groups } = readBundle(); + const directory = path.join(path.resolve(userData), "flows"); + const normalize = flow => { const { meta, ...content } = flow; return JSON.stringify(content); }; + const upgraded = [], skipped = []; + for (const { flow, entry } of groups) { + const target = path.join(directory, entry.file); + const baseline = path.join(path.resolve(baselineDirectory), entry.file); + if (!fs.existsSync(target) || !fs.existsSync(baseline)) { skipped.push({ id: entry.id, reason: "缺少现有任务或旧模板" }); continue; } + let current; + try { current = JSON.parse(fs.readFileSync(target, "utf8")); } + catch { skipped.push({ id: entry.id, reason: "任务文件无法解析,保留原文件" }); continue; } + if (normalize(current) === normalize(flow)) { skipped.push({ id: entry.id, reason: "已是当前版本" }); continue; } + if (normalize(current) !== normalize(JSON.parse(fs.readFileSync(baseline, "utf8")))) { skipped.push({ id: entry.id, reason: "用户已修改,保留现有版本" }); continue; } + fs.mkdirSync(backupDirectory, { recursive: true }); + fs.copyFileSync(target, path.join(backupDirectory, entry.file), fs.constants.COPYFILE_EXCL); + const updated = { ...flow, meta: { ...flow.meta, createdAt: current.meta?.createdAt || flow.meta.createdAt, updatedAt: new Date().toISOString() } }; + const temp = `${target}.tmp`; + fs.writeFileSync(temp, JSON.stringify(updated, null, 2) + "\n", { flag: "wx" }); + fs.renameSync(temp, target); + upgraded.push(entry.id); + } + return { upgraded, skipped, backupDirectory: path.resolve(backupDirectory) }; +} + +async function freePort() { + const server = net.createServer(); + await new Promise((resolve, reject) => { server.once("error", reject); server.listen(0, "127.0.0.1", resolve); }); + const port = server.address().port; + await new Promise(resolve => server.close(resolve)); + return port; +} + +async function cdpCommand(page, method, params, timeout = 180000) { + const socket = new WebSocket(page.webSocketDebuggerUrl); + let timer; + try { + await new Promise((resolve, reject) => { timer = setTimeout(() => reject(new Error("CDP 连接超时")), 10000); socket.onopen = resolve; socket.onerror = reject; }); + clearTimeout(timer); + return await new Promise((resolve, reject) => { + timer = setTimeout(() => reject(new Error(`隔离检查 ${method} 超时`)), timeout); + socket.onerror = reject; + socket.onclose = () => reject(new Error("隔离应用连接提前关闭")); + socket.onmessage = event => { + const response = JSON.parse(event.data); + if (response.id !== 1) return; + if (response.error || response.result?.exceptionDetails) reject(new Error(JSON.stringify(response.error || response.result.exceptionDetails))); + else resolve(response.result); + }; + socket.send(JSON.stringify({ id: 1, method, params })); + }); + } finally { clearTimeout(timer); socket.close(); } +} + +async function evaluate(page, expression, timeout = 180000) { + const response = await cdpCommand(page, "Runtime.evaluate", { expression, returnByValue: true, awaitPromise: true }, timeout); + return response?.result?.value; +} + +async function verifyRenderer(page, output) { + const specs = [ + ["conversion", "Basic_DataTypeConversion", { val: "42", into_type: "number" }], + ["judgment", "Basic_JudgeDataType", { val: 42, into_type: "number" }], + ["kill", "App_KillV1", { close_type: "id", pid: "", p_name: "" }], + ["command", "System_ExecuteCommandV1", { command_type: "1", dos_command: "echo ui-check" }], + ["wake", "ScreenControl_ScreenUnlock", {}] + ]; + const flow = { schemaVersion: 1, id: "test_appsystem_ui", name: "界面验证:组件参数", variables: [], + nodes: [{ id: "ui_start", componentId: "Trigger.Manual", values: {}, options: {}, position: { x: 220, y: 60 } }, ...specs.map(([id, componentId, values], index) => ({ id: `ui_${id}`, componentId, values, options: {}, position: { x: 220, y: 200 + index * 142 } }))], + edges: [], meta: { createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), appVersion: "test" } }; + await evaluate(page, `window.rpa.flows.save(${JSON.stringify(flow)})`); + await evaluate(page, "document.querySelector('.refresh-btn').click()"); + const waitFor = async expression => { + for (let n = 0; n < 100; n++) { if (await evaluate(page, expression)) return; await pause(50); } + throw new Error(`前端状态等待超时:${expression}`); + }; + await waitFor(`Array.from(document.querySelectorAll('.task-row')).some(row => row.textContent.includes(${JSON.stringify(flow.name)}))`); + await evaluate(page, `Array.from(document.querySelectorAll('.task-row')).find(row => row.textContent.includes(${JSON.stringify(flow.name)})).querySelector('button[title="编辑流程"]').click()`); + const select = async (id, componentId) => { + await waitFor(`Boolean(document.querySelector('[data-id="ui_${id}"]'))`); + await evaluate(page, `document.querySelector('[data-id="ui_${id}"]').click()`); + await waitFor(`document.querySelector('.props-id')?.textContent === ${JSON.stringify(componentId)}`); + }; + const labels = () => evaluate(page, "Array.from(document.querySelectorAll('.props .field-label')).map(el => el.textContent.trim())"); + const clickOption = text => evaluate(page, `Array.from(document.querySelectorAll('.props .option-chip')).find(el => el.textContent === ${JSON.stringify(text)}).click()`); + const screenshot = async name => { + const result = await cdpCommand(page, "Page.captureScreenshot", { format: "png", captureBeyondViewport: false }); + fs.writeFileSync(path.join(output, name), Buffer.from(result.data, "base64")); + }; + const observations = {}; + await select("conversion", "Basic_DataTypeConversion"); + observations.conversionOptions = await evaluate(page, "Array.from(document.querySelector('.props select').options).map(o => ({label:o.text,value:o.value}))"); + if (!["number", "int", "bool", "string"].every(value => observations.conversionOptions.some(o => o.value === value))) throw new Error("转换类型下拉选项缺失"); + await screenshot("ui-conversion.png"); + await select("judgment", "Basic_JudgeDataType"); + observations.judgmentOptions = await evaluate(page, "Array.from(document.querySelector('.props select').options).map(o => o.value)"); + if (!["number", "int", "null", "dict", "list", "string", "bool"].every(value => observations.judgmentOptions.includes(value))) throw new Error("判断类型下拉选项缺失"); + await select("kill", "App_KillV1"); + observations.killPidFields = await labels(); + if (!observations.killPidFields.some(s => s.startsWith("进程PID")) || observations.killPidFields.some(s => s.startsWith("进程名称"))) throw new Error("PID 模式显示了错误字段"); + await clickOption("按进程名称"); await pause(80); + observations.killNameFields = await labels(); + if (!observations.killNameFields.some(s => s.startsWith("进程名称")) || observations.killNameFields.some(s => s.startsWith("进程PID"))) throw new Error("名称模式显示了错误字段"); + await screenshot("ui-kill-name.png"); + await select("command", "System_ExecuteCommandV1"); + observations.commandDosFields = await labels(); + if (!observations.commandDosFields.some(s => s.startsWith("DOS命令")) || observations.commandDosFields.some(s => s.startsWith("BAT文件") || s.startsWith("PowerShell命令"))) throw new Error("DOS 模式显示了错误字段"); + await clickOption("PowerShell 命令"); await pause(80); + observations.commandPsFields = await labels(); + if (!observations.commandPsFields.some(s => s.startsWith("PowerShell命令")) || observations.commandPsFields.some(s => s.startsWith("DOS命令") || s.startsWith("BAT文件"))) throw new Error("PowerShell 模式显示了错误字段"); + await screenshot("ui-command-ps.png"); + await select("wake", "ScreenControl_ScreenUnlock"); + observations.wakeTitle = await evaluate(page, "document.querySelector('.props-title').textContent"); + observations.wakeFields = await labels(); + if (!observations.wakeTitle.includes("非登录解锁") || observations.wakeFields.some(s => s === "密码" || s === "用户名")) throw new Error("唤醒组件仍在宣称登录解锁或索要凭据"); + await screenshot("ui-wake.png"); + fs.writeFileSync(path.join(output, "ui-check.json"), JSON.stringify({ passed: true, observations }, null, 2) + "\n"); + return observations; +} + +export async function runSafe(outputDirectory, checkUi = false) { + const output = path.resolve(outputDirectory); + fs.mkdirSync(output, { recursive: true }); + const profile = fs.mkdtempSync(path.join(output, "isolated-")); + const debugPort = await freePort(); + const candidates = [process.env.RPA_ELECTRON_DIST, "C:/electron-rpa/dist", path.join(projectRoot, "node_modules/electron/dist")].filter(Boolean); + const dist = candidates.find(dir => fs.existsSync(path.join(dir, "electron.exe"))); + if (!dist) throw new Error("找不到 Electron,请先安装项目依赖。"); + if (!fs.existsSync(path.join(projectRoot, "out/main/index.js"))) throw new Error("请先执行 npm run build。"); + // Chromium 在隐藏窗口中可能停止后续绘制;界面截图检查使用独立可见窗口。 + const env = { ...process.env, RPA_E2E: checkUi ? "0" : "1", RPA_SKIP_SINGLE_INSTANCE: "1", RPA_FIXTURE_PORT: "0", RPA_APP_SYSTEM_TEST_VALUE: "隔离环境原始值" }; + delete env.ELECTRON_RUN_AS_NODE; + const child = spawn(path.join(dist, "electron.exe"), [projectRoot, `--user-data-dir=${profile}`, `--remote-debugging-port=${debugPort}`, "--remote-debugging-address=127.0.0.1", "--no-sandbox"], { cwd: projectRoot, env, windowsHide: true, stdio: ["ignore", "pipe", "pipe"] }); + let diagnostics = ""; + for (const stream of [child.stdout, child.stderr]) stream.on("data", chunk => { diagnostics = (diagnostics + chunk).slice(-16000); }); + child.on("error", error => { diagnostics += error.message; }); + const runs = []; + try { + let page; + const deadline = Date.now() + 45000; + while (Date.now() < deadline) { + if (child.exitCode !== null) throw new Error(`隔离应用提前退出:${diagnostics}`); + try { + const targets = await (await fetch(`http://127.0.0.1:${debugPort}/json/list`, { signal: AbortSignal.timeout(1500) })).json(); + page = targets.find(p => p.type === "page" && p.title === "RPA Studio"); + if (page && await evaluate(page, "Boolean(window.rpa)", 5000)) break; + } catch { /* Electron 和 preload 尚未就绪,继续有界等待。 */ } + page = undefined; + await pause(200); + } + if (!page) throw new Error(`等待隔离应用超时:${diagnostics}`); + const info = await evaluate(page, "window.rpa.app.info()"); + if (path.resolve(info.userData).toLowerCase() !== profile.toLowerCase()) throw new Error("隔离用户目录不匹配,已拒绝执行测试。"); + const catalog = await evaluate(page, "window.rpa.catalog.get()"); + const checked = await verifyBundle(catalog); + for (const { flow, entry } of checked.groups) { + const issues = checked.validation[entry.id]; + if (entry.manual || issues.some(i => i.severity === "error")) { + const status = issues.some(i => i.severity === "error") ? "BLOCKED" : "MANUAL"; + runs.push({ flowId: flow.id, status, validation: issues, reason: status === "BLOCKED" ? "运行前参数校验拦截,未绕过校验;详见校验问题" : "手动任务不纳入自动执行" }); + console.log(`${flow.name}:${statusNames[status]}`); + continue; + } + const record = await evaluate(page, `(async () => { + const flow = ${JSON.stringify(flow)}; + await window.rpa.flows.save(flow); + const events = []; + const off = window.rpa.run.onEvent(event => events.push(event)); + try { + const started = await window.rpa.run.start(flow); + const finished = await new Promise((resolve, reject) => { + const end = Date.now() + 150000; + const timer = setInterval(() => { + const item = events.find(e => e.runId === started.runId && e.type === 'run.finished'); + if (item) { clearInterval(timer); resolve(item); } + else if (Date.now() > end) { clearInterval(timer); void window.rpa.run.stop(started.runId); reject(new Error('流程执行超时')); } + }, 50); + }); + return { flowId: flow.id, runId: started.runId, status: finished.status, durationMs: finished.durationMs, events }; + } finally { off(); } + })()`); + // run.finished 先通过 IPC 发出,主进程随后落盘,等待真正持久化再读取证据。 + const persisted = path.join(profile, "runs", record.runId, "run.json"); + for (let n = 0; n < 30 && !fs.existsSync(persisted); n++) await pause(100); + if (!fs.existsSync(persisted)) throw new Error(`${record.runId} 没有持久化运行证据`); + record.persistedFile = persisted; + record.result = JSON.parse(fs.readFileSync(persisted, "utf8")); + runs.push(record); + console.log(`${flow.name}:${record.status}(${record.durationMs} ms)`); + } + const report = { generatedAt: new Date().toISOString(), profile, executableCount: checked.executableCount, runs }; + fs.writeFileSync(path.join(output, "latest.json"), JSON.stringify(report, null, 2) + "\n"); + if (checkUi) { + try { report.ui = { passed: true, observations: await verifyRenderer(page, output) }; } + catch (error) { report.ui = { passed: false, reason: error.message }; throw error; } + finally { fs.writeFileSync(path.join(output, "latest.json"), JSON.stringify(report, null, 2) + "\n"); } + } + return report; + } finally { + if (child.pid && child.exitCode === null) { + try { await execFileAsync("taskkill.exe", ["/PID", String(child.pid), "/T", "/F"], { windowsHide: true, timeout: 10000 }); } + catch (error) { if (child.exitCode === null) console.warn(`隔离进程退出检查:${error.message}`); } + } + // 保留隔离目录中的 run.json 作为可审阅证据,不清理用户或仓库目录。 + } +} + +export function caseResults(entry, record) { + return entry.cases.map(c => { + const value = record?.result?.variables?.[c.resultVariable]; + return { ...c, status: value?.[2] || (record?.status === "BLOCKED" ? "BLOCKED" : entry.manual ? "MANUAL" : "UNRUN"), actual: value?.[5], reason: c.blockedReason || record?.reason }; + }); +} + +export function makeReport(evidence) { + const { groups } = readBundle(); + const records = new Map((evidence.runs || []).map(r => [r.flowId, r])); + const cases = groups.flatMap(g => caseResults(g.entry, records.get(g.entry.id))); + const priority = ["FAIL", "BLOCKED", "MANUAL", "UNRUN", "PASS"]; + const catalog = staticCatalog(); + const components = new Map(catalog.components.map(c => [c.id, c])); + const rows = groups.flatMap(({ entry }) => entry.components.map(id => { + const matches = cases.filter(c => c.componentId === id); + const status = priority.find(s => matches.some(c => c.status === s)) || "UNRUN"; + return { id, name: components.get(id)?.name || id, group: entry.id.slice(-2), status }; + })); + const counts = Object.fromEntries(priority.map(s => [s, rows.filter(r => r.status === s).length])); + const escape = value => String(value ?? "无执行记录").replace(/\|/g, "\\|").replace(/[\r\n]+/g, " ").slice(0, 1200); + const recordedAt = evidence.generatedAt ? new Intl.DateTimeFormat("zh-CN", { timeZone: "Asia/Shanghai", dateStyle: "medium", timeStyle: "medium", hour12: false }).format(new Date(evidence.generatedAt)) + "(北京时间)" : "未执行"; + const lines = ["# 应用与系统组件测试报告", "", `记录时间:${recordedAt}。覆盖 49 项可执行组件,13 组任务。`, "", + `按组件统计:通过 ${counts.PASS},失败 ${counts.FAIL},阻塞 ${counts.BLOCKED},待人工确认 ${counts.MANUAL},未运行 ${counts.UNRUN}。`, "", + "状态依据是断言、前置校验和人工证据,节点执行成功不直接代表功能通过。未执行手动系统操作。", "", + "| 组 | 组件 ID | 名称 | 状态 |", "|---|---|---|---|"]; + for (const r of rows) lines.push(`| ${r.group} | ${r.id} | ${r.name} | ${statusNames[r.status]} |`); + if (evidence.ui) lines.push("", "## 真实界面验证", "", evidence.ui.passed ? "已通过独立 Electron 窗口检查:类型下拉选项、PID/名称参数切换、DOS/PowerShell 参数切换,以及唤醒组件不再索要账号密码。界面快照及 ui-check.json 保存在 test-output/app-system/。" : `界面检查未通过:${escape(evidence.ui.reason)}`); + lines.push("", "## 用例证据", "", "| 用例 | 组件 | 状态 | 预期 | 实际/原因 |", "|---|---|---|---|---|"); + for (const c of cases) lines.push(`| ${c.id} | ${c.componentId} | ${statusNames[c.status]} | ${escape(c.expected)} | ${escape([c.actual === undefined ? undefined : JSON.stringify(c.actual), c.reason].filter(Boolean).join(";") || undefined)} |`); + lines.push("", "## 运行前校验阻塞", ""); + for (const r of evidence.runs || []) { + if (!r.validation?.length) continue; + lines.push(`- ${r.flowId}:${r.validation.map(i => i.message).join(";")}`); + } + lines.push("", "## 证据位置", "", `隔离用户目录:${evidence.profile || "未执行"}`, ""); + for (const r of evidence.runs || []) if (r.persistedFile) lines.push(`- ${r.flowId}:${r.persistedFile}`); + return { markdown: lines.join("\n") + "\n", counts, components: rows, cases }; +} + +function option(name, fallback) { + const index = process.argv.indexOf(name); + if (index < 0) return fallback; + if (!process.argv[index + 1] || process.argv[index + 1].startsWith("--")) throw new Error(`${name} 缺少参数`); + return process.argv[index + 1]; +} + +async function main() { + const action = process.argv[2]; + const output = option("--output", path.join(projectRoot, "test-output/app-system")); + if (action === "generate") { const m = writeSuite(); console.log(`已生成 ${m.groups.length} 组任务。`); } + else if (action === "verify") { + const checked = await verifyBundle(); + console.log(JSON.stringify({ groups: checked.groups.length, components: checked.executableCount, validation: checked.validation }, null, 2)); + } else if (action === "install") { + await verifyBundle(); + const userData = option("--user-data", path.join(process.env.APPDATA || path.join(os.homedir(), "AppData/Roaming"), "rpa-studio")); + console.log(JSON.stringify(installBundle(userData), null, 2)); + } else if (action === "upgrade") { + await verifyBundle(); + const baseline = option("--baseline", undefined); + if (!baseline) throw new Error("upgrade 需要 --baseline 指定升级前的旧流程模板目录。"); + const userData = option("--user-data", path.join(process.env.APPDATA || path.join(os.homedir(), "AppData/Roaming"), "rpa-studio")); + const backup = path.join(output, `installed-backup-${Date.now()}`); + console.log(JSON.stringify(upgradeBundle(userData, baseline, backup), null, 2)); + } else if (action === "run-safe") { + await verifyBundle(); + const evidence = await runSafe(output, process.argv.includes("--ui-check")); + const report = makeReport(evidence); + fs.writeFileSync(path.join(output, "report.md"), report.markdown); + console.log(JSON.stringify(report.counts)); + // 2 表示组件存在失败/阻塞;1 才表示测试工具自身无法完成。 + if (report.counts.FAIL || report.counts.BLOCKED) process.exitCode = 2; + } else if (action === "report") { + const evidence = JSON.parse(fs.readFileSync(option("--evidence", path.join(output, "latest.json")), "utf8")); + const report = makeReport(evidence); + const destination = option("--file", path.join(output, "report.md")); + fs.writeFileSync(destination, report.markdown); + console.log(JSON.stringify({ file: destination, counts: report.counts }, null, 2)); + } else { + console.log("用法:node scripts/app-system-tests.mjs generate|verify|install|upgrade|run-safe|report\n安装:install --user-data <应用用户目录>\n升级:upgrade --baseline <旧模板目录> --user-data <应用用户目录>\n运行:run-safe --output <证据目录>\n报告:report --evidence --file <报告.md>"); + } +} + +if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { + main().catch(error => { console.error(error.stack || error.message); process.exitCode = 1; }); +} diff --git a/scripts/app-system-tests.test.mjs b/scripts/app-system-tests.test.mjs new file mode 100644 index 0000000..b4a92ff --- /dev/null +++ b/scripts/app-system-tests.test.mjs @@ -0,0 +1,179 @@ +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { afterEach, describe, expect, it } from "vitest"; +import { buildSuite, bundleRoot } from "./app-system-test-flows.mjs"; +import { installBundle, upgradeBundle, makeReport, caseResults } from "./app-system-tests.mjs"; +import { applyCatalogOverrides } from "./catalog-overrides.mjs"; +import { hasCapability } from "../src/main/capabilities/index.ts"; +import { runFlow } from "../src/main/engine/runtime.ts"; +import { validateFlow } from "../src/renderer/src/validation/flowValidation.ts"; + +const containers = new Set(["logic_control_try_catch", "logic_control_if_else"]); +const catalog = JSON.parse(fs.readFileSync("resources/catalog.json", "utf8")); +for (const c of catalog.components) c.implemented = containers.has(c.id) || hasCapability(c.id) || hasCapability(c.functionName); +const componentMap = new Map(catalog.components.map(c => [c.id, c])); +const temporary = []; +afterEach(() => { for (const dir of temporary.splice(0)) fs.rmSync(dir, { recursive: true, force: true }); }); + +async function execute(number, change) { + const group = buildSuite()[number - 1]; + change?.(group.flow); + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "rpa-appsystem-unit-")); temporary.push(dir); + const logs = []; + const result = await runFlow(group.flow, { + runId: `unit-${group.flow.id}`, evidenceDir: dir, signal: new AbortController().signal, + emit: () => {}, log: (message) => logs.push(message), componentOf: node => componentMap.get(node.componentId) + }); + return { group, result, logs }; +} + +describe("应用与系统测试流程包", () => { + it("覆盖真实注册的全部 49 项,13 组无重复归属,不覆盖待接入组件", () => { + const suite = buildSuite(); + expect(suite).toHaveLength(13); + const covered = suite.flatMap(group => group.entry.components).sort(); + const executable = catalog.components.filter(c => c.group === "app" && c.implemented).map(c => c.id).sort(); + expect(covered).toHaveLength(49); + expect(new Set(covered).size).toBe(49); + expect(covered).toEqual(executable); + for (const { flow, entry } of suite) { + expect(new Set(flow.nodes.map(node => node.id)).size).toBe(flow.nodes.length); + expect(new Set(entry.cases.map(c => c.componentId))).toEqual(new Set(entry.components)); + const reached = new Set([flow.nodes[0].id]); + for (let n = 0; n < flow.nodes.length; n++) { + for (const edge of flow.edges) if (reached.has(edge.source)) reached.add(edge.target); + for (const node of flow.nodes) if (reached.has(node.parentId)) reached.add(node.id); + } + expect(reached.size, flow.name).toBe(flow.nodes.length); + expect(entry.cases.every(c => flow.nodes.some(n => n.id === c.targetNodeId && n.componentId === c.componentId))).toBe(true); + expect(JSON.parse(fs.readFileSync(path.join(bundleRoot, entry.file), "utf8"))).toEqual(flow); + } + }); + + it("目录修正可重复应用,前端类型选项都有实际判断与转换能力", async () => { + expect(applyCatalogOverrides(structuredClone(catalog))).toEqual(catalog); + for (const id of ["Basic_JudgeDataType", "Basic_DataTypeConversion"]) { + const component = componentMap.get(id); + const options = component.fields.find(field => field.key === "into_type").options; + expect(options.length).toBeGreaterThanOrEqual(4); + for (const option of options) { + const output = await import("../src/main/engine/registry.ts").then(({ getHandler }) => getHandler(id)({}, { id: "type-test", componentId: id }, { val: 42, into_type: option.value }, component)); + if (id === "Basic_JudgeDataType") expect(typeof output).toBe("boolean"); + } + } + const wake = componentMap.get("ScreenControl_ScreenUnlock"); + expect(wake.name).toContain("非登录解锁"); + expect(wake.fields).toHaveLength(0); + expect(componentMap.get("System_ScreenSaverShowV1").fields).toHaveLength(0); + }); + + it("只保留真实参数校验阻塞,不出现断链、未知变量或未接入节点", () => { + const blocked = []; + for (const { flow } of buildSuite()) { + const issues = validateFlow(flow, catalog); + expect(issues.every(issue => issue.code === "required"), flow.name).toBe(true); + if (issues.length) blocked.push(flow.id); + } + expect(blocked).toEqual(["test_appsystem_08", "test_appsystem_12"]); + const pidOnly = buildSuite()[0].flow; + const killV1 = pidOnly.nodes.find(n => n.componentId === "App_KillV1"); + killV1.values.p_name = ""; + expect(validateFlow(pidOnly, catalog).filter(issue => issue.nodeId === killV1.id)).toEqual([]); + }); + + it("真实执行转换流程,显式类型选项下完整核对全部用例", async () => { + const { group, result, logs } = await execute(2); + expect(result.status).toBe("succeeded"); + expect(result.variables.failures).toBe(0); + expect(result.variables.blocked).toBe(0); + expect(group.entry.cases.map(c => result.variables[c.resultVariable][2])).toEqual(Array(10).fill("PASS")); + expect(logs.filter(log => log.startsWith("用例结果:"))).toHaveLength(10); + }); + + it("注入错误返回类型时断言会失败,且前面的用例继续留有证据", async () => { + // 只改变内存中的测试副本,不把现有组件缺陷固化成测试的预期行为。 + const { result } = await execute(3, flow => { + const target = flow.nodes.find(n => n.componentId === "Basic_JudgeDataType"); + target.componentId = "Basic_SetVariable"; + target.values = { value: "number" }; + }); + expect(result.variables.failures).toBe(1); + expect(result.variables.case_12[2]).toBe("FAIL"); + expect(result.variables.case_12[5]).toBe("number"); + expect(result.variables.case_11[2]).toBe("PASS"); + }); + + it("变量、深复制、配置、流程信息和计数能够真实通过", async () => { + const { result } = await execute(4); + expect(result.status).toBe("succeeded"); + expect(result.variables.failures).toBe(0); + expect(result.variables.case_10[5]).toBe(14); + }); + + it("手动任务默认保护有效,不调用输入法、远程连接或断连操作", async () => { + for (const number of [9, 13]) { + const { group, result } = await execute(number); + expect(result.status).toBe("failed"); + expect(result.variables.pending).toBe(group.entry.cases.length); + for (const c of group.entry.cases) { + expect(result.nodes.some(n => n.nodeId === c.targetNodeId)).toBe(false); + expect(result.variables[c.resultVariable][2]).toBe("MANUAL"); + } + } + }); + + it("字符串 false 或 true 不会误开启手动保护", async () => { + for (const value of ["false", "true"]) { + const { group, result } = await execute(13, flow => { + flow.nodes.find(n => n.options.outputVar === "manualEnabled").values.value = value; + }); + for (const c of group.entry.cases) expect(result.nodes.some(n => n.nodeId === c.targetNodeId)).toBe(false); + } + }); + + it("只新增 13 个任务,重复安装保留用户已有修改且不改无关文件", () => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "rpa-appsystem-install-")); temporary.push(dir); + const first = installBundle(dir); + expect(first.installed).toHaveLength(13); + const file = path.join(dir, "flows/test_appsystem_01.json"); + fs.writeFileSync(file, "用户自行编辑的内容"); + fs.writeFileSync(path.join(dir, "flows/other.json"), "其他任务"); + const second = installBundle(dir); + expect(second.installed).toHaveLength(0); + expect(second.skipped).toHaveLength(13); + expect(fs.readFileSync(file, "utf8")).toBe("用户自行编辑的内容"); + expect(fs.readFileSync(path.join(dir, "flows/other.json"), "utf8")).toBe("其他任务"); + }); + + it("升级仅覆盖匹配旧模板的测试任务,并保存原文件备份", () => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), "rpa-appsystem-upgrade-")); temporary.push(dir); + installBundle(dir); + const baseline = path.join(dir, "baseline"), backup = path.join(dir, "backup"); + fs.mkdirSync(baseline); + for (const { entry, flow } of buildSuite()) { + const old = { ...flow, description: "旧测试模板" }; + fs.writeFileSync(path.join(baseline, entry.file), JSON.stringify(old)); + fs.writeFileSync(path.join(dir, "flows", entry.file), JSON.stringify(old)); + } + const changed = path.join(dir, "flows/test_appsystem_01.json"); + const userFlow = JSON.parse(fs.readFileSync(changed, "utf8")); userFlow.description = "用户已修改"; + fs.writeFileSync(changed, JSON.stringify(userFlow)); + const result = upgradeBundle(dir, baseline, backup); + expect(result.upgraded).toHaveLength(12); + expect(result.skipped).toContainEqual({ id: "test_appsystem_01", reason: "用户已修改,保留现有版本" }); + expect(fs.readFileSync(changed, "utf8")).toBe(JSON.stringify(userFlow)); + expect(JSON.parse(fs.readFileSync(path.join(backup, "test_appsystem_02.json"), "utf8")).description).toBe("旧测试模板"); + }); + + it("报告按最差用例聚合,不把任务成功或缺失的记录冒充组件通过", () => { + const group = buildSuite()[0]; + const variables = Object.fromEntries(group.entry.cases.map(c => [c.resultVariable, [c.id, c.componentId, "PASS", c.input, c.expected, 42]])); + variables.case_8[2] = "FAIL"; + const report = makeReport({ runs: [{ flowId: group.flow.id, status: "succeeded", result: { variables } }] }); + expect(report.components.find(c => c.id === "App_GetPid").status).toBe("FAIL"); + expect(report.components.find(c => c.id === "Basic_ConvertInt").status).toBe("UNRUN"); + expect(report.components.find(c => c.id === "System_PlaySound").status).toBe("MANUAL"); + expect(caseResults(group.entry, { status: "BLOCKED" }).every(c => c.status === "BLOCKED")).toBe(true); + }); +});