Skip to content

Commit

Permalink
Unit tests for public components #383
Browse files Browse the repository at this point in the history
[BUG] Detector Edit | Custom rule are not selected on update rules #406

Signed-off-by: Jovan Cvetkovic <[email protected]>
  • Loading branch information
jovancvetkovic3006 committed Feb 11, 2023
1 parent 31a5d5c commit e6055f5
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 62 deletions.
3 changes: 3 additions & 0 deletions cypress/fixtures/sample_index_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
},
"ServiceName": {
"type": "text"
},
"DnsQuestionName": {
"type": "text"
}
}
},
Expand Down
78 changes: 24 additions & 54 deletions cypress/integration/1_detectors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,21 @@

import { OPENSEARCH_DASHBOARDS_URL } from '../support/constants';
import sample_index_settings from '../fixtures/sample_index_settings.json';
import { recurse } from 'cypress-recurse';
import dns_rule_data from '../fixtures/integration_tests/rule/create_dns_rule.json';

const testMappings = {
properties: {
'host-hostname': {
type: 'alias',
path: 'HostName',
},
'windows-message': {
type: 'alias',
path: 'Message',
},
'winlog-provider_name': {
type: 'alias',
path: 'Provider_Name',
},
'winlog-event_data-ServiceName': {
type: 'alias',
path: 'ServiceName',
},
'winlog-event_id': {
path: 'EventID',
'dns-question-name': {
type: 'alias',
path: 'DnsQuestionName',
},
},
};

const cypressDNSRule = 'Cypress DNS Rule';

describe('Detectors', () => {
const indexName = 'cypress-test-windows';
const indexName = 'cypress-test-dns';
const detectorName = 'test detector';

before(() => {
Expand All @@ -47,13 +33,15 @@ describe('Detectors', () => {
query: {
nested: {
path: 'rule',
query: { bool: { must: [{ match: { 'rule.category': 'windows' } }] } },
query: { bool: { must: [{ match: { 'rule.category': 'dns' } }] } },
},
},
})
.should('have.property', 'status', 200)
);

cy.createRule(dns_rule_data);

cy.contains(detectorName).should('not.exist');
});

Expand Down Expand Up @@ -95,28 +83,28 @@ describe('Detectors', () => {
}).as('getSigmaRules');

// Select threat detector type (Windows logs)
cy.get(`input[id="windows"]`).click({ force: true });
cy.get(`input[id="dns"]`).click({ force: true });

cy.wait('@getSigmaRules').then(() => {
// Open Detection rules accordion
cy.get('[data-test-subj="detection-rules-btn"]').click({ force: true, timeout: 5000 });

cy.contains('table tr', 'Windows', {
cy.contains('table tr', 'DNS', {
timeout: 120000,
});

// find search, type USB
cy.get(`input[placeholder="Search..."]`).ospSearch('USB Device Plugged');
cy.get(`input[placeholder="Search..."]`).ospSearch(cypressDNSRule);

// Disable all rules
cy.contains('tr', 'USB Device Plugged', { timeout: 1000 });
cy.contains('tr', cypressDNSRule, { timeout: 1000 });
cy.get('table th').within(() => {
cy.get('button').first().click({ force: true });
});

// Enable single rule
cy.contains('table tr', 'USB Device Plugged').within(() => {
cy.get('button').eq(1).click({ force: true });
cy.contains('table tr', cypressDNSRule).within(() => {
cy.get('button').eq(1).click({ force: true, timeout: 2000 });
});
});

Expand All @@ -126,14 +114,6 @@ describe('Detectors', () => {
// Check that correct page now showing
cy.contains('Configure field mapping');

// Show 50 rows per page
cy.contains('Rows per page').click({ force: true });
cy.contains('50 rows').click({ force: true });

// Show 50 rows per page
cy.contains('Rows per page').click({ force: true });
cy.contains('50 rows').click({ force: true });

// Select appropriate names to map fields to
for (let field_name in testMappings.properties) {
const mappedTo = testMappings.properties[field_name].path;
Expand Down Expand Up @@ -174,10 +154,6 @@ describe('Detectors', () => {
// Confirm field mappings registered
cy.contains('Field mapping');

// Show 50 rows per page
cy.contains('Rows per page').click({ force: true });
cy.contains('50 rows').click({ force: true });

for (let field in testMappings.properties) {
const mappedTo = testMappings.properties[field].path;

Expand All @@ -188,7 +164,7 @@ describe('Detectors', () => {
// Confirm entries user has made
cy.contains('Detector details');
cy.contains(detectorName);
cy.contains('windows');
cy.contains('dns');
cy.contains(indexName);
cy.contains('Alert on test_trigger');

Expand Down Expand Up @@ -228,16 +204,10 @@ describe('Detectors', () => {
});

// Change detector name
const detectorNameText = 'test detector edited';
const detectorNameSelector = 'input[placeholder="Enter a name for the detector."]';
cy.get(detectorNameSelector).should('have.value', 'test detector');

recurse(
() => cy.get(detectorNameSelector).clear().type(detectorNameText),
($input) => $input.val() === detectorNameText
).then(() => {
cy.get(detectorNameSelector).should('have.value', 'test detector edited');
});
cy.get(`input[placeholder="Enter a name for the detector."]`)
.realClick()
.ospClear()
.realType('test detector edited');

// Change detector description
cy.get(`[data-test-subj="define-detector-detector-description"]`)
Expand Down Expand Up @@ -295,10 +265,10 @@ describe('Detectors', () => {
});

// Search for specific rule
cy.get(`input[placeholder="Search..."]`).ospSearch('USB Device');
cy.get(`input[placeholder="Search..."]`).ospSearch(cypressDNSRule);

// Toggle single search result to unchecked
cy.contains('table tr', 'USB Device Plugged').within(() => {
cy.contains('table tr', cypressDNSRule).within(() => {
// Of note, timeout can sometimes work instead of wait here, but is very unreliable from case to case.
cy.wait(1000);
cy.get('button').eq(1).click();
Expand All @@ -319,10 +289,10 @@ describe('Detectors', () => {
});

// Search for specific rule
cy.get(`input[placeholder="Search..."]`).ospSearch('USB');
cy.get(`input[placeholder="Search..."]`).ospSearch(cypressDNSRule);

// Toggle single search result to checked
cy.contains('table tr', 'USB Device Plugged').within(() => {
cy.contains('table tr', cypressDNSRule).within(() => {
cy.wait(2000);
cy.get('button').eq(1).click({ force: true });
});
Expand Down
4 changes: 3 additions & 1 deletion cypress/integration/4_findings.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ describe('Findings', () => {
cy.get('.euiFlexItem--flexGrowZero > .euiButtonIcon').click({ force: true });
});

it('displays finding details and create an index pattern from flyout', () => {
// TODO: this one triggers a button handler which goes throw condition and therefor is flaky
// find a better way to test this dialog, condition is based on `indexPatternId`
xit('displays finding details and create an index pattern from flyout', () => {
// filter table to show only sample_detector findings
cy.get(`input[placeholder="Search findings"]`).ospSearch('sample_detector');

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"resolutions": {
"@types/react": "^16.9.8",
"**/@types/angular": "1.6.50",
"**/@types/jest": "^24.0.9",
"**/@types/jest": "^29.3.1",
"**/@types/react-dom": "^16.9.8",
"eslint-utils": "^1.4.2",
"path-parse": "^1.0.7",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,13 @@ export const UpdateDetectorRules: React.FC<UpdateDetectorRulesProps> = (props) =
};

const getRules = async (detector: Detector) => {
const enabledRuleIds = detector.inputs[0].detector_input.pre_packaged_rules.map(
let enabledRuleIds = detector.inputs[0].detector_input.pre_packaged_rules.map(
(rule) => rule.id
);
const enabledCustomRuleIds = detector.inputs[0].detector_input.custom_rules.map(
(rule) => rule.id
);
enabledRuleIds = enabledRuleIds.concat(enabledCustomRuleIds);

const allRules = await rulesViewModelActor?.fetchRules(undefined, {
bool: {
Expand Down
8 changes: 4 additions & 4 deletions public/pages/Overview/utils/helper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
DateOpts,
getAlertsVisualizationSpec,
getChartTimeUnit,
getDomainRange,
getFindingsVisualizationSpec,
getOverviewVisualizationSpec,
getTimeTooltip,
Expand Down Expand Up @@ -127,9 +126,10 @@ describe('helper utilities spec', () => {

describe('tests parseDateString function', () => {
it(' - function should return datetime in ms', () => {
const time = moment(10);
jest.spyOn(dateMath, 'parse').mockReturnValue(time);
expect(parseDateString(DEFAULT_DATE_RANGE.start)).toBe(time.milliseconds());
const mockTime = moment('2023-01-25T10:05:00');
jest.spyOn(dateMath, 'parse').mockReturnValue(mockTime);
jest.fn().mockImplementation('parseDateString', () => mockTime.milliseconds());
expect(parseDateString(DEFAULT_DATE_RANGE.start)).toBe(mockTime._d.getTime());
});
});

Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
"skipLibCheck": true,
"esModuleInterop": true,
"outDir": "./target",
"types": ["cypress", "node", "cypress-real-events"]
"types": ["cypress", "node", "cypress-real-events", "jest"]
}
}

0 comments on commit e6055f5

Please sign in to comment.