vitest-dev / vitest-dev/vitest

Add `.some`, `.every` property chain to matcher that expects an array

Open
#7,629 5 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

feat: browser p2-nice-to-have
Dominant language
TypeScript
Stars
17.1k
Forks
2k
Avg merge
1d 22h
Merged PRs (30d)
94

Description

Clear and concise description of the problem

Currently, when testing elements returned as an array (e.g., screen.getAllByRole in Testing Library), matchers cannot be used directly on individual elements within the array. Specifically, there is no built-in way to check if at least one element satisfies a matcher without manually iterating and extracting a boolean value.

This creates several issues:

  • Manual boolean extraction: Test authors must manually iterate over the array and convert the matcher result into a boolean value.
  • Redundant code: This leads to unnecessary repetition, making tests more verbose.
  • Custom matchers as a workaround: While it is possible to define custom matchers to handle these cases, they must be redefined for every assertion type, increasing maintenance overhead.
Current workarounds
Using Array.prototype.some and a manual boolean assertion
expect(screen.getAllByRole("alert").some((it) => it.textContent === message)).toBe(true);

This approach is verbose and does not leverage existing matchers.

Defining a custom matcher (for each assertion type)

expect.extend({
  toHaveSomeTextContent(received, expected) {
    const pass = received.some((el) => el.textContent === expected);
    return pass
      ? { pass: true, message: () => `Expected at least one element to not have text content ${expected}` }
      : { pass: false, message: () => `Expected at least one element to have text content ${expected}` };
  }
});

expect(screen.getAllByRole("alert")).toHaveSomeTextContent(message);

This solves the problem, but requires defining a separate matcher for each assertion type, which is not practical for general use.
Also, there is the hassle of checking the implementation if you want to reproduce the matcher of the community.

Suggested solution

Introduce .some and .every as built-in property chains, such as Array.prototype, so that assertions can be verified to satisfy some or all of the array.

Proposed syntax

expect(array).some.toHaveTextContent(message);
expect(array).every.toHaveTextContent(message);

Benefits:
Eliminates manual boolean extraction
Avoids the need to define custom matchers for each assertion type
Improves readability by making the test’s intent clear
Enables direct use of community matchers (e.g., testing-library/jest-dom)
For symmetry, .every could also be introduced to allow assertions to be applied to all elements in an array.

.every is not strictly necessary since the combination of for and Array.prototype.every is already a viable alternative. .every is included in the proposal primarily for consistency with .some.

Alternative

No response

Additional context

The implementation should ensure proper TypeScript support so that .some and .every only appear on arrays.
It should be compatible with expect.extend, allowing custom matchers to work seamlessly.
Performance considerations should be taken into account to avoid unnecessary operations when chaining multiple matchers.
By introducing .some (and optionally .every for symmetry), this feature would eliminate boilerplate, improve test readability, and reduce the need for repetitive custom matchers.

Validations

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the expect matcher property-chain entry point and the expect.extend integration. Define how .some and .every should apply existing and custom matchers to arrays, with TypeScript exposing them only for arrays; done means the proposed syntax works with built-in and extended matchers without unnecessary operations.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.