Skip to content

fix: correct <summary> element behavior#2806

Open
nn-morishita wants to merge 6 commits into
vuejs:mainfrom
nn-morishita:fix/issue-2626-description
Open

fix: correct <summary> element behavior#2806
nn-morishita wants to merge 6 commits into
vuejs:mainfrom
nn-morishita:fix/issue-2626-description

Conversation

@nn-morishita

Copy link
Copy Markdown

This PR addresses #2626.

The issue is that

element behavior is inconsistent with the real browser.

I verified this in a real browser, and the issue still occurs.

Reproduction:
https://stackblitz.com/edit/vitejs-vite-qxxwzrgz?file=src%2Fcomponents%2Ftests%2FDetailsComponent.test.ts

@netlify

netlify Bot commented Apr 5, 2026

Copy link
Copy Markdown

Deploy Preview for vue-test-utils-docs ready!

Name Link
🔨 Latest commit 356049c
🔍 Latest deploy log https://app.netlify.com/projects/vue-test-utils-docs/deploys/6a1bdb200c6f0b0009545b72
😎 Deploy Preview https://deploy-preview-2806--vue-test-utils-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@cexbrayat cexbrayat left a comment

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.

Thanks for the PR!

I don't think this is enough though. The PR makes <summary> skip ancestor visibility checks entirely in isElementVisible.
That means a <summary> can be reported visible even when one of its ancestors is hidden (for example display: none), which is a regression because hidden ancestors should make descendants not visible.

pseudo-test to reproduce (did not run it, so maybe it needs tweaking):

it('should consider a summary as hidden when an ancestor is hidden', () => {
  const HiddenAncestorSummary = defineComponent({
    template: `
      <div style="display: none;">
        <details>
          <summary>Summary</summary>
        </details>
      </div>
    `
  })

  const wrapper = mount(HiddenAncestorSummary)
  expect(wrapper.find('summary').isVisible()).toBe(false)
})

I also think the PR treats any <summary> inside a <details> as visible, regardless of structure.
That is too broad: only the primary summary should be visible in a closed <details>. A nested <summary> inside closed details content should remain hidden.

it('should consider a summary as hidden when nested inside closed details content', () => {
  const NestedSummaryInClosedDetails = defineComponent({
    template: `
      <details>
        <summary>Main summary</summary>
        <div>
          <summary>Nested summary</summary>
        </div>
      </details>
    `
  })

  const wrapper = mount(NestedSummaryInClosedDetails)
  const summaries = wrapper.findAll('summary')

  expect(summaries[0].isVisible()).toBe(true)
  expect(summaries[1].isVisible()).toBe(false)
});

@cexbrayat

Copy link
Copy Markdown
Member

@nn-morishita are you still interested in fixing the issue or should we close the PR?

@nn-morishita

Copy link
Copy Markdown
Author

@cexbrayat Sorry for the delayed response. I’ve just pushed a new commit addressing the feedback. I’d appreciate it if you could take a look when you have a chance.

@pkg-pr-new

pkg-pr-new Bot commented May 5, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@vue/test-utils@2806

commit: 356049c

Comment thread src/utils/isElementVisible.ts Outdated
)
if (element instanceof HTMLInputElement && element.type === 'hidden') {
return false
}

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.

This change is unrelated to the issue, but an interesting addition. Could you either:

  • add a unit test in this PR
  • remove this change from this PR and open another one with a unit test

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.

As the funciton no longer use attribute checking, maybe rename it to isElementVisible?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Since a function named isElementVisible already exists, I renamed this function to isElementVisibleByAttribute.

Comment thread tests/isVisible.spec.ts
Comment thread tests/isVisible.spec.ts
Comment thread src/utils/isElementVisible.ts
@nn-morishita

Copy link
Copy Markdown
Author

@cexbrayat
Thank you for your feedback! I've made the changes—please let me know if this aligns with your intention.

Comment thread tests/isVisible.spec.ts Outdated
it('DetailContent should be invisible when display:none is applied by class', () => {
const style = document.createElement('style')
document.head.appendChild(style)
style.sheet!.insertRule('.hidden { display: none; }')

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.

I'm afraid that this will leak into other tests. I would remove this test, the following one should be enough.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I fixed this point. I remove this test case.

Comment thread tests/isVisible.spec.ts
Comment thread src/utils/isElementVisible.ts Outdated
* @returns boolean
*/
function isElementVisibleByAttribute<T extends Element>(element: T) {
if (element instanceof HTMLInputElement && (element.type === 'hidden' || element.hidden)) {

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.

This now only checks hidden for HTMLInputElement whereas it was checking it for all HTMLElements previously.

And as I was mentioning before, the hidden check for inputs is a nice addition but should have a unit test (or even better, a dedicated PR).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for pointing that out! You're right — my change unintentionally removed the hidden check for other HTMLElements. I restored the previous behavior and removed the unrelated input hidden change from this PR.

@nn-morishita

Copy link
Copy Markdown
Author

@cexbrayat
Sorry for the late reply. I've addressed your comments.

@cexbrayat

Copy link
Copy Markdown
Member

@nn-morishita can you make sure format and tests are working (I suspect the removal of mount in a test in your last commit is unintended)?

@nn-morishita

Copy link
Copy Markdown
Author

@cexbrayat
Thanks for pointing that out. The removal of mount was indeed unintended. I've restored it and verified that the formatting and tests pass locally.

@cexbrayat

Copy link
Copy Markdown
Member

@nn-morishita Thanks for the commit, but it looks like the formatting is still failing?

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