[Security Solution] [Serverless] Initial setup for security serverless Cypress (#158707)

This commit is contained in:
Gloria Hornero 2023-06-12 18:21:23 +02:00 committed by GitHub
parent ebcfebed05
commit 0565bc9788
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 395 additions and 1 deletions

View file

@ -47,6 +47,8 @@ disabled:
- x-pack/test/threat_intelligence_cypress/config.ts
- x-pack/test/functional_enterprise_search/visual_config.ts
- x-pack/test/functional_enterprise_search/cli_config.ts
- x-pack/test_serverless/functional/test_suites/security/cypress/config_headless.ts
- x-pack/test_serverless/functional/test_suites/security/cypress/config_visual.ts
- x-pack/plugins/apm/ftr_e2e/ftr_config_open.ts
- x-pack/plugins/apm/ftr_e2e/ftr_config_run.ts
- x-pack/plugins/apm/ftr_e2e/ftr_config.ts

View file

@ -0,0 +1,13 @@
{
"plugins": ["cypress"],
"extends": [
"plugin:cypress/recommended"
],
"env": {
"cypress/globals": true
},
"rules": {
"cypress/no-force": "warn",
"import/no-extraneous-dependencies": "off"
}
}

View file

@ -0,0 +1,3 @@
videos
screenshots
downloads

View file

@ -0,0 +1,65 @@
# Security Serverless Tests
Before considering adding a new Cypress tests, please make sure you have added unit and API tests first and the behaviour can only be exercised with Cypress.
Note that, the aim of Cypress is to test that the user interface operates as expected, hence, you should not be using this tool to test REST API or data contracts.
## Folder Structure
Below you can find the folder structure used on our Cypress tests.
### e2e/
Cypress convention starting version 10 (previously known as integration). Contains the specs that are going to be executed.
### fixtures/
Cypress convention. Fixtures are used as external pieces of static data when we stub responses.
### screens/
Contains the elements we want to interact with in our tests.
Each file inside the screens folder represents a screen in our application. When the screens are complex, e.g. Hosts with its multiple tabs, the page is represented by a folder and the different important parts are represented by files.
Example:
- screens
- hosts
- all_hosts.ts
- authentications.ts
- events.ts
- main.ts
- uncommon_processes.ts
### tasks/
_Tasks_ are functions that may be reused across tests.
Each file inside the tasks folder represents a screen of our application. When the screens are complex, e.g. Hosts with its multiple tabs, the page is represented by a folder and the different important parts are represented by files.
Example:
- tasks
- hosts
- all_hosts.ts
- authentications.ts
- events.ts
- main.ts
- uncommon_processes.ts
## Run tests
Currently serverless tests are not included in any pipeline, so the execution for now should be done in our local machines.
### Visual mode
- Navigate to `x-pack/test_serverless/functional/test_suites/security/cypress`
- Execute `yarn cypress:serverless:open`
- Select `E2E testing`
- Click on `Start E2E testing in chrome`
- Click on the test
### Headless mode
- Navigate to `x-pack/test_serverless/functional/test_suites/security/cypress`
- Execute `yarn cypress:serverless:run`

View file

@ -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 { SecuritySolutionServerlessHeadlessTestRunner } from './runner';
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const svlSecConfig = await readConfigFile(require.resolve('./security_config.base.ts'));
return {
...svlSecConfig.getAll(),
testRunner: SecuritySolutionServerlessHeadlessTestRunner,
};
}

View file

@ -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 { SecuritySolutionServerlessVisualTestRunner } from './runner';
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const svlSecConfig = await readConfigFile(require.resolve('./security_config.base.ts'));
return {
...svlSecConfig.getAll(),
testRunner: SecuritySolutionServerlessVisualTestRunner,
};
}

View file

@ -0,0 +1,27 @@
/*
* 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';
export default defineCypressConfig({
defaultCommandTimeout: 60000,
execTimeout: 60000,
pageLoadTimeout: 60000,
responseTimeout: 60000,
trashAssetsBeforeRuns: false,
video: false,
viewportHeight: 946,
viewportWidth: 1680,
numTestsKeptInMemory: 10,
e2e: {
baseUrl: 'http://localhost:5620/app/security/get_started',
experimentalRunAllSpecs: true,
experimentalMemoryManagement: true,
supportFile: './support/e2e.js',
specPattern: './e2e/**/*.cy.ts',
},
});

View file

@ -0,0 +1,16 @@
/*
* 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 { LEFT_NAVIGATION } from '../screens/landing_page';
import { navigatesToLandingPage } from '../tasks/navigation';
describe('Serverless', () => {
it('Should navigate to the landing page', () => {
navigatesToLandingPage();
cy.get(LEFT_NAVIGATION).should('exist');
});
});

View file

@ -0,0 +1,13 @@
{
"author": "Elastic",
"name": "@kbn/serverless-security",
"version": "1.0.0",
"private": true,
"license": "Elastic License 2.0",
"scripts": {
"cypress:open": "../../../../../../node_modules/.bin/cypress open --config-file ./cypress.config.ts",
"cypress:run": "../../../../../../node_modules/.bin/cypress run --browser chrome --config-file ./cypress.config.ts",
"cypress:serverless:open": "node ../../../../../../scripts/functional_tests --config ./config_visual.ts",
"cypress:serverless:run": "node ../../../../../../scripts/functional_tests --config ./config_headless.ts"
}
}

View file

@ -0,0 +1,40 @@
/*
* 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 { resolve } from 'path';
import { withProcRunner } from '@kbn/dev-proc-runner';
import { FtrProviderContext } from '../../../ftr_provider_context';
export type { FtrProviderContext } from '../../../ftr_provider_context';
export async function SecuritySolutionCypressTestRunner(
{ getService }: FtrProviderContext,
command: string
) {
const log = getService('log');
await withProcRunner(log, async (procs) => {
await procs.run('cypress', {
cmd: 'yarn',
args: [command],
cwd: resolve(__dirname),
env: {
...process.env,
},
wait: true,
});
});
}
export async function SecuritySolutionServerlessVisualTestRunner(context: FtrProviderContext) {
return SecuritySolutionCypressTestRunner(context, 'cypress:open');
}
export async function SecuritySolutionServerlessHeadlessTestRunner(context: FtrProviderContext) {
return SecuritySolutionCypressTestRunner(context, 'cypress:run');
}

View file

@ -0,0 +1,8 @@
/*
* 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 LEFT_NAVIGATION = '[data-test-subj="securitySolutionNavHeading"]';

View file

@ -0,0 +1,36 @@
/*
* 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';
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const svlSharedConfig = await readConfigFile(
require.resolve('../../../../shared/config.base.ts')
);
return {
...svlSharedConfig.getAll(),
esTestCluster: {
...svlSharedConfig.get('esTestCluster'),
serverArgs: [
...svlSharedConfig.get('esTestCluster.serverArgs'),
// define custom es server here
// API Keys is enabled at the top level
'xpack.security.enabled=true',
],
},
kbnTestServer: {
...svlSharedConfig.get('kbnTestServer'),
serverArgs: [
...svlSharedConfig.get('kbnTestServer.serverArgs'),
'--csp.strict=false',
'--csp.warnLegacyBrowsers=false',
'--serverless=security',
],
},
};
}

View file

@ -0,0 +1,32 @@
/*
* 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.
*/
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })

View file

@ -0,0 +1,32 @@
/*
* 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.
*/
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands';
import 'cypress-real-events/support';
Cypress.on('uncaught:exception', () => {
return false;
});
// Alternatively you can use CommonJS syntax:
// require('./commands')

View file

@ -0,0 +1,52 @@
/*
* 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.
*/
declare namespace Cypress {
interface Chainable<Subject> {
promisify(): Promise<Subject>;
attachFile(fileName: string, fileType?: string): Chainable<JQuery>;
waitUntil(
fn: (subject: Subject) => boolean | Chainable<boolean>,
options?: {
interval: number;
timeout: number;
}
): Chainable<Subject>;
}
}
declare namespace Mocha {
interface SuiteFunction {
(title: string, ftrConfig: Record<string, string | number>, fn: (this: Suite) => void): Suite;
(
title: string,
ftrConfig?: Record<string, string | number>,
config: Cypress.TestConfigOverrides,
fn: (this: Suite) => void
): Suite;
}
interface ExclusiveSuiteFunction {
(title: string, ftrConfig: Record<string, string | number>, fn: (this: Suite) => void): Suite;
(
title: string,
ftrConfig?: Record<string, string | number>,
config: Cypress.TestConfigOverrides,
fn: (this: Suite) => void
): Suite;
}
interface PendingSuiteFunction {
(title: string, ftrConfig: Record<string, string | number>, fn: (this: Suite) => void): Suite;
(
title: string,
ftrConfig?: Record<string, string | number>,
config: Cypress.TestConfigOverrides,
fn: (this: Suite) => void
): Suite | void;
}
}

View file

@ -0,0 +1,15 @@
/*
* 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 navigatesToLandingPage = () => {
cy.visit('/', {
auth: {
username: 'elastic',
password: 'changeme',
},
});
};

View file

@ -3,7 +3,7 @@
"compilerOptions": {
"outDir": "target/types",
"rootDirs": [".", "../test"],
"types": ["node", "@kbn/ambient-ftr-types"],
"types": ["node", "@kbn/ambient-ftr-types", "cypress", "cypress-file-upload", "cypress-real-events", "cypress-recurse"],
},
"include": [
"**/*",
@ -21,5 +21,7 @@
"@kbn/expect",
"@kbn/test",
"@kbn/repo-info",
"@kbn/cypress-config",
"@kbn/dev-proc-runner",
]
}