Skip to content

Commit

Permalink
Merge pull request #349 from upfluence/mb/ENG-1439
Browse files Browse the repository at this point in the history
Added: OSS::ModalDialog @enqueue parameter + tests & doc
  • Loading branch information
Miexil authored Dec 19, 2023
2 parents aa96a5f + 1f4f465 commit ffc95c0
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 28 deletions.
50 changes: 26 additions & 24 deletions addon/components/o-s-s/modal-dialog.hbs
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
<div class="oss-modal-dialog-backdrop fx-row fx-malign-center fx-xalign-center"
{{will-destroy this.destroy}} ...attributes>
<div class="oss-modal-dialog fx-col {{this.modalSize}}" {{on-click-outside this.closeModal}} {{did-insert this.init}}>
<header class="fx-row">
<div class="fx-1 fx-col fx-malign-center">
<span class="title">{{@title}}</span>
<span class="subtitle">{{@subtitle}}</span>
</div>
<OSS::Icon @style="solid" @icon="fa-times" class="padding-px-12" {{on "click" this.closeModal}} role="button"
data-control-name="close-modal-button" />
</header>

{{#if (has-block "illustration")}}
{{yield to="illustration"}}
{{/if}}
{{#if this.displayModal}}
<div class="oss-modal-dialog-backdrop fx-row fx-malign-center fx-xalign-center"
{{will-destroy this.destroy}} ...attributes>
<div class="oss-modal-dialog fx-col {{this.modalSize}}" {{on-click-outside this.closeModal}} {{did-insert this.init}}>
<header class="fx-row">
<div class="fx-1 fx-col fx-malign-center">
<span class="title">{{@title}}</span>
<span class="subtitle">{{@subtitle}}</span>
</div>
<OSS::Icon @style="solid" @icon="fa-times" class="padding-px-12" {{on "click" this.closeModal}} role="button"
data-control-name="close-modal-button" />
</header>

<div class="oss-modal-dialog--content fx-1">
{{#if (has-block "content")}}
{{yield to="content"}}
{{#if (has-block "illustration")}}
{{yield to="illustration"}}
{{/if}}

<div class="oss-modal-dialog--content fx-1">
{{#if (has-block "content")}}
{{yield to="content"}}
{{/if}}
</div>
<footer class="fx-row fx-xalign-center">
{{#if (has-block "footer")}}
{{yield to="footer"}}
{{/if}}
</footer>
</div>
<footer class="fx-row fx-xalign-center">
{{#if (has-block "footer")}}
{{yield to="footer"}}
{{/if}}
</footer>
</div>
</div>
{{/if}}
18 changes: 15 additions & 3 deletions addon/components/o-s-s/modal-dialog.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ export default {
summary: 'close(): void'
}
}
},
enqueue: {
description:
'Checks if an instance of oss-modal-dialog is already running and, if true, waits until the previous instance is closed before displaying the current one.',
table: {
type: {
summary: 'boolean'
},
defaultValue: { summary: 'undefined' }
},
control: { type: 'boolean' }
}
},
parameters: {
Expand All @@ -64,13 +75,14 @@ const defaultArgs = {
title: 'Modal Dialog',
subtitle: 'This is a subtitle',
size: 'sm',
close: action('close')
close: action('close'),
enqueue: undefined
};

const BasicUsageTemplate = (args) => ({
template: hbs`
<OSS::ModalDialog @title={{this.title}} @close={{this.close}} @subtitle={{this.subtitle}} @size={{this.size}}
@close={{this.close}}>
@enqueue={{this.enqueue}}>
<:content>
Content goes here
</:content>
Expand All @@ -85,7 +97,7 @@ const BasicUsageTemplate = (args) => ({
const WithIllustrationTemplate = (args) => ({
template: hbs`
<OSS::ModalDialog @title={{this.title}} @close={{this.close}} @subtitle={{this.subtitle}} @size={{this.size}}
@close={{this.close}}>
@enqueue={{this.enqueue}}>
<:illustration>
This will contain an illustration.
</:illustration>
Expand Down
20 changes: 20 additions & 0 deletions addon/components/o-s-s/modal-dialog.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
import { assert } from '@ember/debug';
import { tracked } from '@glimmer/tracking';
import Component from '@glimmer/component';
import BaseModal, { BaseModalArgs } from './private/base-modal';

export interface OSSModalDialogArgs extends BaseModalArgs {
title: string;
subtitle?: string;
size?: 'sm' | 'md';
enqueue?: boolean;
}

export default class OSSModalDialog extends (BaseModal as typeof Component)<OSSModalDialogArgs> {
@tracked displayModal: boolean = true;

constructor(owner: unknown, args: OSSModalDialogArgs) {
// eslint-disable-next-line constructor-super
super(owner, args);

assert('[component][OSS::ModalDialog] The close function is mandatory', args.close);
assert('[component][OSS::ModalDialog] The title parameter is mandatory', typeof args.title === 'string');

if (args.enqueue) {
this.displayModal = false;
this.modalQueueCheck();
}
}

get modalSize(): string {
Expand All @@ -23,4 +32,15 @@ export default class OSSModalDialog extends (BaseModal as typeof Component)<OSSM
}
return 'oss-modal-dialog-sm';
}

private modalQueueCheck(): void {
const preRenderedModalDialog = document.querySelector('.oss-modal-dialog');
if (preRenderedModalDialog) {
setTimeout(() => {
this.modalQueueCheck();
}, 1000);
return;
}
this.displayModal = true;
}
}
115 changes: 114 additions & 1 deletion tests/integration/components/o-s-s/modal-dialog-test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, setupOnerror, triggerKeyEvent } from '@ember/test-helpers';
import { render, setupOnerror, triggerKeyEvent, waitFor } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import sinon from 'sinon';
import click from '@ember/test-helpers/dom/click';
import EmberObject from '@ember/object';

module('Integration | Component | o-s-s/modal-dialog', function (hooks) {
setupRenderingTest(hooks);
Expand Down Expand Up @@ -92,6 +93,118 @@ module('Integration | Component | o-s-s/modal-dialog', function (hooks) {
assert.dom('.oss-modal-dialog footer').hasText('footer content');
});

module('Queue management - if the @enqueue param is truthy', () => {
module('When rendering two modals', () => {
test('The second modal is not displayed', async function (assert) {
await render(
hbs`<OSS::ModalDialog @title="MODAL A" @subtitle="subtitle" @close={{this.closeModal}} @enqueue={{true}}
data-control-name="modal-a" />
<OSS::ModalDialog @title="MODAL B" @subtitle="subtitle" @close={{this.closeModal}} @enqueue={{true}}
data-control-name="modal-b" />`
);
assert.dom('[data-control-name="modal-a"]').exists();
assert.dom('[data-control-name="modal-b"]').doesNotExist();
});

test('When Modal A is closed, Modal B is displayed', async function (assert) {
this.helper = EmberObject.create({
displayModalA: true
});
await render(
hbs`
{{#if this.helper.displayModalA}}
<OSS::ModalDialog @title="MODAL A" @subtitle="subtitle" @close={{this.closeModal}} @enqueue={{true}}
data-control-name="modal-a" />
{{/if}}
<OSS::ModalDialog @title="MODAL B" @subtitle="subtitle" @close={{this.closeModal}} @enqueue={{true}}
data-control-name="modal-b" />`
);
assert.dom('[data-control-name="modal-a"]').exists();
assert.dom('[data-control-name="modal-b"]').doesNotExist();
await click('.fa-times');
assert.ok(this.closeModal.calledOnce);
this.helper.set('displayModalA', false);
await waitFor('[data-control-name="modal-b"]', { timeout: 1000 });
assert.dom('[data-control-name="modal-a"]').doesNotExist();
assert.dom('[data-control-name="modal-b"]').exists();
});
});

module('When rendering multiple modals', () => {
test('Only the first modal is displayed', async function (assert) {
await render(
hbs`<OSS::ModalDialog @title="MODAL C" @subtitle="subtitle" @close={{this.closeModal}} @enqueue={{true}}
data-control-name="modal-c" />
<OSS::ModalDialog @title="MODAL B" @subtitle="subtitle" @close={{this.closeModal}} @enqueue={{true}}
data-control-name="modal-b" />
<OSS::ModalDialog @title="MODAL A" @subtitle="subtitle" @close={{this.closeModal}} @enqueue={{true}}
data-control-name="modal-a" />`
);
assert.dom('[data-control-name="modal-c"]').exists();
assert.dom('[data-control-name="modal-a"]').doesNotExist();
assert.dom('[data-control-name="modal-b"]').doesNotExist();
});

test('Open & close modal flow check', async function (assert) {
this.helper = EmberObject.create({
displayModalA: true,
displayModalB: true,
displayModalC: true
});
await render(
hbs`
{{#if this.helper.displayModalA}}
<OSS::ModalDialog @title="MODAL A" @subtitle="subtitle" @close={{this.closeModal}} @enqueue={{true}}
data-control-name="modal-a" />
{{/if}}
{{#if this.helper.displayModalB}}
<OSS::ModalDialog @title="MODAL B" @subtitle="subtitle" @close={{this.closeModal}} @enqueue={{true}}
data-control-name="modal-b" />
{{/if}}
{{#if this.helper.displayModalC}}
<OSS::ModalDialog @title="MODAL C" @subtitle="subtitle" @close={{this.closeModal}} @enqueue={{true}}
data-control-name="modal-c" />
{{/if}}
`
);
assert.dom('[data-control-name="modal-a"]').exists();
assert.dom('[data-control-name="modal-b"]').doesNotExist();
assert.dom('[data-control-name="modal-c"]').doesNotExist();

await click('.fa-times');
assert.ok(this.closeModal.calledOnce);
this.helper.set('displayModalA', false);
assert.false(this.helper.displayModalA);

await waitFor('[data-control-name="modal-b"]', { timeout: 1000 });
assert.dom('[data-control-name="modal-a"]').doesNotExist();
assert.dom('[data-control-name="modal-b"]').exists();
assert.dom('[data-control-name="modal-c"]').doesNotExist();

await click('.fa-times');
assert.ok(this.closeModal.calledTwice);
this.helper.set('displayModalB', false);
assert.false(this.helper.displayModalB);

await waitFor('[data-control-name="modal-c"]', { timeout: 1000 });
assert.dom('[data-control-name="modal-a"]').doesNotExist();
assert.dom('[data-control-name="modal-b"]').doesNotExist();
assert.dom('[data-control-name="modal-c"]').exists();
});
});
});

test('If the enqueue parameter is falsy, rendering multiple modals opens all of them', async function (assert) {
await render(
hbs`<OSS::ModalDialog @title="MODAL A" @subtitle="subtitle" @close={{this.closeModal}}
data-control-name="modal-a" />
<OSS::ModalDialog @title="MODAL B" @subtitle="subtitle" @close={{this.closeModal}}
data-control-name="modal-b" />`
);
assert.dom('[data-control-name="modal-a"]').exists();
assert.dom('[data-control-name="modal-b"]').exists();
});

module('Error management', function () {
test('The component throws an error if the title parameter is not passed', async function (assert) {
setupOnerror((err: any) => {
Expand Down

0 comments on commit ffc95c0

Please sign in to comment.