Skip to content

Commit

Permalink
[Automatic Import] Add Cypress tests for Automatic Import UI flow (#1…
Browse files Browse the repository at this point in the history
…94948)

## Summary

Adds Cypress functional UI tests for different flows in Automatic
Import.

- Relates [#192684](#192684)

### RBAC tests

#### Create Integration Landing Page
- Fleet `read` Integrations `all` -- No access
- Fleet `read` Integrations `read` -- No access
- Fleet `read` Integrations `read` -- No access
- Fleet `all` Integrations `all` -- Access

#### Create Integration Assistant Page
- Fleet/integrations `all` Actions `read` [ `show` `execute` ] --
Execute with existing connectors
- Fleet/integrations `all` Actions `all` [ `show` `execute` `save`
`delete` ] -- Create new connector / execute existing ones.

### Create Integration UI Flow - NDJSON example
- Create an integration using Automatic Import with NDJSON samples



https://github.com/user-attachments/assets/9ab4cfc2-f058-4491-a280-6b86bcc5c9ce

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
bhapas and kibanamachine authored Oct 10, 2024
1 parent 7a30154 commit c920033
Show file tree
Hide file tree
Showing 17 changed files with 1,081 additions and 12 deletions.
115 changes: 115 additions & 0 deletions x-pack/plugins/fleet/cypress/e2e/integrations_automatic_import.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { deleteIntegrations } from '../tasks/integrations';
import {
UPLOAD_PACKAGE_LINK,
ASSISTANT_BUTTON,
TECH_PREVIEW_BADGE,
CREATE_INTEGRATION_LANDING_PAGE,
BUTTON_FOOTER_NEXT,
INTEGRATION_TITLE_INPUT,
INTEGRATION_DESCRIPTION_INPUT,
DATASTREAM_TITLE_INPUT,
DATASTREAM_DESCRIPTION_INPUT,
DATASTREAM_NAME_INPUT,
DATA_COLLECTION_METHOD_INPUT,
LOGS_SAMPLE_FILE_PICKER,
EDIT_PIPELINE_BUTTON,
SAVE_PIPELINE_BUTTON,
VIEW_INTEGRATION_BUTTON,
INTEGRATION_SUCCESS_SECTION,
SAVE_ZIP_BUTTON,
} from '../screens/integrations_automatic_import';
import { cleanupAgentPolicies } from '../tasks/cleanup';
import { login, logout } from '../tasks/login';
import { createBedrockConnector, deleteConnectors } from '../tasks/api_calls/connectors';
import {
ecsResultsForJson,
categorizationResultsForJson,
relatedResultsForJson,
} from '../tasks/api_calls/graph_results';

describe('Add Integration - Automatic Import', () => {
beforeEach(() => {
login();

cleanupAgentPolicies();
deleteIntegrations();

// Create a mock connector
deleteConnectors();
createBedrockConnector();
// Mock API Responses
cy.intercept('POST', '/api/integration_assistant/ecs', {
statusCode: 200,
body: {
results: ecsResultsForJson,
},
});
cy.intercept('POST', '/api/integration_assistant/categorization', {
statusCode: 200,
body: {
results: categorizationResultsForJson,
},
});
cy.intercept('POST', '/api/integration_assistant/related', {
statusCode: 200,
body: {
results: relatedResultsForJson,
},
});
});

afterEach(() => {
deleteConnectors();
cleanupAgentPolicies();
deleteIntegrations();
logout();
});

it('should create an integration', () => {
cy.visit(CREATE_INTEGRATION_LANDING_PAGE);

cy.getBySel(ASSISTANT_BUTTON).should('exist');
cy.getBySel(UPLOAD_PACKAGE_LINK).should('exist');
cy.getBySel(TECH_PREVIEW_BADGE).should('exist');

// Create Integration Assistant Page
cy.getBySel(ASSISTANT_BUTTON).click();
cy.getBySel(BUTTON_FOOTER_NEXT).click();

// Integration details Page
cy.getBySel(INTEGRATION_TITLE_INPUT).type('Test Integration');
cy.getBySel(INTEGRATION_DESCRIPTION_INPUT).type('Test Integration Description');
cy.getBySel(BUTTON_FOOTER_NEXT).click();

// Datastream details page
cy.getBySel(DATASTREAM_TITLE_INPUT).type('Audit');
cy.getBySel(DATASTREAM_DESCRIPTION_INPUT).type('Test Datastream Description');
cy.getBySel(DATASTREAM_NAME_INPUT).type('audit');
cy.getBySel(DATA_COLLECTION_METHOD_INPUT).type('file stream');
cy.get('body').click(0, 0);

// Select sample logs file and Analyze logs
cy.fixture('teleport.ndjson', null).as('myFixture');
cy.getBySel(LOGS_SAMPLE_FILE_PICKER).selectFile('@myFixture');
cy.getBySel(BUTTON_FOOTER_NEXT).click();

// Edit Pipeline
cy.getBySel(EDIT_PIPELINE_BUTTON).click();
cy.getBySel(SAVE_PIPELINE_BUTTON).click();

// Deploy
cy.getBySel(BUTTON_FOOTER_NEXT).click();
cy.getBySel(INTEGRATION_SUCCESS_SECTION).should('exist');
cy.getBySel(SAVE_ZIP_BUTTON).should('exist');

// View Integration
cy.getBySel(VIEW_INTEGRATION_BUTTON).click();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import type { User } from '../tasks/privileges';
import {
deleteUsersAndRoles,
getIntegrationsAutoImportRole,
createUsersAndRoles,
AutomaticImportConnectorNoneUser,
AutomaticImportConnectorNoneRole,
AutomaticImportConnectorAllUser,
AutomaticImportConnectorAllRole,
AutomaticImportConnectorReadUser,
AutomaticImportConnectorReadRole,
} from '../tasks/privileges';
import { login, loginWithUserAndWaitForPage, logout } from '../tasks/login';
import {
ASSISTANT_BUTTON,
CONNECTOR_BEDROCK,
CONNECTOR_GEMINI,
CONNECTOR_OPENAI,
CREATE_INTEGRATION_ASSISTANT,
CREATE_INTEGRATION_LANDING_PAGE,
CREATE_INTEGRATION_UPLOAD,
MISSING_PRIVILEGES,
UPLOAD_PACKAGE_LINK,
} from '../screens/integrations_automatic_import';

describe('When the user does not have enough previleges for Integrations', () => {
const runs = [
{ fleetRole: 'read', integrationsRole: 'read' },
{ fleetRole: 'read', integrationsRole: 'all' },
{ fleetRole: 'all', integrationsRole: 'read' },
];

runs.forEach(function (run) {
describe(`When the user has '${run.fleetRole}' role for fleet and '${run.integrationsRole}' role for Integrations`, () => {
const automaticImportIntegrRole = getIntegrationsAutoImportRole({
fleetv2: [run.fleetRole], // fleet
fleet: [run.integrationsRole], // integrations
});
const AutomaticImportIntegrUser: User = {
username: 'automatic_import_integrations_read_user',
password: 'password',
roles: [automaticImportIntegrRole.name],
};

before(() => {
createUsersAndRoles([AutomaticImportIntegrUser], [automaticImportIntegrRole]);
});

beforeEach(() => {
login();
});

afterEach(() => {
logout();
});

after(() => {
deleteUsersAndRoles([AutomaticImportIntegrUser], [automaticImportIntegrRole]);
});

it('Create Assistant is not accessible if user has read role in integrations', () => {
loginWithUserAndWaitForPage(CREATE_INTEGRATION_ASSISTANT, AutomaticImportIntegrUser);
cy.getBySel(MISSING_PRIVILEGES).should('exist');
});

it('Create upload is not accessible if user has read role in integrations', () => {
loginWithUserAndWaitForPage(CREATE_INTEGRATION_UPLOAD, AutomaticImportIntegrUser);
cy.getBySel(MISSING_PRIVILEGES).should('exist');
});
});
});
});

describe('When the user has All permissions for Integrations and No permissions for actions', () => {
before(() => {
createUsersAndRoles([AutomaticImportConnectorNoneUser], [AutomaticImportConnectorNoneRole]);
});

beforeEach(() => {
login();
});

afterEach(() => {
logout();
});

after(() => {
deleteUsersAndRoles([AutomaticImportConnectorNoneUser], [AutomaticImportConnectorNoneRole]);
});

it('Create Assistant is not accessible but upload is accessible', () => {
loginWithUserAndWaitForPage(CREATE_INTEGRATION_LANDING_PAGE, AutomaticImportConnectorNoneUser);
cy.getBySel(ASSISTANT_BUTTON).should('not.exist');
cy.getBySel(UPLOAD_PACKAGE_LINK).should('exist');
});
});

describe('When the user has All permissions for Integrations and read permissions for actions', () => {
before(() => {
createUsersAndRoles([AutomaticImportConnectorReadUser], [AutomaticImportConnectorReadRole]);
});

beforeEach(() => {
login();
});

afterEach(() => {
logout();
});

after(() => {
deleteUsersAndRoles([AutomaticImportConnectorReadUser], [AutomaticImportConnectorReadRole]);
});

it('Create Assistant is not accessible but upload is accessible', () => {
loginWithUserAndWaitForPage(CREATE_INTEGRATION_LANDING_PAGE, AutomaticImportConnectorReadUser);
cy.getBySel(ASSISTANT_BUTTON).should('exist');
cy.getBySel(UPLOAD_PACKAGE_LINK).should('exist');
});

it('Create Assistant is accessible but execute connector is not accessible', () => {
loginWithUserAndWaitForPage(CREATE_INTEGRATION_ASSISTANT, AutomaticImportConnectorReadUser);
cy.getBySel(CONNECTOR_BEDROCK).should('not.exist');
cy.getBySel(CONNECTOR_OPENAI).should('not.exist');
cy.getBySel(CONNECTOR_GEMINI).should('not.exist');
});
});

describe('When the user has All permissions for Integrations and All permissions for actions', () => {
before(() => {
createUsersAndRoles([AutomaticImportConnectorAllUser], [AutomaticImportConnectorAllRole]);
});

beforeEach(() => {
login();
});

afterEach(() => {
logout();
});

after(() => {
deleteUsersAndRoles([AutomaticImportConnectorAllUser], [AutomaticImportConnectorAllRole]);
});

it('Create Assistant is not accessible but upload is accessible', () => {
loginWithUserAndWaitForPage(CREATE_INTEGRATION_ASSISTANT, AutomaticImportConnectorAllUser);
cy.getBySel(CONNECTOR_BEDROCK).should('exist');
cy.getBySel(CONNECTOR_OPENAI).should('exist');
cy.getBySel(CONNECTOR_GEMINI).should('exist');
});
});
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/cypress/fixtures/teleport.ndjson
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"ei":0,"event":"cert.create","uid":"efd326fc-dd13-4df8-acef-3102c2d717d3","code":"TC000I","time":"2024-02-24T06:56:50.648137154Z"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export const UPLOAD_PACKAGE_LINK = 'uploadPackageLink';
export const ASSISTANT_BUTTON = 'assistantButton';
export const TECH_PREVIEW_BADGE = 'techPreviewBadge';
export const MISSING_PRIVILEGES = 'missingPrivilegesCallOut';

export const CONNECTOR_BEDROCK = 'actionType-.bedrock';
export const CONNECTOR_OPENAI = 'actionType-.gen-ai';
export const CONNECTOR_GEMINI = 'actionType-.gemini';

export const BUTTON_FOOTER_NEXT = 'buttonsFooter-nextButton';

export const INTEGRATION_TITLE_INPUT = 'integrationTitleInput';
export const INTEGRATION_DESCRIPTION_INPUT = 'integrationDescriptionInput';
export const DATASTREAM_TITLE_INPUT = 'dataStreamTitleInput';
export const DATASTREAM_DESCRIPTION_INPUT = 'dataStreamDescriptionInput';
export const DATASTREAM_NAME_INPUT = 'dataStreamNameInput';
export const DATA_COLLECTION_METHOD_INPUT = 'dataCollectionMethodInput';
export const LOGS_SAMPLE_FILE_PICKER = 'logsSampleFilePicker';

export const EDIT_PIPELINE_BUTTON = 'editPipelineButton';
export const SAVE_PIPELINE_BUTTON = 'savePipelineButton';
export const VIEW_INTEGRATION_BUTTON = 'viewIntegrationButton';
export const INTEGRATION_SUCCESS_SECTION = 'integrationSuccessSection';
export const SAVE_ZIP_BUTTON = 'saveZipButton';

export const CREATE_INTEGRATION_LANDING_PAGE = '/app/integrations/create';
export const CREATE_INTEGRATION_ASSISTANT = '/app/integrations/create/assistant';
export const CREATE_INTEGRATION_UPLOAD = '/app/integrations/create/upload';
Loading

0 comments on commit c920033

Please sign in to comment.