Skip to content
This repository has been archived by the owner on Nov 28, 2022. It is now read-only.

Commit

Permalink
Added acceptance test for members search
Browse files Browse the repository at this point in the history
refs TryGhost/Product#1336
refs 343ad98

- adds basic search param handling to `GET /members` API mock
- adds acceptance tests for basic search behaviour
- contains regression check for search input not being visible when no members match
  • Loading branch information
kevinansfield committed Feb 14, 2022
1 parent 9251aa3 commit b76291c
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 9 deletions.
15 changes: 8 additions & 7 deletions app/templates/members.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
{{on "focus" (fn (mut this.searchIsFocused) true)}}
{{on "blur" (fn (mut this.searchIsFocused) false)}}
{{will-destroy (fn (mut this.searchIsFocused) false)}}
data-test-input="members-search"
/>
</div>
</div>
Expand Down Expand Up @@ -54,15 +55,15 @@
</li>
<li class="{{if this.members.length "" "disabled"}}">
{{#if this.members.length}}
<button class="mr2" type="button" {{on "click" this.exportData}}>
<button class="mr2" type="button" {{on "click" this.exportData}} data-test-button="export-members">
{{#if this.showingAll}}
<span>Export all members</span>
{{else}}
<span>Export selected members ({{this.members.length}})</span>
<span>Export selected members ({{this.members.length}})</span>
{{/if}}
</button>
{{else}}
<button class="mr2" disabled="true" type="button">
<button class="mr2" disabled="true" type="button" data-test-button="export-members">
<span>Export selected members (0)</span>
</button>
{{/if}}
Expand All @@ -80,7 +81,7 @@
</button>
</li>
<li>
<button class="mr2" data-test-button="remove-label-selected" type="button" {{on "click" this.bulkUnsubscribe}}>
<button class="mr2" data-test-button="unsubscribe-selected" type="button" {{on "click" this.bulkUnsubscribe}}>
<span>Unsubscribe selected members ({{this.members.length}})</span>
</button>
</li>
Expand All @@ -106,7 +107,7 @@
{{else}}
<section class="view-container {{if (or (not this.members) (lt this.members.length 6)) "members-list-container-stretch"}}">
{{#if this.members}}
<div class="gh-list-scrolling {{if (lt this.members.length 6) "gh-list-with-helpsection"}}">
<div class="gh-list-scrolling {{if (lt this.members.length 6) "gh-list-with-helpsection"}}" daat-test-table="members">

This comment has been minimized.

Copy link
@gabrielcsapo

gabrielcsapo Feb 15, 2022

Contributor

should this be data-test-table="members"?

This comment has been minimized.

Copy link
@kevinansfield

kevinansfield Feb 15, 2022

Author Collaborator

Good catch, thanks!

<table class="gh-list">
<thead>
<tr>
Expand Down Expand Up @@ -137,10 +138,10 @@
{{#if this.showingAll}}
<GhMembersNoMembers @afterCreate={{this.refreshData}} @members={{this.members}} />
{{else}}
<div class="gh-members-empty">
<div class="gh-members-empty" data-test-no-matching-members>
{{svg-jar "members-placeholder" class="gh-members-placeholder"}}
<h4>No members match the current filter</h4>
<LinkTo @route="members" @query={{reset-query-params "members.index"}} class="gh-btn mt4">
<LinkTo @route="members" @query={{reset-query-params "members.index"}} class="gh-btn mt4" data-test-button="show-all-members">
<span>Show all members</span>
</LinkTo>
</div>
Expand Down
13 changes: 11 additions & 2 deletions mirage/config/members.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ export default function mockMembers(server) {
});

server.get('/members/', function ({members}, {queryParams}) {
let {filter, page, limit} = queryParams;
let {filter, search, page, limit} = queryParams;

page = +page || 1;
limit = +limit || 15;

let labelFilter = extractFilterParam('label', filter);
const labelFilter = extractFilterParam('label', filter);

let collection = members.all().filter((member) => {
let matchesLabel = true;
Expand All @@ -91,6 +91,15 @@ export default function mockMembers(server) {
return matchesLabel;
});

if (search) {
const query = search.toLowerCase();

collection = collection.filter((member) => {
return member.name.toLowerCase().indexOf(query) !== -1
|| member.email.toLowerCase().indexOf(query) !== -1;
});
}

return paginateModelCollection('members', collection, page, limit);
});

Expand Down
129 changes: 129 additions & 0 deletions tests/acceptance/members/filter-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import {authenticateSession} from 'ember-simple-auth/test-support';
import {click, currentURL, fillIn, find, findAll} from '@ember/test-helpers';
import {expect} from 'chai';
import {setupApplicationTest} from 'ember-mocha';
import {setupMirage} from 'ember-cli-mirage/test-support';
import {visit} from '../../helpers/visit';

describe('Acceptance: Members filtering', function () {
let hooks = setupApplicationTest();
setupMirage(hooks);

beforeEach(async function () {
this.server.loadFixtures('configs');

let role = this.server.create('role', {name: 'Owner'});
this.server.create('user', {roles: [role]});

return await authenticateSession();
});

it('has a known base-state', async function () {
this.server.createList('member', 7);

await visit('/members');

// members are listed
expect(findAll('[data-test-list="members-list-item"]').length, '# of member rows').to.equal(7);

// export is available
expect(find('[data-test-button="export-members"]'), 'export members button').to.exist;
expect(find('[data-test-button="export-members"]'), 'export members button').to.not.have.attribute('disabled');

// bulk actions are hidden
expect(find('[data-test-button="add-label-selected"]'), 'add label to selected button').to.not.exist;
expect(find('[data-test-button="remove-label-selected"]'), 'remove label from selected button').to.not.exist;
expect(find('[data-test-button="unsubscribe-selected"]'), 'unsubscribe selected button').to.not.exist;
expect(find('[data-test-button="delete-selected"]'), 'delete selected button').to.not.exist;

// filter and search are inactive
expect(find('[data-test-input="members-search"]'), 'search input').to.exist;
expect(find('[data-test-input="members-search"]'), 'search input').to.not.have.class('active');
expect(find('[data-test-button="members-filter-actions"]'), 'filter button').to.not.have.class('gh-btn-label-green');
});

describe('search', function () {
beforeEach(function () {
// specific member names+emails so search is deterministic
// (default factory has random names+emails)
this.server.create('member', {name: 'X', email: 'x@x.xxx'});
this.server.create('member', {name: 'Y', email: 'y@y.yyy'});
this.server.create('member', {name: 'Z', email: 'z@z.zzz'});
});

it('works', async function () {
await visit('/members');

expect(findAll('[data-test-list="members-list-item"]').length, '# of initial member rows')
.to.equal(3);

await fillIn('[data-test-input="members-search"]', 'X');

// list updates
expect(findAll('[data-test-list="members-list-item"]').length, '# of members matching "X"')
.to.equal(1);

// URL reflects search
expect(currentURL()).to.equal('/members?search=X');

// search input is active
expect(find('[data-test-input="members-search"]')).to.have.class('active');

// bulk actions become available
expect(find('[data-test-button="add-label-selected"]'), 'add label to selected button').to.exist;
expect(find('[data-test-button="remove-label-selected"]'), 'remove label from selected button').to.exist;
expect(find('[data-test-button="unsubscribe-selected"]'), 'unsubscribe selected button').to.exist;
expect(find('[data-test-button="delete-selected"]'), 'delete selected button').to.exist;

// clearing search returns us to starting state
await fillIn('[data-test-input="members-search"]', '');

expect(findAll('[data-test-list="members-list-item"]').length, '# of members after clearing search')
.to.equal(3);

expect(find('[data-test-input="members-search"]')).to.not.have.class('active');
});

it('populates from query param', async function () {
await visit('/members?search=Y');

expect(findAll('[data-test-list="members-list-item"]').length, '# of initial member rows')
.to.equal(1);

expect(find('[data-test-input="members-search"]')).to.have.value('Y');
expect(find('[data-test-input="members-search"]')).to.have.class('active');
});

it('has an empty state', async function () {
await visit('/members');
await fillIn('[data-test-input="members-search"]', 'unknown');

expect(currentURL()).to.equal('/members?search=unknown');

// replaces members table with the no-matching members state
expect(find('[data-test-table="members"]')).to.not.exist;
expect(find('[data-test-no-matching-members]')).to.exist;

// search input is still shown
expect(find('[data-test-input="members-search"]')).to.be.visible;
expect(find('[data-test-input="members-search"]')).to.have.class('active');

// export is disabled
expect(find('[data-test-button="export-members"]')).to.have.attribute('disabled');

// bulk actions are hidden
expect(find('[data-test-button="add-label-selected"]')).to.not.exist;
expect(find('[data-test-button="remove-label-selected"]')).to.not.exist;
expect(find('[data-test-button="unsubscribe-selected"]')).to.not.exist;
expect(find('[data-test-button="delete-selected"]')).to.not.exist;

// can clear the search
await click('[data-test-no-matching-members] [data-test-button="show-all-members"]');

expect(currentURL()).to.equal('/members');
expect(find('[data-test-input="members-search"]')).to.have.value('');
expect(find('[data-test-input="members-search"]')).to.not.have.class('active');
expect(findAll('[data-test-list="members-list-item"]').length).to.equal(3);
});
});
});

0 comments on commit b76291c

Please sign in to comment.