From 552bac5dc772dd133a77f3045a57e2610769b6eb Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Wed, 6 May 2020 14:16:40 -0400 Subject: [PATCH] [Endpoint] Policy functional (integration) tests (#64803) * Re-enable Policy Functional tests * Test service to provide endpoint policy test data - includes workaround to fleet integration service --- .../endpoint/view/policy/policy_list.tsx | 3 +- .../apps/endpoint/policy_list.ts | 71 +++++++--- x-pack/test/functional_endpoint/config.ts | 2 + .../ftr_provider_context.d.ts | 2 +- .../services/endpoint_policy.ts | 122 ++++++++++++++++++ .../functional_endpoint/services/index.ts | 13 ++ 6 files changed, 196 insertions(+), 17 deletions(-) create mode 100644 x-pack/test/functional_endpoint/services/endpoint_policy.ts create mode 100644 x-pack/test/functional_endpoint/services/index.ts diff --git a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx index f7eafff137f51..39529e7c11ab1 100644 --- a/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx +++ b/x-pack/plugins/endpoint/public/applications/endpoint/view/policy/policy_list.tsx @@ -38,7 +38,7 @@ const PolicyLink: React.FC<{ name: string; route: string; href: string }> = ({ const clickHandler = useNavigateByRouterEventHandler(route); return ( // eslint-disable-next-line @elastic/eui/href-or-on-click - + {name} ); @@ -134,6 +134,7 @@ export const PolicyList = React.memo(() => { render(version: string) { return ( { await pageObjects.common.navigateToUrlWithBrowserHistory('endpoint', '/policy'); - await pageObjects.endpoint.waitForTableToHaveData('policyTable'); }); it('loads the Policy List Page', async () => { await testSubjects.existOrFail('policyListPage'); }); it('displays page title', async () => { - const policyTitle = await testSubjects.getVisibleText('policyViewTitle'); + const policyTitle = await testSubjects.getVisibleText('pageViewHeaderLeftTitle'); expect(policyTitle).to.equal('Policies'); }); it('shows policy count total', async () => { const policyTotal = await testSubjects.getVisibleText('policyTotalCount'); - expect(policyTotal).to.equal('100 Policies'); - }); - it('includes policy list table', async () => { - await testSubjects.existOrFail('policyTable'); + expect(policyTotal).to.equal('0 Policies'); }); it('has correct table headers', async () => { const allHeaderCells = await pageObjects.endpoint.tableHeaderVisibleText('policyTable'); expect(allHeaderCells).to.eql([ 'Policy Name', - 'Total', - 'Pending', - 'Failed', - 'Created By', - 'Created', - 'Last Updated By', - 'Last Updated', + 'Revision', + 'Version', + 'Description', + 'Agent Configuration', ]); }); + it('should show empty table results message', async () => { + const [, [noItemsFoundMessage]] = await pageObjects.endpoint.getEndpointAppTableData( + 'policyTable' + ); + expect(noItemsFoundMessage).to.equal('No items found'); + }); + + describe('and policies exists', () => { + let policyInfo: PolicyTestResourceInfo; + + before(async () => { + // load/create a policy and then navigate back to the policy view so that the list is refreshed + policyInfo = await policyTestResources.createPolicy(); + await pageObjects.common.navigateToUrlWithBrowserHistory('endpoint', '/policy'); + await pageObjects.endpoint.waitForTableToHaveData('policyTable'); + }); + after(async () => { + if (policyInfo) { + await policyInfo.cleanup(); + } + }); + + it('should show policy on the list', async () => { + const [, policyRow] = await pageObjects.endpoint.getEndpointAppTableData('policyTable'); + expect(policyRow).to.eql([ + 'Protect East Coast', + '1', + 'Elastic Endpoint v1.0.0', + 'Protect the worlds data - but in the East Coast', + policyInfo.agentConfig.id, + ]); + }); + it('should show policy name as link', async () => { + const policyNameLink = await testSubjects.find('policyNameLink'); + expect(await policyNameLink.getTagName()).to.equal('a'); + expect(await policyNameLink.getAttribute('href')).to.match( + new RegExp(`\/endpoint\/policy\/${policyInfo.datasource.id}$`) + ); + }); + it('should show agent configuration as link', async () => { + const agentConfigLink = await testSubjects.find('agentConfigLink'); + expect(await agentConfigLink.getTagName()).to.equal('a'); + expect(await agentConfigLink.getAttribute('href')).to.match( + new RegExp(`\/app\/ingestManager\#\/configs\/${policyInfo.datasource.config_id}$`) + ); + }); + }); }); } diff --git a/x-pack/test/functional_endpoint/config.ts b/x-pack/test/functional_endpoint/config.ts index d7f1cc21828d1..a371c548f3022 100644 --- a/x-pack/test/functional_endpoint/config.ts +++ b/x-pack/test/functional_endpoint/config.ts @@ -7,6 +7,7 @@ import { resolve } from 'path'; import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; import { pageObjects } from './page_objects'; +import { services } from './services'; export default async function({ readConfigFile }: FtrConfigProviderContext) { const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); @@ -18,6 +19,7 @@ export default async function({ readConfigFile }: FtrConfigProviderContext) { junit: { reportName: 'X-Pack Endpoint Functional Tests', }, + services, apps: { ...xpackFunctionalConfig.get('apps'), endpoint: { diff --git a/x-pack/test/functional_endpoint/ftr_provider_context.d.ts b/x-pack/test/functional_endpoint/ftr_provider_context.d.ts index 21ab5d5a4e554..bb257cdcbfe1b 100644 --- a/x-pack/test/functional_endpoint/ftr_provider_context.d.ts +++ b/x-pack/test/functional_endpoint/ftr_provider_context.d.ts @@ -7,6 +7,6 @@ import { GenericFtrProviderContext } from '@kbn/test/types/ftr'; import { pageObjects } from './page_objects'; -import { services } from '../functional/services'; +import { services } from './services'; export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test/functional_endpoint/services/endpoint_policy.ts b/x-pack/test/functional_endpoint/services/endpoint_policy.ts new file mode 100644 index 0000000000000..e8e2d9957aa38 --- /dev/null +++ b/x-pack/test/functional_endpoint/services/endpoint_policy.ts @@ -0,0 +1,122 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../ftr_provider_context'; +import { + CreateAgentConfigResponse, + CreateDatasourceResponse, +} from '../../../plugins/ingest_manager/common'; +import { Immutable } from '../../../plugins/endpoint/common/types'; +import { factory as policyConfigFactory } from '../../../plugins/endpoint/common/models/policy_config'; + +const INGEST_API_ROOT = '/api/ingest_manager'; +const INGEST_API_AGENT_CONFIGS = `${INGEST_API_ROOT}/agent_configs`; +const INGEST_API_AGENT_CONFIGS_DELETE = `${INGEST_API_AGENT_CONFIGS}/delete`; +const INGEST_API_DATASOURCES = `${INGEST_API_ROOT}/datasources`; +const INGEST_API_DATASOURCES_DELETE = `${INGEST_API_DATASOURCES}/delete`; + +/** + * Holds information about the test resources created to support an Endpoint Policy + */ +export interface PolicyTestResourceInfo { + /** The Ingest agent configuration created */ + agentConfig: Immutable; + /** The Ingest datasource created and added to agent configuration. + * This is where Endpoint Policy is stored. + */ + datasource: Immutable; + /** will clean up (delete) the objects created (agent config + datasource) */ + cleanup: () => Promise; +} + +export function EndpointPolicyTestResourcesProvider({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + + return { + /** + * Creates an Ingest Agent Configuration and adds to it the Endpoint Datasource that + * stores the Policy configuration data + */ + async createPolicy(): Promise { + // FIXME: Refactor after https://github.com/elastic/kibana/issues/64822 is fixed. `isInitialized` setup below should be deleted + // Due to an issue in Ingest API, we first create the Fleet user. This avoids the Agent Config api throwing a 500 + const isFleetSetupResponse = await supertest + .get('/api/ingest_manager/fleet/setup') + .set('kbn-xsrf', 'xxx') + .expect(200); + if (!isFleetSetupResponse.body.isInitialized) { + await supertest + .post('/api/ingest_manager/fleet/setup') + .set('kbn-xsrf', 'xxx') + .send() + .expect(200); + } + + // create agent config + const { + body: { item: agentConfig }, + }: { body: CreateAgentConfigResponse } = await supertest + .post(INGEST_API_AGENT_CONFIGS) + .set('kbn-xsrf', 'xxx') + .send({ name: 'East Coast', description: 'East Coast call center', namespace: '' }) + .expect(200); + + // create datasource and associated it to agent config + const { + body: { item: datasource }, + }: { body: CreateDatasourceResponse } = await supertest + .post(INGEST_API_DATASOURCES) + .set('kbn-xsrf', 'xxx') + .send({ + name: 'Protect East Coast', + description: 'Protect the worlds data - but in the East Coast', + config_id: agentConfig.id, + enabled: true, + output_id: '', + inputs: [ + // TODO: should we retrieve the latest Endpoint Package and build the input (policy) from that? + { + type: 'endpoint', + enabled: true, + streams: [], + config: { + policy: { + value: policyConfigFactory(), + }, + }, + }, + ], + namespace: '', + package: { + name: 'endpoint', + title: 'Elastic Endpoint', + version: '1.0.0', + }, + }) + .expect(200); + + return { + agentConfig, + datasource, + async cleanup() { + // Delete Datasource + await supertest + .post(INGEST_API_DATASOURCES_DELETE) + .set('kbn-xsrf', 'xxx') + .send({ datasourceIds: [datasource.id] }) + .expect(200); + + // Delete Agent config + await supertest + .post(INGEST_API_AGENT_CONFIGS_DELETE) + .set('kbn-xsrf', 'xxx') + .send({ agentConfigId: agentConfig.id }) + .expect(200); + }, + }; + }, + }; +} diff --git a/x-pack/test/functional_endpoint/services/index.ts b/x-pack/test/functional_endpoint/services/index.ts new file mode 100644 index 0000000000000..0247d9b00968a --- /dev/null +++ b/x-pack/test/functional_endpoint/services/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { services as xPackFunctionalServices } from '../../functional/services'; +import { EndpointPolicyTestResourcesProvider } from './endpoint_policy'; + +export const services = { + ...xPackFunctionalServices, + policyTestResources: EndpointPolicyTestResourcesProvider, +};