From bb22eebfd578f89e369a28c4015b000184f503e5 Mon Sep 17 00:00:00 2001 From: muyangye Date: Fri, 17 Nov 2023 01:53:16 -0800 Subject: [PATCH] implement unit tests for enhanced adapter deletion --- ui/cypress/support/utils/UserUtils.ts | 17 +++- .../support/utils/connect/ConnectUtils.ts | 96 ++++++++++++++++++- .../machineDataSimulator.smoke.spec.ts | 63 +++++++++++- .../delete-adapter-dialog.component.html | 1 + 4 files changed, 166 insertions(+), 11 deletions(-) diff --git a/ui/cypress/support/utils/UserUtils.ts b/ui/cypress/support/utils/UserUtils.ts index 60e735e597..fb505aa81a 100644 --- a/ui/cypress/support/utils/UserUtils.ts +++ b/ui/cypress/support/utils/UserUtils.ts @@ -27,6 +27,15 @@ export class UserUtils { .addRole(UserRole.ROLE_ADMIN) .build(); + public static adapterAndPipelineAdminUser = UserBuilder.create( + 'anpadmin@streampipes.apache.org', + ) + .setName('anpadmin') + .setPassword('anpadmin') + .addRole(UserRole.ROLE_PIPELINE_ADMIN) + .addRole(UserRole.ROLE_CONNECT_ADMIN) + .build(); + public static goToUserConfiguration() { cy.visit('#/configuration/security'); } @@ -42,9 +51,11 @@ export class UserUtils { cy.dataCy('new-user-password-repeat').type(user.password); // Set role - cy.dataCy('role-' + user.role[0]) - .children() - .click(); + for (var i = 0; i < user.role.length; i++) { + cy.dataCy('role-' + user.role[i]) + .children() + .click(); + } cy.dataCy('new-user-enabled').children().click(); // Store diff --git a/ui/cypress/support/utils/connect/ConnectUtils.ts b/ui/cypress/support/utils/connect/ConnectUtils.ts index b6a3f28e80..ee313650bd 100644 --- a/ui/cypress/support/utils/connect/ConnectUtils.ts +++ b/ui/cypress/support/utils/connect/ConnectUtils.ts @@ -22,6 +22,8 @@ import { ConnectEventSchemaUtils } from '../ConnectEventSchemaUtils'; import { DataLakeUtils } from '../datalake/DataLakeUtils'; import { ConnectBtns } from './ConnectBtns'; import { AdapterBuilder } from '../../builder/AdapterBuilder'; +import { UserUtils } from '../UserUtils'; +import { PipelineUtils } from '../PipelineUtils'; export class ConnectUtils { public static testAdapter(adapterConfiguration: AdapterInput) { @@ -193,11 +195,10 @@ export class ConnectUtils { public static deleteAdapter() { // Delete adapter - cy.visit('#/connect'); + this.goToConnect(); cy.dataCy('delete-adapter').should('have.length', 1); - cy.dataCy('delete-adapter').click(); - cy.dataCy('delete-adapter-confirmation').click(); + this.clickDelete(); cy.dataCy('adapter-deletion-in-progress', { timeout: 10000 }).should( 'be.visible', ); @@ -207,6 +208,95 @@ export class ConnectUtils { ); } + public static deleteAdapterAndAssociatedPipelines(switchUserCheck = false) { + // Delete adapter and associated pipelines + this.goToConnect(); + cy.dataCy('delete-adapter').should('have.length', 1); + this.clickDelete(); + cy.dataCy('delete-adapter-and-associated-pipelines-confirmation', { + timeout: 10000, + }).should('be.visible'); + cy.dataCy( + 'delete-adapter-and-associated-pipelines-confirmation', + ).click(); + cy.dataCy('adapter-deletion-in-progress', { timeout: 10000 }).should( + 'be.visible', + ); + if (switchUserCheck) { + cy.switchUser(UserUtils.adapterAndPipelineAdminUser); + } + this.checkAdapterAndAssociatedPipelinesDeleted(); + } + + public static deleteAdapterAndAssociatedPipelinesPermissionDenied() { + // Associated pipelines not owned by the user (unless admin) should not be deleted during adapter deletion + this.goToConnect(); + cy.dataCy('delete-adapter').should('have.length', 1); + this.clickDelete(); + cy.dataCy('delete-adapter-and-associated-pipelines-confirmation', { + timeout: 10000, + }).should('be.visible'); + cy.dataCy( + 'delete-adapter-and-associated-pipelines-confirmation', + ).click(); + cy.dataCy('adapter-deletion-permission-denied', { + timeout: 10000, + }).should('be.visible'); + cy.get('.sp-dialog-actions').click(); + this.checkAdapterNotDeleted(); + + // Switch back to admin to clean up + cy.switchUser(UserUtils.adminUser); + this.goToConnect(); + cy.dataCy('delete-adapter', { timeout: 10000 }).should( + 'have.length', + 1, + ); + this.clickDelete(); + cy.dataCy('delete-adapter-and-associated-pipelines-confirmation', { + timeout: 10000, + }).should('be.visible'); + cy.dataCy( + 'delete-adapter-and-associated-pipelines-confirmation', + ).click(); + cy.dataCy('adapter-deletion-in-progress', { timeout: 10000 }).should( + 'be.visible', + ); + this.checkAdapterAndAssociatedPipelinesDeleted(); + UserUtils.deleteUser(UserUtils.adapterAndPipelineAdminUser); + // Verify that the user is removed + cy.dataCy('user-accounts-table-row', { timeout: 10000 }).should( + 'have.length', + 1, + ); + } + + private static clickDelete() { + cy.dataCy('delete-adapter').click(); + cy.dataCy('delete-adapter-confirmation').click(); + } + + private static checkAdapterNotDeleted() { + this.goToConnect(); + cy.dataCy('delete-adapter', { timeout: 20000 }).should( + 'have.length', + 1, + ); + } + + private static checkAdapterAndAssociatedPipelinesDeleted() { + this.goToConnect(); + cy.dataCy('delete-adapter', { timeout: 20000 }).should( + 'have.length', + 0, + ); + PipelineUtils.goToPipelines(); + cy.dataCy('delete-pipeline', { timeout: 10000 }).should( + 'have.length', + 0, + ); + } + public static setUpPreprocessingRuleTest(): AdapterInput { const adapterConfiguration = AdapterBuilder.create('File_Stream') .setStoreInDataLake() diff --git a/ui/cypress/tests/adapter/machineDataSimulator.smoke.spec.ts b/ui/cypress/tests/adapter/machineDataSimulator.smoke.spec.ts index 3875d5bb14..131a20383b 100644 --- a/ui/cypress/tests/adapter/machineDataSimulator.smoke.spec.ts +++ b/ui/cypress/tests/adapter/machineDataSimulator.smoke.spec.ts @@ -18,19 +18,72 @@ import { ConnectUtils } from '../../support/utils/connect/ConnectUtils'; import { AdapterBuilder } from '../../support/builder/AdapterBuilder'; +import { PipelineBuilder } from '../../support/builder/PipelineBuilder'; +import { PipelineElementBuilder } from '../../support/builder/PipelineElementBuilder'; +import { PipelineUtils } from '../../support/utils/PipelineUtils'; +import { UserUtils } from '../../support/utils/UserUtils'; + +const adapterName = 'simulator'; describe('Test Machine Data Simulator Adapter', () => { beforeEach('Setup Test', () => { cy.initStreamPipesTest(); }); - it('Perform Test', () => { - const adapterInput = AdapterBuilder.create('Machine_Data_Simulator') - .setName('Machine Data Simulator Test') - .addInput('input', 'wait-time-ms', '1000') - .build(); + const adapterInput = AdapterBuilder.create('Machine_Data_Simulator') + .setName(adapterName) + .addInput('input', 'wait-time-ms', '1000') + .build(); + it('Test Basic Delete Adapter', () => { ConnectUtils.testAdapter(adapterInput); ConnectUtils.deleteAdapter(); }); + + const pipelineInput = PipelineBuilder.create('Pipeline Test') + .addSource(adapterName) + .addProcessingElement( + PipelineElementBuilder.create('field_renamer') + .addInput('drop-down', 'convert-property', 'timestamp') + .addInput('input', 'field-name', 't') + .build(), + ) + .addSink( + PipelineElementBuilder.create('data_lake') + .addInput('input', 'db_measurement', 'demo') + .build(), + ) + .build(); + + it('Test Delete Adapter and Associated Pipelines', () => { + UserUtils.addUser(UserUtils.adapterAndPipelineAdminUser); + cy.switchUser(UserUtils.adapterAndPipelineAdminUser); + ConnectUtils.testAdapter(adapterInput); + PipelineUtils.addPipeline(pipelineInput); + PipelineUtils.addPipeline(pipelineInput); + ConnectUtils.deleteAdapterAndAssociatedPipelines(); + }); + + it('Test Admin Should Be Able to Delete Adapter and Not Owned Associated Pipelines', () => { + // Let the user create the adapter and the pipeline + // For some reason, I have to first go to a page before switching user + UserUtils.goToUserConfiguration(); + cy.switchUser(UserUtils.adapterAndPipelineAdminUser); + ConnectUtils.testAdapter(adapterInput); + PipelineUtils.addPipeline(pipelineInput); + PipelineUtils.addPipeline(pipelineInput); + // Then let the admin delete them + cy.switchUser(UserUtils.adminUser); + ConnectUtils.deleteAdapterAndAssociatedPipelines(true); + }); + + it('Test Delete Adapter and Associated Pipelines Permission Denied', () => { + // Let the admin create the adapter and the pipeline + ConnectUtils.testAdapter(adapterInput); + PipelineUtils.addPipeline(pipelineInput); + PipelineUtils.addPipeline(pipelineInput); + // Then the user shouldn't be able to delete them + cy.switchUser(UserUtils.adapterAndPipelineAdminUser); + ConnectUtils.deleteAdapterAndAssociatedPipelinesPermissionDenied(); + }); }); diff --git a/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.html b/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.html index c5a73031b4..0f08cec5c4 100644 --- a/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.html +++ b/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.html @@ -67,6 +67,7 @@

fxLayoutAlign="center center" fxLayout="column" style="width: 100%" + data-cy="adapter-deletion-permission-denied" >