From 8ebcf5f8a862d92ba4b0b87d3f389a7d2f4c7488 Mon Sep 17 00:00:00 2001 From: Alex <40460839+nomadical@users.noreply.github.com> Date: Thu, 1 Oct 2026 13:07:25 +0200 Subject: [PATCH] fix(browser): allow toHaveTextContent without arguments (#11425) --- docs/api/browser/assertions.md | 8 ++++++-- packages/browser/jest-dom.d.ts | 4 +++- .../client/tester/expect/toHaveTextContent.ts | 19 ++++++++++++++++++- .../expect-dom/toHaveTextContent.test.ts | 14 ++++++++++++++ 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/docs/api/browser/assertions.md b/docs/api/browser/assertions.md index c1fc598b5..bc938d5d2 100644 --- a/docs/api/browser/assertions.md +++ b/docs/api/browser/assertions.md @@ -740,13 +740,13 @@ The usual rules of css precedence apply. ```ts function toHaveTextContent( - text: string | number, + text?: string | number, options?: { normalizeWhitespace: boolean } ): Promise ``` This matcher allows you to validate that an element's text matches provided string exactly. This -supports elements, but also text nodes and fragments. +supports elements, but also text nodes and fragments. Called without arguments, it asserts that the element has some text content, so `.not.toHaveTextContent()` checks that it is empty. If you wish to perform a partial check or do a case-sensitive match, use [`toMatchTextContent`](#tomatchtextcontent) instead. @@ -759,6 +759,10 @@ const element = getByTestId('text-content') await expect.element(element).toHaveTextContent('Text Content') await expect.element(element).not.toHaveTextContent('Content') +// element has some text content +await expect.element(element).toHaveTextContent() +// element has no text content +await expect.element(page.getByTestId('empty')).not.toHaveTextContent() ``` ## toMatchTextContent diff --git a/packages/browser/jest-dom.d.ts b/packages/browser/jest-dom.d.ts index c1ebec5e5..4a3afe9e9 100644 --- a/packages/browser/jest-dom.d.ts +++ b/packages/browser/jest-dom.d.ts @@ -412,9 +412,11 @@ export interface TestingLibraryMatchers, T = unkn * const element = page.getByTestId('text-content') * await expect.element(element).toHaveTextContent('Text Content') * await expect.element(element).not.toHaveTextContent('Content') + * // element has some text content + * await expect.element(element).toHaveTextContent() * @see https://vitest.dev/api/browser/assertions#tohavetextcontent */ - toHaveTextContent(text: string | number, options?: { normalizeWhitespace: boolean }): R + toHaveTextContent(text?: string | number, options?: { normalizeWhitespace: boolean }): R /** * @description * Check whether the given element has a text content or not. diff --git a/packages/browser/src/client/tester/expect/toHaveTextContent.ts b/packages/browser/src/client/tester/expect/toHaveTextContent.ts index 321073977..68c57d10b 100644 --- a/packages/browser/src/client/tester/expect/toHaveTextContent.ts +++ b/packages/browser/src/client/tester/expect/toHaveTextContent.ts @@ -20,7 +20,7 @@ import { getMessage, getNodeFromUserInput, normalize } from './utils' export default function toHaveTextContent( this: MatcherState, actual: Element | Locator, - matcher: string | number, + matcher?: string | number, options: { normalizeWhitespace?: boolean } = { normalizeWhitespace: true }, ): MatcherResult { const node = getNodeFromUserInput(actual, toHaveTextContent, this) @@ -29,6 +29,23 @@ export default function toHaveTextContent( ? normalize(node.textContent || '') : (node.textContent || '').replace(/\u00A0/g, ' ') // Replace   with normal spaces + if (matcher === undefined) { + return { + pass: textContent !== '', + message: () => { + const to = this.isNot ? 'not to' : 'to' + return getMessage( + this, + this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toHaveTextContent`, 'element', ''), + `Expected element ${to} have text content`, + '', + 'Received', + textContent, + ) + }, + } + } + const expectedText = String(matcher) return { diff --git a/test/browser/fixtures/expect-dom/toHaveTextContent.test.ts b/test/browser/fixtures/expect-dom/toHaveTextContent.test.ts index b91d0362d..13c48e93c 100644 --- a/test/browser/fixtures/expect-dom/toHaveTextContent.test.ts +++ b/test/browser/fixtures/expect-dom/toHaveTextContent.test.ts @@ -94,6 +94,20 @@ describe('.toHaveTextContent', () => { expect(container.querySelector('span')).toHaveTextContent('') }) + test('asserts presence of content when called without arguments', () => { + const { container } = render(`

text

`) + + expect(container.querySelector('p')).toHaveTextContent() + expect(container.querySelector('span')).not.toHaveTextContent() + expect(container.querySelector('i')).not.toHaveTextContent() + expect(() => + expect(container.querySelector('span')).toHaveTextContent(), + ).toThrow() + expect(() => + expect(container.querySelector('p')).not.toHaveTextContent(), + ).toThrow() + }) + test('throws when element has content but matcher is empty', () => { const { container } = render('not empty') -- 2.51.2