Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call onShow(n)/onHide/onHidden when controlling tooltips and popovers programmatically #1718

Merged
merged 3 commits into from
Jan 8, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions addon/components/bs-contextual-help.js
Original file line number Diff line number Diff line change
Expand Up @@ -670,17 +670,17 @@ export default class ContextualHelp extends Component {
this.triggerTargetElement = this.getTriggerTargetElement();
this.addListeners();
if (this.visible) {
next(this, this.show, true);
next(this, this.show);
}
});
}

@action
showOrHide(visible) {
if (visible) {
this.show();
showOrHide() {
if (this.args.visible) {
next(this, this.show);
} else {
this.hide();
next(this, this.hide);
}
}

Expand Down
1 change: 1 addition & 0 deletions addon/components/bs-popover.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@
{{/let}}
{{/if}}
{{did-insert this.setup}}
{{did-update this.showOrHide @visible}}
3 changes: 2 additions & 1 deletion addon/components/bs-tooltip.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@
</Element>
{{/let}}
{{/if}}
{{did-insert this.setup}}
{{did-insert this.setup}}
{{did-update this.showOrHide @visible}}
88 changes: 88 additions & 0 deletions tests/integration/components/bs-popover-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,94 @@ module('Integration | Component | bs-popover', function (hooks) {
assert.dom('#wrapper .popover').exists({ count: 1 }, 'Popover exists in place.');
});

test('it calls onShow/onShown actions when showing popover by event [fade=false]', async function (assert) {
let showAction = sinon.spy();
this.set('show', showAction);
let shownAction = sinon.spy();
this.set('shown', shownAction);
await render(
hbs`<div id="target"><BsPopover @title="Dummy" @fade={{false}} @onShow={{this.show}} @onShown={{this.shown}} /></div>`
);
await click('#target');
assert.ok(showAction.calledOnce, 'show action has been called');
assert.ok(shownAction.calledOnce, 'shown action has been called');
});

test('it calls onShow/onShown actions when showing popover programmatically [fade=false]', async function (assert) {
let showAction = sinon.spy();
this.set('show', showAction);
let shownAction = sinon.spy();
this.set('shown', shownAction);
this.set('visible', false);
await render(
hbs`<div id="target"><BsPopover @title="Dummy" @visible={{this.visible}} @fade={{false}} @onShow={{this.show}} @onShown={{this.shown}} /></div>`
);
this.set('visible', true);
await settled();
assert.ok(showAction.calledOnce, 'show action has been called');
assert.ok(shownAction.calledOnce, 'shown action has been called');
});

test('it aborts showing if onShow action returns false', async function (assert) {
let showAction = sinon.stub();
showAction.returns(false);
this.set('show', showAction);
let shownAction = sinon.spy();
this.set('shown', shownAction);
await render(
hbs`<div id="target"><BsPopover @title="Dummy" @fade={{false}} @onShow={{this.show}} @onShown={{this.shown}} /></div>`
);
await click('#target');
assert.ok(showAction.calledOnce, 'show action has been called');
assert.ok(shownAction.notCalled, 'show action has not been called');
assert.dom('.popover').doesNotExist('popover is not visible');
});

test('it calls onHide/onHidden actions when hiding popover by event [fade=false]', async function (assert) {
let hideAction = sinon.spy();
this.set('hide', hideAction);
let hiddenAction = sinon.spy();
this.set('hidden', hiddenAction);
await render(
hbs`<div id="target"><BsPopover @title="Dummy" @fade={{false}} @onHide={{this.hide}} @onHidden={{this.hidden}} /></div>`
);
await click('#target');
await click('#target');
assert.ok(hideAction.calledOnce, 'hide action has been called');
assert.ok(hiddenAction.calledOnce, 'hidden action was called');
});

test('it calls onHide/onHidden actions when hiding popover programmatically [fade=false]', async function (assert) {
let hideAction = sinon.spy();
this.set('hide', hideAction);
let hiddenAction = sinon.spy();
this.set('hidden', hiddenAction);
this.set('visible', true);
await render(
hbs`<div id="target"><BsPopover @visible={{this.visible}} @title="Dummy" @fade={{false}} @onHide={{this.hide}} @onHidden={{this.hidden}} /></div>`
);
this.set('visible', false);
await settled();
assert.ok(hideAction.calledOnce, 'hide action has been called');
assert.ok(hiddenAction.calledOnce, 'hidden action was called');
});

test('it aborts hiding if onHide action returns false', async function (assert) {
let hideAction = sinon.stub();
hideAction.returns(false);
this.set('hide', hideAction);
let hiddenAction = sinon.spy();
this.set('hidden', hiddenAction);
await render(
hbs`<div id="target"><BsPopover @title="Dummy" @fade={{false}} @onHide={{this.hide}} @onHidden={{this.hidden}} /></div>`
);
await click('#target');
await click('#target');
assert.ok(hideAction.calledOnce, 'hide action has been called');
assert.ok(hiddenAction.notCalled, 'hidden action has not been called');
assert.dom('.popover').exists({ count: 1 }, 'popover is visible');
});

test('it passes accessibility checks', async function (assert) {
await render(hbs`
<button type="button">
Expand Down
60 changes: 45 additions & 15 deletions tests/integration/components/bs-tooltip-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,56 +143,86 @@ module('Integration | Component | bs-tooltip', function (hooks) {
assert.dom('.tooltip').doesNotExist('tooltip is not visible');
});

test('it calls onShow/onShown actions when showing tooltip [fade=false]', async function (assert) {
test('it calls onShow/onShown actions when showing tooltip by event [fade=false]', async function (assert) {
let showAction = sinon.spy();
this.actions.show = showAction;
this.set('show', showAction);
let shownAction = sinon.spy();
this.actions.shown = shownAction;
this.set('shown', shownAction);
await render(
hbs`<div id="target"><BsTooltip @title="Dummy" @fade={{false}} @onShow={{action "show"}} @onShown={{action "shown"}} /></div>`
hbs`<div id="target"><BsTooltip @title="Dummy" @fade={{false}} @onShow={{this.show}} @onShown={{this.shown}} /></div>`
);
await triggerEvent('#target', 'mouseenter');
assert.ok(showAction.calledOnce, 'show action has been called');
assert.ok(shownAction.calledOnce, 'show action has been called');
assert.ok(shownAction.calledOnce, 'shown action has been called');
});

test('it calls onShow/onShown actions when showing tooltip programmatically [fade=false]', async function (assert) {
let showAction = sinon.spy();
this.set('show', showAction);
let shownAction = sinon.spy();
this.set('shown', shownAction);
this.set('visible', false);
await render(
hbs`<div id="target"><BsTooltip @title="Dummy" @visible={{this.visible}} @fade={{false}} @onShow={{this.show}} @onShown={{this.shown}} /></div>`
);
this.set('visible', true);
await settled();
assert.ok(showAction.calledOnce, 'show action has been called');
assert.ok(shownAction.calledOnce, 'shown action has been called');
});

test('it aborts showing if onShow action returns false', async function (assert) {
let showAction = sinon.stub();
showAction.returns(false);
this.actions.show = showAction;
this.set('show', showAction);
let shownAction = sinon.spy();
this.actions.shown = shownAction;
this.set('shown', shownAction);
await render(
hbs`<div id="target"><BsTooltip @title="Dummy" @fade={{false}} @onShow={{action "show"}} @onShown={{action "shown"}} /></div>`
hbs`<div id="target"><BsTooltip @title="Dummy" @fade={{false}} @onShow={{this.show}} @onShown={{this.shown}} /></div>`
);
await triggerEvent('#target', 'mouseenter');
assert.ok(showAction.calledOnce, 'show action has been called');
assert.notOk(shownAction.calledOnce, 'show action has not been called');
assert.dom('.tooltip').doesNotExist('tooltip is not visible');
});

test('it calls onHide/onHidden actions when hiding tooltip [fade=false]', async function (assert) {
test('it calls onHide/onHidden actions when hiding tooltip by event [fade=false]', async function (assert) {
let hideAction = sinon.spy();
this.actions.hide = hideAction;
this.set('hide', hideAction);
let hiddenAction = sinon.spy();
this.actions.hidden = hiddenAction;
this.set('hidden', hiddenAction);
await render(
hbs`<div id="target"><BsTooltip @title="Dummy" @fade={{false}} @onHide={{action "hide"}} @onHidden={{action "hidden"}} /></div>`
hbs`<div id="target"><BsTooltip @title="Dummy" @fade={{false}} @onHide={{this.hide}} @onHidden={{this.hidden}} /></div>`
);
await triggerEvent('#target', 'mouseenter');
await triggerEvent('#target', 'mouseleave');
assert.ok(hideAction.calledOnce, 'hide action has been called');
assert.ok(hiddenAction.calledOnce, 'hidden action was called');
});

test('it calls onHide/onHidden actions when hiding tooltip programmatically [fade=false]', async function (assert) {
let hideAction = sinon.spy();
this.set('hide', hideAction);
let hiddenAction = sinon.spy();
this.set('hidden', hiddenAction);
this.set('visible', true);
await render(
hbs`<div id="target"><BsTooltip @visible={{this.visible}} @title="Dummy" @fade={{false}} @onHide={{this.hide}} @onHidden={{this.hidden}} /></div>`
);
this.set('visible', false);
await settled();
assert.ok(hideAction.calledOnce, 'hide action has been called');
assert.ok(hiddenAction.calledOnce, 'hidden action was called');
});

test('it aborts hiding if onHide action returns false', async function (assert) {
let hideAction = sinon.stub();
hideAction.returns(false);
this.actions.hide = hideAction;
this.set('hide', hideAction);
let hiddenAction = sinon.spy();
this.actions.hidden = hiddenAction;
this.set('hidden', hiddenAction);
await render(
hbs`<div id="target"><BsTooltip @title="Dummy" @fade={{false}} @onHide={{action "hide"}} @onHidden={{action "hidden"}} /></div>`
hbs`<div id="target"><BsTooltip @title="Dummy" @fade={{false}} @onHide={{this.hide}} @onHidden={{this.hidden}} /></div>`
);
await triggerEvent('#target', 'mouseenter');
await triggerEvent('#target', 'mouseleave');
Expand Down