ui: Intention "Action change" warning modal (#9108)
* ui: Add a warning dialog if you go to remove permissions from an intention * ui: Move modal styles next to component, add warning style * ui: Move back to using the input name for a selector * ui: Fixup negative "isn't" step so its optional * Add warning modal to pageobject * Fixup test for whether to show the warning modal or not * Intention change action warning acceptence test * Add a null/undefined Action
This commit is contained in:
parent
137f7d0a92
commit
1b042943e9
|
@ -1,3 +1,7 @@
|
||||||
|
<div
|
||||||
|
class="consul-intention"
|
||||||
|
...attributes
|
||||||
|
>
|
||||||
<DataForm
|
<DataForm
|
||||||
@type="intention"
|
@type="intention"
|
||||||
@dc={{@dc}}
|
@dc={{@dc}}
|
||||||
|
@ -27,9 +31,46 @@ as |api|>
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
|
|
||||||
<BlockSlot @name="form">
|
<BlockSlot @name="form">
|
||||||
|
|
||||||
{{#let api.data as |item|}}
|
{{#let api.data as |item|}}
|
||||||
{{#if item.IsEditable}}
|
{{#if item.IsEditable}}
|
||||||
|
|
||||||
|
{{#if this.warn}}
|
||||||
|
{{#let (changeset-get item 'Action') as |newAction|}}
|
||||||
|
<ModalDialog
|
||||||
|
class="consul-intention-action-warn-modal warning"
|
||||||
|
data-test-action-warning
|
||||||
|
@onclose={{action (mut this.warn) false}}
|
||||||
|
>
|
||||||
|
<BlockSlot @name="header">
|
||||||
|
<h2>Set intention to {{newAction}}?</h2>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="body">
|
||||||
|
<p>
|
||||||
|
When you change this Intention to {{newAction}}, you will remove all the L7 policy permissions currently saved to this Intention. Are you sure you want to set it to {{newAction}}?
|
||||||
|
</p>
|
||||||
|
</BlockSlot>
|
||||||
|
<BlockSlot @name="actions" as |close|>
|
||||||
|
<button
|
||||||
|
data-test-action-warning-confirm
|
||||||
|
type="button"
|
||||||
|
class="dangerous"
|
||||||
|
{{on 'click' api.submit}}
|
||||||
|
>
|
||||||
|
Set to {{capitalize newAction}}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
data-test-action-warning-cancel
|
||||||
|
type="button"
|
||||||
|
class="type-cancel"
|
||||||
|
onclick={{close}}
|
||||||
|
>
|
||||||
|
No, Cancel
|
||||||
|
</button>
|
||||||
|
</BlockSlot>
|
||||||
|
</ModalDialog>
|
||||||
|
{{/let}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<DataSource
|
<DataSource
|
||||||
@src={{concat '/' @nspace '/' @dc '/services'}}
|
@src={{concat '/' @nspace '/' @dc '/services'}}
|
||||||
@onchange={{action this.createServices item}}
|
@onchange={{action this.createServices item}}
|
||||||
|
@ -43,7 +84,9 @@ as |api|>
|
||||||
{{#if (and api.isCreate this.isManagedByCRDs)}}
|
{{#if (and api.isCreate this.isManagedByCRDs)}}
|
||||||
<Consul::Intention::Notice::CustomResource @type="warning" />
|
<Consul::Intention::Notice::CustomResource @type="warning" />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<form onsubmit={{action api.submit}}>
|
<form
|
||||||
|
{{on 'submit' (fn this.submit item api.submit)}}
|
||||||
|
>
|
||||||
<Consul::Intention::Form::Fieldsets
|
<Consul::Intention::Form::Fieldsets
|
||||||
@nspaces={{this.nspaces}}
|
@nspaces={{this.nspaces}}
|
||||||
@services={{this.services}}
|
@services={{this.services}}
|
||||||
|
@ -127,3 +170,4 @@ as |api|>
|
||||||
|
|
||||||
</BlockSlot>
|
</BlockSlot>
|
||||||
</DataForm>
|
</DataForm>
|
||||||
|
</div>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { action } from '@ember/object';
|
||||||
import { tracked } from '@glimmer/tracking';
|
import { tracked } from '@glimmer/tracking';
|
||||||
|
|
||||||
export default class ConsulIntentionForm extends Component {
|
export default class ConsulIntentionForm extends Component {
|
||||||
|
|
||||||
@tracked services;
|
@tracked services;
|
||||||
@tracked SourceName;
|
@tracked SourceName;
|
||||||
@tracked DestinationName;
|
@tracked DestinationName;
|
||||||
|
@ -15,6 +14,8 @@ export default class ConsulIntentionForm extends Component {
|
||||||
|
|
||||||
@tracked isManagedByCRDs;
|
@tracked isManagedByCRDs;
|
||||||
|
|
||||||
|
@tracked warn = false;
|
||||||
|
|
||||||
@service('repository/intention') repo;
|
@service('repository/intention') repo;
|
||||||
|
|
||||||
constructor(owner, args) {
|
constructor(owner, args) {
|
||||||
|
@ -23,7 +24,7 @@ export default class ConsulIntentionForm extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
ondelete() {
|
ondelete() {
|
||||||
if(this.args.ondelete) {
|
if (this.args.ondelete) {
|
||||||
this.args.ondelete(...arguments);
|
this.args.ondelete(...arguments);
|
||||||
} else {
|
} else {
|
||||||
this.onsubmit(...arguments);
|
this.onsubmit(...arguments);
|
||||||
|
@ -31,7 +32,7 @@ export default class ConsulIntentionForm extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
oncancel() {
|
oncancel() {
|
||||||
if(this.args.oncancel) {
|
if (this.args.oncancel) {
|
||||||
this.args.oncancel(...arguments);
|
this.args.oncancel(...arguments);
|
||||||
} else {
|
} else {
|
||||||
this.onsubmit(...arguments);
|
this.onsubmit(...arguments);
|
||||||
|
@ -39,7 +40,7 @@ export default class ConsulIntentionForm extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
onsubmit() {
|
onsubmit() {
|
||||||
if(this.args.onsubmit) {
|
if (this.args.onsubmit) {
|
||||||
this.args.onsubmit(...arguments);
|
this.args.onsubmit(...arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,9 +49,19 @@ export default class ConsulIntentionForm extends Component {
|
||||||
updateCRDManagement() {
|
updateCRDManagement() {
|
||||||
this.isManagedByCRDs = this.repo.isManagedByCRDs();
|
this.isManagedByCRDs = this.repo.isManagedByCRDs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
createServices (item, e) {
|
submit(item, submit, e) {
|
||||||
|
e.preventDefault();
|
||||||
|
// if the action of the intention has changed and its non-empty then warn
|
||||||
|
// the user
|
||||||
|
if (typeof item.change.Action !== 'undefined' && typeof item.data.Action === 'undefined') {
|
||||||
|
this.warn = true;
|
||||||
|
} else {
|
||||||
|
submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@action
|
||||||
|
createServices(item, e) {
|
||||||
// Services in the menus should:
|
// Services in the menus should:
|
||||||
// 1. Be unique (they potentially could be duplicated due to services from different namespaces)
|
// 1. Be unique (they potentially could be duplicated due to services from different namespaces)
|
||||||
// 2. Only include services that shold have intentions
|
// 2. Only include services that shold have intentions
|
||||||
|
@ -59,9 +70,7 @@ export default class ConsulIntentionForm extends Component {
|
||||||
let items = e.data
|
let items = e.data
|
||||||
.uniqBy('Name')
|
.uniqBy('Name')
|
||||||
.toArray()
|
.toArray()
|
||||||
.filter(
|
.filter(item => !['connect-proxy', 'mesh-gateway', 'terminating-gateway'].includes(item.Kind))
|
||||||
item => !['connect-proxy', 'mesh-gateway', 'terminating-gateway'].includes(item.Kind)
|
|
||||||
)
|
|
||||||
.sort((a, b) => a.Name.localeCompare(b.Name));
|
.sort((a, b) => a.Name.localeCompare(b.Name));
|
||||||
items = [{ Name: '*' }].concat(items);
|
items = [{ Name: '*' }].concat(items);
|
||||||
let source = items.findBy('Name', item.SourceName);
|
let source = items.findBy('Name', item.SourceName);
|
||||||
|
@ -80,7 +89,7 @@ export default class ConsulIntentionForm extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
createNspaces (item, e) {
|
createNspaces(item, e) {
|
||||||
// Nspaces in the menus should:
|
// Nspaces in the menus should:
|
||||||
// 1. Include an 'All Namespaces' option
|
// 1. Include an 'All Namespaces' option
|
||||||
// 2. Include the current SourceNS and DestinationNS incase they don't exist yet
|
// 2. Include the current SourceNS and DestinationNS incase they don't exist yet
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
.consul-intention-action-warn-modal {
|
||||||
|
.modal-dialog-window {
|
||||||
|
max-width: 450px;
|
||||||
|
}
|
||||||
|
.modal-dialog-body p {
|
||||||
|
font-size: $typo-size-600;
|
||||||
|
}
|
||||||
|
button.dangerous {
|
||||||
|
@extend %dangerous-button;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
@import './search-bar';
|
@import './search-bar';
|
||||||
@import './list';
|
@import './list';
|
||||||
|
@import './form';
|
||||||
@import './form/fieldsets';
|
@import './form/fieldsets';
|
||||||
@import './permission/list';
|
@import './permission/list';
|
||||||
@import './permission/form';
|
@import './permission/form';
|
||||||
|
|
|
@ -1,28 +1,44 @@
|
||||||
{{on-window 'resize' (action "resize") }}
|
{{on-window 'resize' (action "resize") }}
|
||||||
<Portal @target="modal">
|
<Portal @target="modal">
|
||||||
{{yield}}
|
{{yield}}
|
||||||
<div {{ref this 'modal'}} ...attributes>
|
<div
|
||||||
<input id={{name}} type="radio" name="modal" data-checked="{{checked}}" checked={{checked}} onchange={{action 'change'}} />
|
class="modal-dialog"
|
||||||
<div role="dialog" aria-modal="true">
|
{{ref this 'modal'}}
|
||||||
|
...attributes
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="modal-dialog-control"
|
||||||
|
id={{name}}
|
||||||
|
type="radio"
|
||||||
|
name="modal"
|
||||||
|
data-checked="{{checked}}"
|
||||||
|
checked={{checked}}
|
||||||
|
onchange={{action 'change'}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="modal-dialog-modal"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
>
|
||||||
<label for="modal_close"></label>
|
<label for="modal_close"></label>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div class="modal-dialog-window">
|
||||||
<header>
|
<header class="modal-dialog-header">
|
||||||
<label for="modal_close">Close</label>
|
<label for="modal_close"></label>
|
||||||
<YieldSlot @name="header">
|
<YieldSlot @name="header">
|
||||||
{{yield (hash
|
{{yield (hash
|
||||||
close=(action "close")
|
close=(action "close")
|
||||||
)}}
|
)}}
|
||||||
</YieldSlot>
|
</YieldSlot>
|
||||||
</header>
|
</header>
|
||||||
<div>
|
<div class="modal-dialog-body">
|
||||||
<YieldSlot @name="body">
|
<YieldSlot @name="body">
|
||||||
{{yield (hash
|
{{yield (hash
|
||||||
close=(action "close")
|
close=(action "close")
|
||||||
)}}
|
)}}
|
||||||
</YieldSlot>
|
</YieldSlot>
|
||||||
</div>
|
</div>
|
||||||
<footer>
|
<footer class="modal-dialog-footer">
|
||||||
<YieldSlot @name="actions" @params={{block-params (action "close")}}>
|
<YieldSlot @name="actions" @params={{block-params (action "close")}}>
|
||||||
{{yield (hash
|
{{yield (hash
|
||||||
close=(action "close")
|
close=(action "close")
|
||||||
|
|
|
@ -19,7 +19,7 @@ export default Component.extend(Slotted, {
|
||||||
set(this, 'checked', true);
|
set(this, 'checked', true);
|
||||||
if (this.height === null) {
|
if (this.height === null) {
|
||||||
if (this.element) {
|
if (this.element) {
|
||||||
const dialogPanel = this.dom.element('[role="dialog"] > div > div', this.modal);
|
const dialogPanel = this.dom.element('.modal-dialog-window', this.modal);
|
||||||
const rect = dialogPanel.getBoundingClientRect();
|
const rect = dialogPanel.getBoundingClientRect();
|
||||||
set(this, 'dialog', dialogPanel);
|
set(this, 'dialog', dialogPanel);
|
||||||
set(this, 'height', rect.height);
|
set(this, 'height', rect.height);
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
@import './skin';
|
||||||
|
@import './layout';
|
||||||
|
.modal-dialog-modal {
|
||||||
|
@extend %modal-dialog;
|
||||||
|
}
|
||||||
|
input[name='modal'] {
|
||||||
|
@extend %modal-control;
|
||||||
|
}
|
||||||
|
html.template-with-modal {
|
||||||
|
@extend %with-modal;
|
||||||
|
}
|
||||||
|
%modal-dialog table {
|
||||||
|
min-height: 149px;
|
||||||
|
}
|
|
@ -70,6 +70,7 @@
|
||||||
%modal-window > header [for='modal_close'] {
|
%modal-window > header [for='modal_close'] {
|
||||||
float: right;
|
float: right;
|
||||||
text-indent: -9000px;
|
text-indent: -9000px;
|
||||||
width: 23px;
|
width: 24px;
|
||||||
height: 23px;
|
height: 24px;
|
||||||
|
margin-top: -3px;
|
||||||
}
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
.modal-dialog.warning header {
|
||||||
|
background-color: $yellow-050;
|
||||||
|
border-color: $yellow-500;
|
||||||
|
color: $yellow-800;
|
||||||
|
}
|
||||||
|
.modal-dialog.warning header > *:not(label) {
|
||||||
|
font-size: $typo-size-500;
|
||||||
|
font-weight: $typo-weight-semibold;
|
||||||
|
}
|
||||||
|
.modal-dialog.warning header::before {
|
||||||
|
@extend %with-alert-triangle-mask, %as-pseudo;
|
||||||
|
color: $yellow-500;
|
||||||
|
float: left;
|
||||||
|
margin-top: 2px;
|
||||||
|
margin-right: 3px;
|
||||||
|
}
|
||||||
|
%modal-dialog > label {
|
||||||
|
background-color: rgba($white, 0.9);
|
||||||
|
}
|
||||||
|
%modal-window {
|
||||||
|
box-shadow: $decor-elevation-800;
|
||||||
|
}
|
||||||
|
%modal-window {
|
||||||
|
/*%frame-gray-000*/
|
||||||
|
background-color: $white;
|
||||||
|
}
|
||||||
|
%modal-window > footer,
|
||||||
|
%modal-window > header {
|
||||||
|
@extend %frame-gray-800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-dialog-body,
|
||||||
|
%modal-window > footer,
|
||||||
|
%modal-window > header {
|
||||||
|
border-color: $gray-300;
|
||||||
|
}
|
||||||
|
.modal-dialog-body {
|
||||||
|
border-style: solid;
|
||||||
|
border-left-width: 1px;
|
||||||
|
border-right-width: 1px;
|
||||||
|
}
|
||||||
|
%modal-window > footer,
|
||||||
|
%modal-window > header {
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
%modal-window > header [for='modal_close'] {
|
||||||
|
@extend %with-cancel-plain-icon;
|
||||||
|
cursor: pointer;
|
||||||
|
border: $decor-border-100;
|
||||||
|
/*%frame-gray-050??*/
|
||||||
|
background-color: $gray-050;
|
||||||
|
border-color: $gray-300;
|
||||||
|
border-radius: $decor-radius-100;
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import Serializer from './application';
|
||||||
import { inject as service } from '@ember/service';
|
import { inject as service } from '@ember/service';
|
||||||
import { get } from '@ember/object';
|
import { get } from '@ember/object';
|
||||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/intention';
|
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/intention';
|
||||||
|
import removeNull from 'consul-ui/utils/remove-null';
|
||||||
|
|
||||||
export default Serializer.extend({
|
export default Serializer.extend({
|
||||||
primaryKey: PRIMARY_KEY,
|
primaryKey: PRIMARY_KEY,
|
||||||
|
@ -28,7 +29,7 @@ export default Serializer.extend({
|
||||||
respond((headers, body) => {
|
respond((headers, body) => {
|
||||||
return cb(
|
return cb(
|
||||||
headers,
|
headers,
|
||||||
body.map(item => this.ensureID(item))
|
body.map(item => this.ensureID(removeNull(item)))
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
query
|
query
|
||||||
|
@ -38,7 +39,7 @@ export default Serializer.extend({
|
||||||
return this._super(
|
return this._super(
|
||||||
cb =>
|
cb =>
|
||||||
respond((headers, body) => {
|
respond((headers, body) => {
|
||||||
body = this.ensureID(body);
|
body = this.ensureID(removeNull(body));
|
||||||
return cb(headers, body);
|
return cb(headers, body);
|
||||||
}),
|
}),
|
||||||
query
|
query
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
@import './form-elements/index';
|
@import './form-elements/index';
|
||||||
@import './inline-alert/index';
|
@import './inline-alert/index';
|
||||||
@import './menu-panel/index';
|
@import './menu-panel/index';
|
||||||
@import './modal-dialog/index';
|
|
||||||
@import './pill/index';
|
@import './pill/index';
|
||||||
@import './popover-menu/index';
|
@import './popover-menu/index';
|
||||||
@import './radio-group/index';
|
@import './radio-group/index';
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
@import './skin';
|
|
||||||
@import './layout';
|
|
|
@ -1,32 +0,0 @@
|
||||||
%modal-dialog > label {
|
|
||||||
background-color: rgba($white, 0.9);
|
|
||||||
}
|
|
||||||
%modal-window {
|
|
||||||
box-shadow: $decor-elevation-800;
|
|
||||||
}
|
|
||||||
%modal-window {
|
|
||||||
/*%frame-gray-000*/
|
|
||||||
background-color: $white;
|
|
||||||
border: $decor-border-100;
|
|
||||||
border-color: $gray-300;
|
|
||||||
}
|
|
||||||
%modal-window > footer,
|
|
||||||
%modal-window > header {
|
|
||||||
@extend %frame-gray-800;
|
|
||||||
}
|
|
||||||
%modal-window > footer {
|
|
||||||
border-top-width: 1px;
|
|
||||||
}
|
|
||||||
%modal-window > header {
|
|
||||||
border-bottom-width: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
%modal-window > header [for='modal_close'] {
|
|
||||||
@extend %with-cancel-plain-icon;
|
|
||||||
cursor: pointer;
|
|
||||||
border: $decor-border-100;
|
|
||||||
/*%frame-gray-050??*/
|
|
||||||
background-color: $gray-050;
|
|
||||||
border-color: $gray-300;
|
|
||||||
border-radius: $decor-radius-100;
|
|
||||||
}
|
|
|
@ -26,7 +26,6 @@
|
||||||
@import './components/flash-message';
|
@import './components/flash-message';
|
||||||
@import './components/code-editor';
|
@import './components/code-editor';
|
||||||
@import './components/confirmation-dialog';
|
@import './components/confirmation-dialog';
|
||||||
@import './components/modal-dialog';
|
|
||||||
@import './components/auth-form';
|
@import './components/auth-form';
|
||||||
@import './components/auth-modal';
|
@import './components/auth-modal';
|
||||||
@import './components/oidc-select';
|
@import './components/oidc-select';
|
||||||
|
@ -55,6 +54,7 @@
|
||||||
/**/
|
/**/
|
||||||
|
|
||||||
@import 'consul-ui/components/notice';
|
@import 'consul-ui/components/notice';
|
||||||
|
@import 'consul-ui/components/modal-dialog';
|
||||||
|
|
||||||
@import 'consul-ui/components/consul/exposed-path/list';
|
@import 'consul-ui/components/consul/exposed-path/list';
|
||||||
@import 'consul-ui/components/consul/external-source';
|
@import 'consul-ui/components/consul/external-source';
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
%auth-modal footer {
|
%auth-modal footer {
|
||||||
border: 0;
|
border-top: 0;
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
margin: 0px 26px;
|
padding-left: 42px;
|
||||||
|
padding-right: 42px;
|
||||||
}
|
}
|
||||||
%auth-modal footer {
|
%auth-modal footer {
|
||||||
background-color: $transparent;
|
background-color: $transparent;
|
||||||
|
|
|
@ -4,6 +4,12 @@ label span {
|
||||||
.has-error {
|
.has-error {
|
||||||
@extend %form-element-error;
|
@extend %form-element-error;
|
||||||
}
|
}
|
||||||
|
// TODO: float right here is too specific, this is currently used just for the role/policy selectors
|
||||||
|
label.type-dialog {
|
||||||
|
@extend %anchor;
|
||||||
|
cursor: pointer;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
.type-toggle {
|
.type-toggle {
|
||||||
@extend %form-element, %sliding-toggle;
|
@extend %form-element, %sliding-toggle;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
[role='dialog'] {
|
|
||||||
@extend %modal-dialog;
|
|
||||||
}
|
|
||||||
input[name='modal'] {
|
|
||||||
@extend %modal-control;
|
|
||||||
}
|
|
||||||
html.template-with-modal {
|
|
||||||
@extend %with-modal;
|
|
||||||
}
|
|
||||||
%modal-dialog table {
|
|
||||||
min-height: 149px;
|
|
||||||
}
|
|
||||||
// TODO: float right here is too specific, this is currently used just for the role/policy selectors
|
|
||||||
label.type-dialog {
|
|
||||||
@extend %anchor;
|
|
||||||
cursor: pointer;
|
|
||||||
float: right;
|
|
||||||
}
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
@setupApplicationTest
|
||||||
|
Feature: dc / intentions / permissions / warn: Intention Permission Warn
|
||||||
|
Scenario:
|
||||||
|
Given 1 datacenter model with the value "datacenter"
|
||||||
|
And 1 intention model from yaml
|
||||||
|
---
|
||||||
|
SourceNS: default
|
||||||
|
SourceName: web
|
||||||
|
DestinationNS: default
|
||||||
|
DestinationName: db
|
||||||
|
Action: ~
|
||||||
|
Permissions:
|
||||||
|
- Action: allow
|
||||||
|
HTTP:
|
||||||
|
PathExact: /path
|
||||||
|
---
|
||||||
|
When I visit the intention page for yaml
|
||||||
|
---
|
||||||
|
dc: datacenter
|
||||||
|
intention: intention-id
|
||||||
|
---
|
||||||
|
Then the url should be /datacenter/intentions/intention-id
|
||||||
|
And I click "[value='deny']"
|
||||||
|
And I submit
|
||||||
|
And the warning object is present
|
||||||
|
And I click the warning.cancel object
|
||||||
|
And the warning object isn't present
|
||||||
|
And I submit
|
||||||
|
And the warning object is present
|
||||||
|
And I click the warning.confirm object
|
||||||
|
Then a PUT request was made to "/v1/connect/intentions/exact?source=default%2Fweb&destination=default%2Fdb&dc=datacenter" from yaml
|
|
@ -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);
|
||||||
|
});
|
||||||
|
}
|
|
@ -94,7 +94,13 @@ const morePopoverMenu = morePopoverMenuFactory(clickable);
|
||||||
const popoverSelect = popoverSelectFactory(clickable, collection);
|
const popoverSelect = popoverSelectFactory(clickable, collection);
|
||||||
const emptyState = emptyStateFactory(isPresent);
|
const emptyState = emptyStateFactory(isPresent);
|
||||||
|
|
||||||
const consulIntentionList = consulIntentionListFactory(collection, clickable, attribute, isPresent, deletable);
|
const consulIntentionList = consulIntentionListFactory(
|
||||||
|
collection,
|
||||||
|
clickable,
|
||||||
|
attribute,
|
||||||
|
isPresent,
|
||||||
|
deletable
|
||||||
|
);
|
||||||
const consulNspaceList = consulNspaceListFactory(
|
const consulNspaceList = consulNspaceListFactory(
|
||||||
collection,
|
collection,
|
||||||
clickable,
|
clickable,
|
||||||
|
@ -176,6 +182,7 @@ export default {
|
||||||
intention(
|
intention(
|
||||||
visitable,
|
visitable,
|
||||||
clickable,
|
clickable,
|
||||||
|
isPresent,
|
||||||
submitable,
|
submitable,
|
||||||
deletable,
|
deletable,
|
||||||
cancelable,
|
cancelable,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
export default function(
|
export default function(
|
||||||
visitable,
|
visitable,
|
||||||
clickable,
|
clickable,
|
||||||
|
isPresent,
|
||||||
submitable,
|
submitable,
|
||||||
deletable,
|
deletable,
|
||||||
cancelable,
|
cancelable,
|
||||||
|
@ -18,6 +19,19 @@ export default function(
|
||||||
form: permissionsForm(),
|
form: permissionsForm(),
|
||||||
list: permissionsList(),
|
list: permissionsList(),
|
||||||
},
|
},
|
||||||
|
warning: {
|
||||||
|
scope: '[data-test-action-warning]',
|
||||||
|
resetScope: true,
|
||||||
|
present: isPresent(),
|
||||||
|
confirm: {
|
||||||
|
scope: '[data-test-action-warning-confirm]',
|
||||||
|
click: clickable(),
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
scope: '[data-test-action-warning-cancel]',
|
||||||
|
click: clickable(),
|
||||||
|
},
|
||||||
|
},
|
||||||
...submitable(),
|
...submitable(),
|
||||||
...cancelable(),
|
...cancelable(),
|
||||||
...deletable(),
|
...deletable(),
|
||||||
|
|
|
@ -47,7 +47,7 @@ export default function(scenario, assert, find, currentPage, $) {
|
||||||
setTimeout(() => next());
|
setTimeout(() => next());
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then(`the $pageObject object is(n't) $state`, function(element, negative, state, next) {
|
.then(`the $pageObject object is(n't)? $state`, function(element, negative, state, next) {
|
||||||
assert[negative ? 'notOk' : 'ok'](element[state]);
|
assert[negative ? 'notOk' : 'ok'](element[state]);
|
||||||
setTimeout(() => next());
|
setTimeout(() => next());
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue