Skip to content

Refactor Jest runner to emit per-test-case events #130

@V3RON

Description

@V3RON

The Harness Jest runner currently reports progress at test-file granularity. That works for normal Jest unit tests, but Harness test files are much more expensive to run because they involve the React Native runtime, bridge communication, Metro/app readiness, and device or simulator execution. When a file contains multiple Harness test cases, the Jest CLI can only show that the whole file is running, not which individual test case is currently active or completed.

Refactoring the runner to use Jest's event-emitting runner API would let the Jest CLI display per-test-case progress while preserving the existing file-level result behavior.

Observed Findings

  • packages/jest/src/index.ts implements the current runner as a callback-style Jest runner with runTests(tests, watcher, onStart, onResult, onFailure, options).
  • packages/jest/src/execute-run.ts calls onStart, onResult, and onFailure at test-file granularity only.
  • packages/jest/src/run.ts already converts completed Harness results into Jest TestResult objects, including per-test assertion results with titles, statuses, ancestor titles, durations, and errors.
  • packages/jest/src/harness-session.ts already listens to raw bridge events, but those events are currently only forwarded into Harness plugin hooks and are not exposed to the Jest runner as Jest TestEvents.
  • packages/bridge/src/shared/test-runner.ts already defines runtime runner events such as test-started and test-finished, but those events currently include only flattened fields like name, suite, file, duration, status, and error.
  • packages/runtime/src/runner/runSuite.ts emits test-started before each test runs and test-finished for passed, failed, skipped, todo, and dynamically skipped tests.
  • packages/runtime/src/runner/runSuite.ts has access to the current TestSuite and its parent chain, so it can derive ancestorTitles and fullName at runtime.
  • packages/runtime/src/collector/functions.ts knows declaration-time metadata such as test.only, test.skip, and test.todo, but the exported TestCase model currently collapses this to status: 'active' | 'skipped' | 'todo'.
  • Runtime context.skip() is an execution outcome, not a declaration mode. It should result in a final skipped status, but should not be reported as declared mode: 'skip'.

Suggested Behavior

  • Refactor packages/jest to implement Jest's event-emitting runner interface while preserving the existing behavior for file-level starts, successes, failures, watch mode, Harness session reuse, and final Jest TestResult generation.
  • Emit Jest file-level events equivalent to the current callbacks:
    • test-file-start
    • test-file-success
    • test-file-failure
  • Translate Harness runtime test events into Jest test-case events:
    • test-started -> test-case-start
    • test-finished -> test-case-result
  • Enrich Harness runtime test events with enough metadata for direct Jest mapping:
    • ancestorTitles: string[]
    • fullName: string
    • startedAt: number
    • declaration metadata such as declarationMode?: 'only' | 'skip' | 'todo'
  • Keep declaration mode separate from execution status:
    • declared test.skip maps to Jest mode: 'skip'
    • declared test.todo maps to Jest mode: 'todo'
    • declared test.only maps to Jest mode: 'only'
    • normal tests have no Jest mode
    • dynamic context.skip() keeps normal declaration mode but finishes with skipped status
  • Avoid deriving Jest mode from status, because status: 'skipped' can also come from focus filtering, test name filtering, skipped suites, or runtime context.skip().
  • Decide and document how skipped suites should behave for per-test events. If describe.skip(...) should show individual skipped test cases in Jest output, runSuite must not return before emitting per-test skipped events for descendants.

Resolution Summary

The Jest runner should continue producing the same final file-level results it produces today, but it should also emit Jest-compatible per-test-case progress events. Harness runtime events should carry explicit declaration metadata and hierarchy information so the Jest adapter can report each test case accurately without guessing from final status alone.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions