diff --git a/ui/src/__tests__/components/service/__snapshots__/ProviderTable.test.js.snap b/ui/src/__tests__/components/service/__snapshots__/ProviderTable.test.js.snap
index bd71c6b31b7..ab55b869174 100644
--- a/ui/src/__tests__/components/service/__snapshots__/ProviderTable.test.js.snap
+++ b/ui/src/__tests__/components/service/__snapshots__/ProviderTable.test.js.snap
@@ -71,10 +71,16 @@ exports[`ProviderTable should render 1`] = `
vertical-align: text-bottom;
}
+.emotion-17 {
+ text-align: left;
+ padding: 5px 0 5px 15px;
+ vertical-align: middle;
+}
+
@@ -147,7 +162,5 @@ exports[`ProviderTable should render error if allow api throws error 1`] = `
data-testid="error-message"
name="red600"
style="color: rgb(208, 17, 17); display: inline-block;"
->
- Failed to fetch template details.
-
+/>
`;
diff --git a/ui/src/__tests__/components/service/__snapshots__/ServiceList.test.js.snap b/ui/src/__tests__/components/service/__snapshots__/ServiceList.test.js.snap
index f136f7f918c..6146997a2a1 100644
--- a/ui/src/__tests__/components/service/__snapshots__/ServiceList.test.js.snap
+++ b/ui/src/__tests__/components/service/__snapshots__/ServiceList.test.js.snap
@@ -136,6 +136,7 @@ exports[`ServiceList should render add service modal after click 1`] = `
@@ -264,7 +265,7 @@ exports[`ServiceList should render add service modal after click 1`] = `
class="emotion-29"
data-testid="icon"
height="1.25em"
- id=""
+ id="openhouse-providers"
viewBox="0 0 1024 1024"
width="1.25em"
>
@@ -451,6 +452,7 @@ exports[`ServiceList should render delete service modal error(other) after click
@@ -579,7 +581,7 @@ exports[`ServiceList should render delete service modal error(other) after click
class="emotion-29"
data-testid="icon"
height="1.25em"
- id=""
+ id="openhouse-providers"
viewBox="0 0 1024 1024"
width="1.25em"
>
@@ -756,6 +758,7 @@ exports[`ServiceList should render delete service modal error(refresh) after cli
@@ -884,7 +887,7 @@ exports[`ServiceList should render delete service modal error(refresh) after cli
class="emotion-29"
data-testid="icon"
height="1.25em"
- id=""
+ id="openhouse-providers"
viewBox="0 0 1024 1024"
width="1.25em"
>
@@ -1061,6 +1064,7 @@ exports[`ServiceList should render serviceList again after cancel delete 1`] = `
@@ -1189,7 +1193,7 @@ exports[`ServiceList should render serviceList again after cancel delete 1`] = `
class="emotion-29"
data-testid="icon"
height="1.25em"
- id=""
+ id="openhouse-providers"
viewBox="0 0 1024 1024"
width="1.25em"
>
@@ -1344,6 +1348,7 @@ exports[`ServiceList should render serviceList again after confirm delete 1`] =
@@ -1525,6 +1530,7 @@ exports[`ServiceList should render with services 1`] = `
@@ -1653,7 +1659,7 @@ exports[`ServiceList should render with services 1`] = `
class="emotion-29"
data-testid="icon"
height="1.25em"
- id=""
+ id="openhouse-providers"
viewBox="0 0 1024 1024"
width="1.25em"
>
@@ -1808,6 +1814,7 @@ exports[`ServiceList should render without services 1`] = `
diff --git a/ui/src/__tests__/components/service/__snapshots__/ServiceRow.test.js.snap b/ui/src/__tests__/components/service/__snapshots__/ServiceRow.test.js.snap
index 91b2528fede..b781689f7ad 100644
--- a/ui/src/__tests__/components/service/__snapshots__/ServiceRow.test.js.snap
+++ b/ui/src/__tests__/components/service/__snapshots__/ServiceRow.test.js.snap
@@ -178,7 +178,7 @@ exports[`ServiceRow should render row 1`] = `
class="emotion-8"
data-testid="icon"
height="1.25em"
- id=""
+ id="serviceName-providers"
viewBox="0 0 1024 1024"
width="1.25em"
>
diff --git a/ui/src/__tests__/pages/domain/[domain]/__snapshots__/service.test.js.snap b/ui/src/__tests__/pages/domain/[domain]/__snapshots__/service.test.js.snap
index a87ecc08937..312aba3dbae 100644
--- a/ui/src/__tests__/pages/domain/[domain]/__snapshots__/service.test.js.snap
+++ b/ui/src/__tests__/pages/domain/[domain]/__snapshots__/service.test.js.snap
@@ -1361,6 +1361,7 @@ exports[`ServicePage should render 1`] = `
@@ -1489,7 +1490,7 @@ exports[`ServicePage should render 1`] = `
class="emotion-84"
data-testid="icon"
height="1.25em"
- id=""
+ id="bastion-providers"
viewBox="0 0 1024 1024"
width="1.25em"
>
@@ -1612,7 +1613,7 @@ exports[`ServicePage should render 1`] = `
class="emotion-84"
data-testid="icon"
height="1.25em"
- id=""
+ id="openhouse-providers"
viewBox="0 0 1024 1024"
width="1.25em"
>
diff --git a/ui/src/__tests__/spec/tests/services.spec.js b/ui/src/__tests__/spec/tests/services.spec.js
index 04b0bce1b22..8a7487db740 100644
--- a/ui/src/__tests__/spec/tests/services.spec.js
+++ b/ui/src/__tests__/spec/tests/services.spec.js
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+const serviceNameForProvidersTest = 'providers-error-test-service';
+
describe('services screen tests', () => {
it('when clicking help tooltip link, it should open a tab with athenz guide', async () => {
// open browser
@@ -81,4 +83,95 @@ describe('services screen tests', () => {
let modalDeleteButton = await $('button*=Delete');
await modalDeleteButton.click();
});
+
+ it('when clicking "Allow" button on a provider without having appropriate authorisation, the error should be displayed to the right of the button', async () => {
+ // open browser
+ await browser.newUser();
+ await browser.url(`/`);
+ // select domain
+ let domain = 'athenz.dev.functional-test';
+ let testDomain = await $(`a*=${domain}`);
+ await browser.waitUntil(async () => await testDomain.isClickable());
+ await testDomain.click();
+
+ // open Services
+ let servicesDiv = await $('div*=Services');
+ await servicesDiv.click();
+
+ // use date and time when creating a service because if we recreate service with same name - it will reference
+ // previous provider allowances
+ const now = new Date();
+ const year = now.getFullYear();
+ const month = String(now.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed
+ const day = String(now.getDate()).padStart(2, '0');
+ const hours = String(now.getHours()).padStart(2, '0');
+ const minutes = String(now.getMinutes()).padStart(2, '0');
+ const seconds = String(now.getSeconds()).padStart(2, '0');
+ const dateTimeFormatted = `${year}-${month}-${day}-${hours}-${minutes}-${seconds}`;
+
+ // add service
+ const serviceNameWithDate = `${serviceNameForProvidersTest}-${dateTimeFormatted}`;
+ let addServiceButton = await $('button*=Add Service');
+ await addServiceButton.click();
+ let serviceNameInput = await $('input[id="service-name"]');
+ await serviceNameInput.addValue(serviceNameWithDate);
+ let submitButton = await $('button*=Submit');
+ await submitButton.click();
+
+ // click Providers
+ let providersButton = await $(`.//*[local-name()="svg" and @id="${serviceNameWithDate + '-providers'}"]`);
+ await providersButton.click();
+
+ // click Azure provider
+ let awsProviderAllowButton = await $(`td[data-testid="provider-table"]`)
+ .$(`//td[text()="Azure VM launches instances for the service"]/following-sibling::td//button`);
+ await awsProviderAllowButton.click();
+
+ // warning should appear
+ let warning = await $(`td[data-testid="provider-table"]`)
+ .$(`//td[text()="Azure VM launches instances for the service"]/following-sibling::td//div[text()="Status: 404. Message: unknown domain - athenz.azure.provider"]`);
+ await expect(warning).toHaveText('Status: 404. Message: unknown domain - athenz.azure.provider');
+ });
+
+ // after - runs after the last test in order of declaration
+ after(async() => {
+ // open browser
+ await browser.newUser();
+ await browser.url(`/`);
+ // select domain
+ let domain = 'athenz.dev.functional-test';
+ let testDomain = await $(`a*=${domain}`);
+ await browser.waitUntil(async () => await testDomain.isClickable());
+ await testDomain.click();
+
+ // open Services
+ let servicesDiv = await $('div*=Services');
+ await servicesDiv.click();
+
+ // wait until services table is populated with services
+ await browser.waitUntil(async () => {
+ const table = await $('//table[@id="services-table"]')
+ const rows = await table.$$('tr');
+ return rows.length > 0;
+ }, {
+ timeout: 1000,
+ timeoutMsg: `Services table did not have a service containing ${serviceNameForProvidersTest}.`
+ });
+
+ // get all the services created during the test
+ let deleteButtons = await $$(`[id*="delete-service-${serviceNameForProvidersTest}"]`);
+
+ // iteratively get delete buttons, pick only ones that match our ID and delete these
+ for (let i = 0; i < await deleteButtons.length; i++) {
+ const deleteButton = deleteButtons[i];
+ const id = await deleteButton.getAttribute('id');
+ await deleteButton.click();
+ let deleteButtonOnModal = await $('button*=Delete');
+ await deleteButtonOnModal.click();
+ // wait until the notification about successful deletion disappears - so that next deletion can be done
+ let deletedDiv = await $('div*=Successfully deleted service');
+ await deletedDiv.waitForDisplayed({ reverse: true, timeout: 10000 });
+ console.log("DELETED SERVICE", id)
+ }
+ });
})
diff --git a/ui/src/components/service/ProviderTable.js b/ui/src/components/service/ProviderTable.js
index cd2b3aab02d..14865e9f469 100644
--- a/ui/src/components/service/ProviderTable.js
+++ b/ui/src/components/service/ProviderTable.js
@@ -59,6 +59,12 @@ const TableHeadStyledRight = styled.th`
border-right: none;
`;
+const TableHeadStyledError = styled.th`
+ padding-bottom: 5px;
+ padding: 5px 0 5px 15px;
+ border-right: none;
+`;
+
const TdStyled = styled.td`
padding: 20px;
text-align: left;
@@ -80,6 +86,12 @@ const ProviderTd = styled.td`
word-break: break-all;
`;
+const ErrorTd = styled.td`
+ text-align: left;
+ padding: 5px 0 5px 15px;
+ vertical-align: middle;
+`;
+
const AllowTd = styled.td`
text-align: left;
padding: 5px 0 5px 15px;
@@ -96,6 +108,7 @@ class ProviderTable extends React.Component {
constructor(props) {
super(props);
this.state = {
+ providerWithError: null,
errorMessage: null,
};
}
@@ -107,9 +120,12 @@ class ProviderTable extends React.Component {
this.props.service,
provider,
this.props._csrf
- )
+ ).then((data) => {
+ this.setState({ providerWithError: '' });
+ })
.catch((err) => {
this.setState({
+ providerWithError: provider,
errorMessage: RequestUtils.xhrErrorCheckHelper(err),
});
});
@@ -117,72 +133,56 @@ class ProviderTable extends React.Component {
render() {
let providerContent = [];
- if (this.state.errorMessage) {
+ providerContent = this.props.allProviders.map((provider) => {
return (
-
-
- Failed to fetch template details.
-
-
+
+ {provider.name}
+
+ {this.props.provider[provider.id] === 'allow' ? (
+
+
+
+ ) : (
+
+ )}
+
+
+
+ {
+ provider.id === this.state.providerWithError ? this.state.errorMessage : ''
+ }
+
+
+
);
- } else {
- providerContent = this.props.allProviders.map((provider) => {
- // if (this.props.provider[provider.id] === 'allow') {
- return (
-
- {provider.name}
-
- {this.props.provider[provider.id] === 'allow' ? (
-
-
-
- ) : (
-
- )}
-
-
- );
- // } else if (this.props.provider[provider.id] === 'not') {
- // let onAllow = this.onAllow.bind(this, provider.id);
- // return (
- //
- // {provider.name}
- //
- //
- // );
- // }
- // });
- });
- }
+ });
return (
- {this.state.errorMessage && (
-
- {this.state.errorMessage}
-
- )}
Provider
Status
+ { this.state.errorMessage ?
+ : ''
+ }
{providerContent}
diff --git a/ui/src/components/service/ServiceList.js b/ui/src/components/service/ServiceList.js
index d6ce6392bbe..70018f844a6 100644
--- a/ui/src/components/service/ServiceList.js
+++ b/ui/src/components/service/ServiceList.js
@@ -223,7 +223,9 @@ class ServiceList extends React.Component {
{addService}
-
+
diff --git a/ui/src/components/service/ServiceRow.js b/ui/src/components/service/ServiceRow.js
index e5ebe432eab..539082851a4 100644
--- a/ui/src/components/service/ServiceRow.js
+++ b/ui/src/components/service/ServiceRow.js
@@ -174,6 +174,7 @@ class ServiceRow extends React.Component {
|