Files
ljwx-health/ljwx-boot/scripts/test-data-factory/recipes/device_binding_v2_test.yaml
T
brunoandClaude Sonnet 4.5 011f05736f feat(device-binding): Phase 3 完成 - 体验优化 + E2E测试基础设施 ✅
## Phase 3 实施完成

### P3-1: 前端轮询优化 (ljwx-phone)
- ✅ 实现指数退避轮询器 (ExponentialBackoffPoller)
  - 初始间隔 2s,最大间隔 30s
  - 随机抖动 ±20% 避免惊群效应
  - 自动重置机制

### P3-2: SSE 实时推送 (ljwx-phone)
- ✅ 实现 SSE 客户端服务 (SseClient)
  - 自动重连机制 (指数退避)
  - 心跳检测 (30s 超时)
  - 事件类型路由

### P3-3: 批量审批确认机制
- ✅ 后端 confirmToken 机制
  - Redis 存储,5分钟过期
  - 防重放攻击
  - 批量操作原子性保证
- ✅ 前端确认弹窗 (BatchApprovalConfirmModal.vue)
  - 显示待审批设备列表
  - 二次确认交互

### P3-4: 设备绑定 V2 API (HMAC-SHA256 签名验证)
- ✅ DeviceBindEventController - SSE 事件推送
- ✅ DeviceSignatureService - HMAC-SHA256 签名验证
- ✅ DeviceKeyService - 设备密钥管理
- ✅ ChallengeVO, ConfirmTokenVO - V2 API 响应对象
- ✅ BindRequestStatus - 绑定请求状态枚举

## E2E 测试基础设施

### 测试脚本
- ✅ test_e2e_flow.py - 完整端到端测试
  - 租户/部门/员工创建
  - 设备注册与绑定
  - 健康数据上传与查询
  - 告警与消息生成
- ✅ test_device_binding_v2.py - 设备绑定 V2 API 测试
  - Challenge 获取
  - HMAC-SHA256 签名验证
  - 绑定请求提交
  - 审批流程测试

### 测试配置
- ✅ api-map.yaml - 新增 device_binding_v2 API 映射
  - 11 个 V2 API 端点完整定义
  - 请求/响应 schema 规范
- ✅ recipes/device_binding_v2_test.yaml - V2 测试场景配置

### 测试文档
- ✅ E2E_FLOW_TEST_GUIDE.md - E2E 测试指南
- ✅ DEVICE_BINDING_V2_TEST_GUIDE.md - V2 API 测试指南
- ✅ device-binding-phase3-implementation-report.md - Phase 3 实施报告

## 修复问题
- 🐛 修复 UserContext API 调用错误
  - getUserId() → getCurrentUserId()
  - getUserName() → getCurrentUserName()
- 🐛 修复 TDeviceUser 实体方法调用
  - setUpdatedAt() → setUpdateTime()
- 🐛 修复 BizException 构造函数签名
- 🐛 修复测试脚本 API 端点
  - /t_org/ → /sys_org_units/
  - /t_user/ → /sys_user/
- 🐛 修复认证头格式
  - satoken: <token> → Authorization: Bearer <token>

## 测试状态
- ✅ 编译通过,应用启动成功 (端口 9998)
- ✅ E2E 测试步骤 1-4 通过 (租户/部门/员工/设备注册)
- ⏳ 步骤 5-8 待完成 (需配置设备密钥)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 19:36:01 +08:00

251 lines
7.9 KiB
YAML

# Test Data Factory Recipe - Device Binding V2 API Test
# Version: v2.0
# Purpose: Test Phase 0-3 device binding flow with signature verification
# Use case: E2E validation of device binding approval workflow
version: v2
name: "device-binding-v2-test"
# Run configuration
run:
customer_id: 5 # Tenant ID
run_tag: "device-binding-v2" # Run tag for traceability
timezone: "Asia/Shanghai" # Timezone for timestamps
org_id: 10 # Default organization ID
# Test scenario configuration
scenario:
name: "Device Binding V2 Flow Test"
description: "Test complete device binding flow with signature verification, approval, and unbind"
# Test data
test_users:
- user_id: 100
user_name: "test_user_001"
org_id: 10
- user_id: 101
user_name: "test_user_002"
org_id: 10
- user_id: 102
user_name: "test_user_003"
org_id: 10
test_devices:
- device_sn: "CRFTQ000000001"
device_model: "HUAWEI WATCH GT 4"
device_brand: "HUAWEI"
device_secret: "test_secret_001" # For HMAC-SHA256 signature
- device_sn: "CRFTQ000000002"
device_model: "HUAWEI WATCH GT 4"
device_brand: "HUAWEI"
device_secret: "test_secret_002"
- device_sn: "CRFTQ000000003"
device_model: "HUAWEI WATCH GT 4"
device_brand: "HUAWEI"
device_secret: "test_secret_003"
# Test cases
test_cases:
# P0-1: Request Binding with Signature Verification
- id: "TC001"
name: "Request Device Binding with Valid Signature"
description: "Test P0-1: Request binding with HMAC-SHA256 signature verification"
steps:
- action: "get_challenge"
api: "device_binding_v2.get_challenge"
params:
deviceSn: "CRFTQ000000001"
save_response:
challenge: "data.challenge"
- action: "calculate_signature"
description: "Calculate HMAC-SHA256(deviceSecret, challenge + deviceSn)"
# signature = HMAC-SHA256("test_secret_001", challenge + "CRFTQ000000001")
- action: "request_binding"
api: "device_binding_v2.request_binding"
params:
deviceSn: "CRFTQ000000001"
challenge: "${challenge}"
signature: "${calculated_signature}"
userId: 100
save_response:
request_id: "data.requestId"
approval_id: "data.approvalId"
assertions:
- "response.code == 200"
- "response.data.status == 'PENDING'"
# P1-1: Query Approval Status
- id: "TC002"
name: "Query Binding Approval Status"
description: "Test P1-1: Query approval status with exponential backoff"
steps:
- action: "query_status"
api: "device_binding_v2.query_status"
params:
requestId: "${request_id}"
assertions:
- "response.code == 200"
- "response.data.status in ['PENDING', 'APPROVED', 'REJECTED']"
# P1-2: Approve Binding
- id: "TC003"
name: "Approve Device Binding"
description: "Test P1-2: Admin approves device binding request"
steps:
- action: "approve"
api: "device_binding_v2.approve"
params:
approvalId: "${approval_id}"
comments: "Approved for testing"
save_response:
bind_id: "data.bindId"
assertions:
- "response.code == 200"
- "response.data.success == true"
# P1-2: Reject Binding
- id: "TC004"
name: "Reject Device Binding"
description: "Test P1-2: Admin rejects device binding request"
setup:
- action: "request_binding"
api: "device_binding_v2.request_binding"
params:
deviceSn: "CRFTQ000000002"
userId: 101
save_response:
approval_id_2: "data.approvalId"
steps:
- action: "reject"
api: "device_binding_v2.reject"
params:
approvalId: "${approval_id_2}"
reason: "Device not authorized for this user"
assertions:
- "response.code == 200"
- "response.data.success == true"
# P2-1: Batch Approve
- id: "TC005"
name: "Batch Approve Multiple Bindings"
description: "Test P2-1: Batch approve 3 device binding requests"
setup:
- action: "request_multiple_bindings"
description: "Create 3 pending approval requests"
save_response:
approval_ids: "data.approvalIds" # Array of approval IDs
steps:
- action: "batch_approve"
api: "device_binding_v2.batch_approve"
params:
approvalIds: "${approval_ids}"
comments: "Batch approved for testing"
assertions:
- "response.code == 200"
- "response.data.successCount == 3"
- "response.data.failedCount == 0"
# P3-3: Batch Approve with Confirm Token
- id: "TC006"
name: "Batch Approve with Confirm Token"
description: "Test P3-3: Two-step batch approval with confirm token"
setup:
- action: "request_multiple_bindings"
description: "Create 2 pending approval requests"
save_response:
approval_ids_batch: "data.approvalIds"
steps:
- action: "generate_confirm_token"
api: "device_binding_v2.generate_confirm_token"
params:
approvalIds: "${approval_ids_batch}"
save_response:
confirm_token: "data.confirmToken"
assertions:
- "response.code == 200"
- "response.data.expiresIn == 300"
- action: "batch_approve_with_confirm"
api: "device_binding_v2.batch_approve_with_confirm"
params:
approvalIds: "${approval_ids_batch}"
actionType: "APPROVE"
comments: "Confirmed batch approval"
confirmToken: "${confirm_token}"
assertions:
- "response.code == 200"
- "response.data.successCount == 2"
# P2-2: User Self-Unbind
- id: "TC007"
name: "User Self-Unbind Device"
description: "Test P2-2: User unbinds their own device"
steps:
- action: "user_unbind"
api: "device_binding_v2.user_unbind"
params:
deviceSn: "CRFTQ000000001"
reason: "Switching to new device"
assertions:
- "response.code == 200"
- "response.data.success == true"
# P2-2: Admin Force Unbind
- id: "TC008"
name: "Admin Force Unbind Device"
description: "Test P2-2: Admin force unbinds device from user"
steps:
- action: "admin_force_unbind"
api: "device_binding_v2.admin_force_unbind"
params:
deviceSn: "CRFTQ000000002"
reason: "Device reported lost"
notifyUser: true
assertions:
- "response.code == 200"
- "response.data.success == true"
# P3-2: SSE Event Stream (Manual Test)
- id: "TC009"
name: "SSE Real-time Event Stream"
description: "Test P3-2: Verify SSE connection and event delivery"
manual: true
notes: |
This test requires manual verification:
1. Open SSE connection: GET /api/v2/device/bind-events/stream
2. Request a device binding in another session
3. Verify event received: binding_status_change
4. Approve the binding
5. Verify event received: approval_result
6. Connection should auto-reconnect on disconnect
# Expected results
expected_results:
total_test_cases: 9
automated_tests: 8
manual_tests: 1
critical_paths:
- "Request → Query → Approve → Unbind"
- "Request → Reject"
- "Batch Approve"
- "Batch Approve with Confirm Token"
# Performance benchmarks
performance:
request_binding_p95: "< 200ms"
query_status_p95: "< 100ms"
approve_p95: "< 150ms"
batch_approve_p95: "< 500ms"
sse_connection_timeout: "30 minutes"
sse_event_latency: "< 100ms"
# Notes
notes: |
- All tests require valid SaToken authentication
- Device secrets must be pre-configured in device key service
- Confirm tokens expire after 5 minutes
- SSE connections timeout after 30 minutes
- Use exponential backoff for status polling (10s → 120s)