Skip to content

Migrate five more glimmer integration tests to plain .gjs tests with setupRenderingTest - #21672

Merged
NullVoxPopuli merged 2 commits into
emberjs:mainfrom
NullVoxPopuli-ai-agent:nvp/vanilla-gjs-tests-2
Oct 9, 2026
Merged

NullVoxPopuli merged 2 commits into
emberjs:mainfrom
NullVoxPopuli-ai-agent:nvp/vanilla-gjs-tests-2

Conversation

@NullVoxPopuli-ai-agent

@NullVoxPopuli-ai-agent NullVoxPopuli-ai-agent commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Review by commit for the smallest diff. The first commit only renames two files. The second commit has all the changes.

Five more test files now use module, test, setupRenderingTest, render and settled, in the style of #21659.

No test was added, removed or renamed. The module names are the same.

Files

  • integration/custom-helper-test.gjs
  • integration/helpers/if-laziness-test.gjs
  • integration/components/glimmer-component-test.gjs
  • integration/helpers/log-test.js, renamed to .gjs
  • integration/helpers/concat-test.js, renamed to .gjs

What changed in each test

  • runTask(() => ...) is now an assignment and await settled().
  • this.assertText(x) after an update is now assert.dom().hasText(x), or assert.dom().hasNoText() for no text.
  • set(this.context, ...) is now an assignment to a @tracked field.
  • this.render('...', context) is now await render(<template>...</template>).
  • No test imports from internal-test-helpers.

qunit-dom

This PR adds qunit-dom ^3.6.0 (the version of the smoke tests) as a dev dependency. setup-test-helpers.js calls its setup() with getRootElement from @ember/test-helpers, so assert.dom() with no argument is the rendered element.

assert.stableRender()

assertStableRerender() of RenderingTestCase has no equivalent in a plain test, so this PR adds a QUnit assertion for it. The definition is in internal-test-helpers/lib/ember-dev/setup-test-helpers.js.

await assert.stableRender();
await assert.stableRender('onetwo');

The assertion does these steps:

  1. It records the DOM nodes.
  2. It writes to a trackedValue() that no template reads. A write to any tracked state makes the renderer run an update pass over every root, so this is an unrelated change that causes a new render.
  3. It waits for a promise that resolves in the afterRender queue, then for settled().
  4. It checks that each node is the same node.

With a string, it also compares the rendered HTML with the string. This is the expect option of renderComponent(), and it uses the same token comparison as assertHTML().

The old this.rerender() also dirtied the tag of the classic test component. A plain test has no such component, so the unrelated write is the equivalent. An update step tests reactivity, so it stays an assignment, await settled() and assert.dom().hasText().

Semantic differences

  • Each assertStableRerender() is now await assert.stableRender(). Each renderComponent(X, { expect }) is now render() and await assert.stableRender(expect).
  • Where assertText(x) came before a stable check, the test now uses await assert.stableRender(x). That compares HTML, not text.
  • The steps runTask(() => this.rerender()) in concat-test are gone.
  • assert.dom().hasText() trims the text and collapses white space. assertText() compared the exact textContent.
  • if-laziness-test: after assert.stableRender(), the test also changes a tracked value in the same template, then checks that the helper did not run.
  • log-test: the tests for a property and for this use a @glimmer/component class. Before, this was the classic component of RenderingTestCase.
  • concat-test: the model is a class with @tracked fields. Before, it was a plain object changed with set. The x-eq helper is now a plain function in scope.
  • custom-helper-test: Helper comes from @ember/component/helper, not from the relative ../../index.

Checks

  • The 13 tests pass on the development build, on the production build, and with ALL_DEPRECATIONS_ENABLED=true.
  • The full suite passes on the development build: 9523 pass, 18 skip, 0 fail.
  • assert.stableRender() fails when a text node is replaced between the snapshot and the check, and the string form fails on a wrong string. I tried both on earlier versions of this branch.
  • A temporary probe in the assertion showed that the write opens a run loop, and that the render queue and the afterRender queue run before the promise resolves.
  • The test page from pnpm vite dev loads qunit-dom and the concat-test module passes there.
  • tsc --noEmit, eslint and prettier --check pass.

🤖 Generated with Claude Code

A separate commit keeps the file history, because git does not detect
the rename after the rewrite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

class Subject extends Component {
@tracked count = 0;
await assert.stableRender('subject');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I've decided for any of our custom, low-level, asserts, I'm going to make new helpers for the modern syntax here -- I don't think we'll have too many of these

@ef4

ef4 commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

I don't like that the new stableRender helper is weaker than what the old one tested. It's trying to see what happens after some unrelated change causes a re-render.

We do need to force re-render, but I think we can do it without any private API just by writing any piece of tracked state. You can confirm that it's working by resolving a promise in afterRender.

The tests now use module and test from qunit, setupRenderingTest from
ember-qunit, and render and settled from @ember/test-helpers.

No test is added, removed or renamed.

Two additions support the tests:

- qunit-dom is a dev dependency, for assert.dom().hasText() after an
  update.
- assert.stableRender() records the DOM nodes, waits for settled(), then
  checks that each node is the same node. With a string, it also
  compares the rendered HTML. It replaces assertStableRerender() and the
  expect option of renderComponent() of RenderingTestCase.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@NullVoxPopuli
NullVoxPopuli merged commit eef7970 into emberjs:main Oct 9, 2026
71 checks passed
@NullVoxPopuli
NullVoxPopuli deleted the nvp/vanilla-gjs-tests-2 branch October 9, 2026 18:00
@github-actions github-actions Bot mentioned this pull request Oct 9, 2026
ef4 added a commit that referenced this pull request Oct 19, 2026
…-tests-layout

Format the templates of the plain glimmer integration tests from #21672
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.

3 participants