一键导入
qa-testing
Execute scenario-based QA testing with browser automation, database validation, and automatic ticket creation for failures.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Execute scenario-based QA testing with browser automation, database validation, and automatic ticket creation for failures.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Run E2E tests for Auth9 portal using Playwright with hybrid testing strategy.
Run tests, check logs, and troubleshoot Auth9 services in Docker and Kubernetes environments.
Run performance benchmarks for auth9-core API using hey load testing tool.
Reset Auth9 local Docker development environment to a clean state.
Rust coding conventions and patterns for auth9-core development.
Run tests and check coverage for Auth9 backend, frontend, and SDK with mock-based testing patterns.
| name | qa-testing |
| description | Execute scenario-based QA testing with browser automation, database validation, and automatic ticket creation for failures. |
Execute scenario-based manual QA testing for Auth9 using Playwright browser automation with Docker environment validation.
./scripts/reset-docker.sh (avoid hard-coding in docs/skills)To prevent repository-root pollution during QA:
DATE=$(date +%F)
EVIDENCE_DIR="artifacts/qa/${DATE}"
mkdir -p "$EVIDENCE_DIR"
$EVIDENCE_DIR (or its subfolders).*.png, *.jpg, *.json, ad-hoc logs) to repository root.scripts/qa/, not root.artifacts/qa/{date}/tickets/{ticket_filename_without_ext}/artifacts/qa/{date}/ immediately.QA testing against auth9-core API requires a Bearer token. Do NOT explore the codebase to figure out how to get a token. Use the helper tools below directly.
# Generate admin JWT token (valid 1 hour, RS256 signed)
TOKEN=$(.claude/skills/tools/gen-admin-token.sh)
# Use in curl requests
curl -s http://localhost:8080/api/v1/tenants \
-H "Authorization: Bearer $TOKEN"
For repeated API calls, use the wrapper script that auto-injects the token:
# GET request
.claude/skills/tools/qa-api-test.sh GET /api/v1/tenants
# POST with JSON body
.claude/skills/tools/qa-api-test.sh POST /api/v1/users '{"email":"test@example.com","password":"Pass123!"}' # pragma: allowlist secret
# PUT with JSON body
.claude/skills/tools/qa-api-test.sh PUT /api/v1/tenants/{id}/password-policy '{"min_length":12}'
746ceba8-3ddf-4a8b-b021-a1337b7a1a35 (admin@auth9.local).claude/skills/tools/jwt_private_clean.key)http://localhost:8080node + jsonwebtoken npm package (already in project root gen_token.js)Use hey for concurrent request testing:
hey -n 20 -c 20 -m POST \
-H "Content-Type: application/json" \
-d '{"email": "test@example.com"}' \
http://localhost:8080/api/v1/auth/forgot-password
Note: Rate limiting is active on some endpoints (e.g., forgot-password: 5 req/min, token: 10 req/min).
All test data (emails, URLs, domains) must comply with docs/testing/test-domain-policy.md. Summary:
@example.com, @test.com, @auth9.localhttps://*.example.com/...*.example.com (e.g. acme.example.com)evil.com, attacker.com, attacker.exampleexample.comtest-enterprise.com, acme.com, corp.com, etc.scripts/qa/)IMPORTANT: A collection of reusable QA test scripts already exists in scripts/qa/. Before writing any new test script, always check scripts/qa/ first for an existing script that covers the same or similar scenario.
ls scripts/qa/ or Glob: scripts/qa/* to find existing scripts. If a matching script exists, use it directly (or adapt it) instead of creating a new one.scripts/qa/: When a new test script is needed, always place it under scripts/qa/ — never in the project root or other ad-hoc locations.test-{feature}.{js,mjs,py,sh} or {feature}_test.py.IMPORTANT: This skill is strictly for testing and reporting. NEVER attempt to fix, patch, or modify any source code during QA testing. If a test fails, create a ticket immediately and move on to the next scenario.
1. Confirm QA document with user
2. List all test scenarios
3. For each scenario:
a. Execute test in browser
b. If error → Check Docker logs
c. Validate database state
d. If FAIL → Immediately create ticket in docs/ticket/ (DO NOT defer)
e. Report scenario result (PASS/FAIL) before moving to next
4. Report final summary to user
5. Run workspace hygiene check (no QA artifacts in repository root)
Ticket creation rule: Create the ticket the moment a scenario is confirmed as FAIL — before starting the next scenario. This ensures no failure is lost if the session is interrupted, and gives the user real-time visibility into issues as they surface.
CRITICAL: Always confirm with user which QA document to test.
Glob: docs/qa/**/*.md
Modules: tenant/, user/, rbac/, service/, invitation/, session/, webhook/, auth/
Exclude docs/qa/README.md (just an index).
docs/qa/README.md, list modules, ask user to chooseExtract from confirmed document:
token_type and tenant_id fieldsid valuesUUID(), configure missing service). Do NOT skip gates and proceed — this is the primary cause of false-positive tickets.Use playwright-cli commands via Bash:
# 1. Open browser and navigate
playwright-cli open http://localhost:3000
# 2. Snapshot to get page structure and element refs
playwright-cli snapshot
# 3. Login (if needed):
playwright-cli fill e1 "admin"
playwright-cli fill e2 "SecurePass123!"
playwright-cli click e3
# 4. Execute test steps:
# - snapshot before each interaction
playwright-cli snapshot
# - click, type, fill for interactions
playwright-cli click e5
playwright-cli type "some text"
# - snapshot to verify results
playwright-cli snapshot
# 5. Close browser when done
playwright-cli close
If screenshots are required for evidence, always save into $EVIDENCE_DIR:
# Example only; keep filenames scenario-oriented
playwright-cli screenshot "$EVIDENCE_DIR/scenario-01-login.png"
Rules:
playwright-cli snapshot before interactions to get element refsIf step fails:
docker logs auth9-core --tail 50
docker logs auth9-portal --tail 50
docker logs auth9-oidc --tail 50
After each scenario:
mysql -h 127.0.0.1 -P 4000 -u root auth9 -e "SELECT ..."
Compare actual vs expected:
CRITICAL: Create the ticket RIGHT NOW, before moving to the next scenario. Do NOT accumulate failures for batch ticket creation later. Each failed scenario gets its own ticket written to docs/ticket/ immediately upon confirmation of failure.
Workflow per failure:
docs/ticket/ using the naming and structure belowdocs/ticket/{filename}.md"This ensures:
When attaching evidence in ticket markdown, use paths under artifacts/qa/{date}/... only.
For UIUX test documents: In addition to functional failures, visibility and accessibility issues MUST also result in ticket creation. This applies even when the underlying functionality works correctly. Examples include:
When creating a ticket for a UIUX visibility/accessibility issue, set:
Medium (default) — raise to High if the issue blocks a user action or violates WCAG 2.1 Level AFrontendFormat: {module}_{document}_scenario{N}_{YYMMDD_HHMMSS}.md
Example: docs/ticket/user_01-crud_scenario2_260203_143052.md
# Ticket: {Scenario Title}
**Created**: {YYYY-MM-DD HH:mm:ss}
**QA Document**: `docs/qa/{module}/{document}.md`
**Scenario**: #{number}
**Status**: FAILED
---
## 测试内容
{Brief description}
**Test Location**: {UI path or API endpoint}
---
## 预期结果
{Expected outcome}
**Expected Database State**:
```sql
{SQL queries}
{Initial state requirements}
UI Error:
{Error message}
Database State:
{Actual data}
Data Mismatch:
{Relevant log lines}
Root Cause: {Analysis} Severity: High / Medium / Low Related Components: Frontend / Backend / Database / Auth9-OIDC / Redis
Ticket generated by QA Testing Skill
## Step 4: Final Test Summary (report to user, don't save)
```markdown
✅ 测试完成!
📊 测试结果:
- 通过: 11/13 (84.6%)
- 失败: 2/13
🎫 创建的 Tickets:
1. docs/ticket/user_01-crud_scenario4_260203_143052.md
- Scenario #4: Update user profile
- Severity: High
-- User
SELECT id, email, display_name, mfa_enabled FROM users WHERE email = 'test@example.com';
SELECT tu.*, t.name FROM tenant_users tu JOIN tenants t ON t.id = tu.tenant_id WHERE tu.user_id = '{id}';
-- Tenant
SELECT id, name, slug, status FROM tenants WHERE slug = 'test-tenant';
SELECT * FROM services WHERE tenant_id = '{id}';
-- RBAC
SELECT r.name, utr.* FROM user_tenant_roles utr JOIN roles r ON r.id = utr.role_id WHERE utr.tenant_user_id = '{id}';
SELECT p.* FROM permissions p JOIN role_permissions rp ON rp.permission_id = p.id WHERE rp.role_id = '{id}';
reset-local-env skill if needed| Issue | Solution |
|---|---|
| Browser fails | curl http://localhost:3000, check auth9-portal logs |
| DB connection fails | docker ps | grep tidb, reconnect |
| Services not responding | docker ps, restart services, reset env |
| 403 "Identity token is only allowed for tenant selection and exchange" | Using Identity Token instead of Tenant Access Token. Run gate check: echo $TOKEN | cut -d. -f2 | base64 -d | jq .token_type — regenerate with gen-test-tokens.js tenant-owner |
| 500 ColumnDecode error on API call | Non-UUID id values in database (from manual INSERT). Run: SELECT id FROM {table} WHERE id NOT REGEXP '^[0-9a-f]{8}-' — delete and re-insert with UUID() |
| Feature appears missing or unconfigured | Environment prerequisite not met (e.g., IdP not configured, init not run). Check the scenario's 步骤 0 for required state verification |
# Get messages
curl http://localhost:8025/api/v1/messages
# Search
curl "http://localhost:8025/api/v1/search?query=to:test@example.com"
# Clear all
curl -X DELETE http://localhost:8025/api/v1/messages
Invitation flow: Clear mailpit → Send invitation → Get email → Extract link → Complete test
# Parse QR code
zbarimg --raw totp-qr.png
# Output: otpauth://totp/auth9:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=auth9
# Extract secret
SECRET=$(zbarimg --raw totp-qr.png | sed -n 's/.*secret=\([^&]*\).*/\1/p')
# Generate TOTP code
oathtool --totp -b "$SECRET"
API: POST /api/users/{id}/mfa/enable, POST /api/users/{id}/mfa/disable
IMPORTANT: See references/api-testing-cookbook.md for full recipes and common pitfalls.
auth9.TokenExchange (NOT auth9.token_exchange.TokenExchange)-cacert /certs/ca.crt -cert /certs/client.crt -key /certs/client.keyx-api-key: dev-grpc-api-key (required)grpcurl-docker.sh or Docker network-import-path /proto -proto auth9.protoservice_id: Use OAuth client_id string (e.g. auth9-portal), NOT service UUIDauth9-platform tenant: Use auth9-platform tenant ID, not demoTOKEN=$(.claude/skills/tools/gen-admin-token.sh)
PLATFORM_TENANT_ID=$(mysql -u root -h 127.0.0.1 -P 4000 auth9 -N -e \
"SELECT id FROM tenants WHERE slug = 'auth9-platform';")
.claude/skills/tools/grpcurl-docker.sh \
-cacert /certs/ca.crt -cert /certs/client.crt -key /certs/client.key \
-import-path /proto -proto auth9.proto \
-H "x-api-key: dev-grpc-api-key" \
-d "{\"identity_token\": \"$TOKEN\", \"tenant_id\": \"$PLATFORM_TENANT_ID\", \"service_id\": \"auth9-portal\"}" \
auth9-grpc-tls:50051 auth9.TokenExchange/ExchangeToken
IMPORTANT: See references/api-testing-cookbook.md for event type mapping and all recipes.
POST http://localhost:8080/api/v1/identity/eventsdev-webhook-secretx-webhook-signature: sha256=<HMAC-SHA256 hex> (legacy x-keycloak-signature also accepted)credentialType, authMethod, ipAddress)BODY='{"type":"LOGIN_ERROR","realmId":"auth9","userId":"00000000-0000-0000-0000-000000000001","error":"invalid_user_credentials","time":1704067200000,"details":{"username":"test","email":"test@example.com","credentialType":"otp"}}'
SECRET="dev-webhook-secret-change-in-production" # pragma: allowlist secret
SIG=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2)
curl -s -w "\nHTTP: %{http_code}" -X POST "http://localhost:8080/api/v1/identity/events" \
-H "Content-Type: application/json" \
-H "x-webhook-signature: sha256=$SIG" \
-d "$BODY"
auth9-oidc) — Keycloak has been removed.admin@auth9.local / SecurePass123!) for testing.Some QA documents have pre-built executable test scripts in scripts/qa/auto/. These scripts encode all API calls, assertions, and DB validations so you do NOT need to construct curl commands manually.
Check the QA document's corresponding entry in docs/qa/_manifest.yaml for a test_script field:
- id: integration/04-health-check
test_script: scripts/qa/auto/integration-04-health-check.sh
Or check if a matching script exists by convention:
# For docs/qa/auth/07-public-endpoints.md -> scripts/qa/auto/auth-07-public-endpoints.sh
ls scripts/qa/auto/auth-07-public-endpoints.sh
bash scripts/qa/auto/xxx.sh 2>/tmp/qa-stderr.log{"type":"scenario","id":1,"title":"...","status":"PASS",...} — scenario result{"type":"assert","status":"FAIL","label":"...","expected":"...","actual":"..."} — assertion detail{"type":"summary","total":5,"passed":4,"failed":1,...} — final summaryFollow the standard manual testing workflow described above (construct curl/browser steps from the QA doc).
Scripts use shared libraries in scripts/qa/lib/:
lib/assert.sh — assert_eq, assert_http_status, assert_json_field, assert_db, etc.lib/setup.sh — gen_admin_token, gen_tenant_token, api_get, api_post, db_query, etc.lib/runner.sh — scenario registration, timing, JSONL output, run_all execution