Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions addon/components/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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();
}
Expand Down
47 changes: 46 additions & 1 deletion tests/integration/components/modal-test.js
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -244,4 +244,49 @@ module('Integration | Component | modal', function (hooks) {

assert.dom('.flb--modal-backdrop').hasClass('fade');
});
// <Modal> declares `keyboard` and `backdropClose` and hands them to <Modal::Dialog>, 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 <Modal>, 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`<Modal @renderInPlace={{true}} @fade={{false}} @onClose={{this.onClose}}>body</Modal>`);
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`<Modal @renderInPlace={{true}} @fade={{false}} @keyboard={{false}} @onClose={{this.onClose}}>body</Modal>`);
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`<Modal @renderInPlace={{true}} @fade={{false}} @onClose={{this.onClose}}>body</Modal>`);
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`<Modal @renderInPlace={{true}} @fade={{false}} @backdropClose={{false}} @onClose={{this.onClose}}>body</Modal>`);
await click(DIALOG);

assert.deepEqual(closes, [], 'the modal stays open');
});
});
});