From 9e3ef9f52d2524906cd080aa85185feac705ff26 Mon Sep 17 00:00:00 2001 From: Madhvi Atroliya Date: Mon, 20 Sep 2021 11:16:22 +0530 Subject: [PATCH] Madhvi/data feed webhook custom (#5663) * minio full code without tests Signed-off-by: Vivek Shankar * added unit and cypress tests Signed-off-by: Vivek Shankar * fixed lint issues Signed-off-by: Vivek Shankar * minio integration test Signed-off-by: Vivek Shankar * minio integration test Signed-off-by: Vivek Shankar * minio test Signed-off-by: Vivek Shankar * minio test Signed-off-by: Vivek Shankar * minio working and reformatted Signed-off-by: Vivek Shankar * integration tests minio and reformatted code Signed-off-by: Vivek Shankar * modified unit tests Signed-off-by: Vivek Shankar * fixed spell check Signed-off-by: Vivek Shankar * fixed spell check 1090 Signed-off-by: Vivek Shankar * fixed save Signed-off-by: Vivek Shankar * changes for custom webhook Signed-off-by: MadhviA * changes for custom webhook Signed-off-by: MadhviA * Changes for custom webhook Signed-off-by: MadhviA * minio full code without tests Signed-off-by: Vivek Shankar * added unit and cypress tests Signed-off-by: Vivek Shankar * fixed lint issues Signed-off-by: Vivek Shankar * minio integration test Signed-off-by: Vivek Shankar * minio integration test Signed-off-by: Vivek Shankar * minio test Signed-off-by: Vivek Shankar * minio test Signed-off-by: Vivek Shankar * minio working and reformatted Signed-off-by: Vivek Shankar * integration tests minio and reformatted code Signed-off-by: Vivek Shankar * modified unit tests Signed-off-by: Vivek Shankar * fixed spell check Signed-off-by: Vivek Shankar * fixed spell check 1090 Signed-off-by: Vivek Shankar * fixed save Signed-off-by: Vivek Shankar * added more tests cases with more coverage improved code Signed-off-by: Vivek Shankar * fixed casing and html logic removed Signed-off-by: Vivek Shankar * cypress test Signed-off-by: MadhviA * Conflicts changes Signed-off-by: MadhviA * changed cypress test Signed-off-by: MadhviA * switch case added Signed-off-by: Vivek Shankar * resolved conflicts Signed-off-by: MadhviA * Resolving conflicts Signed-off-by: MadhviA * Resolving conflicts Signed-off-by: MadhviA * Resolving conflicts Signed-off-by: MadhviA * resolving conflits Signed-off-by: MadhviA * generic code for webhooks Signed-off-by: MadhviA * Changes to resolve PR comments Signed-off-by: MadhviA * lint changes Signed-off-by: MadhviA * header changes Signed-off-by: MadhviA * resolving PR comments Signed-off-by: MadhviA * lint changes Signed-off-by: MadhviA * resolving PR comments Signed-off-by: MadhviA * resolving headers sequence Signed-off-by: MadhviA * resolving headers sequence in test class Signed-off-by: MadhviA * adding test cases Signed-off-by: MadhviA * correcting html changes Signed-off-by: MadhviA * correcting cypress changes Signed-off-by: MadhviA * correcting html changes Signed-off-by: MadhviA * changed username logic Signed-off-by: MadhviA * lint changes for buildkite Signed-off-by: MadhviA * changes for buildkite Signed-off-by: MadhviA Co-authored-by: Vivek Shankar Co-authored-by: MadhviA --- .../destinations/destination.requests.ts | 20 ++- .../automate-ui/src/app/helpers/auth/regex.ts | 5 +- .../data-feed-create.component.html | 42 +++++- .../data-feed-create.component.scss | 39 ++++- .../data-feed-create.component.spec.ts | 25 ++++ .../data-feed-create.component.ts | 77 ++++++++-- .../pages/data-feed/data-feed.component.html | 3 +- .../data-feed/data-feed.component.spec.ts | 134 ++++++++++++++++-- .../pages/data-feed/data-feed.component.ts | 109 +++++++++----- .../data-feed}/chef-datafeed.spec.ts | 1 + .../data-feed/data-feed-create.spec.ts | 63 ++++++++ 11 files changed, 446 insertions(+), 72 deletions(-) rename e2e/cypress/integration/ui/{infra-proxy => settings/data-feed}/chef-datafeed.spec.ts (99%) diff --git a/components/automate-ui/src/app/entities/destinations/destination.requests.ts b/components/automate-ui/src/app/entities/destinations/destination.requests.ts index d02c3dd6d24..b1286ec5a7a 100644 --- a/components/automate-ui/src/app/entities/destinations/destination.requests.ts +++ b/components/automate-ui/src/app/entities/destinations/destination.requests.ts @@ -139,12 +139,24 @@ export class DestinationRequests { return this.testDestinationWithSecretId(destination); } } - public testDestinationWithUsernamePassword(url: string, username: string, password: string): Observable { - return this.http.post(encodeURI( - this.joinToDataFeedUrl(['destinations', 'test'])), - { url, 'username_password': {username, password} }); + return this.http.post(encodeURI( + this.joinToDataFeedUrl(['destinations', 'test'])), + { url, 'username_password': {username, password} }); + } + + public testDestinationWithUsernamePasswordWithHeaders(url: string, + username: string, password: string, headers: string): Observable { + if (headers !== '') { + return this.http.post(encodeURI( + this.joinToDataFeedUrl(['destinations', 'test'])), + { url, headers, 'username_password': {username, password} }); + } else { + return this.http.post(encodeURI( + this.joinToDataFeedUrl(['destinations', 'test'])), + { url, 'username_password': {username, password} }); + } } public testDestinationWithHeaders(url: string, diff --git a/components/automate-ui/src/app/helpers/auth/regex.ts b/components/automate-ui/src/app/helpers/auth/regex.ts index 359e5767921..43e93ed2c0d 100644 --- a/components/automate-ui/src/app/helpers/auth/regex.ts +++ b/components/automate-ui/src/app/helpers/auth/regex.ts @@ -37,7 +37,10 @@ export class Regex { VALID_IP_ADDRESS: '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$', // Allow valid versions only Eg: 1.2.3 - VALID_VERSION: /^\d{1,9}\.\d{1,9}\.\d{1,9}$/ + VALID_VERSION: /^\d{1,9}\.\d{1,9}\.\d{1,9}$/, + + // Allow valid header input for Custom webhook + VALID_HEADER: /([a-zA-Z]):([a-zA-Z])[^\r\n]/ }; } diff --git a/components/automate-ui/src/app/pages/data-feed-create/data-feed-create.component.html b/components/automate-ui/src/app/pages/data-feed-create/data-feed-create.component.html index 1ff019ebb3b..03cc90c56e0 100644 --- a/components/automate-ui/src/app/pages/data-feed-create/data-feed-create.component.html +++ b/components/automate-ui/src/app/pages/data-feed-create/data-feed-create.component.html @@ -27,7 +27,7 @@

Webhook Integration

-
+
Coming Soon
@@ -126,7 +126,7 @@

{{item.name}}

-
+
+ + token type is required. +
-
+
-
+
-
+
+
+ + + + Headers are invalid. + + +
diff --git a/components/automate-ui/src/app/pages/data-feed/data-feed.component.spec.ts b/components/automate-ui/src/app/pages/data-feed/data-feed.component.spec.ts index 8ffccbb1514..3b2b16a97e6 100644 --- a/components/automate-ui/src/app/pages/data-feed/data-feed.component.spec.ts +++ b/components/automate-ui/src/app/pages/data-feed/data-feed.component.spec.ts @@ -6,7 +6,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { MockComponent } from 'ng2-mock-component'; import { StoreModule, Store } from '@ngrx/store'; import { NgrxStateAtom, ngrxReducers, runtimeChecks } from 'app/ngrx.reducers'; -import { DataFeedComponent } from './data-feed.component'; +import { DataFeedComponent, UrlTestState } from './data-feed.component'; import { DestinationRequests } from 'app/entities/destinations/destination.requests'; import { HttpClient, HttpHandler } from '@angular/common/http'; import { Destination } from 'app/entities/destinations/destination.model'; @@ -20,6 +20,7 @@ import { StorageIntegrationTypes, WebhookIntegrationTypes } from '../data-feed-create/data-feed-create.component'; +import { of, throwError } from 'rxjs'; describe('DataFeedComponent', () => { let component: DataFeedComponent; @@ -93,12 +94,21 @@ describe('DataFeedComponent', () => { const bucketName = 'b123'; const accessKey = 'test123'; const secretKey = 'test123'; + const headers = 'test:123'; const destination = { id: '1', name: 'new data feed', secret: 'testSecret', url: 'http://foo.com' }; + const destinationwithHeader = { + id: '1', + name: 'new data feed', + secret: 'testSecret', + url: 'http://foo.com', + headers: 'test:123' + }; + beforeEach(() => { store = TestBed.inject(Store); @@ -111,6 +121,16 @@ describe('DataFeedComponent', () => { expect(component.createModalVisible).toBe(true); }); + it('reveal url status success', () => { + component.revealUrlStatus(UrlTestState.Success); + expect(component.createChild.notificationMessage).not.toBe(''); + }); + + it('reveal url status failure', () => { + component.revealUrlStatus(UrlTestState.Failure); + expect(component.createChild.notificationMessage).not.toBe(''); + }); + it('on success, closes slider and adds new data feed', () => { spyOnProperty(component.createChild, 'saveDone', 'set'); @@ -306,39 +326,41 @@ describe('DataFeedComponent', () => { }); it('on test success for Service now and check dispatched store data', () => { - component.createDataFeedForm.controls['name'].setValue(destination.name); component.createDataFeedForm.controls['url'].setValue(destination.url); component.createDataFeedForm.controls['username'].setValue(username); component.createDataFeedForm.controls['password'].setValue(password); - - spyOn(component['datafeedRequests'], 'testDestinationWithUsernamePassword'); + spyOn(component, 'revealUrlStatus'); + spyOn(component['datafeedRequests'], 'testDestinationWithHeaders') + .and.returnValue(of([])); component.sendTestForDataFeed({ auth: AuthTypes.USERNAMEANDPASSWORD, name: WebhookIntegrationTypes.SERVICENOW }); + const userToken = JSON.stringify({ + Authorization: 'Basic ' + btoa(username + ':' + password) + }); expect(component['datafeedRequests'] - .testDestinationWithUsernamePassword).toHaveBeenCalledWith( + .testDestinationWithHeaders).toHaveBeenCalledWith( destination.url, - username, - password + userToken ); + expect(component.revealUrlStatus).toHaveBeenCalledWith(UrlTestState.Success); }); it('on test success for Splunk and check dispatched store data', () => { - component.createDataFeedForm.controls['name'].setValue(destination.name); component.createDataFeedForm.controls['url'].setValue(destination.url); component.createDataFeedForm.controls['tokenType'].setValue('Bearer'); component.createDataFeedForm.controls['token'].setValue(token); - - spyOn(component['datafeedRequests'], 'testDestinationWithHeaders'); + spyOn(component, 'revealUrlStatus'); + spyOn(component['datafeedRequests'], 'testDestinationWithHeaders') + .and.returnValue(throwError([])); component.sendTestForDataFeed({ auth: AuthTypes.ACCESSTOKEN, name: WebhookIntegrationTypes.SPLUNK }); - expect(component['datafeedRequests'] .testDestinationWithHeaders).toHaveBeenCalledWith( destination.url, @@ -346,6 +368,7 @@ describe('DataFeedComponent', () => { Authorization: 'Bearer' + ' ' + token }) ); + expect(component.revealUrlStatus).toHaveBeenCalledWith(UrlTestState.Failure); }); it('on test success for Minio and check dispatched store data', () => { @@ -373,6 +396,95 @@ describe('DataFeedComponent', () => { }); }); + it('add Headers for Custom dataFeed', () => { + component.createDataFeedForm.controls['headers'].setValue(headers); + const headerJson = component.addHeadersforCustomDataFeed(headers); + expect(headerJson).toEqual({test : '123'}); + }); + + it('on success, closes slider and adds new custom data feed with username-password', () => { + spyOnProperty(component.createChild, 'saveDone', 'set'); + component.createDataFeedForm.controls['name'].setValue(destination.name); + component.createDataFeedForm.controls['url'].setValue(destination.url); + component.createDataFeedForm.controls['username'].setValue(username); + component.createDataFeedForm.controls['password'].setValue(password); + component.createDataFeedForm.controls['headers'].setValue(headers); + + component.saveDestination({ + auth: AuthTypes.USERNAMEANDPASSWORD, + name: WebhookIntegrationTypes.CUSTOM + }); + store.dispatch(new CreateDestinationSuccess(destinationwithHeader)); + component.sortedDestinations$.subscribe(destinations => { + expect(destinations).toContain(destinationwithHeader); + }); + }); + + it('on success, closes slider and adds new custom data feed with access token', () => { + spyOnProperty(component.createChild, 'saveDone', 'set'); + + component.createDataFeedForm.controls['name'].setValue(destination.name); + component.createDataFeedForm.controls['url'].setValue(destination.url); + component.createDataFeedForm.controls['username'].setValue(username); + component.createDataFeedForm.controls['password'].setValue(password); + component.createDataFeedForm.controls['headers'].setValue(headers); + component.saveDestination({ + auth: AuthTypes.ACCESSTOKEN, + name: WebhookIntegrationTypes.CUSTOM + }); + store.dispatch(new CreateDestinationSuccess(destination)); + component.sortedDestinations$.subscribe(destinations => { + expect(destinations).toContain(destination); + }); + }); + + it('on test success for custom and check dispatched store data', () => { + component.createDataFeedForm.controls['url'].setValue(destination.url); + component.createDataFeedForm.controls['tokenType'].setValue('Bearer'); + component.createDataFeedForm.controls['token'].setValue(token); + component.createDataFeedForm.controls['headers'].setValue(headers); + component.checkedHeaders = true; + spyOn(component['datafeedRequests'], 'testDestinationWithHeaders'); + component.sendTestForDataFeed({ + auth: AuthTypes.ACCESSTOKEN, + name: WebhookIntegrationTypes.CUSTOM + }); + const userToken = JSON.stringify({ + Authorization: 'Bearer' + ' ' + token + }); + const headersJson = component.addHeadersforCustomDataFeed(headers); + const headersVal = {...headersJson, ...JSON.parse(userToken)}; + + expect(component['datafeedRequests'] + .testDestinationWithHeaders).toHaveBeenCalledWith( + destination.url, + JSON.stringify(headersVal) + ); + }); + + it('on test success for Custom now and check dispatched store data', () => { + component.createDataFeedForm.controls['url'].setValue(destination.url); + component.createDataFeedForm.controls['username'].setValue(username); + component.createDataFeedForm.controls['password'].setValue(password); + component.createDataFeedForm.controls['headers'].setValue(headers); + component.checkedHeaders = true; + spyOn(component['datafeedRequests'], 'testDestinationWithHeaders'); + component.sendTestForDataFeed({ + auth: AuthTypes.USERNAMEANDPASSWORD, + name: WebhookIntegrationTypes.CUSTOM + }); + const userToken = JSON.stringify({ + Authorization: 'Basic ' + btoa(username + ':' + password) + }); + const headersJson = component.addHeadersforCustomDataFeed(headers); + const headersVal = {...headersJson, ...JSON.parse(userToken)}; + + expect(component['datafeedRequests'] + .testDestinationWithHeaders).toHaveBeenCalledWith( + destination.url, + JSON.stringify(headersVal) + ); + }); }); }); diff --git a/components/automate-ui/src/app/pages/data-feed/data-feed.component.ts b/components/automate-ui/src/app/pages/data-feed/data-feed.component.ts index fb2677de6d9..7ace1bbccac 100644 --- a/components/automate-ui/src/app/pages/data-feed/data-feed.component.ts +++ b/components/automate-ui/src/app/pages/data-feed/data-feed.component.ts @@ -35,7 +35,7 @@ import { WebhookIntegrationTypes } from '../data-feed-create/data-feed-create.component'; -enum UrlTestState { +export enum UrlTestState { Inactive, Loading, Success, @@ -59,6 +59,7 @@ export class DataFeedComponent implements OnInit, OnDestroy { public deleteModalVisible = false; public sendingDataFeed = false; private isDestroyed = new Subject(); + public checkedHeaders = false; @ViewChild(DataFeedCreateComponent) createChild: DataFeedCreateComponent; @@ -160,40 +161,74 @@ export class DataFeedComponent implements OnInit, OnDestroy { this.deleteModalVisible = false; } + public setCheck(event) { + this.checkedHeaders = event; + } + + public addHeadersforCustomDataFeed(customHeaders: string): {} { + const headersJson = {}; + const headersVal = customHeaders.split('\n'); + for (const values in headersVal) { + if (headersVal[values]) { + const word = headersVal[values].split(':'); + headersJson[word[0]] = word[1]; + } + } + return headersJson; + } + public sendTestForDataFeed(event: {name: string, auth: string}): void { let testConnectionObservable: Observable = null; switch (event.name) { case WebhookIntegrationTypes.SERVICENOW: case WebhookIntegrationTypes.SPLUNK: - case WebhookIntegrationTypes.ELK_KIBANA: { + case WebhookIntegrationTypes.ELK_KIBANA: + case WebhookIntegrationTypes.CUSTOM: { switch (event.auth) { case AuthTypes.ACCESSTOKEN: { const targetUrl: string = this.createDataFeedForm.controls['url'].value; const tokenType: string = this.createDataFeedForm.controls['tokenType'].value; const token: string = this.createDataFeedForm.controls['token'].value; - const value = JSON.stringify({ + const headerVal: string = this.createDataFeedForm.controls['headers'].value; + const userToken = JSON.stringify({ Authorization: tokenType + ' ' + token }); - testConnectionObservable = this.datafeedRequests.testDestinationWithHeaders(targetUrl, - value); + let value; + if (headerVal && this.checkedHeaders) { + const headersJson = this.addHeadersforCustomDataFeed(headerVal); + const headers = {...headersJson, ...JSON.parse(userToken)}; + value = JSON.stringify(headers); + } else { + value = userToken; + } + testConnectionObservable = this.datafeedRequests. + testDestinationWithHeaders(targetUrl, value); break; } case AuthTypes.USERNAMEANDPASSWORD: { const targetUrl: string = this.createDataFeedForm.controls['url'].value; const targetUsername: string = this.createDataFeedForm.controls['username'].value; const targetPassword: string = this.createDataFeedForm.controls['password'].value; - testConnectionObservable = this.datafeedRequests.testDestinationWithUsernamePassword( - targetUrl, targetUsername, targetPassword); + const headerVal: string = this.createDataFeedForm.controls['headers'].value; + const userToken = JSON.stringify({ + Authorization: 'Basic ' + btoa(targetUsername + ':' + targetPassword) + }); + let value; + if (headerVal && this.checkedHeaders) { + const headersJson = this.addHeadersforCustomDataFeed(headerVal); + const headers = {...headersJson, ...JSON.parse(userToken)}; + value = JSON.stringify(headers); + } else { + value = userToken; + } + testConnectionObservable = this.datafeedRequests. + testDestinationWithHeaders(targetUrl, value); + break; } } break; } - case WebhookIntegrationTypes.CUSTOM: { - // handling access token and user pass auth - // with headers for custom webhooks - break; - } case StorageIntegrationTypes.MINIO: { // handling minio const targetUrl: string = this.createDataFeedForm.controls['endpoint'].value; @@ -216,7 +251,7 @@ export class DataFeedComponent implements OnInit, OnDestroy { } } - private revealUrlStatus(status: UrlTestState) { + revealUrlStatus(status: UrlTestState) { this.createChild.testDoneSetter = false; if (status === UrlTestState.Success) { this.createChild.testSuccessSetter = true; @@ -241,45 +276,52 @@ export class DataFeedComponent implements OnInit, OnDestroy { switch (event.name) { case WebhookIntegrationTypes.SERVICENOW: case WebhookIntegrationTypes.SPLUNK: - case WebhookIntegrationTypes.ELK_KIBANA: { + case WebhookIntegrationTypes.ELK_KIBANA: + case WebhookIntegrationTypes.CUSTOM: { + destinationObj = { + name: this.createDataFeedForm.controls['name'].value.trim(), + url: this.createDataFeedForm.controls['url'].value.trim(), + integration_types: IntegrationTypes.WEBHOOK, + services: event.name + }; switch (event.auth) { case AuthTypes.ACCESSTOKEN: { - destinationObj = { - name: this.createDataFeedForm.controls['name'].value.trim(), - url: this.createDataFeedForm.controls['url'].value.trim(), - integration_types: IntegrationTypes.WEBHOOK, - services: event.name - }; const tokenType: string = this.createDataFeedForm.controls['tokenType'].value.trim(); const token: string = this.createDataFeedForm.controls['token'].value.trim(); - headers = JSON.stringify({ + const headerVal: string = this.createDataFeedForm.controls['headers'].value; + const userToken = JSON.stringify({ Authorization: tokenType + ' ' + token }); + if (headerVal && this.checkedHeaders) { + const headersJson = this.addHeadersforCustomDataFeed(headerVal); + const value = {...headersJson, ...JSON.parse(userToken)}; + headers = JSON.stringify(value); + } else { + headers = userToken; + } storage = null; break; } case AuthTypes.USERNAMEANDPASSWORD: { - destinationObj = { - name: this.createDataFeedForm.controls['name'].value.trim(), - url: this.createDataFeedForm.controls['url'].value.trim(), - integration_types: IntegrationTypes.WEBHOOK, - services: event.name - }; const username: string = this.createDataFeedForm.controls['username'].value.trim(); const password: string = this.createDataFeedForm.controls['password'].value.trim(); - headers = JSON.stringify({ + const headerVal: string = this.createDataFeedForm.controls['headers'].value; + const userToken = JSON.stringify({ Authorization: 'Basic ' + btoa(username + ':' + password) }); + if (headerVal && this.checkedHeaders) { + const headersJson = this.addHeadersforCustomDataFeed(headerVal); + const value = {...headersJson, ...JSON.parse(userToken)}; + headers = JSON.stringify(value); + } else { + headers = userToken; + } storage = null; + break; } } break; } - case WebhookIntegrationTypes.CUSTOM: { - // handling access token and user pass auth - // with headers for custom webhooks - break; - } case StorageIntegrationTypes.MINIO: { // handling minio destinationObj = { @@ -305,4 +347,3 @@ export class DataFeedComponent implements OnInit, OnDestroy { } } } - diff --git a/e2e/cypress/integration/ui/infra-proxy/chef-datafeed.spec.ts b/e2e/cypress/integration/ui/settings/data-feed/chef-datafeed.spec.ts similarity index 99% rename from e2e/cypress/integration/ui/infra-proxy/chef-datafeed.spec.ts rename to e2e/cypress/integration/ui/settings/data-feed/chef-datafeed.spec.ts index 77f21784aba..5a0e4198d59 100644 --- a/e2e/cypress/integration/ui/infra-proxy/chef-datafeed.spec.ts +++ b/e2e/cypress/integration/ui/settings/data-feed/chef-datafeed.spec.ts @@ -1,4 +1,5 @@ describe('chef datafeed', () => { + before(() => { cy.adminLogin('/settings/notifications').then(() => { const admin = JSON.parse(localStorage.getItem('chef-automate-user')); diff --git a/e2e/cypress/integration/ui/settings/data-feed/data-feed-create.spec.ts b/e2e/cypress/integration/ui/settings/data-feed/data-feed-create.spec.ts index 1dbaa1167ca..e9c76f5d652 100644 --- a/e2e/cypress/integration/ui/settings/data-feed/data-feed-create.spec.ts +++ b/e2e/cypress/integration/ui/settings/data-feed/data-feed-create.spec.ts @@ -131,6 +131,69 @@ describe('chef datafeed', () => { cy.get('[data-cy=close-feed-button]').click(); }); + it('create data feed Custom with token', () => { + const date = Date.now(); + cy.get('[data-cy=create-data-feed]').click(); + cy.get('[data-cy=Custom]').click(); + cy.get('[data-cy=add-name]').type(name + date); + cy.get('[data-cy=add-url]').type(url); + cy.get('[data-cy=add-token-type]').type(tokenType); + cy.get('[data-cy=add-token]').type(token); + cy.get('[data-cy=add-button]').click(); + cy.get('app-notification.info').should('be.visible'); + cy.get('app-notification.info chef-icon').click(); + cy.contains('Data Feeds').click(); + cy.get('chef-table chef-tbody chef-td').contains('cytest' + date).should('exist'); + }); + + it('test connection in data feed Custom', () => { + const date = Date.now(); + cy.get('[data-cy=create-data-feed]').click(); + cy.get('[data-cy=Custom]').click(); + cy.get('[data-cy=add-name]').type(name + date); + cy.get('[data-cy=add-url]').type(url); + cy.get('[data-cy=select-auth-type]').click(); + cy.get('[data-cy=select-username-password]').click(); + cy.get('[data-cy=add-username]').type(username); + cy.get('[data-cy=add-password]').type(password); + cy.get('[data-cy=test-button]').click(); + cy.get('app-data-feed-create').scrollTo('top'); + cy.get('.data-feed-slider app-notification.error').should('be.visible'); + cy.get('.data-feed-slider app-notification.error chef-icon').click(); + cy.get('[data-cy=close-feed-button]').click(); + }); + + it('create data feed Custom with username', () => { + const date = Date.now(); + cy.get('[data-cy=create-data-feed]').click(); + cy.get('[data-cy=Custom]').click(); + cy.get('[data-cy=add-name]').type(name + date); + cy.get('[data-cy=add-url]').type(url); + cy.get('[data-cy=select-auth-type]').click(); + cy.get('[data-cy=select-username-password]').click(); + cy.get('[data-cy=add-username]').type(username); + cy.get('[data-cy=add-password]').type(password); + cy.get('[data-cy=add-button]').click(); + cy.get('app-notification.info').should('be.visible'); + cy.get('app-notification.info chef-icon').click(); + cy.contains('Data Feeds').click(); + cy.get('chef-table chef-tbody chef-td').contains('cytest' + date).should('exist'); + }); + + it('create data feed error custom', () => { + cy.get('[data-cy=create-data-feed]').click(); + cy.get('[data-cy=Custom]').click(); + cy.get('[data-cy=add-name]').type(name + reusableDate); + cy.get('[data-cy=add-url]').type(url); + cy.get('[data-cy=add-token-type]').type(tokenType); + cy.get('[data-cy=add-token]').type(token); + cy.get('[data-cy=add-button]').click(); + cy.get('app-data-feed-create').scrollTo('top'); + cy.get('.data-feed-slider app-notification.error').should('be.visible'); + cy.get('.data-feed-slider app-notification.error chef-icon').click(); + cy.get('[data-cy=close-feed-button]').click(); + }); + it('create data feed minio', () => { const date = Date.now(); cy.get('[data-cy=create-data-feed]').click();