Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .claude/skills/frontend-api-testing/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ description: Tauri 前端 API 自动化测试开发技能。使用场景:(1)
|------|------|
| 添加自动测试 | [添加自动测试](#添加自动测试) |
| 添加手动测试 | [添加手动测试](#添加手动测试) |
| 添加自定义测试命令 | [添加自定义测试命令](#添加自定义测试命令) |
| 接入新 plugin | [接入新 plugin](#接入新-plugin) |
| 运行测试 | [运行测试](#运行测试) |
| 查看报告 | [测试报告](#测试报告) |
Expand Down Expand Up @@ -133,6 +134,20 @@ async function manualMyApi() {
- 将测试结果赋值给 `manualResult`,`wrapManual` 会自动捕获
- 按钮文案建议包含预期结果(如 `isFocused (should be true)`)

## 添加自定义测试命令(app command)

手动测试/自动测试若需调用自定义 Rust 命令(`#[command]`,如 `set_ime_position_test`),必须**三处都注册**,漏任何一处症状不同:

| # | 位置 | 作用 | 漏了的症状 |
|---|------|------|-----------|
| 1 | `src-tauri/src/cmd.rs` 定义 + `src/lib.rs` `invoke_handler` 注册 | 命令存在且可路由 | 编译错 `cannot find` / invoke 报 `unknown command` |
| 2 | `src-tauri/build.rs` `AppManifest::new().commands(&[...])` 清单 | 生成 ACL 权限标识 | **构建期 panic**:`Permission xxx not found`(改 build.rs 后会触发 codegen 重跑,暴露其他漏网命令) |
| 3 | `src-tauri/capabilities/run-app.json` 加 `"allow-<命令名>"` | 运行时授权 | **编译安装正常,点击按钮时报 `not allowed. Permissions associated with this command: allow-xxx`**(ACL 拦截,见 hilog ARKWEB-CONSOLE) |

> 坑点:第 3 处最隐蔽——前两处漏了会在编译期暴露,第 3 处只有真机点击才触发。新增命令后顺手检查 run-app.json(对照同批已有命令如 `allow-set-ime-position-test` 的位置追加)。

另需注意命令的 cfg 门控要对称:`#[cfg(target_env = "ohos")]` 实现和 `#[cfg(not(...))]` stub 都要定义,否则其他平台编译失败。

## 接入新 plugin

除了添加 TestCase,还需配置依赖和权限。
Expand Down Expand Up @@ -234,6 +249,8 @@ hdc shell "cat /data/app/el2/100/base/com.tauri.api/cache/test-report.md"

**Plugin command 未注册** — 检查 `capabilities/run-app.json` 是否包含对应权限。

**App command 报 `not allowed`(编译安装都正常)** — 命令在 build.rs 和 lib.rs 都注册了,但 `capabilities/run-app.json` 漏了 `allow-<命令名>` 授权。真机点击时 hilog(ARKWEB-CONSOLE)可见 `xxx not allowed. Permissions associated with this command: allow-xxx`。详见 [添加自定义测试命令](#添加自定义测试命令)。

**HTTP scope 限制** — `plugin-http` fetch 需声明 URL scope:
```json
{ "identifier": "http:default", "allow": [{ "url": "https://www.example.com/*" }] }
Expand Down
120 changes: 48 additions & 72 deletions .claude/skills/ohos-build/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ description: 编译 Tauri OpenHarmony 项目(examples/api),生成 HAP 包
> **路径约定**: 以下脚本中 `${PROJECT_ROOT}` 指 tauri 和 openharmony-ability 共同的父目录。
> 例如本地布局为 `/d/xuqiu/tauri-2.0/{tauri,openharmony-ability}` 时,`PROJECT_ROOT=/d/xuqiu/tauri-2.0`。
> 使用前请先 `export PROJECT_ROOT=...` 或在 env.sh 中设置。

## 构建方式

### 方式一:cargo tauri ohos run(推荐)
Expand Down Expand Up @@ -38,14 +38,15 @@ OHOS_DEVICE_TYPE=desktop bash ${PROJECT_ROOT}/tauri/.claude/skills/ohos-build/sc
**注意**:必须先设置 `OHOS_DEVICE_TYPE` 环境变量再调用脚本。不要先 `source env.sh`,因为 `env.sh` 会设置 `OHOS_DEVICE_TYPE` 默认值,可能覆盖你传入的参数。

脚本自动完成全部流程:
1. 检测 `openharmony-ability/` 源码变更,自动重建 HAR 包(ohpm 同步由第 3 步 `cargo tauri ohos run` 内部完成,不手动 ohpm)
2. prerequisites(CLI 不做的前置):pnpm install / build:api / 插件 dist-js / ACL 检查
3. `cargo tauri ohos run` 一步完成:
- 前端构建(beforeBuildCommand,继承 VITE_AUTOTEST=true)
- Rust 交叉编译(aarch64-unknown-linux-ohos,release,--features prod)
- .so 拷贝 + hvigorw assembleHap(TAURI_OHOS_SKIP_DEVECO_SCRIPT 禁用 tauriPlugin,build-profile.json5 证书签名)
- 安装已签名 HAP(带 hdc false-success 检测)→ 启动
4. 等待 30s → 拉取 test-report → 分析结果
1. 检测 `openharmony-ability/` 源码变更,自动重建 HAR 包并 ohpm install
2. 前端构建(pnpm + vite,VITE_AUTOTEST=true)
- Step 2: 构建 @tauri-apps/api(首次或缺失时)
- Step 2.5: 构建插件 dist-js(每次执行,防止 git pull 后插件产物过期)
- Step 3: 前端 vite 构建
3. Rust 交叉编译(aarch64-unknown-linux-ohos,release,--features prod)
4. 拷贝 .so → hvigorw assembleHap(自动禁用/恢复 tauriPlugin,使用 build-profile.json5 中的证书签名)
5. 卸载旧版 → 安装已签名 HAP → 启动
6. 等待 30s → 拉取 test-report → 分析结果

### 方式三:cargo tauri ohos build --app(多形态打包)

Expand Down Expand Up @@ -93,11 +94,10 @@ PR #59 将 app 拆分为 mobile 和 desktop 两个 entry 模块:

| 脚本 | 功能 |
|------|------|
| `env.sh` | 环境配置:DevEco Studio 路径解析(`DEV_ECO_STUDIO_INSTALL_PATH` 优先 → `DEVECO_HOME` → 自动检测,不落盘)、CC/linker/JAVA_HOME/PATH,必须在其他脚本前 source |
| `prerequisites.sh` | CLI 不做的开发期前置:pnpm install / build:api / 插件 dist-js / ACL 检查。被 build-ohos.sh 和 run-tests.sh source,不直接执行 |
| `run-tests.sh` | 一键全流程:HAR 重建 → prerequisites → `cargo tauri ohos run`(build+install+launch,带 hdc false-success 检测)→ 等待 → 拉取报告 → 分析 |
| `build-ohos.sh` | prerequisites + `cargo tauri ohos build`(Rust 编译/.so/hvigorw/签名由 CLI 处理)。项目专属 feature 经 `TAURI_BUILD_FEATURES` 传入 |
| `install.sh` | 仅安装启动(使用已签名 HAP),不构建不签名。日常流程已被 `cargo tauri ohos run` 替代;保留供单独安装场景 |
| `env.sh` | 环境配置:CC/linker/JAVA_HOME/PATH,必须在其他脚本前 source |
| `run-tests.sh` | 一键全流程(含模板检测、HAR 自动重建、tauriPlugin 自动禁用/恢复、自动测试) |
| `build-ohos.sh` | 构建全流程(模板检测 → 前端 → Rust → .so → hvigorw 签名打包),自动处理 tauriPlugin |
| `sign-and-install.sh` | 仅安装启动(使用 hvigorw 已签名的 HAP),不构建不签名 |

## 模板修改后的完整生效流程

Expand All @@ -113,17 +113,16 @@ cmd.exe /c "rmdir /s /q ${PROJECT_ROOT}\\tauri\\examples\\api\\src-tauri\\gen\\o

# 3. 执行「init 后补充步骤」(见下方章节)

# 4. 重建 HAR(仅当改了 openharmony-ability 的 ArkTS 源码;改 Rust 源码跳过此步)
# 4. 重建 HAR 并 ohpm install
cd ${PROJECT_ROOT}/openharmony-ability
source ${PROJECT_ROOT}/tauri/.claude/skills/ohos-build/scripts/env.sh
./pack.bat # Windows 批处理:同步 native_ability ETS → package/ + tar 打 ability.har
# 5. 构建 HAP —— cargo tauri 内部会自动跑 ohpm install 同步依赖,严禁手动 ohpm
cd ${PROJECT_ROOT}/tauri/examples/api/src-tauri
cargo tauri ohos build --device-type desktop --features prod
ohrs build --arch arm64 --skip-napi-check 2>&1 | tail -5 || true
bash scripts/pack.sh
tar -czf ability.har package
cd ${PROJECT_ROOT}/tauri/examples/api/src-tauri/gen/ohos
ohpm install --all
```

> **严禁手动 `ohpm install`**:`cargo tauri ohos build/run` 内部会跑 ohpm 同步依赖(受 `oh-package-lock.json5` 约束,安全)。手动 `ohpm install --all` 会删掉 lock 文件、清空 `oh_modules/@tauri/` junction、误删本地包目录,导致 hvigorw 00304056 / 00625003。详见 memory `ohos-arkts-rebuild-flow`。

## init 后补充步骤(每次 `tauri ohos init` 后必须执行)

`tauri ohos init` 重新生成 `gen/ohos/` 后,以下内容会丢失或缺失,需要手动补充:
Expand Down Expand Up @@ -233,69 +232,33 @@ cp ${PROJECT_ROOT}/tauri/.claude/skills/ohos-build/templates/testtrayability/Tes
3. **hdc 路径转义** — Git Bash 把 `/data/...` 转为 Windows 路径。设备路径命令用 `hdc shell "cat ..."` 加引号。
4. **签名由 hvigorw 完成** — build-profile.json5 中配置了含 system_basic 权限的证书,hvigorw assembleHap 自动签名。无需手动签名。
5. **HAR 缓存** — 修改了 openharmony-ability 后必须重建 HAR。`run-tests.sh` Step 0 自动检测并处理。
6. **tauriPlugin** — hvigorfile.ts 中的 tauriPlugin 需要 TCP 回调 tauri CLI,独立构建时必须禁用。`cargo tauri ohos build/run` 通过 `TAURI_OHOS_SKIP_DEVECO_SCRIPT=1` 环境变量自动处理(非 sed 改文件)
6. **tauriPlugin** — hvigorfile.ts 中的 tauriPlugin 需要 TCP 回调 tauri CLI,独立构建时必须禁用。`build-ohos.sh` 和 `run-tests.sh` 自动处理
7. **tauri-cli 修改后必须重装** — 如果修改了 `crates/tauri-cli/` 下的 Rust 源码(非模板文件),必须重新安装 tauri-cli,否则 `cargo` 使用缓存的旧二进制,改动不生效:
```bash
cargo install --path crates/tauri-cli --locked
```
仅修改模板文件(`templates/` 下)不需要重装,`cargo tauri ohos build/run` 的 `ensure_init` 会自动检测并重建 `gen/ohos/`。
8. **插件 dist-js 自动构建** — `prerequisites.sh` 每次执行 `pnpm build` 构建 `plugins-workspace/` 下所有插件的 `dist-js`,防止 git pull/rebase 后插件产物过期导致测试失败(如 notification 插件 `index.js` 过期)。
仅修改模板文件(`templates/` 下)不需要重装,`build-ohos.sh` 会自动检测模板 mtime 并重建 `gen/ohos/`。
8. **插件 dist-js 自动构建** — `build-ohos.sh` Step 2.5 每次执行 `pnpm build` 构建 `plugins-workspace/` 下所有插件的 `dist-js`,防止 git pull/rebase 后插件产物过期导致测试失败(如 notification 插件 `index.js` 过期)。
9. **cargo-mobile2 仓库** — `tauri-cli` 依赖 `cargo-mobile2`(位于 `${PROJECT_ROOT}/cargo-mobile2`)。如果 tauri-cli 编译报 `unresolved import cargo_mobile2::open_harmony::app`,说明 cargo-mobile2 需要 rebase 到 upstream/ohdev。
10. **PR #59 双 Entry 模块** — 项目结构从单一 `entry/` 拆分为 `entry_desktop/` + `entry_mobile/`。`OHOS_DEVICE_TYPE` 决定激活哪个模块(`active_entry_module()` 返回 `entry_{form}`)。`cargo tauri ohos build --app` 同时构建两个模块。
11. **@tauri ohpm junctions** — `ohpm install` 会删除 `@tauri/*` 本地链接(`oh_modules/@tauri/`)。每次 `ohpm install` 后需要手动重建 junction:
```bash
cd gen/ohos && mkdir -p oh_modules/@tauri && for pkg in app notification global-shortcut dialog; do
src=""; case $pkg in app) src="tauri" ;; *) src="$pkg" ;; esac
[ -d "$src" ] && cmd //c "mklink /J \"oh_modules\\@tauri\\$pkg\" \"$(pwd -W)\\$src\"" 2>/dev/null
done
```

## 设备日志与故障诊断

### 标准 hilog 捕获流程(调试任何窗口/IPC/能力不生效问题)

**核心原则:必须先开流式 grep 转存到本地文件,再启动 app,等测试跑完,最后读文件。**

严禁:
- ❌ 在控制台直接流式阅读(`hilog | grep` 挂在前台肉眼看)—— 行数多、易漏、无法回溯
- ❌ `nohup hdc shell hilog > /tmp/full.log` 全量落盘再 grep —— 每秒千行,文件几十万行,既慢又浪费
- ❌ 只用 `hilog -x`(dump 历史)排查已发生事件 —— 缓冲区会轮转,早于几分钟前的日志已被冲掉
- ❌ 不关流量控制就开流 —— hilog 默认按进程/domain 流量控制(drop 策略),高量时段会静默丢弃日志行,导致捕获文件缺行(现象:明明设备打了某条日志,你的文件里却没有)。**必须先 `hilog -Q pidoff` + `hilog -Q domainoff` 关闭流量控制再开流**

正确流程(5 步):

```bash
# 0. 【必须先做】关闭 hilog 流量控制,否则高量时段日志被静默丢弃导致捕获缺行
hdc shell "hilog -Q pidoff"
hdc shell "hilog -Q domainoff"

# 1. 单开一个控制台,启动 hilog 流式 grep 转存到本地文件
# 关键字: tauritest (Rust log, domain A00000) + 1999 (ArkTS hilog, domain A01999)
# 按需加业务关键字: setFullscreen / WindowManager / resizeWindow 等
nohup hdc shell "hilog 2>/dev/null | grep -aE 'tauritest|1999'" > /tmp/hilog-capture.log 2>&1 &

# 2. 重启 app 触发待调试行为(force-stop → aa start)
hdc shell "aa force-stop com.tauri.api"
sleep 2
hdc shell "aa start -b com.tauri.api -a EntryAbility"

# 3. 等待测试执行完毕(autotest 全量约 60s,单用例约 2-5s,按需调整)
sleep 60

# 4. 阅读转存文件(停止流后读,或读过程中 tail)
pkill -f "hilog 2>/dev/null" # 停止后台流
grep -aE 'setFullscreen|setWindowLayoutFullScreen' /tmp/hilog-capture.log
```

**关键字说明:**
- `tauritest` — Rust 侧 `log::info!` / `crate::info!`(domain `A00000`,tag `tauritest`)。仅当 openharmony-ability 的 `log` feature 启用时输出;examples/api 默认**未启用**,Rust 日志为 no-op。
- `1999` — ArkTS `hilog`(domain `A01999`,tag 如 `WindowManager` / `ArkHelper`)。ArkTS hilog 无条件输出,是排查"ArkTS 方法是否被调用"的首要证据。
- `-a` 强制文本匹配(避免二进制行被过滤);设备端管道 grep 完才传回,只传匹配行。

**用此流程区分"flag 翻转但效果不生效"类问题:**
- ArkTS 方法 `ENTER` 日志**有** → NAPI 调用链通,问题在 ArkTS/系统层
- ArkTS 方法 `ENTER` 日志**无** → NAPI 断裂(Rust `let _ =` 吞错),问题在 Rust→ArkTS 桥接
# 实时日志(持续输出,Ctrl+C 停止)
hdc shell "hilog | grep -i 关键词"

### 其他诊断命令

```bash

# 缓冲区历史日志(非阻塞,-x dump 历史)
# 注意:缓冲区会轮转,仅适合查近几分钟事件;查更早用下方归档文件
hdc shell "hilog -x 2>/dev/null | grep -aE '关键字'"
# 缓冲区日志(非阻塞,-z 取最后 N 行)
# Rust log::info/error 的 domain 为 A00000,tag 为 tauritest
hdc shell "hilog -x" | grep "com.tauri"

# hilog 归档文件(选 hilog.*.gz,忽略 hilog_kmsg.*.gz)
hdc shell "ls -lt /data/log/hilog/ | grep -v hilog_kmsg | grep hilog | head -3"
Expand All @@ -318,3 +281,16 @@ hdc shell "cat /data/app/el2/100/base/com.tauri.api/cache/panic.log"
|------|------|------|
| App 内部(Rust 代码中) | `/data/storage/el2/base/cache/` | 应用沙箱路径 |
| 外部(hdc 访问) | `/data/app/el2/100/base/com.tauri.api/cache/` | 实际物理路径 |

## 手动 HAR 重建(仅在脚本自动检测失效时需要)

```bash
cd ${PROJECT_ROOT}/openharmony-ability
source ${PROJECT_ROOT}/tauri/.claude/skills/ohos-build/scripts/env.sh
ohrs build --arch arm64 # 末尾 panic 是已知问题,不影响
bash scripts/pack.sh
tar -czf ability.har package
cd ${PROJECT_ROOT}/tauri/examples/api/src-tauri/gen/ohos
ohpm install --all
# 重建 @tauri junctions(见注意事项 #11)
```
Loading
Loading