Skip to content

Commit

Permalink
fix(drawer): Use parentNode DOM API when selecting scrim to make it w…
Browse files Browse the repository at this point in the history
…ork with Shadow DOM (#4265)
  • Loading branch information
abhiomkar committed Jan 31, 2019
1 parent dffbcc1 commit 385a223
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 29 deletions.
2 changes: 1 addition & 1 deletion packages/mdc-drawer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class MDCDrawer extends MDCComponent {

if (this.root_.classList.contains(MODAL)) {
const {SCRIM_SELECTOR} = MDCDismissibleDrawerFoundation.strings;
this.scrim_ = /** @type {!Element} */ (this.root_.parentElement.querySelector(SCRIM_SELECTOR));
this.scrim_ = /** @type {!Element} */ (this.root_.parentNode.querySelector(SCRIM_SELECTOR));
this.handleScrimClick_ = () => /** @type {!MDCModalDrawerFoundation} */ (this.foundation_).handleScrimClick();
this.scrim_.addEventListener('click', this.handleScrimClick_);
this.focusTrap_ = util.createFocusTrapInstance(this.root_, this.focusTrapFactory_);
Expand Down
72 changes: 44 additions & 28 deletions test/unit/mdc-drawer/mdc-drawer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,39 +31,50 @@ import {strings, cssClasses} from '../../../packages/mdc-drawer/constants';
import {MDCListFoundation} from '../../../packages/mdc-list/index';
import MDCDismissibleDrawerFoundation from '../../../packages/mdc-drawer/dismissible/foundation';

function getFixture(variantClass) {
let scrimEl;
if (variantClass === cssClasses.MODAL) {
scrimEl = bel`<div class="mdc-drawer-scrim"></div>`;
}

return bel`
<div class="body-content">
<div class="mdc-drawer ${variantClass}">
function getFixture(options) {
const drawerEl = bel`
<div class="mdc-drawer ${options.variantClass}">
<div class="mdc-drawer__content">
<div class="mdc-list-group">
<nav class="mdc-list">
<a class="mdc-list-item mdc-list-item--activated" href="#" aria-selected="true">
<i class="material-icons mdc-list-item__graphic" aria-hidden="true">inbox</i>Inbox
</a>
</nav>
<div class="mdc-list-group">
<nav class="mdc-list">
<a class="mdc-list-item mdc-list-item--activated" href="#" aria-selected="true">
<i class="material-icons mdc-list-item__graphic" aria-hidden="true">inbox</i>Inbox
</a>
</nav>
</div>
</div>
</div>
${scrimEl}
</div>
`;
`;
const scrimEl = bel`<div class="mdc-drawer-scrim"></div>`;
const isModal = options.variantClass === cssClasses.MODAL;

if (options.shadowRoot) {
const fragment = document.createDocumentFragment();
fragment.appendChild(drawerEl);
if (isModal) {
fragment.appendChild(scrimEl);
}
return fragment;
} else {
return bel`
<div class="body-content">
${drawerEl}
${isModal ? scrimEl : ''}
</div>`;
}
}

function setupTest(variantClass = cssClasses.DISMISSIBLE) {
const root = getFixture(variantClass);
const defaultSetupOptions = {variantClass: cssClasses.DISMISSIBLE, shadowRoot: false};

function setupTest(options = defaultSetupOptions) {
const root = getFixture(options);
const drawer = root.querySelector('.mdc-drawer');
const component = new MDCDrawer(drawer);
return {root, drawer, component};
}


function setupTestWithMocks(variantClass = cssClasses.DISMISSIBLE) {
const root = getFixture(variantClass);
function setupTestWithMocks(options = defaultSetupOptions) {
const root = getFixture(options);
const drawer = root.querySelector('.mdc-drawer');
const MockFoundationCtor = td.constructor(MDCDismissibleDrawerFoundation);
const mockFoundation = new MockFoundationCtor();
Expand All @@ -83,7 +94,7 @@ function setupTestWithMocks(variantClass = cssClasses.DISMISSIBLE) {
suite('MDCDrawer');

test('attachTo initializes and returns a MDCDrawer instance', () => {
const drawer = getFixture(cssClasses.DISMISSIBLE).querySelector('.mdc-drawer');
const drawer = getFixture({variantClass: cssClasses.DISMISSIBLE}).querySelector('.mdc-drawer');
assert.isTrue(MDCDrawer.attachTo(drawer) instanceof MDCDrawer);
});

Expand Down Expand Up @@ -119,8 +130,8 @@ test('transitionend event calls foundation.handleTransitionEnd method', () => {
});

test('component should throw error when invalid variant class name is used or no variant specified', () => {
assert.throws(() => setupTest('mdc-drawer--test-invalid-variant'), Error);
assert.throws(() => setupTest(' '), Error);
assert.throws(() => setupTest({variantClass: 'mdc-drawer--test-invalid-variant'}), Error);
assert.throws(() => setupTest({variantClass: ' '}), Error);
});

test('#destroy removes keydown event listener', () => {
Expand Down Expand Up @@ -232,14 +243,14 @@ test('adapter#restoreFocus focus is not restored if saveFocus never called', ()
});

test('adapter#trapFocus traps focus on root element', () => {
const {component, mockFocusTrapInstance} = setupTestWithMocks(cssClasses.MODAL);
const {component, mockFocusTrapInstance} = setupTestWithMocks({variantClass: cssClasses.MODAL});
component.getDefaultFoundation().adapter_.trapFocus();

td.verify(mockFocusTrapInstance.activate());
});

test('adapter#releaseFocus releases focus on root element after trap focus', () => {
const {component, mockFocusTrapInstance} = setupTestWithMocks(cssClasses.MODAL);
const {component, mockFocusTrapInstance} = setupTestWithMocks({variantClass: cssClasses.MODAL});
component.getDefaultFoundation().adapter_.releaseFocus();

td.verify(mockFocusTrapInstance.deactivate());
Expand Down Expand Up @@ -276,3 +287,8 @@ test('adapter#focusActiveNavigationItem focuses on active navigation item', () =
assert.equal(activedNavigationItemEl, document.activeElement);
document.body.removeChild(root);
});

test('#initialSyncWithDOM should not throw any errors when DOM rendered in DocumentFragment i.e., Shadow DOM', () => {
const {component} = setupTest({variantClass: cssClasses.MODAL, shadowRoot: true});
assert.doesNotThrow(() => component.initialSyncWithDOM());
});

0 comments on commit 385a223

Please sign in to comment.