Skip to content

Commit

Permalink
fix: check for inherited :disabled (#872)
Browse files Browse the repository at this point in the history
  • Loading branch information
ph-fritsche authored Mar 4, 2022
1 parent 75fdd44 commit 1a00fdf
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 3 deletions.
38 changes: 35 additions & 3 deletions src/utils/misc/isDisabled.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
// This should probably be extended with checking the element type
// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled
import {isElementType} from './isElementType'

// This should probably just rely on the :disabled pseudo-class, but JSDOM doesn't implement it properly.
export function isDisabled(element: Element | null): boolean {
return Boolean(element && (element as {disabled?: boolean}).disabled)
for (let el = element; el; el = el.parentElement) {
if (
isElementType(el, [
'button',
'input',
'select',
'textarea',
'optgroup',
'option',
])
) {
if (el.hasAttribute('disabled')) {
return true
}
} else if (isElementType(el, 'fieldset')) {
if (
el.hasAttribute('disabled') &&
!el.querySelector(':scope > legend')?.contains(element)
) {
return true
}
} else if (el.tagName.includes('-')) {
if (
(el.constructor as {formAssociated?: boolean}).formAssociated &&
el.hasAttribute('disabled')
) {
return true
}
}
}

return false
}
73 changes: 73 additions & 0 deletions tests/utils/misc/isDisabled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import cases from 'jest-in-case'
import {isDisabled} from '#src/utils'
import {render} from '#testHelpers'

customElements.define(
'form-associated',
class FormAssociated extends HTMLElement {
static formAssociated = true
get disabled() {
return this.hasAttribute('disabled')
}
},
)

customElements.define(
'custom-el',
class CustomEl extends HTMLElement {
get disabled() {
return this.hasAttribute('disabled')
}
},
)

// https://html.spec.whatwg.org/multipage/semantics-other.html#disabled-elements
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#enabling-and-disabling-form-controls:-the-disabled-attribute
cases(
'check if element is disabled',
({html, node = '//input', expected = true}) => {
const {xpathNode} = render(html)
expect(isDisabled(xpathNode<Element>(node))).toBe(expected)
},
{
control: {
html: `<input/>`,
expected: false,
},
'disabled control': {
html: `<input disabled/>`,
},
'control in disabled fieldset': {
html: `<fieldset disabled><input/></fieldset>`,
},
'control in first legend of disabled fieldset': {
html: `<fieldset disabled><legend><input/></legend></fieldset>`,
expected: false,
},
'control in other legend of disabled fieldset': {
html: `<fieldset disabled><legend></legend><legend><input/></legend></fieldset>`,
},
'control in nested legend of disabled fieldset': {
html: `<fieldset disabled><div>><legend><input/></legend></div></fieldset>`,
},
'element without support for disabled': {
html: `<div disabled></div>`,
node: '*',
expected: false,
},
'form-associated disabled custom element': {
html: `<form-associated disabled></form-associated>`,
node: '*',
},
'form-associated enabled custom element': {
html: `<form-associated></form-associated>`,
node: '*',
expected: false,
},
'other custom element': {
html: `<custom-el disabled></custom-el>`,
node: '*',
expected: false,
},
},
)

0 comments on commit 1a00fdf

Please sign in to comment.