|
1 | 1 | import { expect } from '@vaadin/chai-plugins'; |
2 | 2 | import { fixtureSync, nextRender, oneEvent, tabKeyDown } from '@vaadin/testing-helpers'; |
3 | | -import '../src/vaadin-overlay.js'; |
4 | 3 | import { getFocusableElements, isElementFocused } from '@vaadin/a11y-base/src/focus-utils.js'; |
| 4 | +import { Overlay } from '../src/vaadin-overlay.js'; |
5 | 5 |
|
6 | 6 | describe('focus-trap', () => { |
7 | 7 | let overlay, overlayPart, focusableElements; |
@@ -195,4 +195,119 @@ describe('focus-trap', () => { |
195 | 195 | expect(outer.hasAttribute('aria-hidden')).to.be.false; |
196 | 196 | }); |
197 | 197 | }); |
| 198 | + |
| 199 | + describe('aria-hidden modal root', () => { |
| 200 | + customElements.define( |
| 201 | + 'custom-overlay-wrapper', |
| 202 | + class extends HTMLElement { |
| 203 | + constructor() { |
| 204 | + super(); |
| 205 | + |
| 206 | + this.attachShadow({ mode: 'open' }); |
| 207 | + |
| 208 | + const overlay = document.createElement('custom-overlay'); |
| 209 | + |
| 210 | + const owner = document.createElement('div'); |
| 211 | + overlay.owner = owner; |
| 212 | + |
| 213 | + // Forward the slotted content from wrapper to overlay |
| 214 | + const slot = document.createElement('slot'); |
| 215 | + overlay.appendChild(slot); |
| 216 | + |
| 217 | + overlay.focusTrap = true; |
| 218 | + overlay.renderer = (root) => { |
| 219 | + root.innerHTML = '<input placeholder="Input">'; |
| 220 | + }; |
| 221 | + |
| 222 | + this.shadowRoot.append(overlay); |
| 223 | + this.append(owner); |
| 224 | + } |
| 225 | + }, |
| 226 | + ); |
| 227 | + |
| 228 | + customElements.define( |
| 229 | + 'custom-overlay', |
| 230 | + class extends Overlay { |
| 231 | + get _contentRoot() { |
| 232 | + return this.owner; |
| 233 | + } |
| 234 | + |
| 235 | + get _modalRoot() { |
| 236 | + return this.owner; |
| 237 | + } |
| 238 | + |
| 239 | + _attachOverlay() { |
| 240 | + this.setAttribute('popover', 'manual'); |
| 241 | + this.showPopover(); |
| 242 | + } |
| 243 | + |
| 244 | + _detachOverlay() { |
| 245 | + this.hidePopover(); |
| 246 | + } |
| 247 | + }, |
| 248 | + ); |
| 249 | + |
| 250 | + let outer, inner, wrapper, overlay; |
| 251 | + |
| 252 | + beforeEach(() => { |
| 253 | + // Create outer element and pass it explicitly. |
| 254 | + outer = document.createElement('main'); |
| 255 | + |
| 256 | + // Our `fixtureSync()` requires a single parent. |
| 257 | + inner = fixtureSync( |
| 258 | + ` |
| 259 | + <div> |
| 260 | + <aside> |
| 261 | + <button>Foo</button> |
| 262 | + </aside> |
| 263 | + <div> |
| 264 | + <button>Bar</button> |
| 265 | + <custom-overlay-wrapper></custom-overlay-wrapper> |
| 266 | + <button>Baz</button> |
| 267 | + </div> |
| 268 | + </div> |
| 269 | + `, |
| 270 | + outer, |
| 271 | + ); |
| 272 | + |
| 273 | + wrapper = inner.querySelector('custom-overlay-wrapper'); |
| 274 | + overlay = wrapper.shadowRoot.querySelector('custom-overlay'); |
| 275 | + }); |
| 276 | + |
| 277 | + afterEach(() => { |
| 278 | + overlay.opened = false; |
| 279 | + }); |
| 280 | + |
| 281 | + it('should not set aria-hidden on wrapping elements on overlay open', async () => { |
| 282 | + overlay.opened = true; |
| 283 | + await oneEvent(overlay, 'vaadin-overlay-open'); |
| 284 | + |
| 285 | + expect(outer.hasAttribute('aria-hidden')).to.be.false; |
| 286 | + expect(inner.hasAttribute('aria-hidden')).to.be.false; |
| 287 | + expect(wrapper.hasAttribute('aria-hidden')).to.be.false; |
| 288 | + }); |
| 289 | + |
| 290 | + it('should not set aria-hidden on content root element on overlay open', async () => { |
| 291 | + overlay.opened = true; |
| 292 | + await oneEvent(overlay, 'vaadin-overlay-open'); |
| 293 | + |
| 294 | + const root = wrapper.querySelector('div'); |
| 295 | + const input = root.firstElementChild; |
| 296 | + |
| 297 | + expect(root.hasAttribute('aria-hidden')).to.be.false; |
| 298 | + expect(input.hasAttribute('aria-hidden')).to.be.false; |
| 299 | + }); |
| 300 | + |
| 301 | + it('should set aria-hidden on sibling elements on overlay open', async () => { |
| 302 | + overlay.opened = true; |
| 303 | + await oneEvent(overlay, 'vaadin-overlay-open'); |
| 304 | + |
| 305 | + const buttons = wrapper.parentElement.querySelectorAll('button'); |
| 306 | + expect(buttons[0].getAttribute('aria-hidden')).to.equal('true'); |
| 307 | + expect(buttons[1].getAttribute('aria-hidden')).to.equal('true'); |
| 308 | + |
| 309 | + const aside = outer.querySelector('aside'); |
| 310 | + expect(aside.getAttribute('aria-hidden')).to.equal('true'); |
| 311 | + }); |
| 312 | + }); |
198 | 313 | }); |
0 commit comments