Skip to content

@wenext/test-toolkit-web v0.2.16

Local-first test toolkit for WeNext frontend repositories.

It gives the workflow deterministic commands for:

  • Frontend Logic Test doctor/setup/run
  • E2E Testing doctor/setup/run
  • diff-aware test candidate planning
  • scoped FLT and smoke/integration E2E execution
  • latest-version enforcement and frozen Quality Plan validation
  • Readiness execution with immutable environment/harness receipts
  • local full check
  • explicit Playwright browser install

Usage from the repository root:

bash
pnpm run wenext-test -- version-check --require-latest --json
pnpm run wenext-test -- plan --base origin/master --json
pnpm run wenext-test -- readiness --pkg yoki-payment \
  --task-dir .wenext-spec/tasks/<task> \
  --locale en --auth-app yoki --entry /coin-agent-center?tab=diamond-agency \
  --target-url http://127.0.0.1:5288/coin-agent-center?tab=diamond-agency \
  --test-file e2e/specs/readiness.spec.ts \
  --carrier src/pages/coin-agent-center/tabs/diamond-agency/diamond-agency.vue \
  --target-scenario "merchant image upload" \
  --harness-file e2e/fixtures/shared.ts \
  --request-policy-file e2e/fixtures/request-policy.json --json
pnpm run wenext-test -- doctor --pkg fungo-greedy \
  --test-file src/store/modules/__tests__/greedy.spec.js --json
pnpm run wenext-test -- doctor --pkg fungo-greedy --coverage # only after the skill decides required
pnpm run wenext-test -- prepare --pkg fungo-greedy --gate flt \
  --test-file src/store/modules/__tests__/greedy.spec.js \
  --carrier src/store/modules/greedy.js --target-scenario "changed greedy behavior" \
  --coverage --coverage-scope src/store/modules/greedy.js \
  --auto-install --install-mode persist
pnpm run wenext-test -- setup --pkg fungo-greedy --gate all
pnpm run wenext-test -- flt --pkg fungo-greedy --coverage \
  --task-dir .wenext-spec/tasks/<task> \
  --coverage-scope src/store/modules/greedy.js \
  --test-file src/store/modules/__tests__/greedy.spec.js \
  --carrier src/store/modules/greedy.js \
  --target-scenario "jackpot store init/reset/status flow"
pnpm run wenext-test -- flt --pkg fungo-greedy --coverage --coverage-policy changed \
  --coverage-base origin/master \
  --coverage-scope src/store/modules/greedy.js \
  --test-file src/store/modules/__tests__/greedy.spec.js
pnpm run wenext-test -- e2e --pkg fungo-greedy --stage smoke \
  --task-dir .wenext-spec/tasks/<task> \
  --test-file e2e/specs/smoke.spec.ts \
  --carrier src/views/index/index.vue \
  --target-scenario "changed user flow"
pnpm run wenext-test -- e2e --pkg fungo-greedy --stage integration
pnpm run wenext-test -- check --pkg fungo-greedy --gate flt --coverage \
  --task-dir .wenext-spec/tasks/<task> \
  --coverage-scope src/store/modules/greedy.js --auto-install --install-mode transient
pnpm run wenext-test -- check --pkg fungo-greedy --gate e2e --stage smoke \
  --task-dir .wenext-spec/tasks/<task> \
  --e2e-profile standard --bridge-package @wenext/bridge --auto-install --install-mode persist
pnpm run wenext-test -- check --pkg gameparty-pro --gate e2e --stage smoke \
  --platform-gate required --task-dir .wenext-spec/tasks/<task>
pnpm run wenext-test -- record --pkg fungo-greedy --gate flt --task-dir .wenext-spec/tasks/<task> --result pass \
  --carrier "src/store/modules/greedy.js" \
  --collaborator "src/views/index/index.vue" \
  --covered-scenario "jackpot store init/reset/status flow" \
  --coverage-state required \
  --coverage-scope "src/store/modules/greedy.js" \
  --coverage-reason "observable store behavior changed" \
  --coverage-report "coverage/full-coverage.json" \
  --command "pnpm run wenext-test -- flt --pkg fungo-greedy --coverage --coverage-scope src/store/modules/greedy.js --test-file src/store/modules/__tests__/greedy.spec.js"
pnpm run wenext-test -- browser install

doctor does not install dependencies or browsers. setup writes baseline files only. Before the Quality Plan is frozen, prepare --auto-install first completes missing scaffold, then attempts missing dependency and browser setup. A dirty pnpm-lock.yaml is an input to that attempt, not an immediate blocker. Frozen check rejects --auto-install.

prepare automatically uses persist when declarations, scripts, configs, or the lockfile need durable changes. It uses transient only when declarations are complete and the local installation needs recovery. A file changed again after installation is left untouched instead of being overwritten. After each check, the toolkit writes a local receipt under node_modules/.cache/wenext-test/. record uses that receipt when transient restoration makes the current infrastructure state partial; failed checks, unsafe restores, mismatched coverage scopes, or mismatched E2E stages still cannot be recorded as pass.

For --gate all, an FLT prerequisite/environment failure is reported but E2E setup and execution still run. An FLT test assertion failure stops E2E. The final result never uses E2E success to hide an FLT failure. --stage selects the E2E smoke, integration, or full command during check as well as the standalone e2e command. Standard-profile setup keeps test:e2e smoke-only. When a real API spec exists, setup adds an explicit integration command with E2E_SUITE_MODE=integration and a test:e2e:full command that runs smoke before integration. A full stage uses that layered command; packages without an integration entry safely fall back to smoke. It never uses an unscoped test:e2e command to discover every spec.

The toolkit never decides whether coverage is required. The FLT skill records that semantic decision as required, not-required, review, or blocked. When required, pass only changed business carriers through --coverage-scope; collaborator tests may execute without adding unchanged collaborators to the coverage denominator. Missing providers are installed only by the explicit pre-plan prepare --gate flt --auto-install --coverage --coverage-scope path.

For standard E2E packages, doctor and record also expose a static smoke-layer audit. It reports business requests discovered in the smoke spec and whether a reachable page.route/fixture mock can be traced. It also checks that mock fixtures are automatic (or installed from beforeEach), that a catch-all guard in every standard smoke collects then aborts unmatched business traffic before asserting the collection is empty, and that a route proxy using route.fetch is not mistaken for a mock. A smoke result with an unmocked business API is blocked: test-layer-violation during Readiness (or review when protection cannot be resolved statically). A new fixture/mock/locale problem discovered only during a Business Run is also blocked: test-layer-violation, never a business assertion or contract failure. Smoke/full execution and record --result pass reject that unsafe state before it can be treated as a stable gate. Move real API contract cases to e2e/specs/integration.real-api.spec.ts and keep them behind the explicit integration script.

doctor validates script semantics as well as script presence. An old broad test:e2e, an integration command without E2E_SUITE_MODE=integration, or an unsafe full command keeps the package in partially-installed. setup --upgrade replaces only exact legacy toolkit templates; custom commands are reported for manual review instead of being overwritten. Upgrade dry-runs expose autoMigrations, manualReview, and unchanged before they write anything.

For standard packages, test:e2e:smoke is the only smoke baseline source. It must directly name one package-local Playwright spec, so valid custom names such as reward.spec.ts are supported without a second hard-coded smoke.spec.ts. Scoped smoke also audits that baseline together with the selected case. Scoped --test-file is intentionally unavailable for --stage full; full always runs the package-level layered command. prepare --auto-install restores missing root Playwright/login dependencies separately from the target Vue and Vite/Vue CLI runtime, and never upgrades existing scripts.

Installation

bash
pnpm add -D @wenext/test-toolkit-web

Workflow Integration

Use the toolkit as the deterministic execution layer under the wenextSpec workflow:

  1. The Root Quality Planner runs version-check --require-latest --json and freezes the returned version, integrity, scope, and diff fingerprint in an immutable Quality Plan.
  2. Run readiness with that task directory, explicit test/carrier/scenario, harness, request-policy files, and the same Vite config, Playwright profile, fixture, auth app, locale, entry, and request policy used by formal E2E. A blocked receipt does not create a Business Quality Run.
  3. Start with plan; FLT/E2E skills refine candidates into add/update/rerun/review and smoke/integration required/suggested decisions.
  4. Run doctor to classify FLT and E2E infrastructure.
  5. Missing scripts/config/tests enter setup; they are not classified as blocked before setup and installation have been attempted.
  6. Vue2 .vue carriers use --profile vue2-component; plain Vue2 logic keeps --profile logic. A ready runner without business tests reports needs-test-authoring, then the Skill continues Analyze → Generate → Verify.
  7. Run scoped FLT and required E2E stages with the skill-selected --e2e-profile, --bridge-package, and --stage values.
  8. Call record after each gate. A pass record needs a coverage matrix; baseline or smoke-only evidence cannot pass changed business flows. When an E2E transient check is recorded, pass the same --stage to record.

--test-file limits the actual Jest/Vitest/Playwright execution. Execution uses --target-scenario; only record accepts --covered-scenario, which must exactly cover the receipt targets for pass. Without --test-file, execution remains package-level diagnostic evidence with authoringState=not-assessed and cannot be used for a task-level pass or fail.

For a failed gate, record --result fail requires a failed scenario, --failure-type assertion|coverage|contract|runtime|test-layer-violation|auth-chain|auth-context, the exact --command, and --rerun-condition. The current failed receipt and its redacted execution log are added to the summary automatically; E2E failures also require their actual --stage. Successful execution logs are removed after writing the receipt. needs-test-authoring evidence can only become a coverage failure, and a test-layer-violation receipt cannot be relabeled as runtime or contract.

Platform Verification Gate

普通 FLT/E2E 不传 --platform-gate,平台 Gate 行为保持向后兼容。E2E Skill 明确判断真实 App WebView、系统解码、Canvas/WebGL、GPU 或 VAP 等目标平台验收 为 required 时,自动化执行与 record 必须同时传入:

bash
--platform-gate required --task-dir .wenext-spec/tasks/<task>

自动化完成后、执行 record 前,Skill 在任务目录写入:

text
quality/e2e-testing/platform-verification.json

最小结构如下:

json
{
  "schemaVersion": 1,
  "package": { "name": "gameparty-pro", "path": "packages/gameparty-pro" },
  "automation": {
    "receiptPath": "node_modules/.cache/wenext-test/<receipt>.json",
    "stage": "smoke",
    "sourceRevision": "<HEAD>",
    "worktreeState": "dirty",
    "diffFingerprint": "<SHA-256>"
  },
  "platformGate": {
    "policy": "required",
    "targets": [
      {
        "runtime": "ios-app-wkwebview",
        "required": true,
        "reason": "VAP 透明通道依赖真实 WebView 与系统解码",
        "status": "pending-human-confirmation"
      }
    ]
  }
}

平台完成验收后,target 增加 verification,至少包含源码绑定 sourceRevision/worktreeState/diffFingerprint、唯一 artifactId、H5 版本、环境、 设备与系统、App appVersion/buildNumber、场景、检查项、证据、确认人和确认时间。

Toolkit 根据 automation receipt 和平台证据单点计算整体结果,并拒绝不一致的 --result

  • 自动化实际失败:fail
  • 自动化执行阻断:blocked
  • 任一匹配当前源码与构建的 required 平台证据为 failfail,优先于其他 target 的 pending。
  • 自动化成功但 required 平台证据待确认、失配或过期: blocked + platform-verification-pending
  • 全部 required 平台证据匹配且通过:pass

平台失败仍需要 --failed-scenario--failure-type--command--rerun-condition,只放宽“必须存在失败 Playwright receipt”这一项;自动化 receipt 必须成功,设备证据和构建指纹必须匹配。再次执行 record 会从独立 JSON 重新生成 summary,不会丢失平台 Gate。

源码指纹使用 HEAD、相对 HEAD 的 staged/unstaged tracked binary diff,以及按路径排序的 untracked 文件路径、类型和内容哈希计算 SHA-256。只精确排除当前任务 quality/e2e-testing/**node_modules/.cache/wenext-test/** 和目标包 e2e-artifacts/**;其他源码或任务目录变化会使证据过期。

明确不需要平台验收时可传 --platform-gate not-required。该模式不要求证据文件, 但若文件中仍存在 required target,Toolkit 会拒绝记录。未传 --platform-gate 仅用于 兼容旧调用方。

The toolkit does not replace the FLT/E2E skills. Skills own business analysis, case selection, profile/bridge selection, assertions, fixtures, mocks, and review judgement. The toolkit owns repeatable setup/install/run commands, baseline templates, restoration, and state reporting.

Runtime Version Contract

The repository root must declare an exact @wenext/test-toolkit-web version, and its resolved root node_modules version must match the CLI that is executing. The toolkit rejects a mismatch before plan, doctor, setup, FLT, E2E, check, or record can produce evidence. Upgrade the root dependency and reinstall before retrying; do not select legacy command paths for an older resolved toolkit.

Repository integrations should expose wenext-test through a root script that checks the registry before a new Quality Plan and invokes the root-resolved binary itself, so a stale installed CLI cannot bypass the workflow guard:

json
{
  "scripts": {
    "wenext-test": "node scripts/assert-wenext-test-runtime.mjs"
  }
}

The wrapper prompts once before changing package.json, pnpm-lock.yaml, and the root node_modules link, then runs version-check --require-latest --json. WENEXT_TEST_AUTO_UPDATE=1 is explicit non-interactive authorization. CI never updates files and reports blocked: toolkit-update-required. Existing frozen Quality Plans keep their pinned Toolkit version and do not chase later releases.

The 0.2.7 implementation preserves explicit apps/* and packages/* targets, resolves FLT execution to the package's real pnpm selector, and supports changed-line coverage with --coverage-policy changed --coverage-base <ref>. FLT --coverage-scope and --test-file accept repository-relative, package-relative, or absolute paths. Carriers and coverage scopes must exist; a missing explicit test file is kept as needs-test-authoring. Directories, glob patterns, and paths or symlinks outside the package are rejected. Receipts store repo-relative POSIX paths; FLT runner arguments are package-relative.

0.2.10 additionally separates infrastructure, authoring, and verification state, makes explicit test files the task evidence boundary, and separates execution targetScenarios from record-time coveredScenarios. It retains the root-common E2E and target-direct FLT declarations. A workspace target must declare its own Vitest/Jest runner, while pnpm installs the resolved packages once from the repository root. If the runner and script are ready but business test files are absent, FLT records needs-test-authoring with generate-or-update rather than reporting an environment blocker; an all-gate check still proceeds to E2E. Vue detection prefers the declared vue major, then the matching Vite Vue plugin; a bare vite.config.* or vitest.config.* is not treated as Vue3 evidence. The vue2-component profile adds Jest 27 SFC support only for Vue2 .vue carriers, including an exact vue-template-compiler version matched to Vue.

0.2.11 keeps Vue2 SFC dependency repair scoped to vue2-component checks. Transient checks preserve the repository's effective pnpmfile hooks, append a temporary hook that binds vue-template-compiler to the target package's exact Vue 2 version, and recheck the compiler dependency closure immediately before Jest starts. The temporary hook and tracked package/lock changes are restored; pnpm store entries and node_modules links may remain as local cache. Vue3, Activity Component, E2E, custom Jest 26 + vue-jest@4, and persist-mode workspace configuration are unchanged.

0.2.12 classifies FLT failures by whether the runner started: pre-run dependency or runtime failures remain blocked, while test execution and coverage report or threshold failures are failed.

0.2.14 adds the latest-version gate, frozen Plan validation, Readiness execution, immutable receipts, environment/test-harness/request-policy fingerprints, startup request and locale classification, and one-time Planner consumption fields. Readiness receipts use the Root Planner's frozen business diff fingerprint; the Planner independently rechecks the current source and environment before creating a Business Quality Run.

0.2.15 adds prepare --auto-install for dependency recovery before the Quality Plan. It does not execute a gate or create a receipt. When coverage is required, it restores Vitest first, then installs @vitest/coverage-v8 at the exact version resolved from the target package. It never derives the provider from a version range. Compatible manifest ranges are preserved when the installed provider already matches Vitest; actual version mismatches are repaired with an exact provider install. Chromium probe output must be one absolute path. Readiness receipts use Planner contract v3. Chromium probe state and errors remain available for diagnostics, while the environment fingerprint only uses the stable browser version and executable path fields shared with the Planner.

Each coverage run writes its raw JSON into a unique temporary directory and removes only that directory after verification. Existing package coverage/coverage-final.json files are never used as current-run evidence; the derived coverage/changed-coverage.json or coverage/full-coverage.json remains available for recording.

Standalone Activity Result Repository

web-wenext-activity-components is detected by package name @wenext/activity-ui. From that repository root:

bash
pnpm run wenext-test -- doctor --pkg .
pnpm run wenext-test -- setup --pkg . --gate e2e
H5_TEST_LOGIN_APP=<app> E2E_ACTIVITY_ID=<numeric-id> pnpm run test:e2e:integration

The generated Playwright config starts two native webServer entries: the result repository on port 8939 and sibling wenext-web-new-mono/apps/h5-activity-next on port 8940. E2E_ACTIVITY_HOST_REPO overrides the host location. H5_TEST_LOGIN_APP selects both the real-login product and render app; E2E_ACTIVITY_ID is the real activity ID. This Profile D gate is integration-only: it uses real login and real activity APIs, never a fake user or arbitrary mock smoke fixture.

Boundaries

  • Detects FLT / E2E installation state for a target package.
  • Collects worktree/base diffs and emits FLT candidates plus E2E handoff.
  • Plans and writes minimum Jest/Vitest and Playwright baseline files.
  • Generates bridge baselines backed by @wenext/h5-test-login, never fake auth.
  • Adds package scripts for local FLT and E2E commands.
  • Runs scoped FLT and E2E commands after the target package is ready.
  • Writes wenextSpec quality summaries with result, evidence, artifacts, infrastructure state, and coverage matrix.
  • Supports standalone @wenext/activity-ui result repositories with a local h5-activity-next rendering host.

It does not decide whether candidates need update versus rerun, or generate business-specific test cases and full E2E fixtures.

Planner contract 4(0.2.16)

本版本需要与消费端一起升级;旧 contract v2/v3 receipt 只保留作历史证据,不改写。 先完成按任务审核路径的候选分析、测试编写与依赖准备,再冻结 Quality Plan。计划分别 声明 readiness_test_files、各 Gate 的 gate_scopes 和保守的 execution_inputs;拆分 后验收目标/carrier/test 的并集不减少。显式 changedFiles: [] 不回退 worktree。

Readiness 直接运行实际解析的 Playwright,仅选择 readiness.spec,不审计或执行业务 smoke。新 setup 生成专用 script/spec 与 request-policy JSON;既有自定义配置不自动 覆盖。迁移时接入 WENEXT_E2E 的 mode/config/locale 并填写精确启动 mocks。默认空 policy 不许可未知请求。额外共享 fixture/config 必须属于冻结执行输入。

Node browser probe --pkg <pkg> --json 输出消费端共用的环境 JSON,验证实际解析版本和 可执行文件,warning 不作为 version。Readiness 在执行前复用未过期、未消费的匹配 passed 凭据;显式瞬时 retry、过期 refresh 与输入修复分别关联,check attempt 的连续 恢复预算不会随 plan ID 重置。执行时间取 runner,记录时间单列,历史时间 unknown。

执行凭据绑定 task instance、Quality Plan 和 Business Run。多任务同包记录用 record --execution-receipt <immutable-runtime-receipt> 避免共享 current 索引串用。 record 保留全部场景/coverage/平台/失败验证,另外生成不可变、task-local 的 verificationPath,由 Planner record --receipt <verificationPath> 消费;重复消费 同一结论可恢复记录,不重跑命令,也不能替换结果或证据。运行输入漂移不能采用 pass。

发布前执行包级 check 及消费仓跨端契约测试。发布本包、根依赖/锁文件升级和业务包 实际启动验证是分别确认的发布步骤;源码版本变更本身不代表已发布或已接入。