From 5bede9facd63474d2ab4a14b1cc3215861905732 Mon Sep 17 00:00:00 2001 From: Tomasz Ciecierski Date: Wed, 1 Nov 2023 07:09:41 +0100 Subject: [PATCH] [EDR Workflows] Verify flaky osquery tests (#169749) (cherry picked from commit a15a9484e67b52fe4c8d2b411f1f621a2e3bb1c8) # Conflicts: # .buildkite/scripts/lifecycle/post_command.sh # x-pack/plugins/osquery/cypress/e2e/all/alerts_automated_action_results.cy.ts # x-pack/plugins/osquery/cypress/e2e/all/alerts_response_actions_form.cy.ts # x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts # x-pack/plugins/osquery/cypress/support/e2e.ts --- .buildkite/scripts/lifecycle/post_command.sh | 2 + .../plugins/osquery/cypress/cypress.config.ts | 5 +- .../all/alerts_automated_action_results.cy.ts | 51 +++- .../cypress/e2e/all/alerts_cases.cy.ts | 4 + .../cypress/e2e/all/alerts_linked_apps.cy.ts | 5 +- .../e2e/all/alerts_multiple_agents.cy.ts | 2 + .../all/alerts_response_actions_form.cy.ts | 264 ++++++++---------- .../osquery/cypress/e2e/all/cases.cy.ts | 10 +- .../cypress/e2e/all/custom_space.cy.ts | 2 + .../cypress/e2e/all/ecs_mappings.cy.ts | 5 + .../osquery/cypress/e2e/all/live_query.cy.ts | 2 +- .../cypress/e2e/all/packs_create_edit.cy.ts | 6 +- .../cypress/e2e/all/packs_integration.cy.ts | 84 +++--- .../cypress/e2e/all/saved_queries.cy.ts | 29 +- .../osquery/cypress/e2e/all/timelines.cy.ts | 4 + .../cypress/e2e/roles/alert_test.cy.ts | 2 + .../cypress/serverless_cypress.config.ts | 6 +- x-pack/plugins/osquery/cypress/support/e2e.ts | 6 + .../osquery/cypress/support/filter_videos.ts | 21 ++ .../osquery/cypress/tasks/integrations.ts | 3 +- .../osquery/cypress/tasks/inventory.ts | 12 +- .../osquery/cypress/tasks/live_query.ts | 4 +- x-pack/plugins/osquery/cypress/tasks/login.ts | 17 ++ .../osquery/cypress/tasks/navigation.ts | 13 + x-pack/plugins/osquery/cypress/tasks/packs.ts | 24 +- .../osquery/cypress/tasks/wait_until.ts | 2 +- .../public/packs/active_state_switch.tsx | 1 + .../osquery/public/packs/add_pack_button.tsx | 1 + .../osquery/public/packs/form/index.tsx | 1 + x-pack/test/osquery_cypress/agent.ts | 20 +- x-pack/test/osquery_cypress/runner.ts | 10 +- x-pack/test/osquery_cypress/utils.ts | 4 + 32 files changed, 363 insertions(+), 259 deletions(-) create mode 100644 x-pack/plugins/osquery/cypress/support/filter_videos.ts create mode 100644 x-pack/plugins/osquery/cypress/tasks/login.ts diff --git a/.buildkite/scripts/lifecycle/post_command.sh b/.buildkite/scripts/lifecycle/post_command.sh index 01877bedbef8c..d0a5837ed5a67 100755 --- a/.buildkite/scripts/lifecycle/post_command.sh +++ b/.buildkite/scripts/lifecycle/post_command.sh @@ -14,6 +14,8 @@ if [[ "$IS_TEST_EXECUTION_STEP" == "true" ]]; then buildkite-agent artifact upload 'target/kibana-coverage/functional/**/*' buildkite-agent artifact upload 'target/kibana-*' buildkite-agent artifact upload 'target/kibana-security-solution/**/*.png' + buildkite-agent artifact upload 'target/kibana-osquery/**/*.png' + buildkite-agent artifact upload 'target/kibana-osquery/**/*.mp4' buildkite-agent artifact upload 'target/kibana-fleet/**/*.png' buildkite-agent artifact upload 'target/test-metrics/*' buildkite-agent artifact upload 'target/test-suites-ci-plan.json' diff --git a/x-pack/plugins/osquery/cypress/cypress.config.ts b/x-pack/plugins/osquery/cypress/cypress.config.ts index 26b1d9b67850d..9d3b7d075a50e 100644 --- a/x-pack/plugins/osquery/cypress/cypress.config.ts +++ b/x-pack/plugins/osquery/cypress/cypress.config.ts @@ -11,6 +11,7 @@ import path from 'path'; import { safeLoad as loadYaml } from 'js-yaml'; import { readFileSync } from 'fs'; +import { getFailedSpecVideos } from './support/filter_videos'; import type { YamlRoleDefinitions } from '../../../test_serverless/shared/lib'; import { setupUserDataLoader } from '../../../test_serverless/functional/test_suites/security/cypress/support/setup_data_loader_tasks'; const ROLES_YAML_FILE_PATH = path.join( @@ -31,8 +32,9 @@ export default defineCypressConfig({ screenshotsFolder: '../../../target/kibana-osquery/cypress/screenshots', trashAssetsBeforeRuns: false, - video: false, + video: true, videosFolder: '../../../target/kibana-osquery/cypress/videos', + videoCompression: 15, viewportHeight: 900, viewportWidth: 1440, experimentalStudio: true, @@ -54,6 +56,7 @@ export default defineCypressConfig({ numTestsKeptInMemory: 3, setupNodeEvents(on, config) { setupUserDataLoader(on, config, { roleDefinitions, additionalRoleName: 'viewer' }); + on('after:spec', getFailedSpecVideos); return config; }, diff --git a/x-pack/plugins/osquery/cypress/e2e/all/alerts_automated_action_results.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts_automated_action_results.cy.ts index 4505af882da94..1a8854c479775 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts_automated_action_results.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts_automated_action_results.cy.ts @@ -5,23 +5,52 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { cleanupRule, loadRule } from '../../tasks/api_fixtures'; import { checkActionItemsInResults, loadRuleAlerts } from '../../tasks/live_query'; const UUID_REGEX = '[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}'; -describe( - 'Alert Flyout Automated Action Results', - { - tags: ['@ess', '@serverless'], - }, - () => { - let ruleId: string; +describe('Alert Flyout Automated Action Results', () => { + let ruleId: string; - beforeEach(() => { - loadRule(true).then((data) => { - ruleId = data.id; - loadRuleAlerts(data.name); + before(() => { + initializeDataViews(); + }); + + beforeEach(() => { + loadRule(true).then((data) => { + ruleId = data.id; + loadRuleAlerts(data.name); + }); + }); + + afterEach(() => { + cleanupRule(ruleId); + }); + + it('can visit discover from response action results', { tags: ['@ess'] }, () => { + const discoverRegex = new RegExp(`action_id: ${UUID_REGEX}`); + cy.getBySel('expand-event').first().click(); + cy.getBySel('securitySolutionFlyoutResponseSectionHeader').click(); + cy.getBySel('securitySolutionFlyoutResponseButton').click(); + cy.getBySel('responseActionsViewWrapper').should('exist'); + checkActionItemsInResults({ + lens: true, + discover: true, + cases: true, + timeline: true, + }); + cy.contains('View in Discover') + .should('exist') + .should('have.attr', 'href') + .then(($href) => { + // @ts-expect-error-next-line href string - check types + cy.visit($href); + cy.getBySel('discoverDocTable', { timeout: 60000 }).within(() => { + cy.contains('action_data{ "query":'); + }); + cy.contains(discoverRegex); }); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/alerts_cases.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts_cases.cy.ts index 2d681bdc71729..3c93bef865b96 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts_cases.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts_cases.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { OSQUERY_FLYOUT_BODY_EDITOR } from '../../screens/live_query'; import { cleanupCase, @@ -29,6 +30,9 @@ describe('Alert Event Details - Cases', { tags: ['@ess', '@serverless'] }, () => let packId: string; let packName: string; const packData = packFixture(); + before(() => { + initializeDataViews(); + }); beforeEach(() => { loadPack(packData).then((data) => { diff --git a/x-pack/plugins/osquery/cypress/e2e/all/alerts_linked_apps.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts_linked_apps.cy.ts index 8fca7b0164eef..945410e656beb 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts_linked_apps.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts_linked_apps.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { cleanupRule, loadRule } from '../../tasks/api_fixtures'; import { RESPONSE_ACTIONS_ITEM_0, RESPONSE_ACTIONS_ITEM_1 } from '../../tasks/response_actions'; import { @@ -25,7 +26,9 @@ describe( () => { let ruleId: string; let ruleName: string; - + before(() => { + initializeDataViews(); + }); beforeEach(() => { loadRule().then((data) => { ruleId = data.id; diff --git a/x-pack/plugins/osquery/cypress/e2e/all/alerts_multiple_agents.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts_multiple_agents.cy.ts index 6dde203828a19..afea9bb8c0adf 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts_multiple_agents.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts_multiple_agents.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { cleanupRule, loadRule } from '../../tasks/api_fixtures'; import { inputQuery, @@ -24,6 +25,7 @@ describe( let ruleName: string; before(() => { + initializeDataViews(); loadRule(true).then((data) => { ruleId = data.id; ruleName = data.name; diff --git a/x-pack/plugins/osquery/cypress/e2e/all/alerts_response_actions_form.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts_response_actions_form.cy.ts index 6b8f314ba8d58..a88e15d2cb8da 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts_response_actions_form.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts_response_actions_form.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { cleanupPack, cleanupRule, @@ -27,47 +28,22 @@ import { } from '../../tasks/live_query'; import { closeDateTabIfVisible, closeToastIfVisible } from '../../tasks/integrations'; -interface ITestRuleBody { - response_actions: [ - { - params: { - queries: Array<{ - interval?: number; - query: string; - platform: string; - id: string; - }>; - }; - } - ]; -} -// flaky -describe.skip( - 'Alert Event Details - Response Actions Form', - { tags: ['@ess', '@serverless'] }, - () => { - let multiQueryPackId: string; - let multiQueryPackName: string; - let ruleId: string; - let ruleName: string; - let packId: string; - let packName: string; - const packData = packFixture(); - const multiQueryPackData = multiQueryPackFixture(); - - beforeEach(() => { - loadPack(packData).then((data) => { - packId = data.saved_object_id; - packName = data.name; - }); - loadPack(multiQueryPackData).then((data) => { - multiQueryPackId = data.saved_object_id; - multiQueryPackName = data.name; - }); - loadRule().then((data) => { - ruleId = data.id; - ruleName = data.name; - }); +describe('Alert Event Details - Response Actions Form', { tags: ['@ess', '@serverless'] }, () => { + let multiQueryPackId: string; + let multiQueryPackName: string; + let ruleId: string; + let ruleName: string; + let packId: string; + let packName: string; + const packData = packFixture(); + const multiQueryPackData = multiQueryPackFixture(); + before(() => { + initializeDataViews(); + }); + beforeEach(() => { + loadPack(packData).then((data) => { + packId = data.saved_object_id; + packName = data.name; }); afterEach(() => { cleanupPack(packId); @@ -75,101 +51,104 @@ describe.skip( cleanupRule(ruleId); }); - it('adds response actions with osquery with proper validation and form values', () => { - cy.visit('/app/security/rules'); - clickRuleName(ruleName); - cy.getBySel('editRuleSettingsLink').click(); - cy.getBySel('globalLoadingIndicator').should('not.exist'); - closeDateTabIfVisible(); - cy.getBySel('edit-rule-actions-tab').click(); - cy.contains('Response actions are run on each rule execution.'); - cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click(); - cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { - cy.contains('Query is a required field'); - inputQuery('select * from uptime1'); - }); - cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click(); - cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { - cy.contains('Run a set of queries in a pack').click(); - }); - cy.getBySel('response-actions-error') - .within(() => { - cy.contains('Pack is a required field'); - }) - .should('exist'); - cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { + it('adds response actions with osquery with proper validation and form values', () => { + cy.visit('/app/security/rules'); + clickRuleName(ruleName); + cy.getBySel('globalLoadingIndicator').should('not.exist'); + cy.getBySel('editRuleSettingsLink').click(); + cy.getBySel('globalLoadingIndicator').should('not.exist'); + closeDateTabIfVisible(); + cy.getBySel('edit-rule-actions-tab').click(); + cy.contains('Response actions are run on each rule execution.'); + cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click(); + cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { + cy.contains('Query is a required field'); + inputQuery('select * from uptime1'); + }); + cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click(); + cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { + cy.contains('Run a set of queries in a pack').click(); + }); + cy.getBySel('response-actions-error') + .within(() => { cy.contains('Pack is a required field'); cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`); }); cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click(); - cy.getBySel(RESPONSE_ACTIONS_ITEM_2).within(() => { + cy.getBySel(RESPONSE_ACTIONS_ITEM_2) + .within(() => { cy.contains('Query is a required field'); inputQuery('select * from uptime'); + cy.contains('Query is a required field').should('not.exist'); cy.contains('Advanced').click(); - typeInECSFieldInput('message{downArrow}{enter}'); + typeInECSFieldInput('{downArrow}{enter}'); cy.getBySel('osqueryColumnValueSelect').type('days{downArrow}{enter}'); - cy.wait(1000); // wait for the validation to trigger - cypress is way faster than users ;) - }); + }) + .clickOutside(); cy.getBySel('ruleEditSubmitButton').click(); cy.contains(`${ruleName} was saved`).should('exist'); closeToastIfVisible(); - cy.getBySel('editRuleSettingsLink').click(); - cy.getBySel('globalLoadingIndicator').should('not.exist'); - cy.getBySel('edit-rule-actions-tab').click(); - cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { - cy.contains('select * from uptime1'); - }); - cy.getBySel(RESPONSE_ACTIONS_ITEM_2).within(() => { - cy.contains('select * from uptime'); - cy.contains('Log message optimized for viewing in a log viewer'); - cy.contains('Days of uptime'); - }); - cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { - cy.contains(packName); - cy.getBySel('comboBoxInput').type('{backspace}{enter}'); - }); - cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { - cy.contains('select * from uptime1'); - cy.getBySel('remove-response-action').click(); - }); - cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { + cy.getBySel('globalLoadingIndicator').should('not.exist'); + cy.getBySel('editRuleSettingsLink').click(); + cy.getBySel('globalLoadingIndicator').should('not.exist'); + cy.getBySel('edit-rule-actions-tab').click(); + cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { + cy.contains('select * from uptime1'); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_2).within(() => { + cy.contains('select * from uptime'); + cy.contains('Custom key/value pairs. e.g. {"application":"foo-bar","env":"production"}'); + cy.contains('Days of uptime'); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { + cy.contains(packName); + cy.getBySel('comboBoxInput').type('{backspace}{enter}'); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { + cy.contains('select * from uptime1'); + cy.getBySel('remove-response-action').click(); + }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_0) + .within(() => { cy.contains('Search for a pack to run'); cy.contains('Pack is a required field'); cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`); - }); - cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { - cy.contains('select * from uptime'); - cy.contains('Log message optimized for viewing in a log viewer'); - cy.contains('Days of uptime'); - }); - cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleChangesOne'); - cy.getBySel('ruleEditSubmitButton').click(); + }) + .clickOutside(); + cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { + cy.contains('select * from uptime'); + cy.contains('Custom key/value pairs. e.g. {"application":"foo-bar","env":"production"}'); + cy.contains('Days of uptime'); + }); + + cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleSingleQuery'); - cy.wait('@saveRuleChangesOne'); - cy.get<{ request: { url: string; body: ITestRuleBody } }>('@saveRuleChangesOne').should( - ({ request }) => { - const oneQuery = [ - { - interval: 3600, - query: 'select * from uptime;', - id: Object.keys(packData.queries)[0], - }, - ]; - expect(request.body.response_actions[0].params.queries).to.deep.equal(oneQuery); - } - ); + cy.getBySel('ruleEditSubmitButton').click(); + cy.wait('@saveRuleSingleQuery').should(({ request }) => { + const oneQuery = [ + { + interval: 3600, + query: 'select * from uptime;', + id: Object.keys(packData.queries)[0], + }, + ]; + expect(request.body.response_actions[0].params.queries).to.deep.equal(oneQuery); + }); cy.contains(`${ruleName} was saved`).should('exist'); closeToastIfVisible(); - cy.getBySel('editRuleSettingsLink').click(); - cy.getBySel('globalLoadingIndicator').should('not.exist'); - cy.getBySel('edit-rule-actions-tab').click(); - cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { + cy.getBySel('globalLoadingIndicator').should('not.exist'); + cy.getBySel('editRuleSettingsLink').click(); + cy.getBySel('globalLoadingIndicator').should('not.exist'); + + cy.getBySel('edit-rule-actions-tab').click(); + cy.getBySel(RESPONSE_ACTIONS_ITEM_0) + .within(() => { cy.contains(packName); cy.getBySel('comboBoxInput').type(`${multiQueryPackName}{downArrow}{enter}`); checkActionItemsInResults({ @@ -186,31 +165,36 @@ describe.skip( }); cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleChangesTwo'); - cy.contains('Save changes').click(); - cy.wait('@saveRuleChangesTwo'); - cy.get<{ request: { url: string; body: ITestRuleBody } }>('@saveRuleChangesTwo').should( - ({ request }) => { - const threeQueries = [ - { - interval: 3600, - query: 'SELECT * FROM memory_info;', - platform: 'linux', - id: Object.keys(multiQueryPackData.queries)[0], - }, - { - interval: 3600, - query: 'SELECT * FROM system_info;', - id: Object.keys(multiQueryPackData.queries)[1], - }, - { - interval: 10, - query: 'select opera_extensions.* from users join opera_extensions using (uid);', - id: Object.keys(multiQueryPackData.queries)[2], - }, - ]; - expect(request.body.response_actions[0].params.queries).to.deep.equal(threeQueries); - } - ); + cy.getBySel(RESPONSE_ACTIONS_ITEM_1) + .within(() => { + cy.contains('select * from uptime'); + cy.contains('Custom key/value pairs. e.g. {"application":"foo-bar","env":"production"}'); + cy.contains('Days of uptime'); + }) + .clickOutside(); + cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleMultiQuery'); + + cy.contains('Save changes').click(); + cy.wait('@saveRuleMultiQuery').should(({ request }) => { + const threeQueries = [ + { + interval: 3600, + query: 'SELECT * FROM memory_info;', + platform: 'linux', + id: Object.keys(multiQueryPackData.queries)[0], + }, + { + interval: 3600, + query: 'SELECT * FROM system_info;', + id: Object.keys(multiQueryPackData.queries)[1], + }, + { + interval: 10, + query: 'select opera_extensions.* from users join opera_extensions using (uid);', + id: Object.keys(multiQueryPackData.queries)[2], + }, + ]; + expect(request.body.response_actions[0].params.queries).to.deep.equal(threeQueries); }); - } -); + }); +}); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/cases.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/cases.cy.ts index 4ba7ab5befabf..1c6a96bfccb4f 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/cases.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/cases.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { addLiveQueryToCase, checkActionItemsInResults, @@ -18,6 +19,7 @@ describe('Add to Cases', () => { let liveQueryId: string; let liveQueryQuery: string; before(() => { + initializeDataViews(); loadLiveQuery({ agent_all: true, query: "SELECT * FROM os_version where name='Ubuntu';", @@ -31,7 +33,7 @@ describe('Add to Cases', () => { describe('observability', { tags: ['@ess'] }, () => { let caseId: string; let caseTitle: string; - before(() => { + beforeEach(() => { loadCase('observability').then((caseInfo) => { caseId = caseInfo.id; caseTitle = caseInfo.title; @@ -40,7 +42,7 @@ describe('Add to Cases', () => { navigateTo('/app/osquery'); }); - after(() => { + afterEach(() => { cleanupCase(caseId); }); @@ -63,7 +65,7 @@ describe('Add to Cases', () => { let caseId: string; let caseTitle: string; - before(() => { + beforeEach(() => { loadCase('securitySolution').then((caseInfo) => { caseId = caseInfo.id; caseTitle = caseInfo.title; @@ -72,7 +74,7 @@ describe('Add to Cases', () => { navigateTo('/app/osquery'); }); - after(() => { + afterEach(() => { cleanupCase(caseId); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/custom_space.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/custom_space.cy.ts index 0c46fbf074966..7a232c880e922 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/custom_space.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/custom_space.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { navigateTo } from '../../tasks/navigation'; import { checkActionItemsInResults, @@ -28,6 +29,7 @@ describe('ALL - Custom space', () => { let spaceId: string; before(() => { + initializeDataViews(); cy.wrap( new Promise((resolve) => { if (testSpace.name !== 'default') { diff --git a/x-pack/plugins/osquery/cypress/e2e/all/ecs_mappings.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/ecs_mappings.cy.ts index 98ad7ad0a26c2..069753f96fa9a 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/ecs_mappings.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/ecs_mappings.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { getAdvancedButton } from '../../screens/integrations'; import { navigateTo } from '../../tasks/navigation'; import { @@ -19,6 +20,10 @@ import { import { ServerlessRoleName } from '../../support/roles'; describe('EcsMapping', { tags: ['@ess', '@serverless'] }, () => { + before(() => { + initializeDataViews(); + }); + beforeEach(() => { cy.login(ServerlessRoleName.SOC_MANAGER); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts index 2a920ef22ef6a..21308b52ba057 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts @@ -86,6 +86,6 @@ describe('ALL - Live Query', { tags: ['@ess', '@serverless'] }, () => { inputQuery('{selectall}{backspace}{selectall}{backspace}'); // not sure if this is how it used to work when I implemented the functionality, but let's leave it like this for now - cy.get(LIVE_QUERY_EDITOR).invoke('height').should('be.gt', 200).and('be.lt', 380); + cy.get(LIVE_QUERY_EDITOR).invoke('height').should('be.gt', 200).and('be.lt', 400); }); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts index 79afcb04cb9bb..63a6e43e825ec 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts @@ -15,7 +15,7 @@ import { findFormFieldByRowsLabelAndType, inputQuery, } from '../../tasks/live_query'; -import { activatePack, deactivatePack, preparePack } from '../../tasks/packs'; +import { changePackActiveStatus, preparePack } from '../../tasks/packs'; import { closeModalIfVisible, closeToastIfVisible, @@ -505,8 +505,8 @@ describe('Packs - Create and Edit', { tags: ['@ess', '@serverless'] }, () => { it('', () => { cy.contains('Packs').click(); - deactivatePack(packName); - activatePack(packName); + changePackActiveStatus(packName); + changePackActiveStatus(packName); }); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts index 49e01b5524ab3..995249b5db24e 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts @@ -8,17 +8,15 @@ import { find } from 'lodash'; import type { PackagePolicy } from '@kbn/fleet-plugin/common'; import { API_VERSIONS } from '../../../common/constants'; -import { FLEET_AGENT_POLICIES, navigateTo } from '../../tasks/navigation'; +import { FLEET_AGENT_POLICIES, navigateToWithoutWaitForReact } from '../../tasks/navigation'; import { checkActionItemsInResults, checkResults, deleteAndConfirm, - findAndClickButton, - findFormFieldByRowsLabelAndType, selectAllAgents, submitQuery, } from '../../tasks/live_query'; -import { activatePack, cleanupAllPrebuiltPacks, deactivatePack } from '../../tasks/packs'; +import { changePackActiveStatus, cleanupAllPrebuiltPacks } from '../../tasks/packs'; import { addIntegration, closeModalIfVisible, @@ -62,19 +60,19 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { cy.contains(integration).click(); addIntegration(AGENT_POLICY_NAME); cy.contains('Add Elastic Agent later').click(); - navigateTo('app/osquery/packs'); - findAndClickButton('Add pack'); - findFormFieldByRowsLabelAndType('Name', REMOVING_PACK); - findFormFieldByRowsLabelAndType('Scheduled agent policies (optional)', AGENT_POLICY_NAME); - findAndClickButton('Save pack'); - + navigateToWithoutWaitForReact('app/osquery/packs'); + cy.getBySel('addPackButton').click(); + cy.get('input[name="name"]').type(`${REMOVING_PACK}{downArrow}{enter}`); + cy.getBySel('policyIdsComboBox').type(`${AGENT_POLICY_NAME}{downArrow}{enter}`); + cy.getBySel('savePackButton').click(); closeToastIfVisible(); cy.getBySel('tablePaginationPopoverButton').click(); cy.getBySel('tablePagination-50-rows').click(); - cy.react('ScheduledQueryNameComponent', { props: { name: REMOVING_PACK } }).click(); + cy.contains(REMOVING_PACK).click(); cy.contains(`${REMOVING_PACK} details`).should('exist'); - findAndClickButton('Edit'); - cy.react('EuiComboBoxInput', { props: { value: AGENT_POLICY_NAME } }).should('exist'); + cy.get('span').contains('Edit').click(); + + cy.getBySel('comboBoxInput').contains(AGENT_POLICY_NAME).should('exist'); cy.visit(FLEET_AGENT_POLICIES); cy.contains(AGENT_POLICY_NAME).click(); @@ -86,12 +84,13 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { cy.contains(/^Delete integration$/).click(); closeModalIfVisible(); cy.contains(/^Deleted integration 'osquery_manager-*/); - navigateTo('app/osquery/packs'); + navigateToWithoutWaitForReact('app/osquery/packs'); cy.contains(REMOVING_PACK).click(); cy.contains(`${REMOVING_PACK} details`).should('exist'); cy.wait(1000); - findAndClickButton('Edit'); - cy.react('EuiComboBoxInput', { props: { value: '' } }).should('exist'); + cy.get('span').contains('Edit').click(); + + cy.getBySel('comboBoxInput').should('have.value', ''); }); } ); @@ -100,49 +99,44 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { afterEach(() => { cleanupAllPrebuiltPacks(); }); - const PREBUILD_PACK_NAME = 'it-compliance'; describe('', () => { beforeEach(() => { cy.login(ServerlessRoleName.SOC_MANAGER); - navigateTo('/app/osquery/packs'); + navigateToWithoutWaitForReact('/app/osquery/packs'); }); it('should load prebuilt packs', () => { cy.contains('Load Elastic prebuilt packs').click(); cy.contains('Load Elastic prebuilt packs').should('not.exist'); cy.wait(1000); - cy.react('EuiTableRow').should('have.length.above', 5); + cy.get('tbody > tr').should('have.length.above', 5); }); it('should be able to activate pack', () => { - activatePack(PREBUILD_PACK_NAME); - deactivatePack(PREBUILD_PACK_NAME); + changePackActiveStatus(PREBUILD_PACK_NAME); + changePackActiveStatus(PREBUILD_PACK_NAME); }); it('should be able to add policy to it', () => { cy.contains(PREBUILD_PACK_NAME).click(); cy.contains('Edit').click(); - findFormFieldByRowsLabelAndType( - 'Scheduled agent policies (optional)', - `${DEFAULT_POLICY} {downArrow}{enter}` - ); - cy.contains('Update pack').click(); + cy.getBySel('policyIdsComboBox').type(`${DEFAULT_POLICY} {downArrow}{enter}`); + cy.getBySel('updatePackButton').click(); cy.getBySel('confirmModalConfirmButton').click(); cy.contains(`Successfully updated "${PREBUILD_PACK_NAME}" pack`); }); it('should be able to activate pack with agent inside', () => { - activatePack(PREBUILD_PACK_NAME); - deactivatePack(PREBUILD_PACK_NAME); + changePackActiveStatus(PREBUILD_PACK_NAME); + changePackActiveStatus(PREBUILD_PACK_NAME); }); it('should not be able to update prebuilt pack', () => { cy.contains(PREBUILD_PACK_NAME).click(); cy.contains('Edit').click(); - cy.react('EuiFieldText', { props: { name: 'name', isDisabled: true } }); - cy.react('EuiFieldText', { props: { name: 'description', isDisabled: true } }); + cy.get('input[name="name"]').should('be.disabled'); + cy.get('input[name="description"]').should('be.disabled'); cy.contains('Add Query').should('not.exist'); - cy.react('ExpandedItemActions', { options: { timeout: 1000 } }); cy.get('.euiTableRowCell--hasActions').should('not.exist'); }); it('should be able to delete prebuilt pack and add it again', () => { @@ -156,7 +150,7 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { }); it('should be able to run live prebuilt pack', () => { - navigateTo('/app/osquery/live_queries'); + navigateToWithoutWaitForReact('/app/osquery/live_queries'); cy.contains('New live query').click(); cy.contains('Run a set of queries in a pack.').click(); cy.get(LIVE_QUERY_EDITOR).should('not.exist'); @@ -171,7 +165,7 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { cases: true, timeline: false, }); - navigateTo('/app/osquery'); + navigateToWithoutWaitForReact('/app/osquery'); cy.contains('osquery-monitoring'); }); }); @@ -179,8 +173,8 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { describe('Global packs', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { - cy.login('elastic'); - navigateTo('/app/osquery/packs'); + cy.login(ServerlessRoleName.PLATFORM_ENGINEER); + navigateToWithoutWaitForReact('/app/osquery/packs'); }); describe('add proper shard to policies packs config', () => { @@ -204,14 +198,12 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { }); it('add global packs to policies', () => { - findAndClickButton('Add pack'); - findFormFieldByRowsLabelAndType('Name', globalPack); + cy.getBySel('addPackButton').click(); + cy.get('input[name="name"]').type(`${globalPack}{downArrow}{enter}`); cy.getBySel('policyIdsComboBox').should('exist'); cy.getBySel('osqueryPackTypeGlobal').click(); cy.getBySel('policyIdsComboBox').should('not.exist'); - - findAndClickButton('Save pack'); - + cy.getBySel('savePackButton').click(); cy.getBySel('tablePaginationPopoverButton').click(); cy.getBySel('tablePagination-50-rows').click(); cy.contains(globalPack); @@ -268,8 +260,8 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { it('', () => { const shardPack = 'shardPack' + generateRandomStringName(1)[0]; - findAndClickButton('Add pack'); - findFormFieldByRowsLabelAndType('Name', shardPack); + cy.getBySel('addPackButton').click(); + cy.get('input[name="name"]').type(`${shardPack}{downArrow}{enter}`); cy.contains('Partial deployment (shards)').click(); cy.getBySel('packShardsForm-0').within(() => { @@ -280,7 +272,7 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { cy.getBySel('shards-field-policy').type(`${OSQUERY_POLICY}{downArrow}{enter}`); cy.get('#shardsPercentage1').type('{backspace}{backspace}{backspace}'); }); - findAndClickButton('Save pack'); + cy.getBySel('savePackButton').click(); cy.contains(`Successfully created "${shardPack}" pack`); closeToastIfVisible(); @@ -318,9 +310,9 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { cy.get('[data-test-subj="packShardsForm-1"]').within(() => { cy.get(`[aria-label="Delete shards row"]`).click(); }); - cy.getBySel('comboBoxInput').contains(OSQUERY_POLICY).should('not.exist'); - cy.getBySel('policyIdsComboBox').click(); - cy.contains(OSQUERY_POLICY).should('exist'); + cy.getBySel('policyIdsComboBox').contains(OSQUERY_POLICY).should('not.exist'); + cy.getBySel('policyIdsComboBox').click().type(`${OSQUERY_POLICY}{downArrow}{enter}`); + cy.getBySel('policyIdsComboBox').contains(OSQUERY_POLICY).should('exist'); }); }); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts index c7528a1410d87..dd812d25d6bc2 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts @@ -105,18 +105,14 @@ describe('ALL - Saved queries', { tags: ['@ess', '@serverless'] }, () => { }); it('checks result type on prebuilt saved query', () => { - cy.react('CustomItemAction', { - props: { index: 1, item: { id: 'users_elastic' } }, - }).click(); + cy.get(`[aria-label="Edit users_elastic"]`).click(); cy.getBySel('resultsTypeField').within(() => { cy.contains('Snapshot'); }); }); it('user can run prebuilt saved query and add to case', () => { - cy.react('PlayButtonComponent', { - props: { savedQuery: { id: 'users_elastic' } }, - }).click(); + cy.get(`[aria-label="Run users_elastic"]`).click(); selectAllAgents(); submitQuery(); @@ -126,9 +122,7 @@ describe('ALL - Saved queries', { tags: ['@ess', '@serverless'] }, () => { }); it('user can not delete prebuilt saved query but can delete normal saved query', () => { - cy.react('CustomItemAction', { - props: { index: 1, item: { id: 'users_elastic' } }, - }).click(); + cy.get(`[aria-label="Edit users_elastic"]`).click(); cy.contains('Delete query').should('not.exist'); navigateTo(`/app/osquery/saved_queries/${savedQueryId}`); @@ -142,18 +136,14 @@ describe('ALL - Saved queries', { tags: ['@ess', '@serverless'] }, () => { findAndClickButton('Add query'); cy.contains('Attach next query'); - cy.react('EuiComboBox', { - props: { placeholder: 'Search for a query to run, or write a new query below' }, - }) - .click() - .type('users_elastic{downArrow} {enter}'); + cy.getBySel('savedQuerySelect').click().type('users_elastic{downArrow} {enter}'); inputQuery('where name=1'); cy.getBySel('resultsTypeField').click(); cy.contains('Differential (Ignore removals)').click(); cy.contains('Unique identifier of the us').should('exist'); cy.contains('User ID').should('exist'); - cy.react('EuiFlyoutBody').within(() => { + cy.get(`[aria-labelledby="flyoutTitle"]`).within(() => { cy.getBySel('ECSMappingEditorForm') .first() .within(() => { @@ -162,16 +152,15 @@ describe('ALL - Saved queries', { tags: ['@ess', '@serverless'] }, () => { }); cy.contains('Unique identifier of the us').should('not.exist'); cy.contains('User ID').should('not.exist'); - cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click(); + cy.get(`[aria-labelledby="flyoutTitle"]`).contains('Save').click(); + + cy.get(`[aria-label="Edit users_elastic"]`).click(); - cy.react('CustomItemAction', { - props: { index: 0, item: { id: 'users_elastic' } }, - }).click(); cy.contains('SELECT * FROM users;where name=1'); cy.contains('Unique identifier of the us.').should('not.exist'); cy.contains('User ID').should('not.exist'); cy.contains('Differential (Ignore removals)').should('exist'); - cy.react('EuiFlyoutFooter').react('EuiButtonEmpty').contains('Cancel').click(); + cy.get(`[aria-labelledby="flyoutTitle"]`).contains('Cancel').click(); }); }); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/timelines.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/timelines.cy.ts index 08a1c0925ffb9..6c2380664ba4d 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/timelines.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/timelines.cy.ts @@ -5,10 +5,14 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { takeOsqueryActionWithParams } from '../../tasks/live_query'; import { ServerlessRoleName } from '../../support/roles'; describe.skip('ALL - Timelines', { tags: ['@ess'] }, () => { + before(() => { + initializeDataViews(); + }); beforeEach(() => { cy.login(ServerlessRoleName.SOC_MANAGER); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/roles/alert_test.cy.ts b/x-pack/plugins/osquery/cypress/e2e/roles/alert_test.cy.ts index 38352c49c6459..718c2f32fd581 100644 --- a/x-pack/plugins/osquery/cypress/e2e/roles/alert_test.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/roles/alert_test.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { checkResults, clickRuleName, submitQuery } from '../../tasks/live_query'; import { loadRule, cleanupRule } from '../../tasks/api_fixtures'; import { ServerlessRoleName } from '../../support/roles'; @@ -14,6 +15,7 @@ describe('Alert Test', { tags: ['@ess'] }, () => { let ruleId: string; before(() => { + initializeDataViews(); loadRule().then((data) => { ruleName = data.name; ruleId = data.id; diff --git a/x-pack/plugins/osquery/cypress/serverless_cypress.config.ts b/x-pack/plugins/osquery/cypress/serverless_cypress.config.ts index fff0d4431df52..9438a959ec7b1 100644 --- a/x-pack/plugins/osquery/cypress/serverless_cypress.config.ts +++ b/x-pack/plugins/osquery/cypress/serverless_cypress.config.ts @@ -6,6 +6,7 @@ */ import { defineCypressConfig } from '@kbn/cypress-config'; +import { getFailedSpecVideos } from './support/filter_videos'; import { setupUserDataLoader } from '../../../test_serverless/functional/test_suites/security/cypress/support/setup_data_loader_tasks'; // eslint-disable-next-line import/no-default-export @@ -16,7 +17,9 @@ export default defineCypressConfig({ responseTimeout: 60000, screenshotsFolder: '../../../target/kibana-osquery/cypress/screenshots', trashAssetsBeforeRuns: false, - video: false, + video: true, + videosFolder: '../../../target/kibana-osquery/cypress/videos', + videoCompression: 15, viewportHeight: 946, viewportWidth: 1680, @@ -35,6 +38,7 @@ export default defineCypressConfig({ numTestsKeptInMemory: 3, setupNodeEvents: (on, config) => { setupUserDataLoader(on, config, { additionalRoleName: 'viewer' }); + on('after:spec', getFailedSpecVideos); return config; }, diff --git a/x-pack/plugins/osquery/cypress/support/e2e.ts b/x-pack/plugins/osquery/cypress/support/e2e.ts index 3a3d32f4d0954..1f88082a22b21 100644 --- a/x-pack/plugins/osquery/cypress/support/e2e.ts +++ b/x-pack/plugins/osquery/cypress/support/e2e.ts @@ -23,6 +23,7 @@ // *********************************************************** // force ESM in this module + export {}; // @ts-expect-error ts(2306) module has some interesting ways of importing, see https://github.com/cypress-io/cypress/blob/0871b03c5b21711cd23056454da8f23dcaca4950/npm/grep/README.md#support-file @@ -31,6 +32,11 @@ import registerCypressGrep from '@cypress/grep'; registerCypressGrep(); import type { SecuritySolutionDescribeBlockFtrConfig } from '@kbn/security-solution-plugin/scripts/run_cypress/utils'; +<<<<<<< HEAD +======= +import { login } from '@kbn/security-solution-plugin/public/management/cypress/tasks/login'; + +>>>>>>> a15a9484e67 ([EDR Workflows] Verify flaky osquery tests (#169749)) import type { ServerlessRoleName } from './roles'; import 'cypress-react-selector'; diff --git a/x-pack/plugins/osquery/cypress/support/filter_videos.ts b/x-pack/plugins/osquery/cypress/support/filter_videos.ts new file mode 100644 index 0000000000000..69826fb39b0bc --- /dev/null +++ b/x-pack/plugins/osquery/cypress/support/filter_videos.ts @@ -0,0 +1,21 @@ +/* + * 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 fs from 'fs'; + +// makes sure we save videos just for failed specs +export const getFailedSpecVideos = (spec: Cypress.Spec, results: CypressCommandLine.RunResult) => { + if (results && results.video) { + // Do we have failures for any retry attempts? + const failures = results.tests.some((test) => + test.attempts.some((attempt) => attempt.state === 'failed') + ); + if (!failures) { + // delete the video if the spec passed and no tests retried + fs.unlinkSync(results.video); + } + } +}; diff --git a/x-pack/plugins/osquery/cypress/tasks/integrations.ts b/x-pack/plugins/osquery/cypress/tasks/integrations.ts index c8bb688dac0f5..5eb52f3faea81 100644 --- a/x-pack/plugins/osquery/cypress/tasks/integrations.ts +++ b/x-pack/plugins/osquery/cypress/tasks/integrations.ts @@ -53,7 +53,8 @@ export const integrationExistsWithinPolicyDetails = (integrationName: string) => }; export const interceptAgentPolicyId = (cb: (policyId: string) => void) => { - cy.intercept('POST', '**/api/fleet/agent_policies**', (req) => { + // create policy has agent_policies?SOMEPARAMS=true , this ? helps to distinguish it from the delete agent_policies/delete route + cy.intercept('POST', '**/api/fleet/agent_policies?**', (req) => { req.continue((res) => { cb(res.body.item.id); diff --git a/x-pack/plugins/osquery/cypress/tasks/inventory.ts b/x-pack/plugins/osquery/cypress/tasks/inventory.ts index 8ba6fc0702d21..d4a2d1111db8f 100644 --- a/x-pack/plugins/osquery/cypress/tasks/inventory.ts +++ b/x-pack/plugins/osquery/cypress/tasks/inventory.ts @@ -9,7 +9,15 @@ export const triggerLoadData = () => { cy.getBySel('infraWaffleTimeControlsAutoRefreshButton').should('exist'); cy.wait(1000); cy.getBySel('infraWaffleTimeControlsAutoRefreshButton').click(); - cy.getBySel('nodeContainer').last().should('exist'); + // @ts-expect-error update types for multiple true + cy.getBySel('nodeContainer', { multiple: true }) + .not(':contains("dev-fleet-server")') + .first() + .should('exist'); cy.getBySel('infraWaffleTimeControlsStopRefreshingButton').click(); - cy.getBySel('nodeContainer').last().click(); + // @ts-expect-error update types for multiple true + cy.getBySel('nodeContainer', { multiple: true }) + .not(':contains("dev-fleet-server")') + .first() + .click(); }; diff --git a/x-pack/plugins/osquery/cypress/tasks/live_query.ts b/x-pack/plugins/osquery/cypress/tasks/live_query.ts index efcb3687b320b..4b1b2d41b2283 100644 --- a/x-pack/plugins/osquery/cypress/tasks/live_query.ts +++ b/x-pack/plugins/osquery/cypress/tasks/live_query.ts @@ -79,9 +79,9 @@ export const findFormFieldByRowsLabelAndType = (label: string, text: string) => }; export const deleteAndConfirm = (type: string) => { - cy.react('EuiButton').contains(`Delete ${type}`).click(); + cy.get('span').contains(`Delete ${type}`).click(); cy.contains(`Are you sure you want to delete this ${type}?`); - cy.react('EuiButton').contains('Confirm').click(); + cy.get('span').contains('Confirm').click(); cy.get('[data-test-subj="globalToastList"]') .first() .contains('Successfully deleted') diff --git a/x-pack/plugins/osquery/cypress/tasks/login.ts b/x-pack/plugins/osquery/cypress/tasks/login.ts new file mode 100644 index 0000000000000..89dab4ca72e56 --- /dev/null +++ b/x-pack/plugins/osquery/cypress/tasks/login.ts @@ -0,0 +1,17 @@ +/* + * 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 { ServerlessRoleName } from '../support/roles'; + +// Login as a SOC_MANAGER to properly initialize Security Solution App +export const initializeDataViews = () => { + cy.login(ServerlessRoleName.SOC_MANAGER); + cy.visit('/app/security/alerts'); + cy.getBySel('globalLoadingIndicator').should('exist'); + cy.getBySel('globalLoadingIndicator').should('not.exist'); + cy.getBySel('manage-alert-detection-rules').should('exist'); +}; diff --git a/x-pack/plugins/osquery/cypress/tasks/navigation.ts b/x-pack/plugins/osquery/cypress/tasks/navigation.ts index b6acc081feccd..7a4b9df573370 100644 --- a/x-pack/plugins/osquery/cypress/tasks/navigation.ts +++ b/x-pack/plugins/osquery/cypress/tasks/navigation.ts @@ -24,6 +24,19 @@ export const navigateTo = (page: string, opts?: Partial) = waitForReact(); }; +// We're moving away from using react-cypress-selector, I'll be adjusting this on file by file approach +export const navigateToWithoutWaitForReact = ( + page: string, + opts?: Partial +) => { + cy.visit(page, opts); + cy.contains('Loading Elastic').should('exist'); + cy.contains('Loading Elastic').should('not.exist'); + + // There's a security warning toast that seemingly makes ui elements in the bottom right unavailable, so we close it + closeToastIfVisible(); +}; + export const waitForReact = () => { cy.waitForReact( 10000, diff --git a/x-pack/plugins/osquery/cypress/tasks/packs.ts b/x-pack/plugins/osquery/cypress/tasks/packs.ts index f8bd23f2c7b10..98d10e39c1813 100644 --- a/x-pack/plugins/osquery/cypress/tasks/packs.ts +++ b/x-pack/plugins/osquery/cypress/tasks/packs.ts @@ -20,26 +20,16 @@ export const preparePack = (packName: string) => { createdPack.click(); }; -export const deactivatePack = (packName: string) => { - cy.react('ActiveStateSwitchComponent', { - props: { item: { name: packName } }, - }).click(); - closeModalIfVisible(); +export const changePackActiveStatus = (packName: string) => { + const regex = new RegExp(`Successfully (activated|deactivated) "${packName}" pack`); - cy.contains(`Successfully deactivated "${packName}" pack`).should('not.exist'); - cy.contains(`Successfully deactivated "${packName}" pack`).should('exist'); - closeToastIfVisible(); -}; - -export const activatePack = (packName: string) => { - cy.react('ActiveStateSwitchComponent', { - props: { item: { name: packName } }, - }).click(); + cy.getBySel('globalLoadingIndicator').should('not.exist'); + cy.get(`[aria-label="${packName}"]`).click(); closeModalIfVisible(); - - cy.contains(`Successfully activated "${packName}" pack`).should('not.exist'); - cy.contains(`Successfully activated "${packName}" pack`).should('exist'); + cy.contains(regex).should('not.exist'); + cy.contains(regex).should('exist'); closeToastIfVisible(); + cy.contains(regex).should('not.exist'); }; export const cleanupAllPrebuiltPacks = () => { diff --git a/x-pack/plugins/osquery/cypress/tasks/wait_until.ts b/x-pack/plugins/osquery/cypress/tasks/wait_until.ts index 30df5bc0708fe..361a371865dcb 100644 --- a/x-pack/plugins/osquery/cypress/tasks/wait_until.ts +++ b/x-pack/plugins/osquery/cypress/tasks/wait_until.ts @@ -6,7 +6,7 @@ */ export const waitUntil = (fn: () => Cypress.Chainable) => { - const timeout = 90000; + const timeout = 120000; const interval = 5000; let attempts = timeout / interval; diff --git a/x-pack/plugins/osquery/public/packs/active_state_switch.tsx b/x-pack/plugins/osquery/public/packs/active_state_switch.tsx index 7d973e2af82d6..92cd929ae5298 100644 --- a/x-pack/plugins/osquery/public/packs/active_state_switch.tsx +++ b/x-pack/plugins/osquery/public/packs/active_state_switch.tsx @@ -96,6 +96,7 @@ const ActiveStateSwitchComponent: React.FC = ({ item }) checked={!!item.enabled} disabled={!permissions.writePacks || isLoading} showLabel={false} + aria-label={item.name} label="" onChange={handleToggleActiveClick} /> diff --git a/x-pack/plugins/osquery/public/packs/add_pack_button.tsx b/x-pack/plugins/osquery/public/packs/add_pack_button.tsx index 70a97f2354a54..07df6d83c7284 100644 --- a/x-pack/plugins/osquery/public/packs/add_pack_button.tsx +++ b/x-pack/plugins/osquery/public/packs/add_pack_button.tsx @@ -25,6 +25,7 @@ const AddPackButtonComponent: React.FC = ({ fill = {...newQueryLinkProps} iconType="plusInCircle" isDisabled={!permissions.writePacks} + data-test-subj={'addPackButton'} > diff --git a/x-pack/plugins/osquery/public/packs/form/index.tsx b/x-pack/plugins/osquery/public/packs/form/index.tsx index 1a5b9152b3ac5..f9c9c7d15f572 100644 --- a/x-pack/plugins/osquery/public/packs/form/index.tsx +++ b/x-pack/plugins/osquery/public/packs/form/index.tsx @@ -315,6 +315,7 @@ const PackFormComponent: React.FC = ({ size="m" iconType="save" onClick={handleSaveClick} + data-test-subj={`${editMode ? 'update' : 'save'}PackButton`} > {editMode ? ( { + return [...Array(length)].map(() => Math.random().toString(36)[2]).join(''); +};