33 * SPDX-License-Identifier: MPL-2.0
44 */
55
6- import { module , skip , test } from 'qunit' ;
6+ import { module , test , skip } from 'qunit' ;
77import { setupRenderingTest } from 'showcase/tests/helpers' ;
88import {
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 (
0 commit comments