Skip to content

vitest-pool-uxp: no way to obtain positive assertion counts for tests running inside UXP #64

Description

@wojzj57

Summary

When running tests inside Photoshop (UXP) via @bubblydoo/vitest-pool-uxp, there appears to be no way to obtain the number of assertions a test actually executed (a "positive assertion count"). We exhausted every path we could find and would like to report the gap, along with our root-cause analysis and a feature request.

What we tried

We probed all three paths from both sides of the pool:

  1. UXP-side expect API surface. Inside a UXP-executed test, expect.getState, expect.assertions, and expect.hasAssertions are all undefined. We also enumerated every Symbol-keyed Map on globalThis looking for matcher state containing assertion-like keys (e.g. assertionCalls) and found none.
  2. Node-side task results. A custom reporter observing task-update events receives result objects for UXP-run tests whose keys contain no assertion-count field (no assertionCalls or anything matching /assert/i).
  3. Task event stream. The per-task event payloads forwarded across the pool boundary likewise carry no assertion-related content.

For comparison, the equivalent counting surface is available for host-side (Node) assertions, so the gap is specific to tests executed inside the UXP worker. Assertion failure messages do flow through correctly (JUnit/events), which is how we confirmed the result plumbing itself works — only the positive count is missing.

Root cause (as far as we can tell)

@bubblydoo/vitest-pool-cdp@0.0.13 ships a frozen, prebuilt dist/worker-runtime.global.js that is evaluated inside the UXP runtime. It re-implements the Vitest expect API on top of @vitest/expect + chai (via use(JestExtend), use(JestChaiExpect), etc.) with a local createExpect(test) that wraps the chai expect and adds withTest attribution, then Object.assigns the statics.

That re-implementation does not include the counting wrapper from Vitest's own createExpect: Vitest's version increments an assertionCalls counter in the matcher state on every matcher invocation and mounts the public statics expect.getState / expect.setState / expect.assertions / expect.hasAssertions. The internal getState() from @vitest/expect is present in the bundle, but the matcher state it returns carries no assertion counter, and no public statics are mounted — which matches what we observed empirically.

Since the worker → host protocol (task-update / TaskResult) also doesn't carry assertion data, the count can't be reconstructed on the Node side either.

Request

Would it be possible to make positive assertion counts available for UXP-executed tests? Either of these directions would work for us:

  1. Integrate the counting expect into the worker runtime — mirror Vitest's createExpect behavior (wrap matcher invocations to maintain assertionCalls in the matcher state; mount expect.getState / expect.assertions / expect.hasAssertions statics), so tests and hooks running inside UXP can read the count; and/or
  2. Expose the count over the RPC boundary — track the count in the worker and include an assertion-count field in the task result sent with task-update, so custom reporters on the Node side can read it.

Our use case: we run contract tests against real Photoshop and gate passing tests on having actually performed a positive number of assertions (guards against accidentally-empty test bodies). Once this lands we'd happily upgrade and re-verify.

Environment

  • vitest 4.1.11
  • @bubblydoo/vitest-pool-uxp 0.0.13 (with @bubblydoo/vitest-pool-cdp 0.0.13)
  • Photoshop 26.11.6, UXP runtime uxp-9.0.2
  • Node v22.22.1, Windows (win32)

Happy to provide probe artifacts or a minimal reproduction if useful. Thanks for the toolkit — apart from this gap it has been working well for us.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions