Skip to content

test(runner): add isolated repo-readiness e2e framework#1384

Draft
Michael Price (michael-pr) wants to merge 2 commits into
mainfrom
e2e-repo-readiness-framework
Draft

test(runner): add isolated repo-readiness e2e framework#1384
Michael Price (michael-pr) wants to merge 2 commits into
mainfrom
e2e-repo-readiness-framework

Conversation

@michael-pr

Copy link
Copy Markdown
Contributor

Relates to WIZ-10907

Overview of Changes

Adds a standalone, manually-run E2E framework under e2e/ that drives the real built CLI as a subprocess black box across 8 repo/monorepo shapes on both the Node and compiled-binary channels. It codifies the ad-hoc matrix used to verify the WIZ-10907 runtime-deps fix, replacing it with a reproducible, data-driven gate. The framework is not bundled into dist/cli.js or dist/qawolf and has no effect on the shipped product.

Design highlights:

  • Run by reference — builds both artifacts once (bun run build:binary), then spawns node dist/cli.js … and dist/qawolf … directly. No global install, no npm link, no ~/.local/bin mutation.
  • Isolated — points QAWOLF_RUNTIME_DIR at a throwaway dir (warmed once per channel) and materializes each shape into a fresh tmp project dir, so it never touches ~/Library/Application Support/qawolf-nodejs. Imports nothing from src/.
  • Data-driven & expandable — add a case = push a RepoShape to fixtures/shapes.ts; add a suite = one file in suites/ + one registry line.

Testing

Run the full suite manually (builds both artifacts once, then runs 16 cells — 8 shapes × node + binary):

bun run e2e -- repo-readiness

Expected: all 16 cells pass (exit 0, JUnit failures=0, ≥1 test each, zero node_modules pollution in project dirs), and the global runtime dir is untouched. Verified locally: 16/16 green, zero pollution, global runtime untouched, full local gate green (typecheck/lint/knip/format, 1075 tests).

Single channel for faster iteration:

bun run e2e -- repo-readiness --channel node
bun run e2e -- repo-readiness --channel binary

Inspect tmp project dirs after a run (skips cleanup):

bun run e2e -- repo-readiness --no-cleanup

Case-08 (08-native-and-versioned-deps) confirms sharp (native module) and diff@^8.0.3 resolve without FILE_HEADERS_ONLY, Could not load the "sharp" module, or Cannot find package on both channels — verifying the inner-hop version-shadowing fix holds on the compiled binary.

Checklist

  • Changes follow the code style of this project
  • Self-review completed
  • Tests added/updated (or not applicable)
  • No breaking changes (or described below)

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Adds a repo-readiness E2E harness that materializes repo shapes into temporary projects, runs the built CLI through node and binary channels, checks JUnit output and project pollution, and reports pass/fail results. It also adds fixture flows and shape data, suite registration and a runner entrypoint, a Bun script, and supporting documentation plus toolchain exclusions for the new E2E files.

Sequence Diagram(s)

sequenceDiagram
  participant RunTs as e2e/run.ts
  participant SuitesIndex as getSuite()/allSuites()
  participant Channels as resolveChannels()
  participant RunCaseFn as runCase()
  participant SpawnCli as spawnCli()
  participant Reporter as report()
  RunTs->>SuitesIndex: resolve suite name or list suites
  RunTs->>Channels: build dist/cli.js and dist/qawolf
  RunTs->>RunCaseFn: run RepoShape cases for selected channels
  RunCaseFn->>SpawnCli: run flows run in a temp project
  RunCaseFn->>RunCaseFn: parse JUnit, scan pollution, collect assertions
  RunTs->>Reporter: render JSON or TTY results
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • smonn
  • MateusZitelli
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows Conventional Commits and accurately summarizes the isolated repo-readiness E2E framework change.
Description check ✅ Passed The description matches the template’s Overview, Testing, and Checklist sections and includes the relevant issue reference.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch e2e-repo-readiness-framework

Warning

Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption.


Comment @coderabbitai help to get the list of available commands.

@michael-pr

Copy link
Copy Markdown
Contributor Author

CodeRabbit (@coderabbitai) review

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.oxlintrc.json:
- Around line 111-117: Keep import-boundary linting enabled for the e2e/**/*.ts
override in .oxlintrc.json and replace the blanket eslint/no-restricted-imports
off setting with a narrower exception for only the specific imports the e2e
harness truly needs. Update the override so the restriction still protects e2e
code from internal or Bun-only imports while allowing only the approved
patterns, preserving the intent of the existing lint boundary rules.

In `@e2e/fixtures/flows/simpleNav.flow.ts`:
- Around line 7-8: The smoke flow in test("navigates") currently depends on
external network access via page.goto("https://example.com"), which makes the
suite brittle. Replace that navigation with an offline-safe approach such as
page.setContent() or a data: URL so the flow only exercises local browser
readiness. Keep the change within the navigates test in simpleNav.flow.ts and
avoid any egress-dependent URL.

In `@e2e/harness/materialize.ts`:
- Around line 26-29: The writeProjectFile helper currently trusts ShapeFile.path
and can write outside the temp project if the path is absolute or contains ../
segments. Update writeProjectFile to resolve the target path against projectDir
and validate that it stays within the project root before
mkdirSync/writeFileSync are called; reject any path that escapes that root using
the existing join/dirname/absPath flow as the place to enforce the check.

In `@e2e/harness/spawnCli.ts`:
- Around line 24-43: The spawnCli harness can hang forever because spawn() is
created without any timeout or kill behavior. Update the spawnCli promise to
enforce a bounded timeout on the child process, terminate it with a kill signal
when exceeded, and resolve with exitCode -1 while preserving any captured
stdout/stderr. Make sure the timeout path is handled alongside the existing
child.on("error") and child.on("close") logic so stalled CLI or browser
downloads fail fast with a clear diagnostic.

In `@e2e/README.md`:
- Line 142: The ordered-list item in the README uses a non-preferred prefix and
will trigger MD029; update the list entry under the suite registration
instructions to use the repo’s standard ordered-list style with 1. so the
markdown linter treats it correctly. Locate the affected text in the README
section that mentions registering the suite in suites/index.ts and adjust only
the list marker format.
- Around line 158-180: The fenced repository layout block in README.md is
missing a language tag and should be updated to satisfy the markdown linter. Add
the appropriate fence language to that block so it is explicitly marked as text,
keeping the documentation lint-clean.

In `@e2e/run.ts`:
- Around line 49-62: `runSuite` is silently treating an unsupported
single-channel selection as success after still doing `build:binary`. Update
`selectChannelNames`/`runSuite` so that when `args.channel` resolves to no
supported channels, the run fails fast or emits a clear warning before the build
step. Use the `selectChannelNames`, `runSuite`, and `resolveChannels` flow to
detect the empty selection and prevent `report` from returning a false green.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 388b1cab-9d55-4c46-a385-9f081aa51c19

📥 Commits

Reviewing files that changed from the base of the PR and between 9850bc3 and ba0db6e.

📒 Files selected for processing (21)
  • .oxfmtrc.json
  • .oxlintrc.json
  • e2e/README.md
  • e2e/fixtures/flows/nativeAndVersioned.flow.ts
  • e2e/fixtures/flows/simpleNav.flow.ts
  • e2e/fixtures/shapeFiles.ts
  • e2e/fixtures/shapes.ts
  • e2e/harness/assertions.ts
  • e2e/harness/channels.ts
  • e2e/harness/materialize.ts
  • e2e/harness/report.ts
  • e2e/harness/runCase.ts
  • e2e/harness/spawnCli.ts
  • e2e/harness/tmpWorkspace.ts
  • e2e/harness/types.ts
  • e2e/run.ts
  • e2e/suites/index.ts
  • e2e/suites/repoReadiness.ts
  • knip.config.ts
  • package.json
  • tsconfig.json

Comment thread .oxlintrc.json
Comment thread e2e/fixtures/flows/simpleNav.flow.ts
Comment thread e2e/harness/materialize.ts
Comment thread e2e/harness/spawnCli.ts
Comment thread e2e/README.md Outdated
Comment thread e2e/README.md Outdated
Comment thread e2e/run.ts Outdated
@michael-pr

Copy link
Copy Markdown
Contributor Author

CodeRabbit (@coderabbitai) review

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.oxlintrc.json:
- Around line 115-129: The import restriction in the ESLint config only blocks
the `~` alias, so `e2e` tests can still reach `src/` through relative paths.
Update the `eslint/no-restricted-imports` rule in `.oxlintrc.json` to also
forbid relative imports that resolve into `src/`, keeping the black-box boundary
enforced for nested `e2e/**/*.ts` files.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 691a3b3a-bead-45ac-9bcf-e966d9630f37

📥 Commits

Reviewing files that changed from the base of the PR and between ba0db6e and f4806a1.

📒 Files selected for processing (6)
  • .oxlintrc.json
  • e2e/README.md
  • e2e/harness/materialize.ts
  • e2e/harness/runCase.ts
  • e2e/harness/spawnCli.ts
  • e2e/run.ts

Comment thread .oxlintrc.json
Comment on lines +115 to +129
"eslint/no-restricted-imports": [
"error",
{
"patterns": [
{
"group": ["~/*", "~/**"],
"message": "e2e/ must not import from src/ — it treats the CLI as a subprocess black box."
},
{
"group": ["bun", "bun:*"],
"message": "e2e/ harness uses node: builtins for portability — avoid Bun module imports."
}
]
}
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

python - <<'PY'
import json, pathlib
cfg = json.loads(pathlib.Path(".oxlintrc.json").read_text())
for override in cfg["overrides"]:
    if override.get("files") == ["e2e/**/*.ts"]:
        rule = override["rules"]["eslint/no-restricted-imports"]
        patterns = rule[1]["patterns"]
        groups = [g for p in patterns for g in p.get("group", [])]
        print("e2e restricted-import groups:")
        for g in groups:
            print(" -", g)
        print("\nBlocks alias imports into src/:", any(g.startswith("~") for g in groups))
        print("Blocks relative imports into src/:", any(g.startswith("..") and "src" in g for g in groups))
        break
PY

rg -nP --glob 'e2e/**/*.ts' 'from\s+["'\''](\.\./)+src/' e2e || true

Repository: qawolf/cli

Length of output: 288


🏁 Script executed:

#!/bin/bash
set -euo pipefail

wc -l .oxlintrc.json
sed -n '100,145p' .oxlintrc.json

Repository: qawolf/cli

Length of output: 1451


🏁 Script executed:

#!/bin/bash
set -euo pipefail

nl -ba .oxlintrc.json | sed -n '105,135p'

Repository: qawolf/cli

Length of output: 188


Close the relative-import path into src/. .oxlintrc.json:115-129 only blocks the ~ alias, so nested e2e/**/*.ts files can still reach src/ via relative imports. Add a restricted-import pattern for relative paths into src/ to keep the black-box boundary enforced.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.oxlintrc.json around lines 115 - 129, The import restriction in the ESLint
config only blocks the `~` alias, so `e2e` tests can still reach `src/` through
relative paths. Update the `eslint/no-restricted-imports` rule in
`.oxlintrc.json` to also forbid relative imports that resolve into `src/`,
keeping the black-box boundary enforced for nested `e2e/**/*.ts` files.

Source: Path instructions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant