[Enterprise Search] Enterprise Search Cypress configuration (#155398)

## Summary

Updated Test configurations to make Enterprise Search run with basic
Cypress tests. In Enterprise Search root folder run `cypress.sh` or
`cypress.sh open` to run tests via FTR servers running.

You can run Cypress manually on a already running stack while developing
with `cypress.sh dev`.


### Checklist

Delete any items that are not applicable to this PR.

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Efe Gürkan YALAMAN 2023-04-21 17:06:41 +02:00 committed by GitHub
parent 3e81f8f093
commit 0cd7973e1f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 234 additions and 177 deletions

View file

@ -43,7 +43,8 @@ disabled:
- x-pack/test/threat_intelligence_cypress/visual_config.ts
- x-pack/test/threat_intelligence_cypress/cli_config_parallel.ts
- x-pack/test/threat_intelligence_cypress/config.ts
- x-pack/test/functional_enterprise_search/with_host_configured.config.ts
- x-pack/test/functional_enterprise_search/visual_config.ts
- x-pack/test/functional_enterprise_search/cli_config.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
@ -224,7 +225,6 @@ enabled:
- x-pack/test/functional_basic/apps/transform/feature_controls/config.ts
- x-pack/test/functional_cors/config.ts
- x-pack/test/functional_embedded/config.ts
- x-pack/test/functional_enterprise_search/without_host_configured.config.ts
- x-pack/test/functional_execution_context/config.ts
- x-pack/test/functional_with_es_ssl/apps/cases/group1/config.ts
- x-pack/test/functional_with_es_ssl/apps/cases/group2/config.ts

View file

@ -89,29 +89,13 @@ Cypress tests can be run directly from the `x-pack/plugins/enterprise_search` fo
```bash
# Basic syntax
sh cypress.sh {run|open} {suite}
sh cypress.sh {run|open|dev}
# Examples
sh cypress.sh run overview # run Enterprise Search overview tests
sh cypress.sh open overview # open Enterprise Search overview tests
sh cypress.sh run # run Enterprise Search tests
sh cypress.sh open # open Enterprise Search tests
sh cypress.sh dev # run "cypress only" with Enterprise Search config
sh cypress.sh run as # run App Search tests
sh cypress.sh open as # open App Search tests
sh cypress.sh run ws # run Workplace Search tests
sh cypress.sh open ws # open Workplace Search tests
# Overriding env variables
sh cypress.sh open as --env username=enterprise_search password=123
# Overriding config settings, e.g. changing the base URL to a dev path, or enabling video recording
sh cypress.sh open as --config baseUrl=http://localhost:5601/xyz video=true
# Only run a single specific test file
sh cypress.sh run ws --spec '**/example.spec.ts'
# Opt to run Chrome headlessly
sh cypress.sh run ws --headless
```
There are 3 ways you can spin up the required environments to run our Cypress tests:
@ -126,13 +110,8 @@ There are 3 ways you can spin up the required environments to run our Cypress te
- Enterprise Search:
- Nothing extra is required to run Cypress tests, only what is already needed to run Kibana/Enterprise Search locally.
2. Running Cypress against Kibana's functional test server:
- :information_source: While we won't use the runner, we can still make use of Kibana's functional test server to help us spin up Elasticsearch and Kibana instances.
- NOTE: We recommend stopping any other local dev processes, to reduce issues with memory/performance
- From the `x-pack/` project folder, run `node scripts/functional_tests_server --config test/functional_enterprise_search/cypress.config.ts`
- Kibana:
- You will need to pass `--config baseUrl=http://localhost:5620` into your Cypress command.
- Enterprise Search:
- :warning: TODO: We _currently_ do not have a way of spinning up Enterprise Search from Kibana's FTR - for now, you can use local Enterprise Search (pointed at the FTR's `http://localhost:9220` Elasticsearch host instance)
- Make sure docker is up and running in you system
- From the `x-pack/` project folder, run `sh cypress.sh` which will spin up Kibana, Elasticsearch through functional test runners and Enterprise Search instance in Docker.
3. Running Cypress against Enterprise Search dockerized stack scripts
- :warning: This is for Enterprise Search devs only, as this requires access to our closed source Enterprise Search repo
- `stack_scripts/start-with-es-native-auth.sh --with-kibana`
@ -158,4 +137,4 @@ To track what Cypress is doing while running tests, you can pass in `--config vi
See [our functional test runner README](../../test/functional_enterprise_search).
Our automated accessibility tests can be found in [x-pack/test/accessibility/apps](../../test/accessibility/apps/enterprise_search.ts).
Our automated accessibility tests can be found in [x-pack/test/accessibility/apps](../../test/accessibility/apps/enterprise_search.ts).

View file

@ -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 { defineCypressConfig } from '@kbn/cypress-config';
export default defineCypressConfig({
defaultCommandTimeout: 60000,
execTimeout: 120000,
pageLoadTimeout: 120000,
requestTimeout: 60000,
responseTimeout: 60000,
retries: {
runMode: 2,
},
screenshotOnRunFailure: false,
screenshotsFolder: '../../../target/kibana-fleet/cypress/screenshots',
trashAssetsBeforeRuns: false,
video: false,
videosFolder: '../../../target/kibana-fleet/cypress/videos',
viewportHeight: 900,
viewportWidth: 1440,
// eslint-disable-next-line sort-keys
env: {
configport: '5601',
hostname: 'localhost',
protocol: 'http',
},
// eslint-disable-next-line sort-keys
e2e: {
baseUrl: 'http://localhost:5601',
supportFile: './cypress/support/e2e.ts',
},
});

28
x-pack/plugins/enterprise_search/cypress.sh Normal file → Executable file
View file

@ -1,18 +1,22 @@
#! /bin/bash
# Use either `cypress run` or `cypress open` - defaults to run
MODE="${1:-run}"
MODE="${1}"
# Choose which product folder to use, e.g. `yarn cypress open as`
PRODUCT="${2}"
# Provide helpful shorthands
if [ "$PRODUCT" == "as" ]; then PRODUCT='app_search'; fi
if [ "$PRODUCT" == "ws" ]; then PRODUCT='workplace_search'; fi
if [ "$PRODUCT" == "overview" ]; then PRODUCT='enterprise_search'; fi
if [ "$MODE" == "dev" ]; then
echo "Running dev mode. This will run cypress only"
node ../../../node_modules/.bin/cypress open --config-file ./cypress.config.ts ${2}
else
if ! docker info > /dev/null 2>&1; then
echo "This script needs docker to run. Start docker and try again."
echo "If you are testing against your own setup use ./cypress.sh dev"
exit 1
fi
# Pass all remaining arguments (e.g., ...rest) from the 3rd arg onwards
# as an open-ended string. Appends onto to the end the Cypress command
# @see https://docs.cypress.io/guides/guides/command-line.html#Options
ARGS="${*:3}"
if [ "$MODE" == "open" ]; then
node ../../../scripts/functional_tests --config ../../test/functional_enterprise_search/visual_config.ts
else
node ../../../scripts/functional_tests --config ../../test/functional_enterprise_search/cli_config.ts
fi
fi
../../../node_modules/.bin/cypress "$MODE" --project "public/applications/$PRODUCT" --browser chrome $ARGS

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.
*/
import { login } from '../../tasks/login';
describe('Enterprise Search Crawler', () => {
it('test', () => {
login();
cy.visit('/app/enterprise_search/content/search_indices/new_index');
});
});

View file

@ -0,0 +1,48 @@
/*
* 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.
*/
// / <reference types="cypress" />
// ***********************************************************
// 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
// ***********************************************************
// Enforce building this file.
export {};
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
interface Chainable {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getBySel(value: string, ...args: any[]): Chainable<any>;
getKibanaVersion(): Chainable<string>;
}
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function getBySel(selector: string, ...args: any[]) {
return cy.get(`[data-test-subj="${selector}"]`, ...args);
}
Cypress.Commands.add('getBySel', getBySel);
Cypress.on('uncaught:exception', () => {
return false;
});

View file

@ -0,0 +1,45 @@
/*
* 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.
*/
const ELASTICSEARCH_USERNAME = 'elastic';
const ELASTICSEARCH_PASSWORD = 'changeme';
const LOGIN_API_ENDPOINT = '/internal/security/login';
export const constructUrlWithUser = (route: string) => {
const url = Cypress.config().baseUrl;
const kibana = new URL(String(url));
const hostname = kibana.hostname;
const username = ELASTICSEARCH_USERNAME;
const password = ELASTICSEARCH_PASSWORD;
const protocol = kibana.protocol.replace(':', '');
const port = kibana.port;
const path = `${route.startsWith('/') ? '' : '/'}${route}`;
const strUrl = `${protocol}://${username}:${password}@${hostname}:${port}${path}`;
const builtUrl = new URL(strUrl);
cy.log(`origin: ${builtUrl.href}`);
return builtUrl.href;
};
export const login = () => {
cy.session('user', () => {
cy.request({
body: {
currentURL: '/',
params: {
password: ELASTICSEARCH_PASSWORD,
username: ELASTICSEARCH_USERNAME,
},
providerName: 'basic',
providerType: 'basic',
},
headers: { 'kbn-xsrf': 'cypress-creds-via-config' },
method: 'POST',
url: constructUrlWithUser(LOGIN_API_ENDPOINT),
});
});
};

View file

@ -0,0 +1,20 @@
{
"extends": "../../../../tsconfig.base.json",
"include": ["**/*", "../cypress.config.ts"],
"exclude": ["target/**/*"],
"compilerOptions": {
"outDir": "target/types",
"types": ["cypress", "node", "cypress-react-selector"],
"resolveJsonModule": true
},
"kbn_references": [
"@kbn/cypress-config",
// cypress projects that are nested inside of other ts project use code
// from the parent ts project in ways that can't be automatically deteceted
// at this time so we have to force the inclusion of this reference
{
"path": "../tsconfig.json",
"force": true
}
]
}

View file

@ -1,41 +0,0 @@
/*
* 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 expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
export default function enterpriseSearchSetupGuideTests({
getService,
getPageObjects,
}: FtrProviderContext) {
const browser = getService('browser');
const retry = getService('retry');
const kibanaServer = getService('kibanaServer');
const PageObjects = getPageObjects(['appSearch']);
describe('Setup Guide', function () {
before(async () => {
await kibanaServer.savedObjects.cleanStandardList();
});
after(async () => {
await kibanaServer.savedObjects.cleanStandardList();
});
describe('when no enterpriseSearch.host is configured', () => {
it('navigating to the plugin will redirect a user to the setup guide', async () => {
await PageObjects.appSearch.navigateToPage();
await retry.try(async function () {
const currentUrl = await browser.getCurrentUrl();
expect(currentUrl).to.contain('/app_search/setup_guide');
const documentTitle = await browser.getTitle();
expect(documentTitle).to.contain('Setup Guide - App Search - Elastic');
});
});
});
});
}

View file

@ -1,15 +0,0 @@
/*
* 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 { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('Enterprise Search', function () {
loadTestFile(require.resolve('./app_search/setup_guide'));
loadTestFile(require.resolve('./workplace_search/setup_guide'));
});
}

View file

@ -1,41 +0,0 @@
/*
* 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 expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../ftr_provider_context';
export default function enterpriseSearchSetupGuideTests({
getService,
getPageObjects,
}: FtrProviderContext) {
const browser = getService('browser');
const retry = getService('retry');
const kibanaServer = getService('kibanaServer');
const PageObjects = getPageObjects(['workplaceSearch']);
describe('Setup Guide', function () {
before(async () => {
await kibanaServer.savedObjects.cleanStandardList();
});
after(async () => {
await kibanaServer.savedObjects.cleanStandardList();
});
describe('when no enterpriseSearch.host is configured', () => {
it('navigating to the plugin will redirect a user to the setup guide', async () => {
await PageObjects.workplaceSearch.navigateToPage();
await retry.try(async function () {
const currentUrl = await browser.getCurrentUrl();
expect(currentUrl).to.contain('/workplace_search/setup_guide');
const documentTitle = await browser.getTitle();
expect(documentTitle).to.contain('Setup Guide - Workplace Search - Elastic');
});
});
});
});
}

View file

@ -0,0 +1,34 @@
/*
* 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 { EnterpriseSearchCypressCliTestRunner } from './runner';
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const kibanaCommonTestsConfig = await readConfigFile(
require.resolve('../../../test/common/config.js')
);
const baseConfig = await readConfigFile(require.resolve('./cypress.config'));
return {
...kibanaCommonTestsConfig.getAll(),
// default to the xpack functional config
...baseConfig.getAll(),
junit: {
reportName: 'X-Pack Enterprise Search Functional Tests with Host Configured',
},
kbnTestServer: {
...baseConfig.get('kbnTestServer'),
serverArgs: [
...baseConfig.get('kbnTestServer.serverArgs'),
'--enterpriseSearch.host=http://localhost:3022',
],
},
testRunner: EnterpriseSearchCypressCliTestRunner,
};
}

View file

@ -7,9 +7,6 @@
import { FtrConfigProviderContext } from '@kbn/test';
// TODO: If Kibana CI doesn't end up using this (e.g., uses Dockerized containers
// instead of the functional test server), we can opt to delete this file later.
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const baseConfig = await readConfigFile(require.resolve('./base_config'));
@ -32,7 +29,9 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
...baseConfig.get('kbnTestServer.serverArgs'),
'--csp.strict=false',
'--csp.warnLegacyBrowsers=false',
'--enterpriseSearch.host=http://localhost:3002',
'--enterpriseSearch.host=http://localhost:3022',
'--usageCollection.uiCounters.enabled=false',
`--home.disableWelcomeScreen=true`,
],
},
};

View file

@ -52,7 +52,7 @@ export async function setupEnterpriseSearch(logger: ToolingLog): Promise<void> {
`--name=enterprise-search-ftr`,
`--rm`,
`-p`,
`3002:3002`,
`3022:3022`,
`-e`,
`elasticsearch.host='http://host.docker.internal:9220'`,
`-e`,
@ -66,9 +66,9 @@ export async function setupEnterpriseSearch(logger: ToolingLog): Promise<void> {
`-e`,
`ENT_SEARCH_DEFAULT_PASSWORD=changeme`,
`-e`,
`ent_search.listen_port=3002`,
`ent_search.listen_port=3022`,
`-e`,
`ent_search.external_url='http://localhost:3002'`,
`ent_search.external_url='http://localhost:3022'`,
`docker.elastic.co/enterprise-search/enterprise-search:${await getLatestVersion()}`,
];

View file

@ -35,12 +35,8 @@ export async function runEnterpriseSearchTests(
await withEnterpriseSearch(context, (runnerEnv) =>
withProcRunner(log, async (procs) => {
await procs.run('cypress', {
cmd: 'sh',
args: [
`${resolve(__dirname, '../../plugins/enterprise_search/cypress.sh')}`,
`${cypressCommand}`,
'as',
],
cmd: '../../../node_modules/.bin/cypress',
args: [cypressCommand, '--config-file', './cypress.config.ts', '--browser', 'chrome'],
cwd: resolve(__dirname, '../../plugins/enterprise_search'),
env: {
FORCE_COLOR: '1',

View file

@ -26,7 +26,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
...baseConfig.get('kbnTestServer'),
serverArgs: [
...baseConfig.get('kbnTestServer.serverArgs'),
'--enterpriseSearch.host=http://localhost:3002',
'--enterpriseSearch.host=http://localhost:3022',
],
},
testRunner: EnterpriseSearchCypressVisualTestRunner,

View file

@ -1,24 +0,0 @@
/*
* 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 { FtrConfigProviderContext } from '@kbn/test';
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const baseConfig = await readConfigFile(require.resolve('./base_config'));
return {
// default to the xpack functional config
...baseConfig.getAll(),
testFiles: [resolve(__dirname, './apps/enterprise_search/without_host_configured')],
junit: {
reportName: 'X-Pack Enterprise Search Functional Tests without Host Configured',
},
};
}