diff --git a/addon/components/modal.js b/addon/components/modal.js index b482633e..3808f512 100644 --- a/addon/components/modal.js +++ b/addon/components/modal.js @@ -450,6 +450,7 @@ export default class Modal extends Component { return; } + /* istanbul ignore next -- FastBoot-only: this suite runs in a browser, where isFastBoot() is always false. */ if (!isFastBoot(this)) { this.checkScrollbar(); this.setScrollbar(); @@ -462,6 +463,7 @@ export default class Modal extends Component { return; } + /* istanbul ignore next -- FastBoot-only: this suite runs in a browser, where isFastBoot() is always false. */ if (!isFastBoot(this)) { modalElement.scrollTop = 0; this.adjustDialog(); @@ -513,6 +515,7 @@ export default class Modal extends Component { this.removeBodyClass(); + /* istanbul ignore next -- FastBoot-only: this suite runs in a browser, where isFastBoot() is always false. */ if (!isFastBoot(this)) { this.resetAdjustments(); this.resetScrollbar(); @@ -633,6 +636,7 @@ export default class Modal extends Component { // Only add the body class if this is the first modal if (this.modalsManager.modals.length === 1) { // special handling for FastBoot, where real `document` is not available + /* istanbul ignore next -- FastBoot-only: this suite runs in a browser, where isFastBoot() is always false. */ if (isFastBoot(this)) { // a SimpleDOM instance with just a subset of the DOM API! let document = this.document; @@ -653,6 +657,7 @@ export default class Modal extends Component { removeBodyClass() { // Only remove the body class if there are no more modals if (this.modalsManager.modals.length === 0) { + /* istanbul ignore next -- FastBoot-only: this suite runs in a browser, where isFastBoot() is always false. */ if (isFastBoot(this)) { // no need for FastBoot support here return; @@ -683,6 +688,7 @@ export default class Modal extends Component { this.removeBodyClass(); + /* istanbul ignore next -- FastBoot-only: this suite runs in a browser, where isFastBoot() is always false. */ if (!isFastBoot(this)) { this.resetScrollbar(); } diff --git a/tests/integration/components/modal-test.js b/tests/integration/components/modal-test.js index ccb20d50..e06bfc31 100644 --- a/tests/integration/components/modal-test.js +++ b/tests/integration/components/modal-test.js @@ -1,6 +1,6 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'dummy/tests/helpers'; -import { render, click, settled, find, findAll } from '@ember/test-helpers'; +import { render, click, settled, find, findAll, triggerKeyEvent } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; const DIALOG = '.flb--modal'; @@ -244,4 +244,49 @@ module('Integration | Component | modal', function (hooks) { assert.dom('.flb--modal-backdrop').hasClass('fade'); }); + // declares `keyboard` and `backdropClose` and hands them to , which + // only reads them from inside its keydown and click handlers. Glimmer evaluates arguments + // lazily, so until one of those handlers actually runs through a real , the modal's own + // defaults are never resolved. + module('the dialog arguments the modal supplies', function () { + test('escape closes the modal by default', async function (assert) { + const closes = []; + this.set('onClose', () => closes.push('closed')); + + await render(hbs`body`); + await triggerKeyEvent(DIALOG, 'keydown', 'Escape'); + + assert.deepEqual(closes, ['closed'], 'the default keyboard handling is on'); + }); + + test('escape is ignored when keyboard handling is switched off', async function (assert) { + const closes = []; + this.set('onClose', () => closes.push('closed')); + + await render(hbs`body`); + await triggerKeyEvent(DIALOG, 'keydown', 'Escape'); + + assert.deepEqual(closes, [], 'the modal stays open'); + }); + + test('clicking the backdrop area closes the modal by default', async function (assert) { + const closes = []; + this.set('onClose', () => closes.push('closed')); + + await render(hbs`body`); + await click(DIALOG); + + assert.deepEqual(closes, ['closed'], 'the default backdrop-close is on'); + }); + + test('clicking it is ignored when backdropClose is switched off', async function (assert) { + const closes = []; + this.set('onClose', () => closes.push('closed')); + + await render(hbs`body`); + await click(DIALOG); + + assert.deepEqual(closes, [], 'the modal stays open'); + }); + }); });