mirror of https://github.com/status-im/consul.git
ui: Add sorting to Intentions with tests (#8348)
* Add sorting to Intentions with tests * Skip Intentions url back test * Create comparator for intention and implement in template * Add a intentions navigation feature test
This commit is contained in:
parent
505de6dc29
commit
c73d53e188
|
@ -1,9 +1,7 @@
|
||||||
import Controller from '@ember/controller';
|
import Controller from '@ember/controller';
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
queryParams: {
|
queryParams: {
|
||||||
filterBy: {
|
sortBy: 'sort',
|
||||||
as: 'action',
|
|
||||||
},
|
|
||||||
search: {
|
search: {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import service from 'consul-ui/sort/comparators/service';
|
import service from 'consul-ui/sort/comparators/service';
|
||||||
import check from 'consul-ui/sort/comparators/check';
|
import check from 'consul-ui/sort/comparators/check';
|
||||||
|
import intention from 'consul-ui/sort/comparators/intention';
|
||||||
|
|
||||||
export function initialize(container) {
|
export function initialize(container) {
|
||||||
// Service-less injection using private properties at a per-project level
|
// Service-less injection using private properties at a per-project level
|
||||||
|
@ -7,6 +8,7 @@ export function initialize(container) {
|
||||||
const comparators = {
|
const comparators = {
|
||||||
service: service(),
|
service: service(),
|
||||||
check: check(),
|
check: check(),
|
||||||
|
intention: intention(),
|
||||||
};
|
};
|
||||||
Sort.reopen({
|
Sort.reopen({
|
||||||
comparator: function(type) {
|
comparator: function(type) {
|
||||||
|
|
|
@ -2,9 +2,7 @@ import Route from '@ember/routing/route';
|
||||||
|
|
||||||
export default Route.extend({
|
export default Route.extend({
|
||||||
queryParams: {
|
queryParams: {
|
||||||
filterBy: {
|
sortBy: 'sort',
|
||||||
as: 'action',
|
|
||||||
},
|
|
||||||
search: {
|
search: {
|
||||||
as: 'filter',
|
as: 'filter',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
export default () => key => {
|
||||||
|
return key;
|
||||||
|
};
|
|
@ -7,14 +7,18 @@
|
||||||
|
|
||||||
<BlockSlot @name="loaded">
|
<BlockSlot @name="loaded">
|
||||||
|
|
||||||
{{#let (filter-by "Action" "deny" api.data) as |denied|}}
|
|
||||||
{{#let (selectable-key-values
|
{{#let (selectable-key-values
|
||||||
(array "" (concat "All (" api.data.length ")"))
|
(array "Action:asc" "Allow to Deny")
|
||||||
(array "allow" (concat "Allow (" (sub api.data.length denied.length) ")"))
|
(array "Action:desc" "Deny to Allow")
|
||||||
(array "deny" (concat "Deny (" denied.length ")"))
|
(array "SourceName:asc" "Source: A to Z")
|
||||||
selected=filterBy
|
(array "SourceName:desc" "Source: Z to A")
|
||||||
|
(array "DestinationName:asc" "Destination: A to Z")
|
||||||
|
(array "DestinationName:desc" "Destination: Z to A")
|
||||||
|
(array "Precedence:asc" "Precedence: Asc")
|
||||||
|
(array "Precedence:desc" "Precedence: Desc")
|
||||||
|
selected=sortBy
|
||||||
)
|
)
|
||||||
as |filter|
|
as |sort|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
<AppView @class="intention list">
|
<AppView @class="intention list">
|
||||||
|
@ -33,15 +37,16 @@
|
||||||
data-test-intention-filter="true"
|
data-test-intention-filter="true"
|
||||||
@value={{search}}
|
@value={{search}}
|
||||||
@onsearch={{action (mut search) value="target.value"}}
|
@onsearch={{action (mut search) value="target.value"}}
|
||||||
@selected={{filter.selected}}
|
@secondary="sort"
|
||||||
@options={{filter.items}}
|
@selected={{sort.selected}}
|
||||||
@onchange={{action (mut filterBy) value='target.value'}}
|
@options={{sort.items}}
|
||||||
|
@onchange={{action (mut sortBy) value='target.value'}}
|
||||||
/>
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
<BlockSlot @name="content">
|
<BlockSlot @name="content">
|
||||||
|
{{#let (sort-by (comparator 'intention' sort.selected.key) api.data) as |sorted|}}
|
||||||
<ChangeableSet @dispatcher={{searchable 'intention' (if (eq filter.selected.key "") api.data (filter-by "Action" filter.selected.key api.data))}} @terms={{search}}>
|
<ChangeableSet @dispatcher={{searchable 'intention' sorted}} @terms={{search}}>
|
||||||
<BlockSlot @name="content" as |filtered|>
|
<BlockSlot @name="content" as |filtered|>
|
||||||
<ConsulIntentionList
|
<ConsulIntentionList
|
||||||
@items={{filtered}}
|
@items={{filtered}}
|
||||||
|
@ -78,12 +83,9 @@
|
||||||
</ConsulIntentionList>
|
</ConsulIntentionList>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</ChangeableSet>
|
</ChangeableSet>
|
||||||
|
{{/let}}
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</AppView>
|
</AppView>
|
||||||
|
|
||||||
{{/let}}
|
{{/let}}
|
||||||
{{/let}}
|
|
||||||
|
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</DataLoader>
|
</DataLoader>
|
|
@ -1,55 +0,0 @@
|
||||||
@setupApplicationTest
|
|
||||||
Feature: components / intention-filter: Intention Filter
|
|
||||||
In order to find the intention I'm looking for easier
|
|
||||||
As a user
|
|
||||||
I should be able to filter by 'policy' (allow/deny) and freetext search tokens by source and destination
|
|
||||||
Scenario: Filtering [Model]
|
|
||||||
Given 1 datacenter model with the value "dc-1"
|
|
||||||
And 2 [Model] models
|
|
||||||
When I visit the [Page] page for yaml
|
|
||||||
---
|
|
||||||
dc: dc-1
|
|
||||||
---
|
|
||||||
Then the url should be [Url]
|
|
||||||
|
|
||||||
Then I see 2 [Model] models
|
|
||||||
And I see allIsSelected on the filter
|
|
||||||
|
|
||||||
When I click allow on the filter
|
|
||||||
Then I see allowIsSelected on the filter
|
|
||||||
And I see 1 [Model] model
|
|
||||||
And I see 1 [Model] model with the action "allow"
|
|
||||||
|
|
||||||
When I click deny on the filter
|
|
||||||
Then I see denyIsSelected on the filter
|
|
||||||
And I see 1 [Model] model
|
|
||||||
And I see 1 [Model] model with the action "deny"
|
|
||||||
|
|
||||||
When I click all on the filter
|
|
||||||
Then I see 2 [Model] models
|
|
||||||
Then I see allIsSelected on the filter
|
|
||||||
Then I fill in with yaml
|
|
||||||
---
|
|
||||||
s: alarm
|
|
||||||
---
|
|
||||||
And I see 1 [Model] model
|
|
||||||
And I see 1 [Model] model with the source "alarm"
|
|
||||||
Then I fill in with yaml
|
|
||||||
---
|
|
||||||
s: feed
|
|
||||||
---
|
|
||||||
And I see 1 [Model] model
|
|
||||||
And I see 1 [Model] model with the destination "feed"
|
|
||||||
Then I fill in with yaml
|
|
||||||
---
|
|
||||||
s: transmitter
|
|
||||||
---
|
|
||||||
And I see 2 [Model] models
|
|
||||||
And I see 1 [Model] model with the source "transmitter"
|
|
||||||
And I see 1 [Model] model with the destination "transmitter"
|
|
||||||
|
|
||||||
Where:
|
|
||||||
---------------------------------------------
|
|
||||||
| Model | Page | Url |
|
|
||||||
| intention | intentions | /dc-1/intentions |
|
|
||||||
---------------------------------------------
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
@setupApplicationTest
|
||||||
|
Feature: dc / intentions / navigation
|
||||||
|
Scenario: Clicking a intention in the listing and back again
|
||||||
|
Given 1 datacenter model with the value "dc-1"
|
||||||
|
And 3 intention models
|
||||||
|
When I visit the intentions page for yaml
|
||||||
|
---
|
||||||
|
dc: dc-1
|
||||||
|
---
|
||||||
|
Then the url should be /dc-1/intentions
|
||||||
|
And the title should be "Intentions - Consul"
|
||||||
|
Then I see 3 intention models
|
||||||
|
When I click intention on the intentions
|
||||||
|
Then a GET request was made to "/v1/internal/ui/services?dc=dc-1&ns=*"
|
||||||
|
And I click "[data-test-back]"
|
||||||
|
Then the url should be /dc-1/intentions
|
||||||
|
Scenario: Clicking the create button and back again
|
||||||
|
Given 1 datacenter model with the value "dc-1"
|
||||||
|
And 3 intention models
|
||||||
|
When I visit the intentions page for yaml
|
||||||
|
---
|
||||||
|
dc: dc-1
|
||||||
|
---
|
||||||
|
Then the url should be /dc-1/intentions
|
||||||
|
And the title should be "Intentions - Consul"
|
||||||
|
Then I see 3 intention models
|
||||||
|
When I click create
|
||||||
|
Then the url should be /dc-1/intentions/create
|
||||||
|
And I click "[data-test-back]"
|
||||||
|
Then the url should be /dc-1/intentions
|
|
@ -0,0 +1,42 @@
|
||||||
|
@setupApplicationTest
|
||||||
|
@notNamespaceable
|
||||||
|
Feature: dc / intentions / sorting
|
||||||
|
Scenario: Sorting Intentions
|
||||||
|
Given 1 datacenter model with the value "dc-1"
|
||||||
|
And 6 intention models from yaml
|
||||||
|
---
|
||||||
|
- Action: "allow"
|
||||||
|
- Action: "allow"
|
||||||
|
- Action: "deny"
|
||||||
|
- Action: "deny"
|
||||||
|
- Action: "allow"
|
||||||
|
- Action: "deny"
|
||||||
|
---
|
||||||
|
When I visit the intentions page for yaml
|
||||||
|
---
|
||||||
|
dc: dc-1
|
||||||
|
---
|
||||||
|
Then I see 6 intention models
|
||||||
|
When I click selected on the sort
|
||||||
|
When I click options.1.button on the sort
|
||||||
|
Then I see action on the intentions vertically like yaml
|
||||||
|
---
|
||||||
|
- "deny"
|
||||||
|
- "deny"
|
||||||
|
- "deny"
|
||||||
|
- "allow"
|
||||||
|
- "allow"
|
||||||
|
- "allow"
|
||||||
|
---
|
||||||
|
When I click selected on the sort
|
||||||
|
When I click options.0.button on the sort
|
||||||
|
Then I see action on the intentions vertically like yaml
|
||||||
|
---
|
||||||
|
- "allow"
|
||||||
|
- "allow"
|
||||||
|
- "allow"
|
||||||
|
- "deny"
|
||||||
|
- "deny"
|
||||||
|
- "deny"
|
||||||
|
---
|
||||||
|
|
|
@ -46,7 +46,6 @@ Feature: page-navigation
|
||||||
| node | nodes | /dc-1/nodes/node-0/health-checks | /v1/session/node/node-0?dc=dc-1&ns=@namespace | /dc-1/nodes |
|
| node | nodes | /dc-1/nodes/node-0/health-checks | /v1/session/node/node-0?dc=dc-1&ns=@namespace | /dc-1/nodes |
|
||||||
| kv | kvs | /dc-1/kv/0-key-value/edit | /v1/session/info/ee52203d-989f-4f7a-ab5a-2bef004164ca?dc=dc-1&ns=@namespace | /dc-1/kv |
|
| kv | kvs | /dc-1/kv/0-key-value/edit | /v1/session/info/ee52203d-989f-4f7a-ab5a-2bef004164ca?dc=dc-1&ns=@namespace | /dc-1/kv |
|
||||||
# | acl | acls | /dc-1/acls/anonymous | /v1/acl/info/anonymous?dc=dc-1 | /dc-1/acls |
|
# | acl | acls | /dc-1/acls/anonymous | /v1/acl/info/anonymous?dc=dc-1 | /dc-1/acls |
|
||||||
| intention | intentions | /dc-1/intentions/ee52203d-989f-4f7a-ab5a-2bef004164ca | /v1/internal/ui/services?dc=dc-1&ns=* | /dc-1/intentions |
|
|
||||||
# These Endpoints will be datacenters due to the datacenters checkbox selectors
|
# These Endpoints will be datacenters due to the datacenters checkbox selectors
|
||||||
| token | tokens | /dc-1/acls/tokens/ee52203d-989f-4f7a-ab5a-2bef004164ca | /v1/catalog/datacenters | /dc-1/acls/tokens |
|
| token | tokens | /dc-1/acls/tokens/ee52203d-989f-4f7a-ab5a-2bef004164ca | /v1/catalog/datacenters | /dc-1/acls/tokens |
|
||||||
| policy | policies | /dc-1/acls/policies/ee52203d-989f-4f7a-ab5a-2bef004164ca | /v1/catalog/datacenters | /dc-1/acls/policies |
|
| policy | policies | /dc-1/acls/policies/ee52203d-989f-4f7a-ab5a-2bef004164ca | /v1/catalog/datacenters | /dc-1/acls/policies |
|
||||||
|
@ -123,7 +122,7 @@ Feature: page-navigation
|
||||||
| Item | Model | URL | Back |
|
| Item | Model | URL | Back |
|
||||||
| kv | kvs | /dc-1/kv/0-key-value/edit | /dc-1/kv |
|
| kv | kvs | /dc-1/kv/0-key-value/edit | /dc-1/kv |
|
||||||
# | acl | acls | /dc-1/acls/anonymous | /dc-1/acls |
|
# | acl | acls | /dc-1/acls/anonymous | /dc-1/acls |
|
||||||
| intention | intentions | /dc-1/intentions/ee52203d-989f-4f7a-ab5a-2bef004164ca | /dc-1/intentions |
|
# | intention | intentions | /dc-1/intentions/ee52203d-989f-4f7a-ab5a-2bef004164ca | /dc-1/intentions |
|
||||||
--------------------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------------------
|
||||||
@ignore
|
@ignore
|
||||||
Scenario: Clicking items in the listings, without depending on the salt ^
|
Scenario: Clicking items in the listings, without depending on the salt ^
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import steps from '../steps';
|
import steps from '../../steps';
|
||||||
|
|
||||||
// step definitions that are shared between features should be moved to the
|
// step definitions that are shared between features should be moved to the
|
||||||
// tests/acceptance/steps/steps.js file
|
// tests/acceptance/steps/steps.js file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import steps from '../../steps';
|
||||||
|
|
||||||
|
// step definitions that are shared between features should be moved to the
|
||||||
|
// tests/acceptance/steps/steps.js file
|
||||||
|
|
||||||
|
export default function(assert) {
|
||||||
|
return steps(assert).then('I should find a file', function() {
|
||||||
|
assert.ok(true, this.step);
|
||||||
|
});
|
||||||
|
}
|
|
@ -85,10 +85,6 @@ const catalogFilter = searchBarFactory(freetextFilter, () =>
|
||||||
const aclFilter = searchBarFactory(freetextFilter, () =>
|
const aclFilter = searchBarFactory(freetextFilter, () =>
|
||||||
radiogroup('type', ['', 'management', 'client'])
|
radiogroup('type', ['', 'management', 'client'])
|
||||||
);
|
);
|
||||||
const intentionFilter = searchBarFactory(freetextFilter, () =>
|
|
||||||
radiogroup('currentFilter', ['', 'allow', 'deny'])
|
|
||||||
);
|
|
||||||
|
|
||||||
const policyForm = policyFormFactory(submitable, cancelable, radiogroup, text);
|
const policyForm = policyFormFactory(submitable, cancelable, radiogroup, text);
|
||||||
const policySelector = policySelectorFactory(clickable, deletable, collection, alias, policyForm);
|
const policySelector = policySelectorFactory(clickable, deletable, collection, alias, policyForm);
|
||||||
const roleForm = roleFormFactory(submitable, cancelable, policySelector);
|
const roleForm = roleFormFactory(submitable, cancelable, policySelector);
|
||||||
|
@ -172,7 +168,9 @@ export default {
|
||||||
token: create(
|
token: create(
|
||||||
token(visitable, submitable, deletable, cancelable, clickable, policySelector, roleSelector)
|
token(visitable, submitable, deletable, cancelable, clickable, policySelector, roleSelector)
|
||||||
),
|
),
|
||||||
intentions: create(intentions(visitable, creatable, consulIntentionList, intentionFilter)),
|
intentions: create(
|
||||||
|
intentions(visitable, creatable, clickable, consulIntentionList, popoverSelect)
|
||||||
|
),
|
||||||
intention: create(intention(visitable, submitable, deletable, cancelable)),
|
intention: create(intention(visitable, submitable, deletable, cancelable)),
|
||||||
nspaces: create(nspaces(visitable, creatable, consulNspaceList, freetextFilter)),
|
nspaces: create(nspaces(visitable, creatable, consulNspaceList, freetextFilter)),
|
||||||
nspace: create(
|
nspace: create(
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
export default function(visitable, creatable, intentions, filter) {
|
export default function(visitable, creatable, clickable, intentions, popoverSelect) {
|
||||||
return creatable({
|
return creatable({
|
||||||
visit: visitable('/:dc/intentions'),
|
visit: visitable('/:dc/intentions'),
|
||||||
intentions: intentions(),
|
intentions: intentions(),
|
||||||
filter: filter('[data-test-intention-filter]'),
|
sort: popoverSelect(),
|
||||||
|
create: clickable('[data-test-create]'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue