diff --git a/ui-v2/app/search/filters/role.js b/ui-v2/app/search/filters/role.js index 3144ac6e26..420b36dc6b 100644 --- a/ui-v2/app/search/filters/role.js +++ b/ui-v2/app/search/filters/role.js @@ -8,7 +8,13 @@ export default function(filterable) { .indexOf(sLower) !== -1 || get(item, 'Description') .toLowerCase() - .indexOf(sLower) !== -1 + .indexOf(sLower) !== -1 || + (get(item, 'Policies') || []).some(function(item) { + return item.Name.toLowerCase().indexOf(sLower) !== -1; + }) || + (get(item, 'ServiceIdentities') || []).some(function(item) { + return item.ServiceName.toLowerCase().indexOf(sLower) !== -1; + }) ); }); } diff --git a/ui-v2/app/search/filters/token.js b/ui-v2/app/search/filters/token.js index f8f5f1c3ef..6645e931da 100644 --- a/ui-v2/app/search/filters/token.js +++ b/ui-v2/app/search/filters/token.js @@ -15,6 +15,12 @@ export default function(filterable) { .indexOf(sLower) !== -1 || (get(item, 'Policies') || []).some(function(item) { return item.Name.toLowerCase().indexOf(sLower) !== -1; + }) || + (get(item, 'ServiceIdentities') || []).some(function(item) { + return item.ServiceName.toLowerCase().indexOf(sLower) !== -1; + }) || + (get(item, 'Roles') || []).some(function(item) { + return item.Name.toLowerCase().indexOf(sLower) !== -1; }) ); }); diff --git a/ui-v2/app/templates/dc/acls/policies/index.hbs b/ui-v2/app/templates/dc/acls/policies/index.hbs index da156c8c43..3e5211ea4b 100644 --- a/ui-v2/app/templates/dc/acls/policies/index.hbs +++ b/ui-v2/app/templates/dc/acls/policies/index.hbs @@ -42,7 +42,7 @@ {{join ', ' (policy/datacenters item)}} - + {{item.Description}} {{/block-slot}} diff --git a/ui-v2/app/templates/dc/acls/roles/index.hbs b/ui-v2/app/templates/dc/acls/roles/index.hbs index e1fb71ec8c..c61c667214 100644 --- a/ui-v2/app/templates/dc/acls/roles/index.hbs +++ b/ui-v2/app/templates/dc/acls/roles/index.hbs @@ -39,12 +39,12 @@ {{item.Name}} - + {{item.Description}} {{#each item.Policies as |item|}} - {{item.Name}} + {{item.Name}} {{/each}} {{/block-slot}} diff --git a/ui-v2/app/templates/dc/acls/tokens/index.hbs b/ui-v2/app/templates/dc/acls/tokens/index.hbs index f2d783cfce..e9a3f7fcc9 100644 --- a/ui-v2/app/templates/dc/acls/tokens/index.hbs +++ b/ui-v2/app/templates/dc/acls/tokens/index.hbs @@ -47,7 +47,7 @@ {{if item.Local 'local' 'global' }} - + {{default item.Description item.Name}} @@ -55,7 +55,7 @@ Legacy tokens have embedded rules. {{ else }} {{#each (append item.Policies item.Roles) as |item|}} - {{item.Name}} + {{item.Name}} {{/each}} {{/if}} diff --git a/ui-v2/tests/acceptance/dc/acls/policies/index.feature b/ui-v2/tests/acceptance/dc/acls/policies/index.feature index 448c84caf2..103a3ec3e4 100644 --- a/ui-v2/tests/acceptance/dc/acls/policies/index.feature +++ b/ui-v2/tests/acceptance/dc/acls/policies/index.feature @@ -10,6 +10,26 @@ Feature: dc / acls / policies / index: ACL Policy List --- Then the url should be /dc-1/acls/policies Then I see 3 policy models + Scenario: Searching the policies + Given 1 datacenter model with the value "dc-1" + And 3 policy models from yaml + --- + - Description: Find me + - Description: Not in search + - Description: Not in search either + --- + When I visit the policies page for yaml + --- + dc: dc-1 + --- + Then the url should be /dc-1/acls/policies + Then I see 3 policy models + Then I fill in with yaml + --- + s: Find me + --- + And I see 1 policy model + And I see 1 policy model with the description "Find me" @ignore Scenario: The global-managment policy can't be deleted And I click actions on the policies diff --git a/ui-v2/tests/acceptance/dc/acls/roles/index.feature b/ui-v2/tests/acceptance/dc/acls/roles/index.feature index 244e4539ae..206e4ae5e7 100644 --- a/ui-v2/tests/acceptance/dc/acls/roles/index.feature +++ b/ui-v2/tests/acceptance/dc/acls/roles/index.feature @@ -10,3 +10,47 @@ Feature: dc / acls / roles / index: ACL Roles List --- Then the url should be /dc-1/acls/roles Then I see 3 role models + Scenario: Searching the roles + Given 1 datacenter model with the value "dc-1" + And 3 role models from yaml + --- + - Description: Description Search + Policies: + - Name: not-in-Polsearch + ServiceIdentities: + - ServiceName: not-in-sisearch + - Description: Not in descsearch + Policies: + - Name: Policy-Search + ServiceIdentities: + - ServiceName: not-in-sisearch + - Description: Not in descsearch either + Policies: + - Name: not-in-Polsearch-either + ServiceIdentities: + - ServiceName: Si-Search + --- + When I visit the roles page for yaml + --- + dc: dc-1 + --- + Then the url should be /dc-1/acls/roles + Then I see 3 role models + Then I fill in with yaml + --- + s: Description + --- + And I see 1 role model + And I see 1 role model with the description "Description Search" + Then I fill in with yaml + --- + s: Policy-Search + --- + And I see 1 role model + And I see 1 role model with the policy "Policy-Search" + Then I fill in with yaml + --- + s: Si-Search + --- + And I see 1 role model + And I see 1 role model with the serviceIdentity "Si-Search" diff --git a/ui-v2/tests/acceptance/dc/acls/tokens/index.feature b/ui-v2/tests/acceptance/dc/acls/tokens/index.feature index 70aa62b1b4..09c4a32c62 100644 --- a/ui-v2/tests/acceptance/dc/acls/tokens/index.feature +++ b/ui-v2/tests/acceptance/dc/acls/tokens/index.feature @@ -10,6 +10,73 @@ Feature: dc / acls / tokens / index: ACL Token List --- Then the url should be /dc-1/acls/tokens Then I see 3 token models + Scenario: Searching the tokens + Given 1 datacenter model with the value "dc-1" + And 4 token models from yaml + --- + - Description: Description Search + Legacy: false + ServiceIdentities: + - ServiceName: not-in-sisearch + Policies: + - Name: not-in-Polsearch + Roles: + - Name: not-in-rolesearch + - Description: Not in descsearch + Legacy: false + ServiceIdentities: + - ServiceName: not-in-sisearch + Policies: + - Name: Policy-Search + Roles: + - Name: not-in-rolesearch-either + - Description: Not in descsearch either + Legacy: false + ServiceIdentities: + - ServiceName: not-in-sisearch + Policies: + - Name: not-int-Polsearch-either + Roles: + - Name: Role-Search + - Description: Not in descsearch either + Legacy: false + ServiceIdentities: + - ServiceName: Si-Search + Policies: + - Name: not-int-Polsearch-either + Roles: + - Name: not-in-rolesearch-either + --- + When I visit the tokens page for yaml + --- + dc: dc-1 + --- + Then the url should be /dc-1/acls/tokens + Then I see 4 token models + Then I fill in with yaml + --- + s: Description + --- + And I see 1 token model + And I see 1 token model with the description "Description Search" + Then I fill in with yaml + --- + s: Policy-Search + --- + And I see 1 token model + And I see 1 token model with the policy "Policy-Search" + Then I fill in with yaml + --- + s: Role-Search + --- + And I see 1 token model + And I see 1 token model with the role "Role-Search" + Then I fill in with yaml + --- + s: Si-Search + --- + And I see 1 token model + And I see 1 token model with the serviceIdentity "Si-Search" Scenario: I see the legacy message if I have one legacy token Given 1 datacenter model with the value "dc-1" And 3 token models from yaml diff --git a/ui-v2/tests/pages.js b/ui-v2/tests/pages.js index cb301ce3d2..7b069db824 100644 --- a/ui-v2/tests/pages.js +++ b/ui-v2/tests/pages.js @@ -67,11 +67,20 @@ export default { acls: create(acls(visitable, deletable, creatable, clickable, attribute, collection, aclFilter)), acl: create(acl(visitable, submitable, deletable, cancelable, clickable)), policies: create( - policies(visitable, deletable, creatable, clickable, attribute, collection, freetextFilter) + policies( + visitable, + deletable, + creatable, + clickable, + attribute, + collection, + text, + freetextFilter + ) ), policy: create(policy(visitable, submitable, deletable, cancelable, clickable, tokenList)), roles: create( - roles(visitable, deletable, creatable, clickable, attribute, collection, freetextFilter) + roles(visitable, deletable, creatable, clickable, attribute, collection, text, freetextFilter) ), // TODO: This needs a policyList role: create(role(visitable, submitable, deletable, cancelable, policySelector, tokenList)), diff --git a/ui-v2/tests/pages/dc/acls/policies/index.js b/ui-v2/tests/pages/dc/acls/policies/index.js index ff9204ad25..60a303a955 100644 --- a/ui-v2/tests/pages/dc/acls/policies/index.js +++ b/ui-v2/tests/pages/dc/acls/policies/index.js @@ -1,10 +1,20 @@ -export default function(visitable, deletable, creatable, clickable, attribute, collection, filter) { +export default function( + visitable, + deletable, + creatable, + clickable, + attribute, + collection, + text, + filter +) { return creatable({ visit: visitable('/:dc/acls/policies'), policies: collection( '[data-test-tabular-row]', deletable({ name: attribute('data-test-policy', '[data-test-policy]'), + description: text('[data-test-description]'), policy: clickable('a'), actions: clickable('label'), }) diff --git a/ui-v2/tests/pages/dc/acls/roles/index.js b/ui-v2/tests/pages/dc/acls/roles/index.js index 4082349265..cae2c9a06e 100644 --- a/ui-v2/tests/pages/dc/acls/roles/index.js +++ b/ui-v2/tests/pages/dc/acls/roles/index.js @@ -1,11 +1,22 @@ -export default function(visitable, deletable, creatable, clickable, attribute, collection, filter) { +export default function( + visitable, + deletable, + creatable, + clickable, + attribute, + collection, + text, + filter +) { return creatable({ visit: visitable('/:dc/acls/roles'), roles: collection( '[data-test-tabular-row]', deletable({ name: attribute('data-test-role', '[data-test-role]'), - policy: clickable('a'), + description: text('[data-test-description]'), + policy: text('[data-test-policy].policy', { multiple: true }), + serviceIdentity: text('[data-test-policy].policy-service-identity', { multiple: true }), actions: clickable('label'), }) ), diff --git a/ui-v2/tests/pages/dc/acls/tokens/index.js b/ui-v2/tests/pages/dc/acls/tokens/index.js index 3b5201ab6f..6cdf957d21 100644 --- a/ui-v2/tests/pages/dc/acls/tokens/index.js +++ b/ui-v2/tests/pages/dc/acls/tokens/index.js @@ -17,6 +17,10 @@ export default function( '[data-test-tabular-row]', deletable({ id: attribute('data-test-token', '[data-test-token]'), + description: text('[data-test-description]'), + policy: text('[data-test-policy].policy', { multiple: true }), + role: text('[data-test-policy].role', { multiple: true }), + serviceIdentity: text('[data-test-policy].policy-service-identity', { multiple: true }), token: clickable('a'), actions: clickable('label'), use: clickable('[data-test-use]'), diff --git a/ui-v2/tests/steps/assertions/model.js b/ui-v2/tests/steps/assertions/model.js index 54b30279b3..12f6b2ae9b 100644 --- a/ui-v2/tests/steps/assertions/model.js +++ b/ui-v2/tests/steps/assertions/model.js @@ -39,7 +39,15 @@ export default function(scenario, assert, find, currentPage, pauseUntil, plurali value ) { const len = currentPage()[pluralize(model)].filter(function(item) { - return item.isVisible && item[property] == value; + if (item.isVisible) { + let prop = item[property]; + // cope with pageObjects that can have a multiple: true + if (!Array.isArray(prop)) { + prop = [prop]; + } + return prop.includes(value); + } + return false; }).length; assert.equal( len, diff --git a/ui-v2/tests/unit/search/filters/role-test.js b/ui-v2/tests/unit/search/filters/role-test.js new file mode 100644 index 0000000000..6a273a42fe --- /dev/null +++ b/ui-v2/tests/unit/search/filters/role-test.js @@ -0,0 +1,89 @@ +import getFilter from 'consul-ui/search/filters/role'; +import { module, test } from 'qunit'; + +module('Unit | Search | Filter | role'); + +const filter = getFilter(cb => cb); +test('items are found by properties', function(assert) { + [ + { + Name: 'name-HIT', + Description: 'description', + Policies: [], + }, + { + Name: 'name', + Description: 'desc-HIT-ription', + Policies: [], + }, + { + Name: 'name', + Description: 'description', + Policies: [{ Name: 'policy' }, { Name: 'policy-HIT' }], + }, + { + Name: 'name', + Description: 'description', + ServiceIdentities: [ + { ServiceName: 'service-identity' }, + { ServiceName: 'service-identity-HIT' }, + ], + }, + ].forEach(function(item) { + const actual = filter(item, { + s: 'hit', + }); + assert.ok(actual); + }); +}); +test('items are not found', function(assert) { + [ + { + Name: 'name', + Description: 'description', + Policies: [], + }, + { + Name: 'name', + Description: 'description', + Policies: [{ Name: 'policy' }, { Name: 'policy-second' }], + }, + { + AccessorID: 'id', + Name: 'name', + Description: 'description', + ServiceIdenitities: [{ ServiceName: 'si' }, { ServiceName: 'si-second' }], + }, + ].forEach(function(item) { + const actual = filter(item, { + s: 'hit', + }); + assert.notOk(actual); + }); +}); +test('arraylike things can be empty', function(assert) { + [ + { + Name: 'name', + Description: 'description', + }, + { + Name: 'name', + Description: 'description', + Policies: null, + ServiceIdentities: null, + }, + { + AccessorID: 'id', + Name: 'name', + Description: 'description', + Policies: [], + ServiceIdentities: [], + }, + ].forEach(function(item) { + const actual = filter(item, { + s: 'hit', + }); + assert.notOk(actual); + }); +}); diff --git a/ui-v2/tests/unit/search/filters/token-test.js b/ui-v2/tests/unit/search/filters/token-test.js index fabe1f9e4d..d46b63c3c7 100644 --- a/ui-v2/tests/unit/search/filters/token-test.js +++ b/ui-v2/tests/unit/search/filters/token-test.js @@ -30,6 +30,21 @@ test('items are found by properties', function(assert) { Description: 'description', Policies: [{ Name: 'policy' }, { Name: 'policy-HIT' }], }, + { + AccessorID: 'id', + Name: 'name', + Description: 'description', + Roles: [{ Name: 'role' }, { Name: 'role-HIT' }], + }, + { + AccessorID: 'id', + Name: 'name', + Description: 'description', + ServiceIdentities: [ + { ServiceName: 'service-identity' }, + { ServiceName: 'service-identity-HIT' }, + ], + }, ].forEach(function(item) { const actual = filter(item, { s: 'hit', @@ -51,6 +66,18 @@ test('items are not found', function(assert) { Description: 'description', Policies: [{ Name: 'policy' }, { Name: 'policy-second' }], }, + { + AccessorID: 'id', + Name: 'name', + Description: 'description', + Roles: [{ Name: 'role' }, { Name: 'role-second' }], + }, + { + AccessorID: 'id', + Name: 'name', + Description: 'description', + ServiceIdenitities: [{ ServiceName: 'si' }, { ServiceName: 'si-second' }], + }, ].forEach(function(item) { const actual = filter(item, { s: 'hit', @@ -58,7 +85,7 @@ test('items are not found', function(assert) { assert.notOk(actual); }); }); -test('policies can be empty', function(assert) { +test('arraylike things can be empty', function(assert) { [ { AccessorID: 'id', @@ -70,12 +97,16 @@ test('policies can be empty', function(assert) { Name: 'name', Description: 'description', Policies: null, + Roles: null, + ServiceIdentities: null, }, { AccessorID: 'id', Name: 'name', Description: 'description', Policies: [], + Roles: [], + ServiceIdentities: [], }, ].forEach(function(item) { const actual = filter(item, {