mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-26 20:34:02 +03:00
Added acceptance test for members search
refs https://github.com/TryGhost/Team/issues/1336
refs bf9bbc3aa6
- 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
This commit is contained in:
parent
450182edf4
commit
995673ad3c
@ -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>
|
||||
@ -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}}
|
||||
@ -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>
|
||||
@ -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">
|
||||
<table class="gh-list">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -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>
|
||||
|
@ -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;
|
||||
@ -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);
|
||||
});
|
||||
|
||||
|
129
ghost/admin/tests/acceptance/members/filter-test.js
Normal file
129
ghost/admin/tests/acceptance/members/filter-test.js
Normal file
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user