WIP Group contributions in UI
This commit is contained in:
@@ -8,11 +8,17 @@ import contributions from '../../../fixtures/contributions';
|
||||
module('Integration | Component | contribution-list', function(hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders all contributions', async function(assert) {
|
||||
test('it renders all contributions with grouped rows collapsed', async function(assert) {
|
||||
let kredits = this.owner.lookup('service:kredits');
|
||||
kredits.set('contributors', contributors);
|
||||
|
||||
this.set('fixtures', contributions);
|
||||
await render(hbs`{{contribution-list contributions=fixtures}}`);
|
||||
|
||||
assert.equal(this.element.querySelectorAll('li').length, 9);
|
||||
// 9 contributions: 2 groups (ids 1+3, 7+8) + 5 singletons = 7 top-level rows
|
||||
assert.equal(this.element.querySelectorAll('li').length, 7, '7 top-level rows when collapsed');
|
||||
assert.equal(this.element.querySelectorAll('li.grouped').length, 2, '2 grouped headers');
|
||||
assert.equal(this.element.querySelectorAll('li.group-item').length, 0, 'no expanded sub-items');
|
||||
});
|
||||
|
||||
test('it renders filtered contributions', async function(assert) {
|
||||
@@ -23,12 +29,87 @@ module('Integration | Component | contribution-list', function(hooks) {
|
||||
await render(hbs`{{contribution-list contributions=fixtures showQuickFilter=true}}`);
|
||||
|
||||
await fillIn('.filter-contributor select', '1');
|
||||
// Contributor 1 is in ids 1, 2, 5, 6, 8. Grouped rows stay whole: id 1's
|
||||
// group (with id 3) and id 8's group (with id 7) show as grouped rows
|
||||
// because id 1 / id 8 match; ids 2, 5, 6 are singletons. 5 top-level rows.
|
||||
assert.equal(this.element.querySelectorAll('li').length, 5, 'select contributor');
|
||||
|
||||
await click('.filter-contribution-size input');
|
||||
// Hide small (<=500): drops id 6 only. Grouped rows stay (matching items
|
||||
// are 1500/1500). 4 top-level rows.
|
||||
assert.equal(this.element.querySelectorAll('li').length, 4, 'hide small contributions');
|
||||
|
||||
await fillIn('.filter-contribution-kind select', 'dev');
|
||||
// Kind dev (still filtered to contributor 1, hide small on): only groups
|
||||
// where a single item passes all three filters survive. Group {1,3}: id 1
|
||||
// is contributor 1 + dev → included. Group {8,7}: id 8 is contributor 1 but
|
||||
// community; id 7 is dev but contributor 3 → no item passes both → excluded.
|
||||
// Singletons id 2 (ops), id 5 (design) → excluded. 1 top-level row.
|
||||
assert.equal(this.element.querySelectorAll('li').length, 1, 'select kind');
|
||||
});
|
||||
|
||||
test('filtering by contributor keeps grouped rows whole', async function(assert) {
|
||||
let kredits = this.owner.lookup('service:kredits');
|
||||
kredits.set('contributors', contributors);
|
||||
|
||||
this.set('fixtures', contributions);
|
||||
await render(hbs`{{contribution-list contributions=fixtures showQuickFilter=true}}`);
|
||||
|
||||
await fillIn('.filter-contributor select', '1');
|
||||
|
||||
// The first row is the group containing id 1 (contributor 1) and id 3
|
||||
// (contributor 2) — it stays grouped, not collapsed to a singleton.
|
||||
const firstRow = this.element.querySelector('li');
|
||||
assert.ok(firstRow.classList.contains('grouped'), 'first row is still grouped');
|
||||
assert.equal(firstRow.querySelectorAll('.avatars img').length, 2, 'shows both contributors avatars');
|
||||
});
|
||||
|
||||
test('grouped row expands on click to reveal sub-items', async function(assert) {
|
||||
let kredits = this.owner.lookup('service:kredits');
|
||||
kredits.set('contributors', contributors);
|
||||
|
||||
this.set('fixtures', contributions);
|
||||
await render(hbs`{{contribution-list contributions=fixtures}}`);
|
||||
|
||||
assert.equal(this.element.querySelectorAll('li.group-item').length, 0, 'no sub-items when collapsed');
|
||||
|
||||
await click('.grouped:first-child');
|
||||
|
||||
assert.equal(this.element.querySelectorAll('li.group-item').length, 2, '2 sub-items when expanded');
|
||||
assert.ok(this.element.querySelector('.grouped').classList.contains('expanded'), 'header has expanded class');
|
||||
|
||||
await click('.grouped:first-child');
|
||||
assert.equal(this.element.querySelectorAll('li.group-item').length, 0, 'sub-items hidden when collapsed');
|
||||
});
|
||||
|
||||
test('grouped row shows stacked avatars and single amount', async function(assert) {
|
||||
let kredits = this.owner.lookup('service:kredits');
|
||||
kredits.set('contributors', contributors);
|
||||
|
||||
this.set('fixtures', contributions);
|
||||
await render(hbs`{{contribution-list contributions=fixtures}}`);
|
||||
|
||||
const firstGroup = this.element.querySelector('.grouped');
|
||||
// Group ids 1+3 → 2 contributors → 2 avatars, no overflow
|
||||
assert.equal(firstGroup.querySelectorAll('.avatars img').length, 2, '2 avatar images');
|
||||
assert.equal(firstGroup.querySelectorAll('.avatar-overflow').length, 0, 'no overflow bubble for 2 contributors');
|
||||
// Single amount (first item's amount = 1500, not the sum)
|
||||
assert.equal(firstGroup.querySelector('.amount').textContent.trim(), '1500', 'shows single contribution amount');
|
||||
});
|
||||
|
||||
test('auto-expands when selectedContributionId is a group child', async function(assert) {
|
||||
let kredits = this.owner.lookup('service:kredits');
|
||||
kredits.set('contributors', contributors);
|
||||
|
||||
this.set('fixtures', contributions);
|
||||
this.set('selectedId', 3);
|
||||
|
||||
await render(hbs`{{contribution-list contributions=fixtures selectedContributionId=selectedId}}`);
|
||||
|
||||
assert.equal(this.element.querySelectorAll('li.group-item').length, 2, 'group auto-expanded');
|
||||
|
||||
const selectedChild = this.element.querySelector('.group-item.selected');
|
||||
assert.ok(selectedChild, 'selected child has selected class');
|
||||
assert.equal(selectedChild.dataset.contributionId, '3', 'correct child is selected');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import contributors from '../../../../fixtures/contributors';
|
||||
import contributions from '../../../../fixtures/contributions';
|
||||
|
||||
module('Unit | Controller | dashboard/contributions/show', function(hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('#siblingContributions returns co-contributor contributions for a grouped contribution', function(assert) {
|
||||
let kredits = this.owner.lookup('service:kredits');
|
||||
kredits.set('contributors', contributors);
|
||||
kredits.set('contributions', contributions);
|
||||
|
||||
let controller = this.owner.lookup('controller:dashboard.contributions.show');
|
||||
// id=1 shares a url with id=3
|
||||
controller.set('model', contributions.findBy('id', 1));
|
||||
|
||||
const siblings = controller.siblingContributions;
|
||||
assert.equal(siblings.length, 1, 'one sibling');
|
||||
assert.equal(siblings[0].id, 3, 'sibling is contribution 3');
|
||||
});
|
||||
|
||||
test('#siblingContributions returns empty for a manual contribution without url', function(assert) {
|
||||
let kredits = this.owner.lookup('service:kredits');
|
||||
kredits.set('contributors', contributors);
|
||||
kredits.set('contributions', contributions);
|
||||
|
||||
let controller = this.owner.lookup('controller:dashboard.contributions.show');
|
||||
// id=2 has no url
|
||||
controller.set('model', contributions.findBy('id', 2));
|
||||
|
||||
assert.deepEqual(controller.siblingContributions, [], 'no siblings for manual contribution');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user