* [Endpoint] Functional Tests cleanup (#68756) * Removed several unnecessary disabled eslint rules * moved common pageobject from endpoint_list to page_utils * Rename functional_endpoint to security_solution_endpoint * Delete `functional_endpoint_ingest_failure` no longer applicable # Conflicts: # .github/CODEOWNERS # x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts * Sync Endpoint Alerts page objects with master - PR https://github.com/elastic/kibana/pull/64704 was never backported, thus this change is needed to ensure build is successful. Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
bd980f8d7c
commit
521493f344
26 changed files with 473 additions and 198 deletions
|
@ -35,8 +35,7 @@ export const ManagementPageView = memo<Omit<PageViewProps, 'tabs'>>((options) =>
|
|||
href: getManagementUrl({ name: 'policyList' }),
|
||||
},
|
||||
];
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [tabName]);
|
||||
}, [options.viewType, tabName]);
|
||||
return <PageView {...options} tabs={tabs} />;
|
||||
});
|
||||
|
||||
|
|
|
@ -137,15 +137,14 @@ export const HostDetails = memo(({ details }: { details: HostMetadata }) => {
|
|||
description: details.agent.version,
|
||||
},
|
||||
];
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
details.agent.version,
|
||||
details.endpoint.policy.id,
|
||||
details.host.hostname,
|
||||
details.host.ip,
|
||||
policyResponseUri.search,
|
||||
policyStatusClickHandler,
|
||||
details.host.hostname,
|
||||
details.agent.version,
|
||||
policyStatus,
|
||||
policyResponseUri,
|
||||
policyStatusClickHandler,
|
||||
]);
|
||||
|
||||
return (
|
||||
|
|
|
@ -40,6 +40,5 @@ export const mockManagementState: Immutable<ManagementState> = {
|
|||
export const managementReducer = immutableCombineReducers({
|
||||
[MANAGEMENT_STORE_POLICY_LIST_NAMESPACE]: policyListReducer,
|
||||
[MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE]: policyDetailsReducer,
|
||||
// @ts-ignore
|
||||
[MANAGEMENT_STORE_ENDPOINTS_NAMESPACE]: hostListReducer,
|
||||
});
|
||||
|
|
|
@ -8,7 +8,7 @@ require('@kbn/plugin-helpers').babelRegister();
|
|||
|
||||
require('@kbn/test').runTestsCli([
|
||||
require.resolve('../test/functional/config.js'),
|
||||
require.resolve('../test/functional_endpoint/config.ts'),
|
||||
require.resolve('../test/security_solution_endpoint/config.ts'),
|
||||
require.resolve('../test/functional_with_es_ssl/config.ts'),
|
||||
require.resolve('../test/functional/config_security_basic.ts'),
|
||||
require.resolve('../test/functional/config_security_trial.ts'),
|
||||
|
|
|
@ -1,27 +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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export function EndpointAlertsPageProvider({ getService }: FtrProviderContext) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
||||
return {
|
||||
async enterSearchBarQuery(query: string) {
|
||||
return await testSubjects.setValue('alertsSearchBar', query, { clearWithKeyboard: true });
|
||||
},
|
||||
async submitSearchBarFilter() {
|
||||
return await testSubjects.click('querySubmitButton');
|
||||
},
|
||||
async setSearchBarDate(timestamp: string) {
|
||||
await testSubjects.click('superDatePickerShowDatesButton');
|
||||
await testSubjects.click('superDatePickerstartDatePopoverButton');
|
||||
await testSubjects.click('superDatePickerAbsoluteTab');
|
||||
await testSubjects.setValue('superDatePickerAbsoluteDateInput', timestamp);
|
||||
await this.submitSearchBarFilter();
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,30 +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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export function EndpointPageUtils({ getService }: FtrProviderContext) {
|
||||
const find = getService('find');
|
||||
|
||||
return {
|
||||
/**
|
||||
* Finds a given EuiCheckbox by test subject and clicks on it
|
||||
*
|
||||
* @param euiCheckBoxTestId
|
||||
*/
|
||||
async clickOnEuiCheckbox(euiCheckBoxTestId: string) {
|
||||
// This utility is needed because EuiCheckbox forwards the test subject on to
|
||||
// the actual `<input>` which is not actually visible/accessible on the page.
|
||||
// In order to actually cause the state of the checkbox to change, the `<label>`
|
||||
// must be clicked.
|
||||
const euiCheckboxLabelElement = await find.byXPath(
|
||||
`//input[@data-test-subj='${euiCheckBoxTestId}']/../label`
|
||||
);
|
||||
|
||||
await euiCheckboxLabelElement.click();
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,14 +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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default function ({ loadTestFile }: FtrProviderContext) {
|
||||
describe('endpoint when the ingest manager fails to setup correctly', function () {
|
||||
this.tags('ciGroup7');
|
||||
|
||||
loadTestFile(require.resolve('./landing_page'));
|
||||
});
|
||||
}
|
|
@ -1,22 +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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
||||
describe('home page', function () {
|
||||
const pageObjects = getPageObjects(['common']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
||||
before(async () => {
|
||||
await pageObjects.common.navigateToApp('endpoint');
|
||||
});
|
||||
|
||||
it('displays an error toast', async () => {
|
||||
await testSubjects.existOrFail('euiToastHeader');
|
||||
});
|
||||
});
|
||||
};
|
|
@ -1,30 +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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { resolve } from 'path';
|
||||
import { FtrConfigProviderContext } from '@kbn/test/types/ftr';
|
||||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const xpackFunctionalConfig = await readConfigFile(
|
||||
require.resolve('../functional_endpoint/config.ts')
|
||||
);
|
||||
|
||||
return {
|
||||
...xpackFunctionalConfig.getAll(),
|
||||
testFiles: [resolve(__dirname, './apps/endpoint')],
|
||||
junit: {
|
||||
reportName: 'X-Pack Endpoint Without Ingest Functional Tests',
|
||||
},
|
||||
kbnTestServer: {
|
||||
...xpackFunctionalConfig.get('kbnTestServer'),
|
||||
serverArgs: [
|
||||
...xpackFunctionalConfig.get('kbnTestServer.serverArgs'),
|
||||
// use a bogus port so the ingest manager setup will fail
|
||||
'--xpack.ingestManager.epm.registryUrl=http://127.0.0.1:12345',
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,12 +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;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { GenericFtrProviderContext } from '@kbn/test/types/ftr';
|
||||
|
||||
import { pageObjects } from '../functional_endpoint/page_objects';
|
||||
import { services } from '../functional/services';
|
||||
|
||||
export type FtrProviderContext = GenericFtrProviderContext<typeof services, typeof pageObjects>;
|
|
@ -16,7 +16,7 @@ import { pageObjects } from './page_objects';
|
|||
/* eslint-disable import/no-default-export */
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const xpackFunctionalConfig = await readConfigFile(
|
||||
require.resolve('../functional_endpoint/config.ts')
|
||||
require.resolve('../security_solution_endpoint/config.ts')
|
||||
);
|
||||
|
||||
// Find all folders in ./plugins since we treat all them as plugin folder
|
||||
|
|
|
@ -8,7 +8,7 @@ import expect from '@kbn/expect';
|
|||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
||||
const pageObjects = getPageObjects(['common', 'endpoint', 'header']);
|
||||
const pageObjects = getPageObjects(['common', 'endpoint', 'header', 'endpointPageUtils']);
|
||||
const esArchiver = getService('esArchiver');
|
||||
const testSubjects = getService('testSubjects');
|
||||
|
||||
|
@ -73,7 +73,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
'Jan 24, 2020 @ 16:06:09.541',
|
||||
],
|
||||
];
|
||||
const tableData = await pageObjects.endpoint.getEndpointAppTableData('hostListTable');
|
||||
const tableData = await pageObjects.endpointPageUtils.tableData('hostListTable');
|
||||
expect(tableData).to.eql(expectedData);
|
||||
});
|
||||
|
||||
|
@ -126,7 +126,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
});
|
||||
it('displays no items found when empty', async () => {
|
||||
// get the endpoint list table data and verify message
|
||||
const [, [noItemsFoundMessage]] = await pageObjects.endpoint.getEndpointAppTableData(
|
||||
const [, [noItemsFoundMessage]] = await pageObjects.endpointPageUtils.tableData(
|
||||
'hostListTable'
|
||||
);
|
||||
expect(noItemsFoundMessage).to.equal('No items found');
|
|
@ -8,7 +8,7 @@ import { FtrProviderContext } from '../../ftr_provider_context';
|
|||
import { PolicyTestResourceInfo } from '../../services/endpoint_policy';
|
||||
|
||||
export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||
const pageObjects = getPageObjects(['common', 'endpoint', 'policy']);
|
||||
const pageObjects = getPageObjects(['common', 'endpoint', 'policy', 'endpointPageUtils']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const policyTestResources = getService('policyTestResources');
|
||||
const RELATIVE_DATE_FORMAT = /\d (?:seconds|minutes) ago/i;
|
||||
|
@ -31,7 +31,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
expect(policyTotal).to.equal('0 Policies');
|
||||
});
|
||||
it('has correct table headers', async () => {
|
||||
const allHeaderCells = await pageObjects.endpoint.tableHeaderVisibleText('policyTable');
|
||||
const allHeaderCells = await pageObjects.endpointPageUtils.tableHeaderVisibleText(
|
||||
'policyTable'
|
||||
);
|
||||
expect(allHeaderCells).to.eql([
|
||||
'Policy Name',
|
||||
'Created By',
|
||||
|
@ -43,7 +45,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
]);
|
||||
});
|
||||
it('should show empty table results message', async () => {
|
||||
const [, [noItemsFoundMessage]] = await pageObjects.endpoint.getEndpointAppTableData(
|
||||
const [, [noItemsFoundMessage]] = await pageObjects.endpointPageUtils.tableData(
|
||||
'policyTable'
|
||||
);
|
||||
expect(noItemsFoundMessage).to.equal('No items found');
|
||||
|
@ -65,7 +67,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('should show policy on the list', async () => {
|
||||
const [, policyRow] = await pageObjects.endpoint.getEndpointAppTableData('policyTable');
|
||||
const [, policyRow] = await pageObjects.endpointPageUtils.tableData('policyTable');
|
||||
// Validate row data with the exception of the Date columns - since those are initially
|
||||
// shown as relative.
|
||||
expect([policyRow[0], policyRow[1], policyRow[3], policyRow[5], policyRow[6]]).to.eql([
|
259
x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts
Normal file
259
x-pack/test/security_solution_endpoint/apps/endpoint/resolver.ts
Normal file
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||
const pageObjects = getPageObjects(['common', 'timePicker', 'endpointAlerts']);
|
||||
const testSubjects = getService('testSubjects');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const retry = getService('retry');
|
||||
const browser = getService('browser');
|
||||
|
||||
describe('Endpoint Alert Resolver', function () {
|
||||
this.tags(['ciGroup7']);
|
||||
before(async () => {
|
||||
const fromTime = 'Sep 22, 2019 @ 20:31:44.000';
|
||||
const toTime = 'Now';
|
||||
await esArchiver.load('endpoint/resolver_tree/api_feature');
|
||||
await pageObjects.common.navigateToUrlWithBrowserHistory('endpoint', '/alerts');
|
||||
await testSubjects.existOrFail('superDatePickerShowDatesButton', { timeout: 20000 });
|
||||
await pageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
|
||||
await testSubjects.existOrFail('alertListPage');
|
||||
await testSubjects.click('alertTypeCellLink');
|
||||
await testSubjects.existOrFail('alertDetailFlyout');
|
||||
await testSubjects.click('overviewResolverTab');
|
||||
await testSubjects.existOrFail('resolverEmbeddable', { timeout: 20000 });
|
||||
await browser.setWindowSize(2400, 1800);
|
||||
});
|
||||
|
||||
it('resolver column Process Name exits', async () => {
|
||||
await testSubjects.existOrFail('tableHeaderCell_name_0');
|
||||
});
|
||||
|
||||
it('resolver column Timestamp exits', async () => {
|
||||
await testSubjects.existOrFail('tableHeaderCell_timestamp_1');
|
||||
});
|
||||
|
||||
it('resolver Table and Node data same length', async () => {
|
||||
let count = 1;
|
||||
const tableData = await pageObjects.endpointAlerts.getEndpointAlertResolverTableData(
|
||||
'resolverEmbeddable',
|
||||
'tr'
|
||||
);
|
||||
await retry.try(async function () {
|
||||
await testSubjects.click('zoom-out');
|
||||
const Nodes = await testSubjects.findAll('resolverNode');
|
||||
expect(tableData.length - 1).to.eql(Nodes.length);
|
||||
count++;
|
||||
});
|
||||
for (let i = 0; i < count; i++) {
|
||||
await testSubjects.click('zoom-in');
|
||||
}
|
||||
});
|
||||
|
||||
it('compare resolver Nodes and Table data', async () => {
|
||||
const $: string[] = [];
|
||||
const tableData = await pageObjects.endpointAlerts.getEndpointAlertResolverTableData(
|
||||
'resolverEmbeddable',
|
||||
'tr'
|
||||
);
|
||||
await testSubjects.click('zoom-out');
|
||||
const Nodes = await testSubjects.findAll('euiButton__text');
|
||||
for (const value of Nodes) {
|
||||
$.push(await value._webElement.getText());
|
||||
}
|
||||
for (let i = 0; i < $.length; i++) {
|
||||
expect(tableData[i + 1][0]).to.eql($[i]);
|
||||
}
|
||||
await testSubjects.click('zoom-in');
|
||||
});
|
||||
|
||||
it('resolver Nodes navigation Up', async () => {
|
||||
const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
await testSubjects.click('north-button');
|
||||
const NewNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
for (let i = 0; i < OriginalNodeDataStyle.length; i++) {
|
||||
expect(parseFloat(OriginalNodeDataStyle[i].top)).to.lessThan(
|
||||
parseFloat(NewNodeDataStyle[i].top)
|
||||
);
|
||||
expect(parseFloat(OriginalNodeDataStyle[i].left)).to.equal(
|
||||
parseFloat(NewNodeDataStyle[i].left)
|
||||
);
|
||||
}
|
||||
await testSubjects.click('center-button');
|
||||
});
|
||||
|
||||
it('resolver Nodes navigation Down', async () => {
|
||||
const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
await testSubjects.click('south-button');
|
||||
|
||||
const NewNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
for (let i = 0; i < NewNodeDataStyle.length; i++) {
|
||||
expect(parseFloat(NewNodeDataStyle[i].top)).to.lessThan(
|
||||
parseFloat(OriginalNodeDataStyle[i].top)
|
||||
);
|
||||
expect(parseFloat(OriginalNodeDataStyle[i].left)).to.equal(
|
||||
parseFloat(NewNodeDataStyle[i].left)
|
||||
);
|
||||
}
|
||||
await testSubjects.click('center-button');
|
||||
});
|
||||
|
||||
it('resolver Nodes navigation Right', async () => {
|
||||
const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
await testSubjects.click('west-button');
|
||||
const NewNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
for (let i = 0; i < NewNodeDataStyle.length; i++) {
|
||||
expect(parseFloat(OriginalNodeDataStyle[i].left)).to.lessThan(
|
||||
parseFloat(NewNodeDataStyle[i].left)
|
||||
);
|
||||
expect(parseFloat(NewNodeDataStyle[i].top)).to.equal(
|
||||
parseFloat(OriginalNodeDataStyle[i].top)
|
||||
);
|
||||
}
|
||||
await testSubjects.click('center-button');
|
||||
});
|
||||
|
||||
it('resolver Nodes navigation Left', async () => {
|
||||
const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
await testSubjects.click('east-button');
|
||||
|
||||
const NewNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
for (let i = 0; i < OriginalNodeDataStyle.length; i++) {
|
||||
expect(parseFloat(NewNodeDataStyle[i].left)).to.lessThan(
|
||||
parseFloat(OriginalNodeDataStyle[i].left)
|
||||
);
|
||||
expect(parseFloat(NewNodeDataStyle[i].top)).to.equal(
|
||||
parseFloat(OriginalNodeDataStyle[i].top)
|
||||
);
|
||||
}
|
||||
await testSubjects.click('center-button');
|
||||
});
|
||||
|
||||
it('resolver Nodes navigation Center', async () => {
|
||||
const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
await testSubjects.click('east-button');
|
||||
await testSubjects.click('south-button');
|
||||
|
||||
const NewNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
for (let i = 0; i < NewNodeDataStyle.length; i++) {
|
||||
expect(parseFloat(NewNodeDataStyle[i].left)).to.lessThan(
|
||||
parseFloat(OriginalNodeDataStyle[i].left)
|
||||
);
|
||||
expect(parseFloat(NewNodeDataStyle[i].top)).to.lessThan(
|
||||
parseFloat(OriginalNodeDataStyle[i].top)
|
||||
);
|
||||
}
|
||||
await (await testSubjects.find('center-button')).click();
|
||||
const CenterNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
|
||||
for (let i = 0; i < CenterNodeDataStyle.length; i++) {
|
||||
expect(parseFloat(CenterNodeDataStyle[i].left)).to.equal(
|
||||
parseFloat(OriginalNodeDataStyle[i].left)
|
||||
);
|
||||
expect(parseFloat(CenterNodeDataStyle[i].top)).to.equal(
|
||||
parseFloat(OriginalNodeDataStyle[i].top)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('resolver Nodes navigation zoom in', async () => {
|
||||
const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
await testSubjects.click('zoom-in');
|
||||
const NewNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
for (let i = 1; i < NewNodeDataStyle.length; i++) {
|
||||
expect(parseFloat(OriginalNodeDataStyle[i].left)).to.lessThan(
|
||||
parseFloat(NewNodeDataStyle[i].left)
|
||||
);
|
||||
expect(parseFloat(OriginalNodeDataStyle[i].top)).to.lessThan(
|
||||
parseFloat(NewNodeDataStyle[i].top)
|
||||
);
|
||||
expect(parseFloat(OriginalNodeDataStyle[i].width)).to.lessThan(
|
||||
parseFloat(NewNodeDataStyle[i].width)
|
||||
);
|
||||
expect(parseFloat(OriginalNodeDataStyle[i].height)).to.lessThan(
|
||||
parseFloat(NewNodeDataStyle[i].height)
|
||||
);
|
||||
await testSubjects.click('zoom-out');
|
||||
}
|
||||
});
|
||||
|
||||
it('resolver Nodes navigation zoom out', async () => {
|
||||
const OriginalNodeDataStyle = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
await testSubjects.click('zoom-out');
|
||||
const NewNodeDataStyle1 = await pageObjects.endpointAlerts.parseStyles(
|
||||
'resolverNode',
|
||||
'style'
|
||||
);
|
||||
for (let i = 1; i < OriginalNodeDataStyle.length; i++) {
|
||||
expect(parseFloat(NewNodeDataStyle1[i].left)).to.lessThan(
|
||||
parseFloat(OriginalNodeDataStyle[i].left)
|
||||
);
|
||||
expect(parseFloat(NewNodeDataStyle1[i].top)).to.lessThan(
|
||||
parseFloat(OriginalNodeDataStyle[i].top)
|
||||
);
|
||||
expect(parseFloat(NewNodeDataStyle1[i].width)).to.lessThan(
|
||||
parseFloat(OriginalNodeDataStyle[i].width)
|
||||
);
|
||||
expect(parseFloat(NewNodeDataStyle1[i].height)).to.lessThan(
|
||||
parseFloat(OriginalNodeDataStyle[i].height)
|
||||
);
|
||||
}
|
||||
await testSubjects.click('zoom-in');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await browser.setWindowSize(1600, 1000);
|
||||
await testSubjects.click('euiFlyoutCloseButton');
|
||||
await pageObjects.common.sleep(2000);
|
||||
await esArchiver.unload('endpoint/resolver_tree/api_feature');
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* 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 { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper';
|
||||
|
||||
export function EndpointAlertsPageProvider({ getService }: FtrProviderContext) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
const retry = getService('retry');
|
||||
|
||||
/**
|
||||
* @function parseStyles
|
||||
* Parses a string of inline styles into a javascript object with casing for react
|
||||
*
|
||||
* @param {string} styles
|
||||
* @returns {Object}
|
||||
*/
|
||||
const parseStyle = (styles: any) =>
|
||||
styles
|
||||
.split(';')
|
||||
.filter((style: any) => style.split(':')[0] && style.split(':')[1])
|
||||
.map((style: any) => [
|
||||
style
|
||||
.split(':')[0]
|
||||
.trim()
|
||||
.replace(/-./g, (c: any) => c.substr(1).toUpperCase()),
|
||||
style.split(':').slice(1).join(':').trim(),
|
||||
])
|
||||
.reduce(
|
||||
(styleObj: any, style: any) => ({
|
||||
...styleObj,
|
||||
[style[0]]: style[1],
|
||||
}),
|
||||
{}
|
||||
);
|
||||
|
||||
return {
|
||||
async enterSearchBarQuery(query: string) {
|
||||
return await testSubjects.setValue('alertsSearchBar', query, { clearWithKeyboard: true });
|
||||
},
|
||||
async submitSearchBarFilter() {
|
||||
return testSubjects.click('querySubmitButton');
|
||||
},
|
||||
async setSearchBarDate(timestamp: string) {
|
||||
await testSubjects.click('superDatePickerShowDatesButton');
|
||||
await testSubjects.click('superDatePickerstartDatePopoverButton');
|
||||
await testSubjects.click('superDatePickerAbsoluteTab');
|
||||
await testSubjects.setValue('superDatePickerAbsoluteDateInput', timestamp);
|
||||
await this.submitSearchBarFilter();
|
||||
},
|
||||
/**
|
||||
* Finds a table and returns the data in a nested array with row 0 is the headers if they exist.
|
||||
* It uses euiTableCellContent to avoid poluting the array data with the euiTableRowCell__mobileHeader data.
|
||||
* @param dataTestSubj
|
||||
* @param element
|
||||
* @returns Promise<string[][]>
|
||||
*/
|
||||
async getEndpointAlertResolverTableData(dataTestSubj: string, element: string) {
|
||||
await testSubjects.exists(dataTestSubj);
|
||||
const hostTable: WebElementWrapper = await testSubjects.find(dataTestSubj);
|
||||
const $ = await hostTable.parseDomContent();
|
||||
return $(element)
|
||||
.toArray()
|
||||
.map((row) =>
|
||||
$(row)
|
||||
.find('.euiTableCellContent')
|
||||
.toArray()
|
||||
.map((cell) =>
|
||||
$(cell)
|
||||
.text()
|
||||
.replace(/ /g, '')
|
||||
.trim()
|
||||
)
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Finds a nodes and returns the data in a nested array of nodes.
|
||||
* @param dataTestSubj
|
||||
* @param element
|
||||
* @returns Promise<string[][]>
|
||||
*/
|
||||
async getEndpointAlertResolverNodeData(dataTestSubj: string, element: string) {
|
||||
await testSubjects.exists(dataTestSubj);
|
||||
const Elements = await testSubjects.findAll(dataTestSubj);
|
||||
const $ = [];
|
||||
for (const value of Elements) {
|
||||
$.push(await value.getAttribute(element));
|
||||
}
|
||||
return $;
|
||||
},
|
||||
/**
|
||||
* Gets a array of not parsed styles and returns the Array of parsed styles.
|
||||
* @returns Promise<string[][]>
|
||||
* @param dataTestSubj
|
||||
* @param element
|
||||
*/
|
||||
async parseStyles(dataTestSubj: string, element: string) {
|
||||
const tableData = await this.getEndpointAlertResolverNodeData(dataTestSubj, element);
|
||||
const $ = [];
|
||||
for (let i = 1; i < tableData.length; i++) {
|
||||
const eachStyle = parseStyle(tableData[i]);
|
||||
$.push(eachStyle);
|
||||
}
|
||||
return $;
|
||||
},
|
||||
|
||||
async waitForTableToHaveData(dataTestSubj: string) {
|
||||
await retry.waitForWithTimeout('table to have data', 2000, async () => {
|
||||
const tableData = await this.getEndpointAlertResolverTableData(dataTestSubj, 'tr');
|
||||
if (tableData[1][0] === 'No items found') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
|
@ -9,7 +9,7 @@ import { FtrProviderContext } from '../ftr_provider_context';
|
|||
|
||||
export function EndpointPageProvider({ getService, getPageObjects }: FtrProviderContext) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
const pageObjects = getPageObjects(['common', 'header']);
|
||||
const pageObjects = getPageObjects(['common', 'header', 'endpointPageUtils']);
|
||||
const retry = getService('retry');
|
||||
|
||||
return {
|
||||
|
@ -23,53 +23,9 @@ export function EndpointPageProvider({ getService, getPageObjects }: FtrProvider
|
|||
await pageObjects.header.waitUntilLoadingHasFinished();
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds the Table with the given `selector` (test subject) and returns
|
||||
* back an array containing the table's header column text
|
||||
*
|
||||
* @param selector
|
||||
* @returns Promise<string[]>
|
||||
*/
|
||||
async tableHeaderVisibleText(selector: string) {
|
||||
const $ = await (await testSubjects.find('policyTable')).parseDomContent();
|
||||
return $('thead tr th')
|
||||
.toArray()
|
||||
.map((th) =>
|
||||
$(th)
|
||||
.text()
|
||||
.replace(/ /g, '')
|
||||
.trim()
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds a table and returns the data in a nested array with row 0 is the headers if they exist.
|
||||
* It uses euiTableCellContent to avoid poluting the array data with the euiTableRowCell__mobileHeader data.
|
||||
* @param dataTestSubj
|
||||
* @returns Promise<string[][]>
|
||||
*/
|
||||
async getEndpointAppTableData(dataTestSubj: string) {
|
||||
await testSubjects.exists(dataTestSubj);
|
||||
const hostTable: WebElementWrapper = await testSubjects.find(dataTestSubj);
|
||||
const $ = await hostTable.parseDomContent();
|
||||
return $('tr')
|
||||
.toArray()
|
||||
.map((row) =>
|
||||
$(row)
|
||||
.find('.euiTableCellContent')
|
||||
.toArray()
|
||||
.map((cell) =>
|
||||
$(cell)
|
||||
.text()
|
||||
.replace(/ /g, '')
|
||||
.trim()
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
async waitForTableToHaveData(dataTestSubj: string) {
|
||||
await retry.waitForWithTimeout('table to have data', 2000, async () => {
|
||||
const tableData = await this.getEndpointAppTableData(dataTestSubj);
|
||||
const tableData = await pageObjects.endpointPageUtils.tableData(dataTestSubj);
|
||||
if (tableData[1][0] === 'No items found') {
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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 { WebElementWrapper } from '../../../../test/functional/services/lib/web_element_wrapper';
|
||||
|
||||
export function EndpointPageUtils({ getService }: FtrProviderContext) {
|
||||
const testSubjects = getService('testSubjects');
|
||||
const find = getService('find');
|
||||
|
||||
return {
|
||||
/**
|
||||
* Finds a given EuiCheckbox by test subject and clicks on it
|
||||
*
|
||||
* @param euiCheckBoxTestId
|
||||
*/
|
||||
async clickOnEuiCheckbox(euiCheckBoxTestId: string) {
|
||||
// This utility is needed because EuiCheckbox forwards the test subject on to
|
||||
// the actual `<input>` which is not actually visible/accessible on the page.
|
||||
// In order to actually cause the state of the checkbox to change, the `<label>`
|
||||
// must be clicked.
|
||||
const euiCheckboxLabelElement = await find.byXPath(
|
||||
`//input[@data-test-subj='${euiCheckBoxTestId}']/../label`
|
||||
);
|
||||
|
||||
await euiCheckboxLabelElement.click();
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds the Table with the given `selector` (test subject) and returns
|
||||
* back an array containing the table's header column text
|
||||
*
|
||||
* @param selector
|
||||
* @returns Promise<string[]>
|
||||
*/
|
||||
async tableHeaderVisibleText(selector: string) {
|
||||
const $ = await (await testSubjects.find(selector)).parseDomContent();
|
||||
return $('thead tr th')
|
||||
.toArray()
|
||||
.map((th) =>
|
||||
$(th)
|
||||
.text()
|
||||
.replace(/ /g, '')
|
||||
.trim()
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Finds a table and returns the data in a nested array with row 0 is the headers if they exist.
|
||||
* It uses euiTableCellContent to avoid poluting the array data with the euiTableRowCell__mobileHeader data.
|
||||
* @param dataTestSubj
|
||||
* @returns Promise<string[][]>
|
||||
*/
|
||||
async tableData(dataTestSubj: string) {
|
||||
await testSubjects.exists(dataTestSubj);
|
||||
const hostTable: WebElementWrapper = await testSubjects.find(dataTestSubj);
|
||||
const $ = await hostTable.parseDomContent();
|
||||
return $('tr')
|
||||
.toArray()
|
||||
.map((row) =>
|
||||
$(row)
|
||||
.find('.euiTableCellContent')
|
||||
.toArray()
|
||||
.map((cell) =>
|
||||
$(cell)
|
||||
.text()
|
||||
.replace(/ /g, '')
|
||||
.trim()
|
||||
)
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue