Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fleet] Add cypress test against space awareness #195372

Merged
merged 11 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .buildkite/ftr_platform_stateful_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ disabled:

# Cypress configs, for now these are still run manually
- x-pack/test/fleet_cypress/cli_config.ts
- x-pack/test/fleet_cypress/cli_config.space_awareness.ts
- x-pack/test/fleet_cypress/config.ts
- x-pack/test/fleet_cypress/config.space_awareness.ts
- x-pack/test/fleet_cypress/visual_config.ts

defaultQueue: 'n2-4-spot'
Expand Down
2 changes: 1 addition & 1 deletion .buildkite/scripts/steps/functional/fleet_cypress.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ echo "--- Fleet Cypress tests (Chrome)"
cd x-pack/plugins/fleet

set +e
yarn cypress:run:reporter; status=$?; yarn junit:merge || :; exit $status
yarn cypress:run:reporter; status=$?; yarn cypress_space_awareness:run:reporter; space_status=$?; yarn junit:merge || :; [ "$status" -ne 0 ] && exit $status || [ "$space_status" -ne 0 ] && exit $space_status || exit 0
49 changes: 49 additions & 0 deletions x-pack/plugins/fleet/cypress.config.space_awareness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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 { defineCypressConfig } from '@kbn/cypress-config';

// eslint-disable-next-line import/no-default-export
export default defineCypressConfig({
defaultCommandTimeout: 60000,
requestTimeout: 60000,
responseTimeout: 60000,
execTimeout: 120000,
pageLoadTimeout: 120000,

retries: {
runMode: 2,
},

env: {
grepFilterSpecs: false,
},

screenshotsFolder: '../../../target/kibana-fleet/cypress/screenshots',
trashAssetsBeforeRuns: false,
video: false,
videosFolder: '../../../target/kibana-fleet/cypress/videos',
viewportHeight: 900,
viewportWidth: 1440,
screenshotOnRunFailure: true,

e2e: {
baseUrl: 'http://localhost:5601',

experimentalRunAllSpecs: true,
experimentalMemoryManagement: true,
numTestsKeptInMemory: 3,

specPattern: './cypress/e2e/space_awareness/**/*.cy.ts',
supportFile: './cypress/support/e2e.ts',

setupNodeEvents(on, config) {
// eslint-disable-next-line @typescript-eslint/no-var-requires, @kbn/imports/no_boundary_crossing
return require('./cypress/plugins')(on, config);
},
},
});
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default defineCypressConfig({

specPattern: './cypress/e2e/**/*.cy.ts',
supportFile: './cypress/support/e2e.ts',
excludeSpecPattern: './cypress/e2e/space_awareness/**/*.cy.ts',

setupNodeEvents(on, config) {
// eslint-disable-next-line @typescript-eslint/no-var-requires, @kbn/imports/no_boundary_crossing
Expand Down
75 changes: 75 additions & 0 deletions x-pack/plugins/fleet/cypress/e2e/space_awareness/policies.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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 {
ADD_AGENT_POLICY_BTN,
AGENT_POLICIES_TABLE,
AGENT_POLICY_CREATE_AGENT_POLICY_NAME_FIELD,
AGENT_POLICY_DETAILS_PAGE,
AGENT_POLICY_FLYOUT_CREATE_BUTTON,
AGENT_POLICY_SYSTEM_MONITORING_CHECKBOX,
} from '../../screens/fleet';
import { login } from '../../tasks/login';
import { createSpaces, enableSpaceAwareness } from '../../tasks/spaces';
import { cleanupAgentPolicies } from '../../tasks/cleanup';

describe('Space aware policies creation', { testIsolation: false }, () => {
before(() => {
enableSpaceAwareness();
createSpaces();
cleanupAgentPolicies();
cleanupAgentPolicies('test');
login();
});

beforeEach(() => {
cy.intercept('GET', /\/api\/fleet\/agent_policies/).as('getAgentPolicies');
cy.intercept('GET', /\/internal\/fleet\/agent_policies_spaces/).as('getAgentPoliciesSpaces');
});

const POLICY_NAME = `Policy 1 space test`;
const NO_AGENT_POLICIES = 'No agent policies';
it('should allow to create an agent policy in the test space', () => {
cy.visit('/s/test/app/fleet/policies');

cy.getBySel(ADD_AGENT_POLICY_BTN).click();
cy.getBySel(AGENT_POLICY_CREATE_AGENT_POLICY_NAME_FIELD).type(POLICY_NAME);
cy.getBySel(AGENT_POLICY_SYSTEM_MONITORING_CHECKBOX).uncheck();

cy.getBySel(AGENT_POLICY_FLYOUT_CREATE_BUTTON).click();
cy.getBySel(AGENT_POLICIES_TABLE).contains(POLICY_NAME);
});

it('the created policy should not be visible in the default space', () => {
cy.visit('/app/fleet/policies');
cy.wait('@getAgentPolicies');
cy.getBySel(AGENT_POLICIES_TABLE).contains(NO_AGENT_POLICIES);
});

it('should allow to update that policy to belong to both test and default space', () => {
cy.visit('/s/test/app/fleet/policies');
cy.getBySel(AGENT_POLICIES_TABLE).contains(POLICY_NAME).click();

cy.getBySel(AGENT_POLICY_DETAILS_PAGE.SETTINGS_TAB).click();
cy.wait('@getAgentPoliciesSpaces');
cy.getBySel(AGENT_POLICY_DETAILS_PAGE.SPACE_SELECTOR_COMBOBOX).click().type('default{enter}');

cy.getBySel(AGENT_POLICY_DETAILS_PAGE.SAVE_BUTTON).click();
});

it('the policy should be visible in the test space', () => {
cy.visit('/s/test/app/fleet/policies');
cy.wait('@getAgentPolicies');
cy.getBySel(AGENT_POLICIES_TABLE).contains(POLICY_NAME);
});

it('the policy should be visible in the default space', () => {
cy.visit('/app/fleet/policies');
cy.wait('@getAgentPolicies');
cy.getBySel(AGENT_POLICIES_TABLE).contains(POLICY_NAME);
});
});
5 changes: 5 additions & 0 deletions x-pack/plugins/fleet/cypress/screens/fleet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export const AGENT_POLICY_CREATE_AGENT_POLICY_NAME_FIELD = 'createAgentPolicyNam
export const AGENT_POLICIES_FLYOUT_ADVANCED_DEFAULT_NAMESPACE_HEADER = 'defaultNamespaceHeader';
export const AGENT_POLICY_FLYOUT_CREATE_BUTTON = 'createAgentPolicyFlyoutBtn';

export const AGENT_POLICIES_TABLE = 'agentPoliciesTable';

export const ENROLLMENT_TOKENS = {
CREATE_TOKEN_BUTTON: 'createEnrollmentTokenButton',
CREATE_TOKEN_MODAL_NAME_FIELD: 'createEnrollmentTokenNameField',
Expand Down Expand Up @@ -241,4 +243,7 @@ export const API_KEYS = {

export const AGENT_POLICY_DETAILS_PAGE = {
ADD_AGENT_LINK: 'addAgentLink',
SETTINGS_TAB: 'agentPolicySettingsTab',
SPACE_SELECTOR_COMBOBOX: 'spaceSelectorComboBox',
SAVE_BUTTON: 'agentPolicyDetailsSaveButton',
};
24 changes: 13 additions & 11 deletions x-pack/plugins/fleet/cypress/tasks/cleanup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,20 @@

import { request } from './common';

export function cleanupAgentPolicies() {
request({ url: '/api/fleet/agent_policies' }).then((response: any) => {
response.body.items
.filter((policy: any) => policy.agents === 0)
.forEach((policy: any) => {
request({
method: 'POST',
url: '/api/fleet/agent_policies/delete',
body: { agentPolicyId: policy.id },
export function cleanupAgentPolicies(spaceId?: string) {
request({ url: `${spaceId ? `/s/${spaceId}` : ''}/api/fleet/agent_policies` }).then(
(response: any) => {
response.body.items
.filter((policy: any) => policy.agents === 0)
.forEach((policy: any) => {
request({
method: 'POST',
url: `${spaceId ? `/s/${spaceId}` : ''}/api/fleet/agent_policies/delete`,
body: { agentPolicyId: policy.id },
});
});
});
});
}
);
}

export function unenrollAgent() {
Expand Down
17 changes: 17 additions & 0 deletions x-pack/plugins/fleet/cypress/tasks/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ export const COMMON_API_HEADERS = Object.freeze({
'Elastic-Api-Version': API_VERSIONS.public.v1,
});

export const COMMON_INTERNAL_API_HEADERS = Object.freeze({
'kbn-xsrf': 'cypress',
'x-elastic-internal-origin': 'fleet',
'Elastic-Api-Version': API_VERSIONS.internal.v1,
});

// Replaces request - adds baseline authentication + global headers
export const request = <T = unknown>({
headers,
Expand All @@ -40,6 +46,17 @@ export const request = <T = unknown>({
});
};

export const internalRequest = <T = unknown>({
headers,
...options
}: Partial<Cypress.RequestOptions>): Cypress.Chainable<Cypress.Response<T>> => {
return cy.request<T>({
auth: API_AUTH,
headers: { ...COMMON_INTERNAL_API_HEADERS, ...headers },
...options,
});
};

/**
* For all the new features tours we show in the app, this method disables them
* by setting their configs in the local storage. It prevents the tours from appearing
Expand Down
38 changes: 38 additions & 0 deletions x-pack/plugins/fleet/cypress/tasks/spaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 { request, internalRequest } from './common';

export function enableSpaceAwareness() {
return internalRequest({
url: '/internal/fleet/enable_space_awareness',
failOnStatusCode: false,
method: 'POST',
});
}

export function createSpaces() {
return request({
url: '/api/spaces/space',
failOnStatusCode: false,
method: 'POST',
body: {
id: 'test',
name: 'Test',
description: 'Test space',
color: '#aabbcc',
initials: 'TE',
disabledFeatures: [],
imageUrl:
'data:image/png;base64,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',
},
}).then((response: any) => {
if (response.status !== 200 && response.status !== 409) {
throw new Error(`Failed to create space test`);
}
});
}
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/cypress/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"include": [
"**/*",
"../cypress.config.ts",
"../cypress.config.space_awareness.ts",
"../../../../typings/**/*"
],
"exclude": [
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/fleet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
"private": true,
"license": "Elastic License 2.0",
"scripts": {
"cypress_space_awareness": "NODE_OPTIONS=--openssl-legacy-provider node ../security_solution/scripts/start_cypress_parallel --config-file ../fleet/cypress.config.space_awareness.ts --ftr-config-file ../../../x-pack/test/fleet_cypress/cli_config.space_awareness",
"cypress_space_awareness:open": "yarn cypress_space_awareness open",
"cypress_space_awareness:run": "yarn cypress_space_awareness run",
"cypress_space_awareness:run:reporter": "yarn cypress_space_awareness run --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=../fleet/cypress/reporter_config.json",
"cypress": "NODE_OPTIONS=--openssl-legacy-provider node ../security_solution/scripts/start_cypress_parallel --config-file ../fleet/cypress.config.ts --ftr-config-file ../../../x-pack/test/fleet_cypress/cli_config",
"cypress:open": "yarn cypress open",
"cypress:run": "yarn cypress run",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ export const SettingsView = memo<{ agentPolicy: AgentPolicy }>(
Object.keys(validation).length > 0 ||
hasAdvancedSettingsErrors
}
data-test-subj="agentPolicyDetailsSaveButton"
iconType="save"
color="primary"
fill
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export const AgentPolicyDetailsPage: React.FunctionComponent = () => {
name: i18n.translate('xpack.fleet.policyDetails.subTabs.settingsTabText', {
defaultMessage: 'Settings',
}),
'data-test-subj': 'agentPolicySettingsTab',
href: getHref('policy_details', { policyId, tabId: 'settings' }),
isSelected: tabId === 'settings',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => {
<EuiSpacer size="m" />
<EuiBasicTable<AgentPolicy>
loading={isLoading}
data-test-subj="agentPoliciesTable"
noItemsMessage={
isLoading ? (
<FormattedMessage
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/fleet/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
},
"exclude": [
"cypress.config.ts",
"cypress.config.space_awareness.ts",
"target/**/*",
],
"include": [
Expand All @@ -17,6 +18,7 @@
"scripts/**/*",
"package.json",
"cypress.config.ts",
"cypress.config.space_awareness.ts",
"../../../typings/**/*"
],
"kbn_references": [
Expand Down
11 changes: 10 additions & 1 deletion x-pack/plugins/security_solution/scripts/run_cypress/parallel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,10 @@ ${JSON.stringify(cypressConfigFile, null, 2)}
const specConfig = cypressConfigFile.e2e.specPattern;
const specArg = argv.spec;
const specPattern = specArg ?? specConfig;
const excludeSpecPattern = cypressConfigFile.e2e.excludeSpecPattern;

log.info('Config spec pattern:', specConfig);
log.info('Exclude spec pattern:', excludeSpecPattern);
log.info('Arguments spec pattern:', specArg);
log.info('Resulting spec pattern:', specPattern);

Expand Down Expand Up @@ -123,7 +125,14 @@ ${JSON.stringify(cypressConfigFile, null, 2)}

const concreteFilePaths = isGrepReturnedFilePaths
? grepSpecPattern // use the returned concrete file paths
: globby.sync(specPattern); // convert the glob pattern to concrete file paths
: globby.sync(
specPattern,
excludeSpecPattern
? {
ignore: excludeSpecPattern,
}
: undefined
); // convert the glob pattern to concrete file paths

let files = retrieveIntegrations(concreteFilePaths);

Expand Down
19 changes: 19 additions & 0 deletions x-pack/test/fleet_cypress/cli_config.space_awareness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* 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 { FtrConfigProviderContext } from '@kbn/test';

import { FleetCypressCliTestRunner } from './runner';

export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const cypressConfig = await readConfigFile(require.resolve('./config.space_awareness.ts'));
return {
...cypressConfig.getAll(),

testRunner: FleetCypressCliTestRunner,
};
}
Loading
Loading