Skip to content

Commit

Permalink
Fix .collapsed markup for accordions
Browse files Browse the repository at this point in the history
Extracted the bug fix from #1561
  • Loading branch information
simonihmig committed Aug 6, 2021
1 parent a496c2c commit 43651d2
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 73 deletions.
6 changes: 3 additions & 3 deletions addon/components/bs-accordion/item/title.hbs
@@ -1,21 +1,21 @@
{{!-- template-lint-disable no-nested-interactive --}}
{{!-- @todo fix this, see https://github.com/kaliber5/ember-bootstrap/issues/999 --}}
<div
class="{{if @collapsed "collapsed" "expanded"}} {{if (macroCondition (macroGetOwnConfig "isNotBS3")) "card-header"}} {{if (macroCondition (macroGetOwnConfig "isBS3")) "panel-heading"}}"
class="{{if (macroCondition (macroGetOwnConfig "isNotBS3")) "card-header"}} {{if (macroCondition (macroGetOwnConfig "isBS3")) "panel-heading"}}"
role="tab"
...attributes
{{on "click" this.handleClick}}
>
{{#if (macroCondition (macroGetOwnConfig "isNotBS3"))}}
<h5 class="mb-0">
<button class="btn btn-link {{if @disabled "disabled"}}" type="button" disabled={{@disabled}}>
<button class="btn btn-link {{if @disabled "disabled"}} {{if @collapsed "collapsed" "expanded"}}" type="button" disabled={{@disabled}}>
{{yield}}
</button>
</h5>
{{/if}}
{{#if (macroCondition (macroGetOwnConfig "isBS3"))}}
<h4 class="panel-title">
<a href="#" class={{if @disabled "disabled"}}>
<a href="#" class="{{if @disabled "disabled"}} {{if @collapsed "collapsed" "expanded"}}" >
{{yield}}
</a>
</h4>
Expand Down
8 changes: 8 additions & 0 deletions tests/helpers/bootstrap.js
Expand Up @@ -95,6 +95,14 @@ export function formHelpTextClass() {
return versionDependent('help-block', 'form-text');
}

export function accordionClass() {
return versionDependent('panel-group', 'accordion');
}

export function accordionItemClass() {
return versionDependent('panel', 'card');
}

export function accordionClassFor(type) {
type = type ? `-${type}` : '';
return versionDependent(`panel${type}`, type ? `bg${type}` : 'card');
Expand Down
111 changes: 47 additions & 64 deletions tests/integration/components/bs-accordion-test.js
@@ -1,13 +1,13 @@
import { module } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, click, settled } from '@ember/test-helpers';
import { click, render, settled } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import {
accordionClassFor,
accordionClass,
accordionItemClass,
accordionItemClickableSelector,
accordionItemHeadClass,
test,
testBS3,
testNotBS3,
visibilityClass,
} from '../../helpers/bootstrap';
import setupNoDeprecations from '../../helpers/setup-no-deprecations';
Expand All @@ -23,34 +23,17 @@ module('Integration | Component | bs-accordion', function (hooks) {
this.send = (actionName, ...args) => this.actions[actionName].apply(this, args);
});

testBS3('accordion has correct default markup', async function (assert) {
test('accordion has correct default markup', async function (assert) {
await render(hbs`
<BsAccordion as |acc|>
<acc.item @value={{1}} @title="TITLE1">CONTENT1</acc.item>
<acc.item @value={{2}} @title="TITLE2">CONTENT2</acc.item>
</BsAccordion>
`);
assert.dom('.panel-group').exists('accordion has panel-group class');
});

testNotBS3('accordion has correct default markup', async function (assert) {
await render(hbs`
<BsAccordion as |acc|>
<acc.item @value={{1}} @title="TITLE1">CONTENT1</acc.item>
<acc.item @value={{2}} @title="TITLE2">CONTENT2</acc.item>
</BsAccordion>
`);
assert.dom('.accordion .card').exists('accordion has card within accordion');
});

test('accordion yields items', async function (assert) {
await render(hbs`
<BsAccordion as |acc|>
<acc.item @value={{1}} @title="TITLE1">CONTENT1</acc.item>
<acc.item @value={{2}} @title="TITLE2">CONTENT2</acc.item>
</BsAccordion>
`);
assert.dom(`.${accordionClassFor()}`).exists({ count: 2 }, 'accordion yields item');
assert.dom(`.${accordionClass()}`).exists({ count: 1 }, 'accordion has correct class');
assert
.dom(`.${accordionClass()} .${accordionItemClass()}`)
.exists({ count: 2 }, 'accordion item has correct class');
});

test('accordion with preselected item has this item expanded', async function (assert) {
Expand All @@ -63,11 +46,11 @@ module('Integration | Component | bs-accordion', function (hooks) {
`);

assert
.dom(`.${accordionClassFor()}:first-child .${accordionItemHeadClass()}`)
.dom(`.${accordionItemClass()}:first-child .${accordionItemHeadClass()}`)
.hasNoClass('collapsed', `${accordionItemHeadClass()} has not collapsed class`);
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert
.dom(`.${accordionClassFor()}:first-child .collapse`)
.dom(`.${accordionItemClass()}:first-child .collapse`)
.hasClass(visibilityClass(), `tabpanel has ${visibilityClass()} class`);
});

Expand All @@ -84,10 +67,10 @@ module('Integration | Component | bs-accordion', function (hooks) {
// wait for transitions to complete
await settled();
assert
.dom(`.${accordionClassFor()}:last-child .${accordionItemHeadClass()}`)
.dom(`.${accordionItemClass()}:last-child .${accordionItemHeadClass()}`)
.hasNoClass('collapsed', `${accordionItemHeadClass()} has not collapsed class`);
assert.dom(`.${accordionClassFor()}:last-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionClassFor()}:last-child .collapse`).hasClass(visibilityClass(), 'tabpanel is visible');
assert.dom(`.${accordionItemClass()}:last-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionItemClass()}:last-child .collapse`).hasClass(visibilityClass(), 'tabpanel is visible');
});

test('clicking collapsed item expands it', async function (assert) {
Expand All @@ -97,13 +80,13 @@ module('Integration | Component | bs-accordion', function (hooks) {
<acc.item @value={{2}} @title="TITLE2">CONTENT2</acc.item>
</BsAccordion>
`);
await click(`.${accordionClassFor()}:first-child .${accordionItemHeadClass()}`);
await click(`.${accordionItemClass()}:first-child ${accordionItemClickableSelector()}`);

assert
.dom(`.${accordionClassFor()}:first-child .${accordionItemHeadClass()}`)
.dom(`.${accordionItemClass()}:first-child .${accordionItemHeadClass()}`)
.hasNoClass('collapsed', `${accordionItemHeadClass()} has not collapsed class`);
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasClass(visibilityClass(), 'tabpanel is visible');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasClass(visibilityClass(), 'tabpanel is visible');
});

test('clicking expanded item collapses it', async function (assert) {
Expand All @@ -115,18 +98,18 @@ module('Integration | Component | bs-accordion', function (hooks) {
`);

assert
.dom(`.${accordionClassFor()}:first-child .${accordionItemHeadClass()}`)
.dom(`.${accordionItemClass()}:first-child ${accordionItemClickableSelector()}`)
.hasNoClass('collapsed', `${accordionItemHeadClass()} has not collapsed class`);
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasClass(visibilityClass(), 'tabpanel is visible');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasClass(visibilityClass(), 'tabpanel is visible');

await click(`.${accordionItemHeadClass()}`);
await click(accordionItemClickableSelector());

assert
.dom(`.${accordionClassFor()}:first-child .${accordionItemHeadClass()}`)
.dom(`.${accordionItemClass()}:first-child ${accordionItemClickableSelector()}`)
.hasClass('collapsed', `${accordionItemHeadClass()} has collapsed class`);
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasNoClass(visibilityClass(), 'tabpanel is hidden');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasNoClass(visibilityClass(), 'tabpanel is hidden');
});

test('calls onChange action when changing selection', async function (assert) {
Expand All @@ -139,7 +122,7 @@ module('Integration | Component | bs-accordion', function (hooks) {
</BsAccordion>
`);

await click(`.${accordionClassFor()}:first-child .${accordionItemHeadClass()}`);
await click(`.${accordionItemClass()}:first-child ${accordionItemClickableSelector()}`);
assert.ok(action.calledWith(1), 'onClick action has been called.');
});

Expand All @@ -154,14 +137,14 @@ module('Integration | Component | bs-accordion', function (hooks) {
</BsAccordion>
`);

await click(`.${accordionClassFor()}:first-child .${accordionItemHeadClass()}`);
await click(`.${accordionItemClass()}:first-child ${accordionItemClickableSelector()}`);
assert.ok(action.calledWith(1), 'onClick action has been called.');

assert
.dom(`.${accordionClassFor()}:first-child .${accordionItemHeadClass()}`)
.dom(`.${accordionItemClass()}:first-child ${accordionItemClickableSelector()}`)
.hasClass('collapsed', `${accordionItemHeadClass()} has collapsed class`);
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasNoClass(visibilityClass(), 'tabpanel is hidden');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasNoClass(visibilityClass(), 'tabpanel is hidden');
});

test('supports undefined as value of onChange argument', async function (assert) {
Expand All @@ -173,7 +156,7 @@ module('Integration | Component | bs-accordion', function (hooks) {
`);
assert.dom(`[data-test-item="1"] .collapse`).hasNoClass(visibilityClass());

await click(`[data-test-item="1"] .${accordionItemHeadClass()}`);
await click(`[data-test-item="1"] ${accordionItemClickableSelector()}`);
assert.dom(`[data-test-item="1"] .collapse`).hasClass(visibilityClass());
});

Expand All @@ -186,7 +169,7 @@ module('Integration | Component | bs-accordion', function (hooks) {
</BsAccordion>
`);

await click(`.${accordionClassFor()}:last-child .${accordionItemHeadClass()}`);
await click(`.${accordionItemClass()}:last-child ${accordionItemClickableSelector()}`);
assert.equal(this.selected, 1, 'Does not modify public selected property');
});

Expand All @@ -202,10 +185,10 @@ module('Integration | Component | bs-accordion', function (hooks) {
await click('#btn');

assert
.dom(`.${accordionClassFor()}:last-child .${accordionItemHeadClass()}`)
.dom(`.${accordionItemClass()}:last-child ${accordionItemClickableSelector()}`)
.hasNoClass('collapsed', `${accordionItemHeadClass()} has not collapsed class`);
assert.dom(`.${accordionClassFor()}:last-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionClassFor()}:last-child .collapse`).hasClass(visibilityClass(), 'tabpanel is visible');
assert.dom(`.${accordionItemClass()}:last-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionItemClass()}:last-child .collapse`).hasClass(visibilityClass(), 'tabpanel is visible');
});

test('clicking collapsed item with contextual title expands it', async function (assert) {
Expand All @@ -219,13 +202,13 @@ module('Integration | Component | bs-accordion', function (hooks) {
</BsAccordion>
`);

await click(`.${accordionClassFor()}:first-child .${accordionItemHeadClass()}`);
await click(`.${accordionItemClass()}:first-child ${accordionItemClickableSelector()}`);

assert
.dom(`.${accordionClassFor()}:first-child .${accordionItemHeadClass()}`)
.dom(`.${accordionItemClass()}:first-child ${accordionItemClickableSelector()}`)
.hasNoClass('collapsed', `${accordionItemHeadClass()} has not collapsed class`);
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasClass(visibilityClass(), 'tabpanel is visible');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasClass(visibilityClass(), 'tabpanel is visible');
});

test('clicking expanded item with contextual title collapses it', async function (assert) {
Expand All @@ -240,18 +223,18 @@ module('Integration | Component | bs-accordion', function (hooks) {
`);

assert
.dom(`.${accordionClassFor()}:first-child .${accordionItemHeadClass()}`)
.dom(`.${accordionItemClass()}:first-child ${accordionItemClickableSelector()}`)
.hasNoClass('collapsed', `${accordionItemHeadClass()} has not collapsed class`);
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasClass(visibilityClass(), 'tabpanel is visible');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasClass(visibilityClass(), 'tabpanel is visible');

await click(`.${accordionItemHeadClass()}`);
await click(accordionItemClickableSelector());

assert
.dom(`.${accordionClassFor()}:first-child .${accordionItemHeadClass()}`)
.dom(`.${accordionItemClass()}:first-child ${accordionItemClickableSelector()}`)
.hasClass('collapsed', `${accordionItemHeadClass()} has collapsed class`);
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionClassFor()}:first-child .collapse`).hasNoClass(visibilityClass(), 'tabpanel is hidden');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasClass('collapse', 'tabpanel has collapse class');
assert.dom(`.${accordionItemClass()}:first-child .collapse`).hasNoClass(visibilityClass(), 'tabpanel is hidden');
});

test('it passes accessibility checks', async function (assert) {
Expand Down
15 changes: 9 additions & 6 deletions tests/integration/components/bs-accordion/item-test.js
Expand Up @@ -10,6 +10,7 @@ import {
accordionItemClickableSelector,
test,
visibilityClass,
accordionItemClass,
} from '../../../helpers/bootstrap';
import setupNoDeprecations from '../../../helpers/setup-no-deprecations';
import sinon from 'sinon';
Expand All @@ -25,11 +26,12 @@ module('Integration | Component | bs-accordion-item', function (hooks) {

test('accordion item has correct default markup', async function (assert) {
await render(hbs`<BsAccordion::Item @title="TITLE">CONTENT</BsAccordion::Item>`);
assert.dom(`.${accordionClassFor()}`).exists(`has ${accordionClassFor()} class`);
assert.dom(`.${accordionItemClass()}`).exists(`has ${accordionItemClass()} class`);
assert
.dom(`.${accordionClassFor()}`)
.dom(`.${accordionItemClass()}`)
.hasClass(accordionClassFor('default'), `has ${accordionClassFor('default')} class`);
assert.dom(`.${accordionItemHeadClass()}`).hasClass('collapsed', `has collapsed class`);
assert.dom(`.${accordionItemClass()} .${accordionItemHeadClass()}`).exists();
assert.dom(accordionItemClickableSelector()).hasClass('collapsed', `has collapsed class`);
assert.dom('.collapse').exists();
assert.dom('.collapse').hasNoClass(visibilityClass(), '.collapse is hidden');
assert.dom(accordionTitleSelector()).hasText('TITLE', `${accordionTitleSelector()} has correct title`);
Expand All @@ -43,7 +45,7 @@ module('Integration | Component | bs-accordion-item', function (hooks) {
hbs`<BsAccordion::Item @value={{1}} @onClick={{action "click"}} @title="TITLE">CONTENT</BsAccordion::Item>`
);

await click(`.${accordionItemHeadClass()}`);
await click(accordionItemClickableSelector());
assert.ok(action.calledWith(1), 'onClick action has been called.');
});

Expand All @@ -67,8 +69,9 @@ module('Integration | Component | bs-accordion-item', function (hooks) {
);
assert
.dom(accordionItemClickableSelector())
.hasClass('disabled', 'Clickable accordion selector has `.disabled` class');
assert.dom(`.${accordionClassFor()}`).hasClass('disabled', 'entire item has `.disabled` class');
.hasClass('disabled', 'Clickable accordion selector has `.disabled` class')
.hasAttribute('disabled');
assert.dom(`.${accordionItemClass()}`).hasClass('disabled', 'entire item has `.disabled` class');
try {
await click(accordionItemClickableSelector());
} catch (e) {
Expand Down

0 comments on commit 43651d2

Please sign in to comment.