Skip to content

Attach a stable testid to default baseElement#44

Merged
sheremet-va merged 18 commits intovitest-community:mainfrom
nizans:fix/stable-base-element-selector
Jan 22, 2026
Merged

Attach a stable testid to default baseElement#44
sheremet-va merged 18 commits intovitest-community:mainfrom
nizans:fix/stable-base-element-selector

Conversation

@nizans
Copy link
Copy Markdown
Contributor

@nizans nizans commented Dec 15, 2025

When baseElement is not provided and render() falls back to document.body, this PR sets a data-testid on the body to ensure getElementLocatorSelectors(baseElement) generates a stable root selector.

Without a stable attribute on the default baseElement, the generated selector sometimes rely's on the document.body text content.
This results in a flakey selector since sometimes the body includes some content that might change.

Adding the test id enforce the generated selector to be a stable testid-based selector.

Issue described here:
#42

@nizans
Copy link
Copy Markdown
Contributor Author

nizans commented Dec 15, 2025

@sheremet-va

Pushed a change where ids are generated using nanoid and the user defined test id attribute is respected.

Let me know what you think about this approach

@nizans
Copy link
Copy Markdown
Contributor Author

nizans commented Jan 22, 2026

@sheremet-va Sorry for the long delay.
I removed second test and simplify the first one.

Copy link
Copy Markdown
Member

@sheremet-va sheremet-va left a comment

Choose a reason for hiding this comment

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

Just a small nitpick

Copy link
Copy Markdown
Member

@sheremet-va sheremet-va left a comment

Choose a reason for hiding this comment

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

Looks great!

return {
container,
baseElement,
locator: page.elementLocator(container),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we do a similar thing for the locator? Sorry, just noticed - It probably has the same issues

Copy link
Copy Markdown
Contributor Author

@nizans nizans Jan 22, 2026

Choose a reason for hiding this comment

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

Yea good call
After seeing youe message I tried to reprudoce this when using the locator and it does reprudoce.
Added a test-id to the container element when its not provided, similar to the baseElement

I'd like to make the snapshot of the first test ignore the test-id, not sure how

@nizans nizans closed this Jan 22, 2026
@nizans nizans reopened this Jan 22, 2026
Copy link
Copy Markdown
Member

@sheremet-va sheremet-va left a comment

Choose a reason for hiding this comment

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

This looks good to me, but I wonder if we should always apply a test id to this elements, not just when users don't pass anything. Just check the existence of the the attribute first

@nizans
Copy link
Copy Markdown
Contributor Author

nizans commented Jan 22, 2026

This looks good to me, but I wonder if we should always apply a test id to this elements, not just when users don't pass anything. Just check the existence of the the attribute first

I guess if we’re only “ensuring” that a testid exists, then unless there’s a case where a user would intentionally want an element with no testid - which I can’t think of why atm - then this sounds good.

Added a commit

Copy link
Copy Markdown
Member

@sheremet-va sheremet-va left a comment

Choose a reason for hiding this comment

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

Thank you for your hard work! 🫡 LGTM!

@nizans
Copy link
Copy Markdown
Contributor Author

nizans commented Jan 22, 2026

@sheremet-va
Not sure but I think this surface another bug.
Whenever I pass an element as a container or baseElement, without actually adding it to the body

test('should not override testid attribute if already set on baseElement', async () => {
  const baseElement = document.createElement('div')

  const screen = await render(<div>Render</div>, { container: baseElement })
})

OR

test('should not override testid attribute if already set on container', async () => {
  const container = document.createElement('div')

  const screen = await render(<div>Render</div>, { container })
})

An exception is raised here:
Cannot read properties of undefined (reading 'includes')
parseSelectorString

Kinda makes sense since the element is not in the document, but I wasn't aware of this.
Maybe we can also ensure the provided elements are actually in the document as well..

@sheremet-va
Copy link
Copy Markdown
Member

Kinda makes sense since the element is not in the document, but I wasn't aware of this.
Maybe we can also ensure the provided elements are actually in the document as well..

This is actually expected behavior (documented in testing-library and soon to be in vitest). But we should check it's in the DOM, we shouldn't add it ourselves

@nizans
Copy link
Copy Markdown
Contributor Author

nizans commented Jan 22, 2026

Kinda makes sense since the element is not in the document, but I wasn't aware of this.
Maybe we can also ensure the provided elements are actually in the document as well..

This is actually expected behavior (documented in testing-library and soon to be in vitest). But we should check it's in the DOM, we shouldn't add it ourselves

got it!
@sheremet-va
Thank you for reviewing and for all the incredible work on the browser mode! 🥇

@sheremet-va sheremet-va merged commit e8acbcb into vitest-community:main Jan 22, 2026
4 checks passed
@sheremet-va
Copy link
Copy Markdown
Member

You know after released I thought that maybe it's better to have a more consistent id like

`__vitest_${idx++}__`

Since it appears in snapshots now. Maybe Vitest could also ignore data-attributes by default

ShaulLavo added a commit to ShaulLavo/vitest-browser-solid that referenced this pull request Mar 27, 2026
Port upstream fix from vitest-browser-react (vitest-community#42, vitest-community#44, vitest-community#45) to prevent
flaky locators when baseElement/container lack a testid attribute.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
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.

2 participants