Skip to content

Commit 815d901

Browse files
committed
updated (and refactored) integration tests for Modal and Flyout to improve coverage
1 parent a79c86e commit 815d901

File tree

2 files changed

+281
-12
lines changed

2 files changed

+281
-12
lines changed

showcase/tests/integration/components/hds/flyout/index-test.js

Lines changed: 155 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
* SPDX-License-Identifier: MPL-2.0
44
*/
55

6-
import { module, skip, test } from 'qunit';
6+
import { module, test, skip } from 'qunit';
77
import { setupRenderingTest } from 'showcase/tests/helpers';
88
import {
99
click,
1010
render,
11+
triggerKeyEvent,
1112
resetOnerror,
1213
setupOnerror,
1314
settled,
@@ -138,6 +139,156 @@ module('Integration | Component | hds/flyout/index', function (hooks) {
138139
await click('button.hds-flyout__dismiss');
139140
assert.dom('#test-flyout').isNotVisible();
140141
});
142+
test('it should close the flyout when the "close" function is called', async function (assert) {
143+
await render(
144+
hbs`<Hds::Flyout id="test-flyout" as |M|>
145+
<M.Footer as |F|>
146+
<Hds::Button id="cancel-button" type="button" @text="Cancel" @color="secondary" {{on "click" F.close}} />
147+
</M.Footer>
148+
</Hds::Flyout>`,
149+
);
150+
assert.dom('#test-flyout').isVisible();
151+
await click('#cancel-button');
152+
assert.dom('#test-flyout').isNotVisible();
153+
});
154+
test('it should close the flyout when the "esc" key is pressed', async function (assert) {
155+
await render(
156+
hbs`<Hds::Flyout id="test-flyout" as |M|><M.Header>Title</M.Header></Hds::Flyout>`,
157+
);
158+
assert.dom('#test-flyout').isVisible();
159+
await triggerKeyEvent('.hds-flyout', 'keydown', 'Escape');
160+
assert.dom('#test-flyout').isNotVisible();
161+
});
162+
test('it should close the flyout when clicking outside', async function (assert) {
163+
await render(
164+
hbs`<Hds::Flyout id="test-flyout" as |M|><M.Header>Title</M.Header></Hds::Flyout>`,
165+
);
166+
assert.dom('#test-flyout').isVisible();
167+
await click('.hds-flyout__overlay');
168+
assert.dom('#test-flyout').isNotVisible();
169+
});
170+
171+
// BODY OVERFLOW
172+
173+
test('it should close the flyout and remove the body overflow style - manual dismiss', async function (assert) {
174+
await render(
175+
hbs`<Hds::Flyout id="test-flyout" as |M|><M.Header>Title</M.Header></Hds::Flyout>`,
176+
);
177+
178+
// when the flyout is open the `<body>` element gets applied an overflow:hidden via inline style
179+
assert.dom('#test-flyout').isVisible();
180+
assert.dom('body', document).hasStyle({ overflow: 'hidden' });
181+
182+
// when the flyout is closed the `overflow:hidden` style should be removed
183+
await click('button.hds-flyout__dismiss');
184+
assert.dom('#test-flyout').isNotVisible();
185+
assert.dom('body', document).doesNotHaveStyle({ overflow: 'hidden' });
186+
});
187+
188+
test('it should close the flyout and remove the body overflow style - click outside', async function (assert) {
189+
await render(
190+
hbs`<Hds::Flyout id="test-flyout" as |M|><M.Header>Title</M.Header></Hds::Flyout>`,
191+
);
192+
193+
// when the flyout is open the `<body>` element gets applied an overflow:hidden via inline style
194+
assert.dom('#test-flyout').isVisible();
195+
assert.dom('body', document).hasStyle({ overflow: 'hidden' });
196+
197+
// when the flyout is closed the `overflow:hidden` style should be removed
198+
await click('.hds-flyout__overlay');
199+
assert.dom('#test-flyout').isNotVisible();
200+
assert.dom('body', document).doesNotHaveStyle({ overflow: 'hidden' });
201+
});
202+
203+
test('it should close the flyout and remove the body overflow style - dismiss via `F.close`', async function (assert) {
204+
await render(
205+
hbs`<Hds::Flyout id="test-flyout" as |M|>
206+
<M.Header>Title</M.Header>
207+
<M.Footer as |F|>
208+
<Hds::Button id="cancel-button" type="button" @text="Cancel" @color="secondary" {{on "click" F.close}} />
209+
</M.Footer>
210+
</Hds::Flyout>`,
211+
);
212+
213+
// when the flyout is open the `<body>` element gets applied an overflow:hidden via inline style
214+
assert.dom('#test-flyout').isVisible();
215+
assert.dom('body', document).hasStyle({ overflow: 'hidden' });
216+
217+
// when the flyout is closed the `overflow:hidden` style should be removed
218+
await click('#cancel-button');
219+
assert.dom('#test-flyout').isNotVisible();
220+
assert.dom('body', document).doesNotHaveStyle({ overflow: 'hidden' });
221+
});
222+
223+
test('it should close the flyout and remove the body overflow style - direct DOM removal', async function (assert) {
224+
this.set('isFlyoutRendered', false);
225+
this.set('deactivateFlyout', function () {
226+
this.set('isFlyoutRendered', false);
227+
}.bind(this));
228+
229+
await render(
230+
hbs`
231+
{{#if this.isFlyoutRendered}}
232+
<Hds::Flyout id="test-flyout" as |M|>
233+
<M.Header>Title</M.Header>
234+
<M.Footer>
235+
<Hds::Button id="confirm-button" type="button" @text="Confirm" @color="primary" {{on "click" this.deactivateFlyout}} />
236+
</M.Footer>
237+
</Hds::Flyout>
238+
{{/if}}
239+
`,
240+
);
241+
242+
assert.dom('#test-flyout').doesNotExist();
243+
this.set('isFlyoutRendered', true);
244+
assert.dom('#test-flyout').exists();
245+
246+
// when the flyout is open the `<body>` element gets applied an overflow:hidden via inline style
247+
assert.dom('#test-flyout').isVisible();
248+
assert.dom('body', document).hasStyle({ overflow: 'hidden' });
249+
250+
// when the flyout is removed from the DOM the `overflow:hidden` style should be removed
251+
await click('#confirm-button');
252+
assert.dom('#test-flyout').doesNotExist();
253+
assert.dom('body', document).doesNotHaveStyle({ overflow: 'hidden' });
254+
});
255+
256+
test('it should close the flyout and remove the body overflow style - form submit', async function (assert) {
257+
this.set('isFlyoutRendered', false);
258+
this.set('deactivateFlyoutOnSubmit', function (event) {
259+
event.preventDefault(); // prevent page reload
260+
this.set('isFlyoutRendered', false);
261+
}.bind(this));
262+
263+
await render(
264+
hbs`
265+
{{#if this.isFlyoutRendered}}
266+
<Hds::Flyout id="test-flyout" as |M|>
267+
<M.Header>Title</M.Header>
268+
<M.Body>
269+
<form id="test-form" {{on "submit" this.deactivateFlyoutOnSubmit}} />
270+
</M.Body>
271+
<M.Footer>
272+
<Hds::Button id="submit-button" form="test-form" type="submit" @text="Confirm" @color="primary" />
273+
</M.Footer>
274+
</Hds::Flyout>
275+
{{/if}}
276+
`,
277+
);
278+
279+
assert.dom('#test-flyout').doesNotExist();
280+
this.set('isFlyoutRendered', true);
281+
assert.dom('#test-flyout').exists();
282+
283+
// when the flyout is open the `<body>` element gets applied an overflow:hidden via inline style
284+
assert.dom('#test-flyout').isVisible();
285+
assert.dom('body', document).hasStyle({ overflow: 'hidden' });
286+
287+
// when the form is submitted and the flyout is removed from the DOM the `overflow:hidden` style should be removed
288+
await click('#submit-button');
289+
assert.dom('#test-flyout').doesNotExist();
290+
assert.dom('body', document).doesNotHaveStyle({ overflow: 'hidden' });
291+
});
141292

142293
// ACCESSIBILITY
143294

@@ -176,7 +327,7 @@ module('Integration | Component | hds/flyout/index', function (hooks) {
176327
assert.dom('#test-button').isFocused();
177328
});
178329

179-
// not sure how to reach the `body` element, it says "body is not a valid root element"
330+
// this test is flaky in CI, so skipping for now
180331
skip('it returns focus to the `body` element, if the one that initiated the open event not anymore in the DOM', async function (assert) {
181332
await render(
182333
hbs`<Hds::Dropdown as |D|>
@@ -194,7 +345,7 @@ module('Integration | Component | hds/flyout/index', function (hooks) {
194345
await click('#test-interactive');
195346
assert.true(this.showFlyout);
196347
await click('button.hds-flyout__dismiss');
197-
assert.dom('body', 'body').isFocused();
348+
assert.dom('body', 'document').isFocused();
198349
});
199350

200351
test('it returns focus to a specific element if provided via`@returnFocusTo`', async function (assert) {
@@ -232,7 +383,7 @@ module('Integration | Component | hds/flyout/index', function (hooks) {
232383
assert.ok(opened);
233384
});
234385

235-
skip('it should call `onClose` function if provided', async function (assert) {
386+
test('it should call `onClose` function if provided', async function (assert) {
236387
let closed = false;
237388
this.set('onClose', () => (closed = true));
238389
await render(

showcase/tests/integration/components/hds/modal/index-test.js

Lines changed: 126 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,23 @@ module('Integration | Component | hds/modal/index', function (hooks) {
139139
await click('#cancel-button');
140140
assert.dom('#test-modal').isNotVisible();
141141
});
142+
test('it should close the modal when the "esc" key is pressed', async function (assert) {
143+
await render(
144+
hbs`<Hds::Modal id="test-modal" as |M|><M.Header>Title</M.Header></Hds::Modal>`,
145+
);
146+
assert.dom('#test-modal').isVisible();
147+
await triggerKeyEvent('.hds-modal', 'keydown', 'Escape');
148+
assert.dom('#test-modal').isNotVisible();
149+
});
150+
// TODO! while we decide what to do about the original bug
151+
skip('it should close the modal when clicking outside', async function (assert) {
152+
await render(
153+
hbs`<Hds::Modal id="test-modal" as |M|><M.Header>Title</M.Header></Hds::Modal>`,
154+
);
155+
assert.dom('#test-modal').isVisible();
156+
await click('.hds-modal__overlay');
157+
assert.dom('#test-modal').isNotVisible();
158+
});
142159
test('it should not close the modal when `@isDismissDisabled` is `true`', async function (assert) {
143160
this.set('isDismissDisabled', true);
144161
await render(
@@ -169,25 +186,126 @@ module('Integration | Component | hds/modal/index', function (hooks) {
169186
assert.dom('#test-modal').isNotVisible();
170187
});
171188

172-
test('it should appropriately dismiss the modal when clicking outside the modal', async function (assert) {
173-
this.set('isDismissDisabled', true);
189+
// BODY OVERFLOW
190+
191+
test('it should close the modal and remove the body overflow style - manual dismiss', async function (assert) {
174192
await render(
175-
hbs`<Hds::Modal @isDismissDisabled={{this.isDismissDisabled}} id="test-modal" as |M|>
193+
hbs`<Hds::Modal id="test-modal" as |M|><M.Header>Title</M.Header></Hds::Modal>`,
194+
);
195+
196+
// when the modal is open the `<body>` element gets applied an overflow:hidden via inline style
197+
assert.dom('#test-modal').isVisible();
198+
assert.dom('body', document).hasStyle({ overflow: 'hidden' });
199+
200+
// when the modal is closed the `overflow:hidden` style should be removed
201+
await click('button.hds-modal__dismiss');
202+
assert.dom('#test-modal').isNotVisible();
203+
assert.dom('body', document).doesNotHaveStyle({ overflow: 'hidden' });
204+
});
205+
206+
test('it should close the modal and remove the body overflow style - click outside', async function (assert) {
207+
await render(
208+
hbs`<Hds::Modal id="test-modal" as |M|><M.Header>Title</M.Header></Hds::Modal>`,
209+
);
210+
211+
// when the modal is open the `<body>` element gets applied an overflow:hidden via inline style
212+
assert.dom('#test-modal').isVisible();
213+
assert.dom('body', document).hasStyle({ overflow: 'hidden' });
214+
215+
// when the modal is closed the `overflow:hidden` style should be removed
216+
await click('.hds-modal__overlay');
217+
assert.dom('#test-flyout').isNotVisible();
218+
assert.dom('body', document).doesNotHaveStyle({ overflow: 'hidden' });
219+
});
220+
221+
test('it should close the modal and remove the body overflow style - dismiss via `F.close`', async function (assert) {
222+
await render(
223+
hbs`<Hds::Modal id="test-modal" as |M|>
176224
<M.Header>Title</M.Header>
177225
<M.Footer as |F|>
178226
<Hds::Button id="cancel-button" type="button" @text="Cancel" @color="secondary" {{on "click" F.close}} />
179227
</M.Footer>
180228
</Hds::Modal>`,
181229
);
182230

183-
await click('.hds-modal__overlay');
231+
// when the modal is open the `<body>` element gets applied an overflow:hidden via inline style
184232
assert.dom('#test-modal').isVisible();
233+
assert.dom('body', document).hasStyle({ overflow: 'hidden' });
185234

186-
// now let's check that the state is reset and it can be closed
187-
this.set('isDismissDisabled', false);
188-
await rerender();
189-
await click('.hds-modal__overlay');
235+
// when the modal is closed the `overflow:hidden` style should be removed
236+
await click('#cancel-button');
190237
assert.dom('#test-modal').isNotVisible();
238+
assert.dom('body', document).doesNotHaveStyle({ overflow: 'hidden' });
239+
});
240+
241+
test('it should close the modal and remove the body overflow style - direct DOM removal', async function (assert) {
242+
this.set('isModalRendered', false);
243+
this.set('deactivateModal', function () {
244+
this.set('isModalRendered', false);
245+
}.bind(this));
246+
247+
await render(
248+
hbs`
249+
{{#if this.isModalRendered}}
250+
<Hds::Modal id="test-modal" as |M|>
251+
<M.Header>Title</M.Header>
252+
<M.Footer>
253+
<Hds::Button id="confirm-button" type="button" @text="Confirm" @color="primary" {{on "click" this.deactivateModal}} />
254+
</M.Footer>
255+
</Hds::Modal>
256+
{{/if}}
257+
`,
258+
);
259+
260+
assert.dom('#test-modal').doesNotExist();
261+
this.set('isModalRendered', true);
262+
assert.dom('#test-modal').exists();
263+
264+
// when the modal is open the `<body>` element gets applied an overflow:hidden via inline style
265+
assert.dom('#test-modal').isVisible();
266+
assert.dom('body', document).hasStyle({ overflow: 'hidden' });
267+
268+
// when the modal is removed from the DOM the `overflow:hidden` style should be removed
269+
await click('#confirm-button');
270+
assert.dom('#test-modal').doesNotExist();
271+
assert.dom('body', document).doesNotHaveStyle({ overflow: 'hidden' });
272+
});
273+
274+
test('it should close the modal and remove the body overflow style - form submit', async function (assert) {
275+
this.set('isModalRendered', false);
276+
this.set('deactivateModalOnSubmit', function (event) {
277+
event.preventDefault(); // prevent page reload
278+
this.set('isModalRendered', false);
279+
}.bind(this));
280+
281+
await render(
282+
hbs`
283+
{{#if this.isModalRendered}}
284+
<Hds::Modal id="test-modal" as |M|>
285+
<M.Header>Title</M.Header>
286+
<M.Body>
287+
<form id="test-form" {{on "submit" this.deactivateModalOnSubmit}} />
288+
</M.Body>
289+
<M.Footer>
290+
<Hds::Button id="submit-button" form="test-form" type="submit" @text="Confirm" @color="primary" />
291+
</M.Footer>
292+
</Hds::Modal>
293+
{{/if}}
294+
`,
295+
);
296+
297+
assert.dom('#test-modal').doesNotExist();
298+
this.set('isModalRendered', true);
299+
assert.dom('#test-modal').exists();
300+
301+
// when the modal is open the `<body>` element gets applied an overflow:hidden via inline style
302+
assert.dom('#test-modal').isVisible();
303+
assert.dom('body', document).hasStyle({ overflow: 'hidden' });
304+
305+
// when the form is submitted and the modal is removed from the DOM the `overflow:hidden` style should be removed
306+
await click('#submit-button');
307+
assert.dom('#test-modal').doesNotExist();
308+
assert.dom('body', document).doesNotHaveStyle({ overflow: 'hidden' });
191309
});
192310

193311
// ACCESSIBILITY

0 commit comments

Comments
 (0)