diff --git a/components/automate-ui/src/app/modules/infra-proxy/create-data-bag-modal/create-data-bag-modal.component.html b/components/automate-ui/src/app/modules/infra-proxy/create-data-bag-modal/create-data-bag-modal.component.html index 444c0dabd25..87659bb2d33 100644 --- a/components/automate-ui/src/app/modules/infra-proxy/create-data-bag-modal/create-data-bag-modal.component.html +++ b/components/automate-ui/src/app/modules/infra-proxy/create-data-bag-modal/create-data-bag-modal.component.html @@ -6,7 +6,8 @@

Create Data Bag

@@ -23,8 +24,10 @@

Create Data Bag

- Cancel - + Cancel + Create Creating Data Bag... diff --git a/components/automate-ui/src/app/modules/infra-proxy/data-bags-list/data-bags-list.component.html b/components/automate-ui/src/app/modules/infra-proxy/data-bags-list/data-bags-list.component.html index 2dff4595d6e..4b11379532e 100644 --- a/components/automate-ui/src/app/modules/infra-proxy/data-bags-list/data-bags-list.component.html +++ b/components/automate-ui/src/app/modules/infra-proxy/data-bags-list/data-bags-list.component.html @@ -15,20 +15,21 @@ [org_Id]="orgId"> - - - - Create Data Bag - - - - + +
+ + + Create Data Bag +
+ + + - Name + Name - + {{ dataBag.name }} @@ -38,12 +39,23 @@ + + + {{ dataBag.name }} + + + Delete + + + +
-
+
No preview -

No Data Bags available.

+

No results found for "{{searchValue}}".

+

No Data Bags available.

diff --git a/components/automate-ui/src/app/modules/infra-proxy/data-bags-list/data-bags-list.component.scss b/components/automate-ui/src/app/modules/infra-proxy/data-bags-list/data-bags-list.component.scss index ba6b09fe9e2..70a21970073 100644 --- a/components/automate-ui/src/app/modules/infra-proxy/data-bags-list/data-bags-list.component.scss +++ b/components/automate-ui/src/app/modules/infra-proxy/data-bags-list/data-bags-list.component.scss @@ -13,7 +13,6 @@ chef-loading-spinner { img { margin-top: 130px; - margin-left: 130PX; width: 70px; } @@ -25,3 +24,29 @@ chef-toolbar chef-button:first-child { margin: 10px 0px 0px 0px; float: right; } + +.search-create-container { + display: flex; + margin: 24px 0 18px; + flex-direction: row; + + app-infra-search-bar { + flex-grow: 2; + } + + chef-button { + margin: 0; + margin-left: 16px; + height: 36px; + } +} + +.full-screen-spinner { + display: flex; + margin: auto; + margin-top: 238px; + background-color: $chef-white; + opacity: 0.7; + width: initial; + height: 100%; +} diff --git a/components/automate-ui/src/app/modules/infra-proxy/data-bags-list/data-bags-list.component.ts b/components/automate-ui/src/app/modules/infra-proxy/data-bags-list/data-bags-list.component.ts index 2e45dd23246..f3513cb038a 100644 --- a/components/automate-ui/src/app/modules/infra-proxy/data-bags-list/data-bags-list.component.ts +++ b/components/automate-ui/src/app/modules/infra-proxy/data-bags-list/data-bags-list.component.ts @@ -31,6 +31,10 @@ export class DataBagsListComponent implements OnInit, OnDestroy { public dataBagsListLoading = true; public dataBagToDelete: DataBag; public deleteModalVisible = false; + public searchValue = ''; + public searchFlag = false; + public searching = false; + public serachArr: DataBag[]; public openDataBagModal = new EventEmitter(); private isDestroyed = new Subject(); @@ -99,4 +103,20 @@ export class DataBagsListComponent implements OnInit, OnDestroy { public openCreateModal(): void { this.openDataBagModal.emit(); } + + public searchDataBags(searchText: string): void { + this.searching = true; + this.searchValue = searchText; + if (!this.dataBags || !searchText) { + this.searchFlag = false; + } else { + this.serachArr = this.dataBags.filter((key) => { + this.searchFlag = true; + if (key) { + return key.name.includes(searchText); + } + }); + } + this.searching = false; + } } diff --git a/e2e/cypress/integration/ui/infra-proxy/infra-databags.spec.ts b/e2e/cypress/integration/ui/infra-proxy/infra-databags.spec.ts new file mode 100644 index 00000000000..43fe1fba7e0 --- /dev/null +++ b/e2e/cypress/integration/ui/infra-proxy/infra-databags.spec.ts @@ -0,0 +1,232 @@ +describe('infra databag', () => { + const now = Cypress.moment().format('MMDDYYhhmmss'); + const cypressPrefix = 'infra'; + let adminIdToken = ''; + const serverID = 'chef-server-dev-test'; + const serverName = 'chef server dev'; + const orgID = 'chef-org-dev'; + const orgName = '4thcoffee'; + const serverFQDN = 'ec2-34-219-25-251.us-west-2.compute.amazonaws.com'; + const serverIP = '34.219.25.251'; + const adminUser = 'chefadmin'; + const adminKey = Cypress.env('AUTOMATE_INFRA_ADMIN_KEY').replace(/\\n/g, '\n'); + const databagName = `${cypressPrefix}-databag-${now}-1`; + + before(() => { + cy.adminLogin('/').then(() => { + const admin = JSON.parse(localStorage.getItem('chef-automate-user')); + adminIdToken = admin.id_token; + + cy.request({ + auth: { bearer: adminIdToken }, + failOnStatusCode: false, + method: 'POST', + url: '/api/v0/infra/servers', + body: { + id: serverID, + name: serverName, + fqdn: serverFQDN, + ip_address: serverIP + } + }).then((resp) => { + if (resp.status === 200 && resp.body.ok === true) { + return; + } else { + cy.request({ + auth: { bearer: adminIdToken }, + method: 'GET', + url: `/api/v0/infra/servers/${serverID}`, + body: { + id: serverID + } + }); + } + }); + + cy.request({ + auth: { bearer: adminIdToken }, + failOnStatusCode: false, + method: 'POST', + url: `/api/v0/infra/servers/${serverID}/orgs`, + body: { + id: orgID, + server_id: serverID, + name: orgName, + admin_user: adminUser, + admin_key: adminKey + } + }).then((response) => { + if (response.status === 200 && response.body.ok === true) { + return; + } else { + cy.request({ + auth: { bearer: adminIdToken }, + method: 'GET', + url: `/api/v0/infra/servers/${serverID}/orgs/${orgID}`, + body: { + id: orgID, + server_id: serverID + } + }); + } + }); + cy.visit(`/infrastructure/chef-servers/${serverID}/organizations/${orgID}`); + cy.get('app-welcome-modal').invoke('hide'); + }); + cy.restoreStorage(); + }); + + beforeEach(() => { + cy.restoreStorage(); + }); + + afterEach(() => { + cy.saveStorage(); + }); + + function getDatabag() { + return cy.request({ + auth: { bearer: adminIdToken }, + failOnStatusCode: false, + method: 'GET', + url: `/api/v0/infra/servers/${serverID}/orgs/${orgID}/databags` + }); + } + + function checkResponse(response: any) { + if (response.body.data_bags === 0) { + cy.get('[data-cy=empty-list]').should('be.visible'); + } else { + cy.get('[data-cy=create-databag-button]').contains('Create Data Bag'); + cy.get('[data-cy=databags-table-container] chef-th').contains('Name'); + return true; + } + } + + describe('infra databags list page', () => { + it('displays org details', () => { + cy.get('.page-title').contains(orgName); + }); + + // databags tabs specs + it('can switch to databags tab', () => { + cy.get('.nav-tab').contains('Data Bags').click(); + }); + + it('can check if databag has list or not', () => { + getDatabag().then((response) => { + checkResponse(response); + }); + }); + + context('can search and change page in dataBag', () => { + it('can search a DataBag and check if empty or not', () => { + cy.get('[data-cy=search-filter]').type(databagName); + cy.get('[data-cy=search-entity]').click(); + cy.get('[data-cy=databags-table-container]').then(body => { + if (body.text().includes(databagName)) { + cy.get('[data-cy=databags-table-container] [data-cy=select-run-list]') + .contains(databagName).should('exist'); + } + }); + cy.get('[data-cy=search-filter]').clear(); + cy.get('[data-cy=search-entity]').click(); + getDatabag().then((response) => { + checkResponse(response); + }); + }); + }); + + // In create databag pop-up details tab specs + context('can create databag with details tab', () => { + it('can add name and create databag', () => { + cy.get('[data-cy=create-databag-button]').contains('Create Data Bag').click(); + cy.get('app-data-bags-list chef-modal').should('exist'); + cy.get('[data-cy=databag-name]').type(databagName); + + cy.get('[data-cy=add-button]').click(); + cy.get('app-data-bags-list chef-modal').should('not.be.visible'); + + // verify success notification and then dismiss it + // so it doesn't get in the way of subsequent interactions + cy.get('app-notification.info').should('be.visible'); + cy.get('app-notification.info chef-icon').click(); + }); + + it('fails to create a databag with a duplicate name', () => { + cy.get('[data-cy=create-databag-button]').contains('Create Data Bag').click(); + cy.get('app-data-bags-list chef-modal').should('exist'); + cy.get('[data-cy=databag-name]').type(databagName); + + cy.get('[data-cy=add-button]').click(); + cy.get('app-data-bags-list chef-modal chef-error').contains('already exists') + .should('be.visible'); + + cy.get('[data-cy=cancel-button]').contains('Cancel').should('be.visible').click(); + cy.get('app-data-bags-list chef-modal').should('not.be.visible'); + }); + + it('can cancel creating a databag', () => { + cy.get('[data-cy=create-databag-button]').contains('Create Data Bag').click(); + cy.get('app-data-bags-list chef-modal').should('exist'); + cy.get('[data-cy=databag-name]').type(databagName); + + // here we exit with the Cancel button + cy.get('[data-cy=cancel-button]').contains('Cancel').should('be.visible').click(); + cy.get('app-data-bags-list chef-modal').should('not.be.visible'); + }); + + it('can check create databag button is disabled until all inputs are filled in', () => { + cy.get('[data-cy=create-databag-button]').contains('Create Data Bag').click(); + cy.get('app-data-bags-list chef-modal').should('exist'); + cy.get('[data-cy=databag-name]').clear(); + + // check for disabled + cy.get('[data-cy=add-button]') + .invoke('attr', 'disabled') + .then(disabled => { + disabled ? cy.log('buttonIsDiabled') : cy.get('[data-cy=add-button]').click(); + }); + + cy.get('app-data-bags-list chef-modal').should('exist'); + + // here we exit with the Cancel button + cy.get('[data-cy=cancel-button]').contains('Cancel').should('be.visible').click(); + cy.get('app-data-bags-list chef-modal').should('not.be.visible'); + }); + }); + + // delete databag spec + context('can delete databags', () => { + it('can delete multiple databags', () => { + cy.get('[data-cy=search-filter]').type(`${cypressPrefix}-databag-${now}`); + cy.get('[data-cy=search-entity]').click(); + + cy.get('[data-cy=databags-table-container]').contains(databagName).should('exist'); + cy.get('app-data-bags-list [data-cy=databags-table-container] chef-td a') + .contains(databagName).parent().parent().find('.mat-select-trigger').click(); + // we throw in a `should` so cypress retries until introspection allows + // menu to be shown + + cy.get('[data-cy=delete]').should('be.visible') + .click(); + // accept dialog + cy.get('app-data-bags-list chef-button').contains('Delete').click(); + // verify success notification and then dismiss it + cy.get('app-notification.info') + .contains(`Successfully deleted data bag - ${databagName}.`); + cy.get('app-notification.info chef-icon').click(); + + getDatabag().then((response) => { + checkResponse(response); + }); + + cy.get('[data-cy=search-filter]').clear(); + cy.get('[data-cy=search-entity]').click(); + getDatabag().then((response) => { + checkResponse(response); + }); + }); + }); + }); +});