Skip to content

fix(types): allow Promise<boolean> as async test return#1254

Open
rohan-devbuilds wants to merge 1 commit intoealush:latestfrom
rohan-devbuilds:patch-1
Open

fix(types): allow Promise<boolean> as async test return#1254
rohan-devbuilds wants to merge 1 commit intoealush:latestfrom
rohan-devbuilds:patch-1

Conversation

@rohan-devbuilds
Copy link
Copy Markdown

@rohan-devbuilds rohan-devbuilds commented Mar 9, 2026

Q A
Bug fix?
New feature?
Breaking change?
Deprecations?
Documentation?
Tests added?
Types added?
Related issues

The AsyncTest type was defined as Promise, which caused TypeScript to reject async test functions that return Promise inside skipWhen. This is a documented and valid pattern in vest's own docs.

Changed AsyncTest from Promise to Promise<void | boolean> so TypeScript accepts both return types without errors.

Fixes #1156

Summary by CodeRabbit

  • New Features
    • Async test functions now support optional boolean return values alongside void, providing greater flexibility in test result handling.

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 9, 2026

@rohan-devbuilds is attempting to deploy a commit to the ealush's projects Team on Vercel.

A member of the Team first needs to authorize it.

@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Allow Promise<boolean> as async test return type

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Allow Promise<boolean> return type in async tests
• Update AsyncTest type definition to accept both void and boolean
• Aligns TypeScript types with documented vest patterns
Diagram
flowchart LR
  A["AsyncTest Type"] -- "changed from" --> B["Promise&lt;void&gt;"]
  A -- "changed to" --> C["Promise&lt;void | boolean&gt;"]
  C -- "enables" --> D["skipWhen async tests"]
Loading

Grey Divider

File Changes

1. packages/vest/src/core/test/TestTypes.ts 🐞 Bug fix +1/-1

Update AsyncTest type to allow boolean returns

• Modified AsyncTest type from Promise<void> to Promise<void | boolean>
• Allows async test functions to return boolean values without TypeScript errors
• Aligns type definition with documented vest usage patterns

packages/vest/src/core/test/TestTypes.ts


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review bot commented Mar 9, 2026

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Async boolean not evaluated 🐞 Bug ✓ Correctness
Description
Changing AsyncTest to Promise<void | boolean> allows async test functions to resolve false,
but the async execution path ignores the resolved value and marks the test completed/passing unless
the promise rejects. This can silently turn async () => false into a passing validation.
Code

packages/vest/src/core/test/TestTypes.ts[8]

+export type AsyncTest = Promise<void | boolean>;
Evidence
The PR widens the accepted async test return type to include boolean. However, the runtime only
treats synchronous false returns as failures, while the async handler’s done callback takes no
arguments and therefore discards the promise’s resolved value; it only fails on rejection. This is
especially risky because Vest’s own docs/examples show async tests written in a way that returns an
awaited boolean value, which will now type-check but won’t influence pass/fail at runtime.

packages/vest/src/core/test/TestTypes.ts[5-10]
packages/vest/src/core/test/testLevelFlowControl/runTest.ts[51-61]
packages/vest/src/core/test/testLevelFlowControl/runTest.ts[120-151]
packages/vest/src/isolates/skipWhen.ts[13-21]
website/docs/writing_your_suite/accessing_the_result.md[256-271]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`AsyncTest` was widened to `Promise&lt;void | boolean&gt;`, but the async test runner ignores the promise’s resolved value and only fails on rejection. As a result, `async () =&gt; false` will incorrectly pass.

## Issue Context
Synchronous tests explicitly fail when returning `false`, while async tests call `onTestCompleted` on fulfillment without inspecting the fulfillment value.

## Fix Focus Areas
- packages/vest/src/core/test/testLevelFlowControl/runTest.ts[120-151]
- packages/vest/src/core/test/__tests__/runAsyncTest.test.ts[135-189]

## Suggested approach
1. Change the async fulfillment handler to accept the resolved value (e.g., `(value?: void | boolean) =&gt; { ... }`).
2. If the resolved value is exactly `false`, call `VestTest.fail(testObject)` before completing.
3. Keep rejection handling as-is.
4. Add tests:
  - An async test that `return false;` and verify final status is failing.
  - An async test that `return true;` (or returns void) and verify passing.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a type incompatibility issue in vest where async test functions returning Promise<boolean> were incorrectly rejected by TypeScript. By broadening the AsyncTest type definition, it ensures that a documented and valid pattern for skipping tests asynchronously is now fully supported, improving the robustness and flexibility of the testing framework.

Highlights

  • Type Definition Update: The AsyncTest type has been updated from Promise<void> to Promise<void | boolean> to correctly support async test functions that return Promise<boolean>, particularly when used with skipWhen.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 9, 2026

📝 Walkthrough

Walkthrough

A single type definition is expanded to allow async test functions to optionally return boolean values in addition to void, enabling test callbacks to indicate conditions without throwing errors.

Changes

Cohort / File(s) Summary
Type Definition Update
packages/vest/src/core/test/TestTypes.ts
AsyncTest type expanded from Promise<void> to Promise<void | boolean>, allowing async test callbacks to return boolean values.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Poem

🐰 A hop, a skip, a boolean true,
Async tests now know what to do!
Void or boolean, the choice is there,
TypeScript smiles without a care. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically describes the main change: allowing Promise as a return type for async tests, which directly addresses the TypeScript error reported in the linked issue.
Linked Issues check ✅ Passed The code change directly resolves the linked issue #1156 by updating the AsyncTest type to accept Promise<void | boolean>, enabling the documented skipWhen pattern with async tests returning boolean values.
Out of Scope Changes check ✅ Passed The change is narrowly scoped to the AsyncTest type definition, directly addressing the type error without introducing unrelated modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates the AsyncTest type definition in packages/vest/src/core/test/TestTypes.ts. The change from Promise<void> to Promise<void | boolean> allows asynchronous tests to return a promise that resolves to a boolean value. This aligns the type system with existing functionality, resolving a type error for a documented usage pattern.


export type TestFn = (payload: TestFnPayload) => TestResult;
export type AsyncTest = Promise<void>;
export type AsyncTest = Promise<void | boolean>;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Async boolean not evaluated 🐞 Bug ✓ Correctness

Changing AsyncTest to Promise<void | boolean> allows async test functions to resolve false,
but the async execution path ignores the resolved value and marks the test completed/passing unless
the promise rejects. This can silently turn async () => false into a passing validation.
Agent Prompt
## Issue description
`AsyncTest` was widened to `Promise<void | boolean>`, but the async test runner ignores the promise’s resolved value and only fails on rejection. As a result, `async () => false` will incorrectly pass.

## Issue Context
Synchronous tests explicitly fail when returning `false`, while async tests call `onTestCompleted` on fulfillment without inspecting the fulfillment value.

## Fix Focus Areas
- packages/vest/src/core/test/testLevelFlowControl/runTest.ts[120-151]
- packages/vest/src/core/test/__tests__/runAsyncTest.test.ts[135-189]

## Suggested approach
1. Change the async fulfillment handler to accept the resolved value (e.g., `(value?: void | boolean) => { ... }`).
2. If the resolved value is exactly `false`, call `VestTest.fail(testObject)` before completing.
3. Keep rejection handling as-is.
4. Add tests:
   - An async test that `return false;` and verify final status is failing.
   - An async test that `return true;` (or returns void) and verify passing.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@packages/vest/src/core/test/TestTypes.ts`:
- Line 8: The async test handler currently discards the resolved Promise value;
update the persisted done callback created via VestRuntime.persist in runTest.ts
so it accepts the resolved result (result?: void | boolean), checks if result
=== false and calls VestTest.fail(testObject) in that case, then calls
onTestCompleted(testObject).unwrap(); this ensures asyncTest.then(done, fail)
propagates a resolved false as a failure just like sync tests while keeping the
existing failure path intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8f128beb-7c7e-4190-be19-ce7af9a9a3e3

📥 Commits

Reviewing files that changed from the base of the PR and between 64a0728 and 470f8da.

📒 Files selected for processing (1)
  • packages/vest/src/core/test/TestTypes.ts


export type TestFn = (payload: TestFnPayload) => TestResult;
export type AsyncTest = Promise<void>;
export type AsyncTest = Promise<void | boolean>;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify if there are any tests or documentation about async tests returning false
rg -n -C3 'async.*return.*false' --type=ts
rg -n 'Promise.*false' --type=ts

Repository: ealush/vest

Length of output: 358


🏁 Script executed:

#!/bin/bash
# Read runTest.ts to see the actual implementation around lines 114-151
cat -n packages/vest/src/core/test/testLevelFlowControl/runTest.ts | sed -n '100,160p'

Repository: ealush/vest

Length of output: 2132


🏁 Script executed:

#!/bin/bash
# Search for onTestCompleted and related implementations
rg -n 'onTestCompleted' --type=ts -A5 | head -80
rg -n 'VestTest.pass' --type=ts -B2 -A2 | head -80

Repository: ealush/vest

Length of output: 5463


🏁 Script executed:

#!/bin/bash
# Look for test files that test async test behavior
fd 'test|spec' --type=f --path='*packages/vest*' | head -20
# Also search for skipWhen patterns with async tests
rg -n 'skipWhen' --type=ts -B2 -A2 | head -60

Repository: ealush/vest

Length of output: 4064


🏁 Script executed:

#!/bin/bash
# Find test files for async test handling
find packages/vest -type f -name "*.test.ts" -o -name "*.spec.ts" | head -20
rg -n 'async.*test' packages/vest/src --type=ts -B2 -A5 | grep -E "(async|Promise|\.then)" | head -40

Repository: ealush/vest

Length of output: 6174


🏁 Script executed:

#!/bin/bash
# Check skipWhen implementation
cat packages/vest/src/isolates/skipWhen.ts

Repository: ealush/vest

Length of output: 1511


🏁 Script executed:

#!/bin/bash
# Look for any comments or references to boolean returns in async tests
rg -n 'Promise.*boolean\|boolean.*Promise\|async.*return.*false' --type=ts -B3 -A3 | head -60

Repository: ealush/vest

Length of output: 37


🏁 Script executed:

#!/bin/bash
# Look at the async tests integration file
cat packages/vest/src/__tests__/integration.async-tests.test.ts | head -200

Repository: ealush/vest

Length of output: 2809


🏁 Script executed:

#!/bin/bash
# Check the synchronous test handling in runTest.ts
cat -n packages/vest/src/core/test/testLevelFlowControl/runTest.ts | sed -n '40,110p'

Repository: ealush/vest

Length of output: 2595


🏁 Script executed:

#!/bin/bash
# Search for skipWhen with async tests that might return boolean
rg -n 'skipWhen' packages/vest/src/__tests__ --type=ts -A10 | grep -E '(skipWhen|async|Promise|return)' | head -40

Repository: ealush/vest

Length of output: 1264


🏁 Script executed:

#!/bin/bash
# Look for tests that might test returning boolean from async tests
rg -n 'Promise.*false\|Promise.*true\|Promise\.resolve.*false\|Promise\.resolve.*true' packages/vest/src --type=ts

Repository: ealush/vest

Length of output: 37


🏁 Script executed:

#!/bin/bash
# Check the TestTypes file and surrounding context
cat -n packages/vest/src/core/test/TestTypes.ts

Repository: ealush/vest

Length of output: 557


Async test handler ignores the resolved boolean value.

The type broadening to Promise<void | boolean> correctly addresses the TypeScript issue, but the async test handler in packages/vest/src/core/test/testLevelFlowControl/runTest.ts (lines 128-130) discards the resolved value:

const done = VestRuntime.persist(() => {
  onTestCompleted(testObject).unwrap();
});

The done callback accepts no parameters, so asyncTest.then(done, fail) at line 150 ignores the promise's resolved value entirely. This creates an inconsistency:

  • Sync test: return false → test fails
  • Async test: return Promise.resolve(false) → test passes

The done callback must be updated to receive and check the resolved value:

const done = VestRuntime.persist((result?: void | boolean) => {
  if (result === false) {
    VestTest.fail(testObject);
  }
  onTestCompleted(testObject).unwrap();
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/vest/src/core/test/TestTypes.ts` at line 8, The async test handler
currently discards the resolved Promise value; update the persisted done
callback created via VestRuntime.persist in runTest.ts so it accepts the
resolved result (result?: void | boolean), checks if result === false and calls
VestTest.fail(testObject) in that case, then calls
onTestCompleted(testObject).unwrap(); this ensures asyncTest.then(done, fail)
propagates a resolved false as a failure just like sync tests while keeping the
existing failure path intact.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TypeScript reports errors with skipWhen

1 participant