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:
- 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.
- 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).
- 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:
- 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
- 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.
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:
expectAPI surface. Inside a UXP-executed test,expect.getState,expect.assertions, andexpect.hasAssertionsare allundefined. We also enumerated every Symbol-keyedMaponglobalThislooking for matcher state containing assertion-like keys (e.g.assertionCalls) and found none.task-updateevents receives result objects for UXP-run tests whose keys contain no assertion-count field (noassertionCallsor anything matching/assert/i).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.13ships a frozen, prebuiltdist/worker-runtime.global.jsthat is evaluated inside the UXP runtime. It re-implements the Vitest expect API on top of@vitest/expect+chai(viause(JestExtend),use(JestChaiExpect), etc.) with a localcreateExpect(test)that wraps the chaiexpectand addswithTestattribution, thenObject.assigns the statics.That re-implementation does not include the counting wrapper from Vitest's own
createExpect: Vitest's version increments anassertionCallscounter in the matcher state on every matcher invocation and mounts the public staticsexpect.getState/expect.setState/expect.assertions/expect.hasAssertions. The internalgetState()from@vitest/expectis 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:
expectinto the worker runtime — mirror Vitest'screateExpectbehavior (wrap matcher invocations to maintainassertionCallsin the matcher state; mountexpect.getState/expect.assertions/expect.hasAssertionsstatics), so tests and hooks running inside UXP can read the count; and/ortask-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
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.