Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: call formDisabledCallback in response to fieldset disabled #90

Closed

Conversation

bennypowers
Copy link
Contributor

closes #88

@calebdwilliams does this test represent expected behavior?

@calebdwilliams
Copy link
Owner

Yeah, this will capture the expected behavior for polyfilled browsers. I'd want to make sure it works for multiple instances of the form-associated element though.

@bennypowers
Copy link
Contributor Author

does the last commit cover your comment?

@calebdwilliams
Copy link
Owner

It does. Thanks!

@bennypowers
Copy link
Contributor Author

854e684 has some code which might work, but I had some trouble testing. Is it the case that I should test in an isolated virtual machine with older browser versions?

@bennypowers bennypowers marked this pull request as ready for review December 6, 2022 21:13
@calebdwilliams
Copy link
Owner

Sorry for the delay in getting to this one. Looks like a test is failing

❌ The ElementInternals polyfill > inside a custom element with a form and containing fieldset > sets aria-disabled when the fieldset is disabled
      AssertionError: expected null to equal 'true'
        at o.<anonymous> (test/ElementInternals.test.js:497:53)

Chromium: |██████████████████████████████| 3/3 test files | 55 passed, 1 failed
Firefox:  |██████████████████████████████| 3/3 test files | 55 passed, 1 failed
Webkit:   |██████████████████████████████| 3/3 test files | 55 passed, 1 failed

@calebdwilliams
Copy link
Owner

What problems have you had testing?

@bennypowers
Copy link
Contributor Author

with this, and a peppering of console.log calls throughout the polyfill code, i'm unable to verify that the polyfill is loading at all during that test, let alone whether the fieldsets are registering :/

  describe.only('inside a custom element with a form and containing fieldset', () => {

I sent an aspirational commit, maybe it will pass in CI 🤷 PTAL when you get a chance

@bennypowers
Copy link
Contributor Author

bennypowers commented Jan 3, 2023

This is what I get when testing.
test/polyfilledBrowsers.test.js:

 ❌ The browser was unable to create and start a test page after 30000ms. You can increase this timeout with the browserStartTimeout option.  (failed on Firefox)

 ❌ browserType.launch: 
╔══════════════════════════════════════════════════════╗
║ Host system is missing dependencies to run browsers. ║
║ Missing libraries:                                   ║
║     libpcre.so.3                                     ║
║     libicui18n.so.66                                 ║
║     libicuuc.so.66                                   ║
║     libjpeg.so.8                                     ║
║     libwebp.so.6                                     ║
║     libenchant.so.1                                  ║
║     libffi.so.7                                      ║
╚══════════════════════════════════════════════════════╝  (failed on Webkit)
    browserType.launch: 
    ╔══════════════════════════════════════════════════════╗
    ║ Host system is missing dependencies to run browsers. ║
    ║ Missing libraries:                                   ║
    ║     libpcre.so.3                                     ║
    ║     libicui18n.so.66                                 ║
    ║     libicuuc.so.66                                   ║
    ║     libjpeg.so.8                                     ║
    ║     libwebp.so.6                                     ║
    ║     libenchant.so.1                                  ║
    ║     libffi.so.7                                      ║
    ╚══════════════════════════════════════════════════════╝
        at /home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-playwright/dist/PlaywrightLauncher.js:101:74
        at PlaywrightLauncher.getOrStartBrowser (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-playwright/dist/PlaywrightLauncher.js:104:15)
        at PlaywrightLauncher.startSession (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-playwright/dist/PlaywrightLauncher.js:42:49)
        at TestScheduler.startSession (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-core/dist/runner/TestScheduler.js:103:62)
        at TestScheduler.runNextScheduled (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-core/dist/runner/TestScheduler.js:83:30)
        at Timeout._onTimeout (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-core/dist/runner/TestScheduler.js:34:26)

Chromium: |██████████████████████████████| 3/3 test files | 8 passed, 1 failed
Firefox:  |██████████████████████████████| 3/3 test files | 0 passed, 0 failed
test/polyfilledBrowsers.test.js:

 ❌ The browser was unable to create and start a test page after 30000ms. You can increase this timeout with the browserStartTimeout option.  (failed on Firefox)

 ❌ browserType.launch: 
╔══════════════════════════════════════════════════════╗
║ Host system is missing dependencies to run browsers. ║
║ Missing libraries:                                   ║
║     libpcre.so.3                                     ║
║     libicui18n.so.66                                 ║
║     libicuuc.so.66                                   ║
║     libjpeg.so.8                                     ║
║     libwebp.so.6                                     ║
║     libenchant.so.1                                  ║
║     libffi.so.7                                      ║
╚══════════════════════════════════════════════════════╝  (failed on Webkit)
    browserType.launch: 
    ╔══════════════════════════════════════════════════════╗
    ║ Host system is missing dependencies to run browsers. ║
    ║ Missing libraries:                                   ║
    ║     libpcre.so.3                                     ║
    ║     libicui18n.so.66                                 ║
    ║     libicuuc.so.66                                   ║
    ║     libjpeg.so.8                                     ║
    ║     libwebp.so.6                                     ║
    ║     libenchant.so.1                                  ║
    ║     libffi.so.7                                      ║
    ╚══════════════════════════════════════════════════════╝
        at /home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-playwright/dist/PlaywrightLauncher.js:101:74
        at PlaywrightLauncher.getOrStartBrowser (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-playwright/dist/PlaywrightLauncher.js:104:15)
        at PlaywrightLauncher.startSession (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-playwright/dist/PlaywrightLauncher.js:42:49)
        at TestScheduler.startSession (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-core/dist/runner/TestScheduler.js:103:62)
        at TestScheduler.runNextScheduled (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-core/dist/runner/TestScheduler.js:83:30)
        at Timeout._onTimeout (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-core/dist/runner/TestScheduler.js:34:26)

Chromium: |██████████████████████████████| 3/3 test files | 8 passed, 1 failed
Firefox:  |██████████████████████████████| 3/3 test files | 0 passed, 0 failed
test/polyfilledBrowsers.test.js:

 ❌ The browser was unable to create and start a test page after 30000ms. You can increase this timeout with the browserStartTimeout option.  (failed on Firefox)

 ❌ browserType.launch: 
╔══════════════════════════════════════════════════════╗
║ Host system is missing dependencies to run browsers. ║
║ Missing libraries:                                   ║
║     libpcre.so.3                                     ║
║     libicui18n.so.66                                 ║
║     libicuuc.so.66                                   ║
║     libjpeg.so.8                                     ║
║     libwebp.so.6                                     ║
║     libenchant.so.1                                  ║
║     libffi.so.7                                      ║
╚══════════════════════════════════════════════════════╝  (failed on Webkit)
    browserType.launch: 
    ╔══════════════════════════════════════════════════════╗
    ║ Host system is missing dependencies to run browsers. ║
    ║ Missing libraries:                                   ║
    ║     libpcre.so.3                                     ║
    ║     libicui18n.so.66                                 ║
    ║     libicuuc.so.66                                   ║
    ║     libjpeg.so.8                                     ║
    ║     libwebp.so.6                                     ║
    ║     libenchant.so.1                                  ║
    ║     libffi.so.7                                      ║
    ╚══════════════════════════════════════════════════════╝
        at /home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-playwright/dist/PlaywrightLauncher.js:101:74
        at PlaywrightLauncher.getOrStartBrowser (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-playwright/dist/PlaywrightLauncher.js:104:15)
        at PlaywrightLauncher.startSession (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-playwright/dist/PlaywrightLauncher.js:42:49)
        at TestScheduler.startSession (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-core/dist/runner/TestScheduler.js:103:62)
        at TestScheduler.runNextScheduled (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-core/dist/runner/TestScheduler.js:83:30)
        at Timeout._onTimeout (/home/bennyp/Developer/element-internals-polyfill/node_modules/@web/test-runner-core/dist/runner/TestScheduler.js:34:26)

Chromium: |██████████████████████████████| 3/3 test files | 8 passed, 1 failed
Firefox:  |██████████████████████████████| 3/3 test files | 0 passed, 0 failed
Webkit:   |██████████████████████████████| 3/3 test files | 0 passed, 0 failed

Asides from that, I'm able to test the correct behaviour if i force the polyfill to always activate by changing the test to if (!isElementInternalsSupported() || true) in

if (!isElementInternalsSupported()) {
but otherwise the test fails :/

@calebdwilliams
Copy link
Owner

Can you run npx playwright install --with-deps locally and/or force push? I finally added a test action to PRs and we can get this out the door once it's ready.

@calebdwilliams
Copy link
Owner

Diving in to this, the only effect that toggling disabled has on the internals host is calling the formDisabledCallback if one is present and set's the host's internal :disabled state. It shouldn't/doesn't modify the ARIA mixin value of ariaDisabled or modify the any specific property on the host itself (like creating a disabled property or attribute).

The test that we should have here is probably something along the lines of

it('will respect the fieldset disabled attribute', async () => {
  const form = await fixture<HTMLFormElement>(html`<form>
    <fieldset>
      <test-el></test-el>
    </fieldset>
  </form>`);
  const fieldset = form.querySelector<HTMLFieldSetElement>('fieldset')!;
  const testEl = form.querySelector<TestEl>('TestEl')!;

  fieldset.disabled = true;
  expect(testEl.formDisabledCallback.called).to.be.true;
});

Unfortunately since formDisabledCallback is a CEReaction, we will have to watch for some side-effect of the method rather than spying on it directly. The simplest solution I can think of is doing something like the following

let disabledCallbackCount = 0;
class TestEl extends HTMLElement {
  static formAssociated = true;
  internals = this.attachInternals();

  formDisabledCallback() {
    disabledCallbackCount += 1;
  }
}

customElements.define('test-el', TestEl);

describe('The thing', () => {
  afterEach(() => {
    disabledCallbackCount = 0;
  });


  it('is a passing test', () => {
    expect(isItAwesome).to.be.true;
  });
});

This is a naive example though. Sorry it's take me so long to get back on top of this, I was really burned out before the holidays, but am trying to balance things better now.

@bennypowers
Copy link
Contributor Author

This is great work, thanks for investigating, @calebdwilliams

So if I understood correctly, that means the polyfill cannot provide matches(':disabled'), right?

@calebdwilliams
Copy link
Owner

Unfortunately I don’t think it can but there’s a lot I don’t know. I think @jonathantneal might have a way to do this with CSSOM shenanigans. Maybe he can ping us in the right direction.

@calebdwilliams
Copy link
Owner

calebdwilliams commented Jan 7, 2023

@bennypowers is this something you’re still interested in tackling?

@bennypowers
Copy link
Contributor Author

yes, i'll take a go at it in light of above comments tomorrow

@jonathantneal
Copy link

jonathantneal commented Jan 8, 2023

To support :disabled, this library would need to patch the query methods (querySelector, querySelectorAll, and matches) akin to how it patches attachShadow. That patch could also be used to support :--state as well.

What would it replace :disabled with? I suppose elements could maintain their LightDOM selector (that is, custom element, itself.)

Here’s how they could generate that reference.

/** Return a unique selector for a specific element. */
let getUniqueSelector = (/** @type {Element} */ element) => {
	/** Unique selector for this element */
	let selector = ''

	/** @type {Element} */
	let parent

	/** @type {number} */
	let nth

	while (parent = element.parentElement) {
		for (nth = 1; element = element.previousElementSibling; ++nth);

		selector = ' > :nth-child(' + nth + ')' + selector

		element = parent
	}

	return ':is(:root, :host)' + selector
}

And then elements could push that selector up to some map that replaces those states on selectors, like selector.replace(":disabled", `:where(${selectorsFor.disabled})`). As a gist, does this make sense?

Happy to help try to contribute something like this, if it would be desired / helpful. If it isn’t, no worries.

@bennypowers bennypowers changed the title fix: respect fieldset disabled attribute fix: call formDisabledCallback in response to fieldset disabled Jan 8, 2023
@calebdwilliams
Copy link
Owner

Fixed in a different PR

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.

Enclosing fieldset's disabled attr does not disable polyfilled elements
3 participants