Skip to content

test(query-devtools/utils): add tests for 'setupStyleSheet'#10649

Merged
sukvvon merged 1 commit intomainfrom
test/query-devtools-setup-stylesheet
May 6, 2026
Merged

test(query-devtools/utils): add tests for 'setupStyleSheet'#10649
sukvvon merged 1 commit intomainfrom
test/query-devtools-setup-stylesheet

Conversation

@sukvvon
Copy link
Copy Markdown
Collaborator

@sukvvon sukvvon commented May 6, 2026

🎯 Changes

Add unit tests for the setupStyleSheet helper in query-devtools/utils.tsx.

The helper inserts a <style id="_goober"> tag with the given nonce attribute, either into document.head or into a provided ShadowRoot target. It is a no-op when no nonce is provided, and it does not insert a duplicate tag if one already exists in the destination.

Cases:

  • no-op when nonce is missing
  • no-op when nonce is an empty string (guards against strict === undefined regressions)
  • appends <style id="_goober"> to document.head
  • sets the nonce attribute on the inserted style tag
  • does not insert a duplicate tag when document.head already has one
  • appends to a provided ShadowRoot target instead of document.head
  • does not insert a duplicate tag when the target already has one

The shared <style> tag in document.head is removed in afterEach to keep tests isolated.

The cross-target dedup behavior (whether a document.head tag should block insertion into a provided ShadowRoot target) is intentionally left unasserted while its intent is being clarified separately.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

📝 Walkthrough

Walkthrough

Adds an exported utility setupStyleSheet(nonce?: string, target?: ShadowRoot) that injects and deduplicates a style element with id _goober into document.head or a provided ShadowRoot. New tests validate insertion, nonce handling, and deduplication behavior. (29 words)

Changes

Stylesheet Setup Utility

Layer / File(s) Summary
Public API / Declaration
packages/query-devtools/src/utils.ts
Exports new function setupStyleSheet(nonce?: string, target?: ShadowRoot).
Core Implementation / Behavior
packages/query-devtools/src/utils.ts
Creates/appends a <style id="_goober">, sets nonce when provided, appends to document.head or supplied ShadowRoot, and avoids inserting duplicates.
Tests
packages/query-devtools/src/__tests__/utils.test.ts
Adds describe('setupStyleSheet', ...) with tests for: no insertion when nonce missing/empty, insertion with nonce and nonce attribute verification, deduplication in document.head, insertion into a provided ShadowRoot (not document.head), and deduplication within the ShadowRoot.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped in with a tiny style tag,
A nonce to keep the markup glad,
Into heads or shadowed nooks I creep,
One _goober only — no duplicates to keep. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding tests for the setupStyleSheet function in query-devtools/utils.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description comprehensively addresses all required template sections with detailed test case documentation and properly marked checkboxes.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/query-devtools-setup-stylesheet

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

@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented May 6, 2026

View your CI Pipeline Execution ↗ for commit 6f595f0

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 3m 13s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1s View ↗

☁️ Nx Cloud last updated this comment at 2026-05-06 03:07:36 UTC

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

🚀 Changeset Version Preview

No changeset entries found. Merging this PR will not cause a version bump for any packages.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 6, 2026

More templates

@tanstack/angular-query-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-experimental@10649

@tanstack/eslint-plugin-query

npm i https://pkg.pr.new/@tanstack/eslint-plugin-query@10649

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@10649

@tanstack/preact-query-devtools

npm i https://pkg.pr.new/@tanstack/preact-query-devtools@10649

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@10649

@tanstack/query-async-storage-persister

npm i https://pkg.pr.new/@tanstack/query-async-storage-persister@10649

@tanstack/query-broadcast-client-experimental

npm i https://pkg.pr.new/@tanstack/query-broadcast-client-experimental@10649

@tanstack/query-core

npm i https://pkg.pr.new/@tanstack/query-core@10649

@tanstack/query-devtools

npm i https://pkg.pr.new/@tanstack/query-devtools@10649

@tanstack/query-persist-client-core

npm i https://pkg.pr.new/@tanstack/query-persist-client-core@10649

@tanstack/query-sync-storage-persister

npm i https://pkg.pr.new/@tanstack/query-sync-storage-persister@10649

@tanstack/react-query

npm i https://pkg.pr.new/@tanstack/react-query@10649

@tanstack/react-query-devtools

npm i https://pkg.pr.new/@tanstack/react-query-devtools@10649

@tanstack/react-query-next-experimental

npm i https://pkg.pr.new/@tanstack/react-query-next-experimental@10649

@tanstack/react-query-persist-client

npm i https://pkg.pr.new/@tanstack/react-query-persist-client@10649

@tanstack/solid-query

npm i https://pkg.pr.new/@tanstack/solid-query@10649

@tanstack/solid-query-devtools

npm i https://pkg.pr.new/@tanstack/solid-query-devtools@10649

@tanstack/solid-query-persist-client

npm i https://pkg.pr.new/@tanstack/solid-query-persist-client@10649

@tanstack/svelte-query

npm i https://pkg.pr.new/@tanstack/svelte-query@10649

@tanstack/svelte-query-devtools

npm i https://pkg.pr.new/@tanstack/svelte-query-devtools@10649

@tanstack/svelte-query-persist-client

npm i https://pkg.pr.new/@tanstack/svelte-query-persist-client@10649

@tanstack/vue-query

npm i https://pkg.pr.new/@tanstack/vue-query@10649

@tanstack/vue-query-devtools

npm i https://pkg.pr.new/@tanstack/vue-query-devtools@10649

commit: 6f595f0

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

size-limit report 📦

Path Size
react full 12.1 KB (0%)
react minimal 9.07 KB (0%)

Copy link
Copy Markdown
Contributor

@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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/query-devtools/src/__tests__/utils.test.ts`:
- Around line 928-948: Add a regression test that ensures a pre-existing head
style tag does not block insertion into a provided ShadowRoot: create and append
a style element with id "_goober" and a known nonce to document.head, then
create a host with attachShadow and call setupStyleSheet('test-nonce', shadow);
assert that shadow.querySelector('#_goober') is not null (and has the expected
nonce if relevant) and that document.head still contains the original style (so
insertion happened into the shadow target despite the head entry). Also add a
variant that calls setupStyleSheet twice (first seeding head, then calling
setupStyleSheet on the same shadow) to ensure no duplicate style is added inside
the ShadowRoot while preserving the head tag; reference setupStyleSheet and the
internal style id "_goober" (and styleExists in utils.tsx) when locating the
behavior to test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1a3250a0-c6ba-45e6-a060-39cef711560a

📥 Commits

Reviewing files that changed from the base of the PR and between 24d0834 and 1fe4036.

📒 Files selected for processing (1)
  • packages/query-devtools/src/__tests__/utils.test.ts

Comment on lines +928 to +948
it('should append the style tag to the provided "ShadowRoot" target', () => {
const host = document.createElement('div')
const shadow = host.attachShadow({ mode: 'open' })

setupStyleSheet('test-nonce', shadow)

expect(shadow.querySelector('#_goober')).not.toBeNull()
expect(document.head.querySelector('#_goober')).toBeNull()
})

it('should not insert a duplicate style tag when the target already has one', () => {
const host = document.createElement('div')
const shadow = host.attachShadow({ mode: 'open' })

setupStyleSheet('first-nonce', shadow)
setupStyleSheet('second-nonce', shadow)

const styleTags = shadow.querySelectorAll('#_goober')
expect(styleTags).toHaveLength(1)
expect(styleTags[0]?.getAttribute('nonce')).toBe('first-nonce')
})
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Missing regression test for head-vs-shadow precedence bug.

On Line 932/Line 942, ShadowRoot behavior is only tested when document.head is clean. In packages/query-devtools/src/utils.tsx (Lines 305-323), styleExists checks document.querySelector('#_goober') first, so an existing head tag can incorrectly block insertion into the provided ShadowRoot target. Please add a test that seeds document.head first, then asserts target insertion still occurs.

Suggested test addition
   it('should not insert a duplicate style tag when the target already has one', () => {
     const host = document.createElement('div')
     const shadow = host.attachShadow({ mode: 'open' })

     setupStyleSheet('first-nonce', shadow)
     setupStyleSheet('second-nonce', shadow)

     const styleTags = shadow.querySelectorAll('#_goober')
     expect(styleTags).toHaveLength(1)
     expect(styleTags[0]?.getAttribute('nonce')).toBe('first-nonce')
   })
+
+  it('should still append to ShadowRoot when document.head already has "_goober"', () => {
+    setupStyleSheet('head-nonce')
+    const host = document.createElement('div')
+    const shadow = host.attachShadow({ mode: 'open' })
+
+    setupStyleSheet('shadow-nonce', shadow)
+
+    expect(document.head.querySelectorAll('#_goober')).toHaveLength(1)
+    expect(shadow.querySelectorAll('#_goober')).toHaveLength(1)
+    expect(shadow.querySelector('#_goober')?.getAttribute('nonce')).toBe(
+      'shadow-nonce',
+    )
+  })
 })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should append the style tag to the provided "ShadowRoot" target', () => {
const host = document.createElement('div')
const shadow = host.attachShadow({ mode: 'open' })
setupStyleSheet('test-nonce', shadow)
expect(shadow.querySelector('#_goober')).not.toBeNull()
expect(document.head.querySelector('#_goober')).toBeNull()
})
it('should not insert a duplicate style tag when the target already has one', () => {
const host = document.createElement('div')
const shadow = host.attachShadow({ mode: 'open' })
setupStyleSheet('first-nonce', shadow)
setupStyleSheet('second-nonce', shadow)
const styleTags = shadow.querySelectorAll('#_goober')
expect(styleTags).toHaveLength(1)
expect(styleTags[0]?.getAttribute('nonce')).toBe('first-nonce')
})
it('should append the style tag to the provided "ShadowRoot" target', () => {
const host = document.createElement('div')
const shadow = host.attachShadow({ mode: 'open' })
setupStyleSheet('test-nonce', shadow)
expect(shadow.querySelector('#_goober')).not.toBeNull()
expect(document.head.querySelector('#_goober')).toBeNull()
})
it('should not insert a duplicate style tag when the target already has one', () => {
const host = document.createElement('div')
const shadow = host.attachShadow({ mode: 'open' })
setupStyleSheet('first-nonce', shadow)
setupStyleSheet('second-nonce', shadow)
const styleTags = shadow.querySelectorAll('#_goober')
expect(styleTags).toHaveLength(1)
expect(styleTags[0]?.getAttribute('nonce')).toBe('first-nonce')
})
it('should still append to ShadowRoot when document.head already has "_goober"', () => {
setupStyleSheet('head-nonce')
const host = document.createElement('div')
const shadow = host.attachShadow({ mode: 'open' })
setupStyleSheet('shadow-nonce', shadow)
expect(document.head.querySelectorAll('#_goober')).toHaveLength(1)
expect(shadow.querySelectorAll('#_goober')).toHaveLength(1)
expect(shadow.querySelector('#_goober')?.getAttribute('nonce')).toBe(
'shadow-nonce',
)
})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/query-devtools/src/__tests__/utils.test.ts` around lines 928 - 948,
Add a regression test that ensures a pre-existing head style tag does not block
insertion into a provided ShadowRoot: create and append a style element with id
"_goober" and a known nonce to document.head, then create a host with
attachShadow and call setupStyleSheet('test-nonce', shadow); assert that
shadow.querySelector('#_goober') is not null (and has the expected nonce if
relevant) and that document.head still contains the original style (so insertion
happened into the shadow target despite the head entry). Also add a variant that
calls setupStyleSheet twice (first seeding head, then calling setupStyleSheet on
the same shadow) to ensure no duplicate style is added inside the ShadowRoot
while preserving the head tag; reference setupStyleSheet and the internal style
id "_goober" (and styleExists in utils.tsx) when locating the behavior to test.

@sukvvon sukvvon force-pushed the test/query-devtools-setup-stylesheet branch from 1fe4036 to 3bfa156 Compare May 6, 2026 02:08
Copy link
Copy Markdown
Contributor

@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.

♻️ Duplicate comments (1)
packages/query-devtools/src/__tests__/utils.test.ts (1)

956-964: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

ShadowRoot precedence test is asserting the wrong contract.

On Line 956, this test currently expects a provided ShadowRoot target to be skipped if document.head already has #_goober. That locks in incorrect behavior: target-scoped insertion should still happen for the provided shadow root, while preserving the head tag.

Suggested test fix
-    it('should not insert into the target when "document.head" already has a style tag', () => {
+    it('should still insert into the target when "document.head" already has a style tag', () => {
       const host = document.createElement('div')
       const shadow = host.attachShadow({ mode: 'open' })

       setupStyleSheet('first-nonce')
       setupStyleSheet('second-nonce', shadow)

-      expect(shadow.querySelector('#_goober')).toBeNull()
+      expect(document.head.querySelectorAll('#_goober')).toHaveLength(1)
+      expect(document.head.querySelector('#_goober')?.getAttribute('nonce')).toBe('first-nonce')
+      expect(shadow.querySelectorAll('#_goober')).toHaveLength(1)
+      expect(shadow.querySelector('#_goober')?.getAttribute('nonce')).toBe('second-nonce')
     })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/query-devtools/src/__tests__/utils.test.ts` around lines 956 - 964,
The test using setupStyleSheet('first-nonce') and
setupStyleSheet('second-nonce', shadow) incorrectly asserts that the shadow
target is skipped when document.head already has `#_goober`; instead, change the
assertion to verify that a head-scoped stylesheet remains and that a
target-scoped stylesheet was also inserted into the provided ShadowRoot: assert
that document.head.querySelector('#_goober') is not null and that
shadow.querySelector('#_goober') is not null (i.e., ensure both the head and the
shadow root contain their own `#_goober` elements after calling setupStyleSheet
with and without the ShadowRoot).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@packages/query-devtools/src/__tests__/utils.test.ts`:
- Around line 956-964: The test using setupStyleSheet('first-nonce') and
setupStyleSheet('second-nonce', shadow) incorrectly asserts that the shadow
target is skipped when document.head already has `#_goober`; instead, change the
assertion to verify that a head-scoped stylesheet remains and that a
target-scoped stylesheet was also inserted into the provided ShadowRoot: assert
that document.head.querySelector('#_goober') is not null and that
shadow.querySelector('#_goober') is not null (i.e., ensure both the head and the
shadow root contain their own `#_goober` elements after calling setupStyleSheet
with and without the ShadowRoot).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c28b3e49-93ec-44da-ba28-adae74fdf0f7

📥 Commits

Reviewing files that changed from the base of the PR and between 1fe4036 and 3bfa156.

📒 Files selected for processing (1)
  • packages/query-devtools/src/__tests__/utils.test.ts

@sukvvon sukvvon self-assigned this May 6, 2026
@sukvvon sukvvon force-pushed the test/query-devtools-setup-stylesheet branch from 3bfa156 to 6f595f0 Compare May 6, 2026 03:03
@sukvvon sukvvon merged commit 150300f into main May 6, 2026
8 checks passed
@sukvvon sukvvon deleted the test/query-devtools-setup-stylesheet branch May 6, 2026 03:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant