Skip to content

Commit

Permalink
updated UI; tests
Browse files Browse the repository at this point in the history
Signed-off-by: Amardeepsingh Siglani <[email protected]>
  • Loading branch information
amsiglan committed Oct 25, 2023
1 parent add406a commit 8d96f57
Show file tree
Hide file tree
Showing 21 changed files with 733 additions and 1,811 deletions.
299 changes: 161 additions & 138 deletions cypress/integration/1_detectors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const cypressIndexDns = 'cypress-index-dns';
const cypressIndexWindows = 'cypress-index-windows';
const detectorName = 'test detector';
const cypressLogTypeDns = 'dns';
const sampleNotificationChannel = 'sample_chime_channel';

const cypressDNSRule = dns_name_rule_data.title;

Expand All @@ -41,6 +42,10 @@ const logTypeLabel = 'Log type';

const getLogTypeField = () => cy.getFieldByLabel(logTypeLabel);

const notificationLabel = 'Notification channel';

const getNotificationField = () => cy.getFieldByLabel(notificationLabel);

const openDetectorDetails = (detectorName) => {
cy.getInputByPlaceholder('Search threat detectors').type(`${detectorName}`).pressEnterKey();
cy.getElementByText('.euiTableCellContent button', detectorName).click();
Expand Down Expand Up @@ -150,6 +155,8 @@ const createDetector = (detectorName, dataSource, expectFailure) => {
.focus()
.blur();

getNotificationField().selectComboboxItem(`[Channel] ${sampleNotificationChannel}`);

cy.intercept('POST', '/_plugins/_security_analytics/mappings').as('createMappingsRequest');
cy.intercept('POST', '/_plugins/_security_analytics/detectors').as('createDetectorRequest');

Expand All @@ -166,8 +173,6 @@ const createDetector = (detectorName, dataSource, expectFailure) => {
cy.url()
.should('contain', detectorId)
.then(() => {
cy.getElementByText('.euiCallOut', `Detector created successfully: ${detectorName}`);

// Confirm detector state
cy.getElementByText('.euiTitle', detectorName);
cy.getElementByText('.euiHealth', 'Active').then(() => {
Expand Down Expand Up @@ -215,144 +220,156 @@ describe('Detectors', () => {

cy.createRule(dns_name_rule_data);
cy.createRule(dns_type_rule_data);
});

describe('...should validate form fields', () => {
beforeEach(() => {
cy.intercept('/_plugins/_security_analytics/detectors/_search').as('detectorsSearch');

// Visit Detectors page before any test
cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`);
cy.wait('@detectorsSearch').should('have.property', 'state', 'Complete');

openCreateForm();
});

it('...should validate name field', () => {
getNameField().should('be.empty');
getNameField().focus().blur();
getNameField().parentsUntil('.euiFormRow__fieldWrapper').siblings().contains('Enter a name.');

getNameField().type('text').focus().blur();

getNameField()
.parents('.euiFormRow__fieldWrapper')
.find('.euiFormErrorText')
.contains(
'Name should only consist of upper and lowercase letters, numbers 0-9, hyphens, spaces, and underscores. Use between 5 and 50 characters.'
);

getNameField().type('{selectall}').type('{backspace}').type('tex&').focus().blur();

getNameField()
.parents('.euiFormRow__fieldWrapper')
.find('.euiFormErrorText')
.contains(
'Name should only consist of upper and lowercase letters, numbers 0-9, hyphens, spaces, and underscores. Use between 5 and 50 characters.'
);

getNameField()
.type('{selectall}')
.type('{backspace}')
.type('Detector name')
.focus()
.blur()
.parents('.euiFormRow__fieldWrapper')
.find('.euiFormErrorText')
.should('not.exist');
});

it('...should validate description field', () => {
const longDescriptionText =
'This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.';

getDescriptionField().should('be.empty');

getDescriptionField().type(longDescriptionText).focus().blur();

getDescriptionField()
.parents('.euiFormRow__fieldWrapper')
.find('.euiFormErrorText')
.contains(
'Description should only consist of upper and lowercase letters, numbers 0-9, commas, hyphens, periods, spaces, and underscores. Max limit of 500 characters.'
);

getDescriptionField()
.type('{selectall}')
.type('{backspace}')
.type('Detector description...')
.focus()
.blur();

getDescriptionField()
.type('{selectall}')
.type('{backspace}')
.type('Detector name')
.focus()
.blur()
.parents('.euiFormRow__fieldWrapper')
.find('.euiFormErrorText')
.should('not.exist');
});

it('...should validate data source field', () => {
getDataSourceField()
.focus()
.blur()
.parentsUntil('.euiFormRow__fieldWrapper')
.siblings()
.contains('Select an input source.');

getDataSourceField().selectComboboxItem(cypressIndexDns);
getDataSourceField()
.focus()
.blur()
.parentsUntil('.euiFormRow__fieldWrapper')
.find('.euiFormErrorText')
.should('not.exist');
});

it('...should validate next button', () => {
getNextButton().should('be.disabled');

fillDetailsForm(detectorName, cypressIndexDns);
getNextButton().should('be.enabled');
});

it('...should validate alerts page', () => {
fillDetailsForm(detectorName, cypressIndexDns);
getNextButton().click({ force: true });
// Open the trigger details accordion
cy.get('[data-test-subj="trigger-details-btn"]').click({ force: true });
getTriggerNameField().should('have.value', 'Trigger 1');
getTriggerNameField()
.parents('.euiFormRow__fieldWrapper')
.find('.euiFormErrorText')
.should('not.exist');

getCreateDetectorButton().should('be.enabled');

getTriggerNameField().type('{selectall}').type('{backspace}').focus().blur();
getCreateDetectorButton().should('be.disabled');

cy.getButtonByText('Remove').click({ force: true });
getCreateDetectorButton().should('be.enabled');
});

it('...should show mappings warning', () => {
fillDetailsForm(detectorName, cypressIndexDns);

getDataSourceField().selectComboboxItem(cypressIndexWindows);
getDataSourceField().focus().blur();

cy.get('[data-test-subj="define-detector-diff-log-types-warning"]')
.should('be.visible')
.contains(
'To avoid issues with field mappings, we recommend creating separate detectors for different log types.'
);
});
cy.request('POST', 'http://localhost:9200/_plugins/_notifications/configs/', {
config_id: 'sa_notification-channel_id',
name: sampleNotificationChannel,
config: {
name: sampleNotificationChannel,
description: 'This is a sample chime channel',
config_type: 'chime',
is_enabled: true,
chime: {
url: 'https://sample-chime-webhook',
},
},
}).should('have.property', 'status', 200);
});

// describe('...should validate form fields', () => {
// beforeEach(() => {
// cy.intercept('/_plugins/_security_analytics/detectors/_search').as('detectorsSearch');

// // Visit Detectors page before any test
// cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`);
// cy.wait('@detectorsSearch').should('have.property', 'state', 'Complete');

// openCreateForm();
// });

// it('...should validate name field', () => {
// getNameField().should('be.empty');
// getNameField().focus().blur();
// getNameField().parentsUntil('.euiFormRow__fieldWrapper').siblings().contains('Enter a name.');

// getNameField().type('text').focus().blur();

// getNameField()
// .parents('.euiFormRow__fieldWrapper')
// .find('.euiFormErrorText')
// .contains(
// 'Name should only consist of upper and lowercase letters, numbers 0-9, hyphens, spaces, and underscores. Use between 5 and 50 characters.'
// );

// getNameField().type('{selectall}').type('{backspace}').type('tex&').focus().blur();

// getNameField()
// .parents('.euiFormRow__fieldWrapper')
// .find('.euiFormErrorText')
// .contains(
// 'Name should only consist of upper and lowercase letters, numbers 0-9, hyphens, spaces, and underscores. Use between 5 and 50 characters.'
// );

// getNameField()
// .type('{selectall}')
// .type('{backspace}')
// .type('Detector name')
// .focus()
// .blur()
// .parents('.euiFormRow__fieldWrapper')
// .find('.euiFormErrorText')
// .should('not.exist');
// });

// it('...should validate description field', () => {
// const longDescriptionText =
// 'This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text.';

// getDescriptionField().should('be.empty');

// getDescriptionField().type(longDescriptionText).focus().blur();

// getDescriptionField()
// .parents('.euiFormRow__fieldWrapper')
// .find('.euiFormErrorText')
// .contains(
// 'Description should only consist of upper and lowercase letters, numbers 0-9, commas, hyphens, periods, spaces, and underscores. Max limit of 500 characters.'
// );

// getDescriptionField()
// .type('{selectall}')
// .type('{backspace}')
// .type('Detector description...')
// .focus()
// .blur();

// getDescriptionField()
// .type('{selectall}')
// .type('{backspace}')
// .type('Detector name')
// .focus()
// .blur()
// .parents('.euiFormRow__fieldWrapper')
// .find('.euiFormErrorText')
// .should('not.exist');
// });

// it('...should validate data source field', () => {
// getDataSourceField()
// .focus()
// .blur()
// .parentsUntil('.euiFormRow__fieldWrapper')
// .siblings()
// .contains('Select an input source.');

// getDataSourceField().selectComboboxItem(cypressIndexDns);
// getDataSourceField()
// .focus()
// .blur()
// .parentsUntil('.euiFormRow__fieldWrapper')
// .find('.euiFormErrorText')
// .should('not.exist');
// });

// it('...should validate next button', () => {
// getNextButton().should('be.disabled');

// fillDetailsForm(detectorName, cypressIndexDns);
// getNextButton().should('be.enabled');
// });

// it('...should validate alerts page', () => {
// fillDetailsForm(detectorName, cypressIndexDns);
// getNextButton().click({ force: true });
// // Open the trigger details accordion
// cy.get('[data-test-subj="trigger-details-btn"]').click({ force: true });
// getTriggerNameField().should('have.value', 'Trigger 1');
// getTriggerNameField()
// .parents('.euiFormRow__fieldWrapper')
// .find('.euiFormErrorText')
// .should('not.exist');

// getTriggerNameField().type('{selectall}').type('{backspace}').focus().blur();
// getCreateDetectorButton().should('be.disabled');

// cy.getButtonByText('Remove').click({ force: true });
// getCreateDetectorButton().should('be.enabled');
// });

// it('...should show mappings warning', () => {
// fillDetailsForm(detectorName, cypressIndexDns);

// getDataSourceField().selectComboboxItem(cypressIndexWindows);
// getDataSourceField().focus().blur();

// cy.get('[data-test-subj="define-detector-diff-log-types-warning"]')
// .should('be.visible')
// .contains(
// 'To avoid issues with field mappings, we recommend creating separate detectors for different log types.'
// );
// });
// });

describe('...validate create detector flow', () => {
beforeEach(() => {
cy.intercept('/_plugins/_security_analytics/detectors/_search').as('detectorsSearch');
Expand Down Expand Up @@ -495,5 +512,11 @@ describe('Detectors', () => {
});
});

after(() => cy.cleanUpTests());
after(() => {
cy.cleanUpTests();
cy.request(
'DELETE',
'http://localhost:9200/_plugins/_notifications/configs/sa_notification-channel_id'
);
});
});
21 changes: 10 additions & 11 deletions public/pages/Alerts/components/AlertFlyout/AlertFlyout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
import { AlertItem, RuleSource } from '../../../../../server/models/interfaces';
import React from 'react';
import { ContentPanel } from '../../../../components/ContentPanel';
import { ALERT_STATE, DEFAULT_EMPTY_DATA } from '../../../../utils/constants';
import { ALERT_STATE, DEFAULT_EMPTY_DATA, ROUTES } from '../../../../utils/constants';
import {
capitalizeFirstLetter,
createTextDetailsGroup,
Expand Down Expand Up @@ -174,10 +174,9 @@ export class AlertFlyout extends React.Component<AlertFlyoutProps, AlertFlyoutSt
) || DEFAULT_EMPTY_DATA,
},
{
field: 'queries',
name: 'Rule name',
sortable: true,
render: (queries: any[]) => rules[queries[0]?.id]?.title || DEFAULT_EMPTY_DATA,
field: 'detectionType',
name: 'Detection type',
render: (detectionType: string) => detectionType || DEFAULT_EMPTY_DATA,
},
{
field: 'detector_id',
Expand Down Expand Up @@ -258,12 +257,12 @@ export class AlertFlyout extends React.Component<AlertFlyoutProps, AlertFlyoutSt
{createTextDetailsGroup([
{ label: 'Start time', content: renderTime(start_time) },
{ label: 'Last updated time', content: renderTime(last_notification_time) },
{ label: '', content: '' },
])}
{createTextDetailsGroup([
{ label: 'Detector', content: detector.name },
{ label: '', content: '' },
{ label: '', content: '' },
{
label: 'Detector',
content: detector.name,
url: `#${ROUTES.DETECTOR_DETAILS}/${detector.id}`,
target: '_blank',
},
])}

<EuiSpacer size={'xxl'} />
Expand Down
Loading

0 comments on commit 8d96f57

Please sign in to comment.