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

[Modal] Fix persisting aria-hidden #16392

Merged
merged 6 commits into from
Jun 28, 2019
Merged

Conversation

eps1lon
Copy link
Member

@eps1lon eps1lon commented Jun 27, 2019

Not a fix yet just a failing test case. Opening this since I have a question: Why do we export ariaHidden from the ModalManager and use it in Modal? Isn't the point of ModalManager that it manages this stuff in which case it shouldn't be exported?

I suspected that the issue was with a rogue parent aria-hidden which is why I added a custom matcher (aria-hidden is inherited but not overwriteable).

Closes #16391

/cc @oliviertassinari

@eps1lon eps1lon added bug 🐛 Something doesn't work component: modal This is the name of the generic UI component, not the React module! labels Jun 27, 2019
chai.Assertion.addProperty('ariaHidden', function elementIsAccessible() {
const element = utils.flag(this, 'object');

// "An element is considered hidden if it, or any of its ancestors are not
Copy link
Member Author

Choose a reason for hiding this comment

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

For integration test we could implement a custom matcher for hidden content as well. It won't catch everything (since it requires layout) but a crude implementation could just join ariaHiden || !displayed || !visible.

@mui-pr-bot
Copy link

mui-pr-bot commented Jun 27, 2019

Details of bundle changes.

Comparing: a0f0843...0a9c506

bundle parsed diff gzip diff prev parsed current parsed prev gzip current gzip
@material-ui/core 0.00% 0.00% 320,047 320,047 88,362 88,363
@material-ui/core/Paper 0.00% 0.00% 68,290 68,290 20,366 20,366
@material-ui/core/Paper.esm 0.00% 0.00% 61,573 61,573 19,161 19,161
@material-ui/core/Popper 0.00% 0.00% 28,945 28,945 10,395 10,395
@material-ui/core/Textarea 0.00% 0.00% 5,524 5,524 2,378 2,378
@material-ui/core/TrapFocus 0.00% 0.00% 3,753 3,753 1,578 1,578
@material-ui/core/styles/createMuiTheme 0.00% 0.00% 16,009 16,009 5,791 5,791
@material-ui/core/useMediaQuery 0.00% 0.00% 2,597 2,597 1,102 1,102
@material-ui/lab 0.00% 0.00% 140,095 140,095 43,397 43,397
@material-ui/styles 0.00% 0.00% 51,698 51,698 15,348 15,348
@material-ui/system 0.00% 0.00% 15,420 15,420 4,391 4,391
Button 0.00% 0.00% 84,316 84,316 25,722 25,722
Modal 0.00% 0.00% 14,427 14,427 5,087 5,087
Portal 0.00% 0.00% 3,473 3,473 1,572 1,572
Slider 0.00% 0.00% 74,775 74,775 23,246 23,246
colorManipulator 0.00% 0.00% 3,904 3,904 1,544 1,544
docs.landing 0.00% 0.00% 54,843 54,843 13,901 13,901
docs.main 0.00% -0.00% 647,121 647,121 203,996 203,994
packages/material-ui/build/umd/material-ui.production.min.js 0.00% 0.00% 293,253 293,253 84,247 84,247

Generated by 🚫 dangerJS against 0a9c506

Copy link
Member

@oliviertassinari oliviertassinari left a comment

Choose a reason for hiding this comment

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

Why do we export ariaHidden from the ModalManager and use it in Modal?

The modal manager handles the active modals. In this case, the aria-hidden is used on a modal that is mounted in the DOM, and that will likely be active in the future. Removing the line breaks this test:

Capture d’écran 2019-06-27 à 11 23 15

<Modal keepMounted open={false}

@@ -161,17 +161,17 @@ describe('ModalManager', () => {
const modal2 = {};
modalManager.add(modal1, container3);
modalManager.mount(modal1);
assert.strictEqual(container3.children[0].getAttribute('aria-hidden'), 'true');
expect(container3.children[0]).to.be.ariaHidden;
Copy link
Member

Choose a reason for hiding this comment

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

What do you think of minimizing the API surface people have to know for contributing? Where does .ariaHidden come from? Would it be simpler with the native DOM API?

Suggested change
expect(container3.children[0]).to.be.ariaHidden;
expect(container3.children[0].getAttribute('aria-hidden')).to.equal('true');

Copy link
Member

@oliviertassinari oliviertassinari Jun 27, 2019

Choose a reason for hiding this comment

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

Ok, I have read the rest of the pull request. The native DOM API is not a good idea. I was confused by the magic behind the API.

What do you think of importing the aria-hidden helper function instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

Doesn't scale very well (need to import all the matchers) and doesn't address the concern (knowledge is required in both cases). It's common to rely on injected matcher methods. Autocomplete should work (needs other PR) which helps with discoverability and teaching.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh and yeah it helps debugging failing test. A simple boolean helper would not.

Copy link
Member

@oliviertassinari oliviertassinari Jun 27, 2019

Choose a reason for hiding this comment

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

need to import all the matchers

I would hope a file test doesn't need to import all the matchers. For instance, will we need the aria-hidden helper outside of the modal context?

knowledge is required in both cases

It depends on the case. When writing the test case, knowledge is required in both cases. When reading the test case, the import can be followed. Considering we spend most of our time reading the test case, I find that value proposing interesting.

Oh and yeah it helps debugging failing test. A simple boolean helper would not.

Yeah, that wasn't a good idea from my part. However, does it invalidate the import helper point? Can we write the helper to run the assertions?

Copy link
Member

@oliviertassinari oliviertassinari Jun 27, 2019

Choose a reason for hiding this comment

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

This is the fundamental issue. When something fails you need to understand how the code works not your test.

Yeah, I wish it was true, it's a great target!

Now, I haven't experienced that in practice in this codebase nor in any other. I have found myself needed to understand what was the initial situation, what was the actions and what was the assertions.

And tests are not always regression test.

Should they all be regression tests (i.e remove the ones that are not)?

Copy link
Member Author

Choose a reason for hiding this comment

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

There's a reason why we say "test" and "regression test". One being more specific and less common therefore having the longer word. Regression test make little sense for behavior that's not observable to the user (e.g. component snapshot test, asserting instance fields).

Copy link
Member

Choose a reason for hiding this comment

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

I have done a quick search on the topic. It seems that people define "regression test" as "when it fails, it tells you that the application no longer behaves the way it used to".
I was using the term in a broader context, closer to "acceptance test": "when it fails, it tells you that the application is not doing what the customer expects it to do".

Copy link
Member Author

Choose a reason for hiding this comment

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

exactly. And these tests next to our components are acceptance test that describe what's expected. The more declarative the better.

Copy link
Member

Choose a reason for hiding this comment

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

The only regression test I'm aware of that is valuable is the screenshot tests. I would be cautious with snapshot tests, it can quickly end-up like this: they take too much time to look, we accept the changes blindly.

@eps1lon eps1lon marked this pull request as ready for review June 27, 2019 12:03
@eps1lon eps1lon force-pushed the fix/modal-aria-hidden branch from 6c5660e to 4f605a1 Compare June 27, 2019 12:15
@eps1lon eps1lon merged commit e36f5d0 into mui:master Jun 28, 2019
@eps1lon eps1lon deleted the fix/modal-aria-hidden branch June 28, 2019 06:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work component: modal This is the name of the generic UI component, not the React module!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ModelManager set aria-hidden=true on <body>
3 participants