From 62f807227bc946ad3493c5b7b461d38e8ffa12aa Mon Sep 17 00:00:00 2001 From: Sandra G Date: Fri, 29 Oct 2021 13:55:32 -0400 Subject: [PATCH] [Stack Monitoring] Logstash Functional Tests (#116481) * logstash overview functional test * logstash nodes listing functional tests * node detail tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../monitoring/public/alerts/status.tsx | 10 +- .../pages/logstash/logstash_template.tsx | 2 + .../pages/logstash/node_pipelines.tsx | 22 +-- .../application/pages/logstash/nodes.tsx | 2 +- .../application/pages/logstash/overview.tsx | 3 +- .../application/pages/logstash/pipelines.tsx | 1 - .../cluster/overview/logstash_panel.js | 1 + .../components/logstash/listing/listing.js | 27 ++-- .../test/functional/apps/monitoring/index.js | 7 +- .../apps/monitoring/logstash/node_detail.js | 125 ++++++++++++++++++ .../monitoring/logstash/node_detail_mb.js | 125 ++++++++++++++++++ .../apps/monitoring/logstash/nodes.js | 104 +++++++++++++++ .../apps/monitoring/logstash/nodes_mb.js | 104 +++++++++++++++ .../apps/monitoring/logstash/overview.js | 44 ++++++ .../apps/monitoring/logstash/overview_mb.js | 44 ++++++ x-pack/test/functional/services/index.ts | 6 + .../services/monitoring/cluster_overview.js | 7 + .../functional/services/monitoring/index.js | 3 + .../monitoring/logstash_node_detail.js | 42 ++++++ .../services/monitoring/logstash_nodes.js | 102 ++++++++++++++ .../services/monitoring/logstash_overview.js | 20 +++ 21 files changed, 772 insertions(+), 29 deletions(-) create mode 100644 x-pack/test/functional/apps/monitoring/logstash/node_detail.js create mode 100644 x-pack/test/functional/apps/monitoring/logstash/node_detail_mb.js create mode 100644 x-pack/test/functional/apps/monitoring/logstash/nodes.js create mode 100644 x-pack/test/functional/apps/monitoring/logstash/nodes_mb.js create mode 100644 x-pack/test/functional/apps/monitoring/logstash/overview.js create mode 100644 x-pack/test/functional/apps/monitoring/logstash/overview_mb.js create mode 100644 x-pack/test/functional/services/monitoring/logstash_node_detail.js create mode 100644 x-pack/test/functional/services/monitoring/logstash_nodes.js create mode 100644 x-pack/test/functional/services/monitoring/logstash_overview.js diff --git a/x-pack/plugins/monitoring/public/alerts/status.tsx b/x-pack/plugins/monitoring/public/alerts/status.tsx index a29d85d43c57..28c2ebcce251 100644 --- a/x-pack/plugins/monitoring/public/alerts/status.tsx +++ b/x-pack/plugins/monitoring/public/alerts/status.tsx @@ -64,10 +64,12 @@ export const AlertsStatus: React.FC = (props: Props) => { {showOnlyCount ? ( count ) : ( - + + + )} diff --git a/x-pack/plugins/monitoring/public/application/pages/logstash/logstash_template.tsx b/x-pack/plugins/monitoring/public/application/pages/logstash/logstash_template.tsx index 12b664129211..96ac605b1ae5 100644 --- a/x-pack/plugins/monitoring/public/application/pages/logstash/logstash_template.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/logstash/logstash_template.tsx @@ -63,6 +63,7 @@ export const LogstashTemplate: React.FC = ({ defaultMessage: 'Pipelines', }), route: `/logstash/node/${instance.nodeSummary?.uuid}/pipelines`, + testSubj: 'logstashNodeDetailPipelinesLink', }); tabs.push({ id: 'advanced', @@ -70,6 +71,7 @@ export const LogstashTemplate: React.FC = ({ defaultMessage: 'Advanced', }), route: `/logstash/node/${instance.nodeSummary?.uuid}/advanced`, + testSubj: 'logstashNodeDetailAdvancedLink', }); } } diff --git a/x-pack/plugins/monitoring/public/application/pages/logstash/node_pipelines.tsx b/x-pack/plugins/monitoring/public/application/pages/logstash/node_pipelines.tsx index 0d89adeaeadd..5ac5fe356db9 100644 --- a/x-pack/plugins/monitoring/public/application/pages/logstash/node_pipelines.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/logstash/node_pipelines.tsx @@ -105,16 +105,18 @@ export const LogStashNodePipelinesPage: React.FC = ({ clusters } cluster={cluster} > {data.pipelines && ( - +
+ +
)} ); diff --git a/x-pack/plugins/monitoring/public/application/pages/logstash/nodes.tsx b/x-pack/plugins/monitoring/public/application/pages/logstash/nodes.tsx index 4822841cd241..a60310624208 100644 --- a/x-pack/plugins/monitoring/public/application/pages/logstash/nodes.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/logstash/nodes.tsx @@ -92,7 +92,7 @@ export const LogStashNodesPage: React.FC = ({ clusters }) => { getPageData={getPageData} cluster={cluster} > -
+
( diff --git a/x-pack/plugins/monitoring/public/application/pages/logstash/overview.tsx b/x-pack/plugins/monitoring/public/application/pages/logstash/overview.tsx index d1e7faed56cb..1412f7b9c55f 100644 --- a/x-pack/plugins/monitoring/public/application/pages/logstash/overview.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/logstash/overview.tsx @@ -85,10 +85,9 @@ export const LogStashOverviewPage: React.FC = ({ clusters }) => title={title} pageTitle={pageTitle} getPageData={getPageData} - data-test-subj="elasticsearchOverviewPage" cluster={cluster} > -
{renderOverview(data)}
+
{renderOverview(data)}
); }; diff --git a/x-pack/plugins/monitoring/public/application/pages/logstash/pipelines.tsx b/x-pack/plugins/monitoring/public/application/pages/logstash/pipelines.tsx index e3a5deebd6ca..7c876c1e950c 100644 --- a/x-pack/plugins/monitoring/public/application/pages/logstash/pipelines.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/logstash/pipelines.tsx @@ -105,7 +105,6 @@ export const LogStashPipelinesPage: React.FC = ({ clusters }) => title={title} pageTitle={pageTitle} getPageData={getPageData} - data-test-subj="logstashPipelinesListing" cluster={cluster} >
{renderOverview(data)}
diff --git a/x-pack/plugins/monitoring/public/components/cluster/overview/logstash_panel.js b/x-pack/plugins/monitoring/public/components/cluster/overview/logstash_panel.js index 1afe75cda402..217bd1d24ff0 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/overview/logstash_panel.js +++ b/x-pack/plugins/monitoring/public/components/cluster/overview/logstash_panel.js @@ -98,6 +98,7 @@ export function LogstashPanel(props) { setupModeEnabled={setupMode.enabled} setupModeData={setupModeData} href={goToLogstash()} + data-test-subj="lsOverview" aria-label={i18n.translate( 'xpack.monitoring.cluster.overview.logstashPanel.overviewLinkAriaLabel', { diff --git a/x-pack/plugins/monitoring/public/components/logstash/listing/listing.js b/x-pack/plugins/monitoring/public/components/logstash/listing/listing.js index 04eb6c5957c2..ddf6a7d7382a 100644 --- a/x-pack/plugins/monitoring/public/components/logstash/listing/listing.js +++ b/x-pack/plugins/monitoring/public/components/logstash/listing/listing.js @@ -66,12 +66,15 @@ export class Listing extends PureComponent { return (
-
- +
+ {name}
-
{node.logstash.http_address}
+
{node.logstash.http_address}
{setupModeStatus}
); @@ -92,7 +95,9 @@ export class Listing extends PureComponent { }), field: 'cpu_usage', sortable: true, - render: (value) => formatPercentageUsage(value, 100), + render: (value) => ( + {formatPercentageUsage(value, 100)} + ), }, { name: i18n.translate('xpack.monitoring.logstash.nodes.loadAverageTitle', { @@ -100,7 +105,7 @@ export class Listing extends PureComponent { }), field: 'load_average', sortable: true, - render: (value) => formatNumber(value, '0.00'), + render: (value) => {formatNumber(value, '0.00')}, }, { name: i18n.translate('xpack.monitoring.logstash.nodes.jvmHeapUsedTitle', { @@ -109,7 +114,9 @@ export class Listing extends PureComponent { }), field: 'jvm_heap_used', sortable: true, - render: (value) => formatPercentageUsage(value, 100), + render: (value) => ( + {formatPercentageUsage(value, 100)} + ), }, { name: i18n.translate('xpack.monitoring.logstash.nodes.eventsIngestedTitle', { @@ -117,7 +124,7 @@ export class Listing extends PureComponent { }), field: 'events_out', sortable: true, - render: (value) => formatNumber(value, '0.[0]a'), + render: (value) => {formatNumber(value, '0.[0]a')}, }, { name: i18n.translate('xpack.monitoring.logstash.nodes.configReloadsTitle', { @@ -126,14 +133,14 @@ export class Listing extends PureComponent { sortable: true, render: (node) => (
-
+
-
+
formatNumber(value), + render: (value) => {formatNumber(value)}, }, ]; } diff --git a/x-pack/test/functional/apps/monitoring/index.js b/x-pack/test/functional/apps/monitoring/index.js index a67964d32516..20217399a919 100644 --- a/x-pack/test/functional/apps/monitoring/index.js +++ b/x-pack/test/functional/apps/monitoring/index.js @@ -34,9 +34,14 @@ export default function ({ loadTestFile }) { loadTestFile(require.resolve('./kibana/instance')); loadTestFile(require.resolve('./kibana/instance_mb')); + loadTestFile(require.resolve('./logstash/overview')); + loadTestFile(require.resolve('./logstash/overview_mb')); + loadTestFile(require.resolve('./logstash/nodes')); + loadTestFile(require.resolve('./logstash/nodes_mb')); loadTestFile(require.resolve('./logstash/pipelines')); loadTestFile(require.resolve('./logstash/pipelines_mb')); - + loadTestFile(require.resolve('./logstash/node_detail')); + loadTestFile(require.resolve('./logstash/node_detail_mb')); loadTestFile(require.resolve('./beats/cluster')); loadTestFile(require.resolve('./beats/overview')); loadTestFile(require.resolve('./beats/listing')); diff --git a/x-pack/test/functional/apps/monitoring/logstash/node_detail.js b/x-pack/test/functional/apps/monitoring/logstash/node_detail.js new file mode 100644 index 000000000000..2e75422f3028 --- /dev/null +++ b/x-pack/test/functional/apps/monitoring/logstash/node_detail.js @@ -0,0 +1,125 @@ +/* + * 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 { getLifecycleMethods } from '../_get_lifecycle_methods'; + +export default function ({ getService, getPageObjects }) { + const PageObjects = getPageObjects(['common']); + const retry = getService('retry'); + const clusterOverview = getService('monitoringClusterOverview'); + const nodes = getService('monitoringLogstashNodes'); + const nodeDetail = getService('monitoringLogstashNodeDetail'); + const pipelinesList = getService('monitoringLogstashPipelines'); + + describe('Logstash node detail', () => { + describe('Node', () => { + const { setup, tearDown } = getLifecycleMethods(getService, getPageObjects); + const nodeSummaryStatus = { + eventsIn: 'Events Received\n42.4k', + eventsOut: 'Events Emitted\n39.4k', + httpAddress: 'Transport Address\n127.0.0.1:9600', + numReloads: 'Config Reloads\n0', + pipelineBatchSize: 'Batch Size\n125', + pipelineWorkers: 'Pipeline Workers\n8', + uptime: 'Uptime\n8 minutes', + version: 'Version\n7.0.0-alpha1', + }; + + before(async () => { + await setup('x-pack/test/functional/es_archives/monitoring/logstash_pipelines', { + from: 'Jan 22, 2018 @ 09:10:00.000', + to: 'Jan 22, 2018 @ 09:41:00.000', + }); + + await clusterOverview.closeAlertsModal(); + + // go to logstash nodes + await clusterOverview.clickLsNodes(); + expect(await nodes.isOnNodesListing()).to.be(true); + }); + + after(async () => { + await tearDown(); + }); + + it('detail view should have summary status showing correct info', async () => { + await nodes.clickRowByResolver('29a3dfa6-c146-4534-9bc0-be475d2ce950'); + expect(await nodeDetail.getSummary()).to.eql(nodeSummaryStatus); + }); + it('advanced view should have summary status showing correct info', async () => { + await nodeDetail.clickAdvanced(); + + expect(await nodeDetail.getSummary()).to.eql(nodeSummaryStatus); + }); + it('pipelines view should have summary status showing correct info', async () => { + await nodeDetail.clickPipelines(); + + expect(await nodeDetail.getSummary()).to.eql(nodeSummaryStatus); + }); + it('pipelines view should have Pipelines table showing correct rows with default sorting', async () => { + const rows = await pipelinesList.getRows(); + expect(rows.length).to.be(3); + + await pipelinesList.clickIdCol(); + + const pipelinesAll = await pipelinesList.getPipelinesAll(); + + const tableData = [ + { id: 'nginx_logs', eventsEmittedRate: '62.5 e/s', nodeCount: '1' }, + { id: 'test_interpolation', eventsEmittedRate: '0 e/s', nodeCount: '1' }, + { id: 'tweets_about_labradoodles', eventsEmittedRate: '1.2 e/s', nodeCount: '1' }, + ]; + + // check the all data in the table + pipelinesAll.forEach((obj, index) => { + expect(pipelinesAll[index].id).to.be(tableData[index].id); + expect(pipelinesAll[index].eventsEmittedRate).to.be(tableData[index].eventsEmittedRate); + expect(pipelinesAll[index].nodeCount).to.be(tableData[index].nodeCount); + }); + }); + + it('should have Pipelines Table showing correct rows after sorting by Events Emitted Rate Asc', async () => { + await pipelinesList.clickEventsEmittedRateCol(); + + const rows = await pipelinesList.getRows(); + expect(rows.length).to.be(3); + + const pipelinesAll = await pipelinesList.getPipelinesAll(); + + const tableData = [ + { id: 'test_interpolation', eventsEmittedRate: '0 e/s', nodeCount: '1' }, + { id: 'tweets_about_labradoodles', eventsEmittedRate: '1.2 e/s', nodeCount: '1' }, + { id: 'nginx_logs', eventsEmittedRate: '62.5 e/s', nodeCount: '1' }, + ]; + + // check the all data in the table + pipelinesAll.forEach((obj, index) => { + expect(pipelinesAll[index].id).to.be(tableData[index].id); + expect(pipelinesAll[index].eventsEmittedRate).to.be(tableData[index].eventsEmittedRate); + expect(pipelinesAll[index].nodeCount).to.be(tableData[index].nodeCount); + }); + }); + + it('should filter for non-existent pipeline', async () => { + await pipelinesList.setFilter('foobar'); + await pipelinesList.assertNoData(); + await pipelinesList.clearFilter(); + }); + + it('should filter for specific pipelines', async () => { + await pipelinesList.setFilter('la'); + await PageObjects.common.pressEnterKey(); + await retry.try(async () => { + const rows = await pipelinesList.getRows(); + expect(rows.length).to.be(2); + }); + await pipelinesList.clearFilter(); + }); + }); + }); +} diff --git a/x-pack/test/functional/apps/monitoring/logstash/node_detail_mb.js b/x-pack/test/functional/apps/monitoring/logstash/node_detail_mb.js new file mode 100644 index 000000000000..aba95b42c304 --- /dev/null +++ b/x-pack/test/functional/apps/monitoring/logstash/node_detail_mb.js @@ -0,0 +1,125 @@ +/* + * 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 { getLifecycleMethods } from '../_get_lifecycle_methods'; + +export default function ({ getService, getPageObjects }) { + const PageObjects = getPageObjects(['common']); + const retry = getService('retry'); + const clusterOverview = getService('monitoringClusterOverview'); + const nodes = getService('monitoringLogstashNodes'); + const nodeDetail = getService('monitoringLogstashNodeDetail'); + const pipelinesList = getService('monitoringLogstashPipelines'); + + describe('Logstash node detail mb', () => { + describe('Node', () => { + const { setup, tearDown } = getLifecycleMethods(getService, getPageObjects); + const nodeSummaryStatus = { + eventsIn: 'Events Received\n42.4k', + eventsOut: 'Events Emitted\n39.4k', + httpAddress: 'Transport Address\n127.0.0.1:9600', + numReloads: 'Config Reloads\n0', + pipelineBatchSize: 'Batch Size\n125', + pipelineWorkers: 'Pipeline Workers\n8', + uptime: 'Uptime\n8 minutes', + version: 'Version\n7.0.0-alpha1', + }; + + before(async () => { + await setup('x-pack/test/functional/es_archives/monitoring/logstash_pipelines_mb', { + from: 'Jan 22, 2018 @ 09:10:00.000', + to: 'Jan 22, 2018 @ 09:41:00.000', + }); + + await clusterOverview.closeAlertsModal(); + + // go to logstash nodes + await clusterOverview.clickLsNodes(); + expect(await nodes.isOnNodesListing()).to.be(true); + await nodes.clickRowByResolver('29a3dfa6-c146-4534-9bc0-be475d2ce950'); + }); + + after(async () => { + await tearDown(); + }); + + it('detail view should have summary status showing correct info', async () => { + expect(await nodeDetail.getSummary()).to.eql(nodeSummaryStatus); + }); + it('advanced view should have summary status showing correct info', async () => { + await nodeDetail.clickAdvanced(); + + expect(await nodeDetail.getSummary()).to.eql(nodeSummaryStatus); + }); + it('pipelines view should have summary status showing correct info', async () => { + await nodeDetail.clickPipelines(); + + expect(await nodeDetail.getSummary()).to.eql(nodeSummaryStatus); + }); + it('pipelines view should have Pipelines table showing correct rows with default sorting', async () => { + const rows = await pipelinesList.getRows(); + expect(rows.length).to.be(3); + + await pipelinesList.clickIdCol(); + + const pipelinesAll = await pipelinesList.getPipelinesAll(); + + const tableData = [ + { id: 'nginx_logs', eventsEmittedRate: '62.5 e/s', nodeCount: '1' }, + { id: 'test_interpolation', eventsEmittedRate: '0 e/s', nodeCount: '1' }, + { id: 'tweets_about_labradoodles', eventsEmittedRate: '1.2 e/s', nodeCount: '1' }, + ]; + + // check the all data in the table + pipelinesAll.forEach((obj, index) => { + expect(pipelinesAll[index].id).to.be(tableData[index].id); + expect(pipelinesAll[index].eventsEmittedRate).to.be(tableData[index].eventsEmittedRate); + expect(pipelinesAll[index].nodeCount).to.be(tableData[index].nodeCount); + }); + }); + + it('should have Pipelines Table showing correct rows after sorting by Events Emitted Rate Asc', async () => { + await pipelinesList.clickEventsEmittedRateCol(); + + const rows = await pipelinesList.getRows(); + expect(rows.length).to.be(3); + + const pipelinesAll = await pipelinesList.getPipelinesAll(); + + const tableData = [ + { id: 'test_interpolation', eventsEmittedRate: '0 e/s', nodeCount: '1' }, + { id: 'tweets_about_labradoodles', eventsEmittedRate: '1.2 e/s', nodeCount: '1' }, + { id: 'nginx_logs', eventsEmittedRate: '62.5 e/s', nodeCount: '1' }, + ]; + + // check the all data in the table + pipelinesAll.forEach((obj, index) => { + expect(pipelinesAll[index].id).to.be(tableData[index].id); + expect(pipelinesAll[index].eventsEmittedRate).to.be(tableData[index].eventsEmittedRate); + expect(pipelinesAll[index].nodeCount).to.be(tableData[index].nodeCount); + }); + }); + + it('should filter for non-existent pipeline', async () => { + await pipelinesList.setFilter('foobar'); + await pipelinesList.assertNoData(); + await pipelinesList.clearFilter(); + }); + + it('should filter for specific pipelines', async () => { + await pipelinesList.setFilter('la'); + await PageObjects.common.pressEnterKey(); + await retry.try(async () => { + const rows = await pipelinesList.getRows(); + expect(rows.length).to.be(2); + }); + await pipelinesList.clearFilter(); + }); + }); + }); +} diff --git a/x-pack/test/functional/apps/monitoring/logstash/nodes.js b/x-pack/test/functional/apps/monitoring/logstash/nodes.js new file mode 100644 index 000000000000..75e3c7bac7c0 --- /dev/null +++ b/x-pack/test/functional/apps/monitoring/logstash/nodes.js @@ -0,0 +1,104 @@ +/* + * 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 { getLifecycleMethods } from '../_get_lifecycle_methods'; + +export default function ({ getService, getPageObjects }) { + const clusterOverview = getService('monitoringClusterOverview'); + const nodes = getService('monitoringLogstashNodes'); + const logstashSummaryStatus = getService('monitoringLogstashSummaryStatus'); + + describe('Logstash nodes', () => { + const { setup, tearDown } = getLifecycleMethods(getService, getPageObjects); + + before(async () => { + await setup('x-pack/test/functional/es_archives/monitoring/logstash_pipelines', { + from: 'Jan 22, 2018 @ 09:10:00.000', + to: 'Jan 22, 2018 @ 09:41:00.000', + }); + + await clusterOverview.closeAlertsModal(); + + // go to logstash nodes + await clusterOverview.clickLsNodes(); + expect(await nodes.isOnNodesListing()).to.be(true); + }); + + after(async () => { + await tearDown(); + }); + it('should have Logstash Cluster Summary Status showing correct info', async () => { + expect(await logstashSummaryStatus.getContent()).to.eql({ + eventsInTotal: 'Events Received\n117.9k', + eventsOutTotal: 'Events Emitted\n111.9k', + memoryUsed: 'Memory\n528.4 MB / 1.9 GB', + nodeCount: 'Nodes\n2', + }); + }); + it('should have a nodes table with the correct number of rows', async () => { + const rows = await nodes.getRows(); + expect(rows.length).to.be(2); + }); + it('should have a nodes table with the correct data', async () => { + const nodesAll = await nodes.getNodesAll(); + + const tableData = [ + { + id: 'Shaunaks-MacBook-Pro.local', + httpAddress: '127.0.0.1:9601', + alertStatus: 'Clear', + cpuUsage: '0.00%', + loadAverage: '4.54', + jvmHeapUsed: '22.00%', + eventsOut: '73.5k', + configReloadsSuccess: '0 successes', + configReloadsFailure: '0 failures', + version: '7.0.0-alpha1', + }, + { + id: 'Shaunaks-MacBook-Pro.local', + httpAddress: '127.0.0.1:9600', + alertStatus: 'Clear', + cpuUsage: '2.00%', + loadAverage: '4.76', + jvmHeapUsed: '30.00%', + eventsOut: '38.4k', + configReloadsSuccess: '0 successes', + configReloadsFailure: '0 failures', + version: '7.0.0-alpha1', + }, + ]; + + nodesAll.forEach((obj, index) => { + expect(nodesAll[index].id).to.be(tableData[index].id); + expect(nodesAll[index].httpAddress).to.be(tableData[index].httpAddress); + expect(nodesAll[index].alertStatus).to.be(tableData[index].alertStatus); + expect(nodesAll[index].cpuUsage).to.be(tableData[index].cpuUsage); + expect(nodesAll[index].loadAverage).to.be(tableData[index].loadAverage); + expect(nodesAll[index].jvmHeapUsed).to.be(tableData[index].jvmHeapUsed); + expect(nodesAll[index].eventsOut).to.be(tableData[index].eventsOut); + expect(nodesAll[index].configReloadsSuccess).to.be(tableData[index].configReloadsSuccess); + expect(nodesAll[index].configReloadsFailure).to.be(tableData[index].configReloadsFailure); + expect(nodesAll[index].version).to.be(tableData[index].version); + }); + }); + + it('should filter for non-existent node', async () => { + await nodes.setFilter('foobar'); + await nodes.assertNoData(); + await nodes.clearFilter(); + }); + + it('should filter for specific nodes', async () => { + await nodes.setFilter('sha'); + const rows = await nodes.getRows(); + expect(rows.length).to.be(2); + await nodes.clearFilter(); + }); + }); +} diff --git a/x-pack/test/functional/apps/monitoring/logstash/nodes_mb.js b/x-pack/test/functional/apps/monitoring/logstash/nodes_mb.js new file mode 100644 index 000000000000..1f55d3a0c72d --- /dev/null +++ b/x-pack/test/functional/apps/monitoring/logstash/nodes_mb.js @@ -0,0 +1,104 @@ +/* + * 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 { getLifecycleMethods } from '../_get_lifecycle_methods'; + +export default function ({ getService, getPageObjects }) { + const clusterOverview = getService('monitoringClusterOverview'); + const nodes = getService('monitoringLogstashNodes'); + const logstashSummaryStatus = getService('monitoringLogstashSummaryStatus'); + + describe('Logstash nodes mb', () => { + const { setup, tearDown } = getLifecycleMethods(getService, getPageObjects); + + before(async () => { + await setup('x-pack/test/functional/es_archives/monitoring/logstash_pipelines_mb', { + from: 'Jan 22, 2018 @ 09:10:00.000', + to: 'Jan 22, 2018 @ 09:41:00.000', + }); + + await clusterOverview.closeAlertsModal(); + + // go to logstash nodes + await clusterOverview.clickLsNodes(); + expect(await nodes.isOnNodesListing()).to.be(true); + }); + + after(async () => { + await tearDown(); + }); + it('should have Logstash Cluster Summary Status showing correct info', async () => { + expect(await logstashSummaryStatus.getContent()).to.eql({ + eventsInTotal: 'Events Received\n117.9k', + eventsOutTotal: 'Events Emitted\n111.9k', + memoryUsed: 'Memory\n528.4 MB / 1.9 GB', + nodeCount: 'Nodes\n2', + }); + }); + it('should have a nodes table with the correct number of rows', async () => { + const rows = await nodes.getRows(); + expect(rows.length).to.be(2); + }); + it('should have a nodes table with the correct data', async () => { + const nodesAll = await nodes.getNodesAll(); + + const tableData = [ + { + id: 'Shaunaks-MacBook-Pro.local', + httpAddress: '127.0.0.1:9601', + alertStatus: 'Clear', + cpuUsage: '0.00%', + loadAverage: '4.54', + jvmHeapUsed: '22.00%', + eventsOut: '73.5k', + configReloadsSuccess: '0 successes', + configReloadsFailure: '0 failures', + version: '7.0.0-alpha1', + }, + { + id: 'Shaunaks-MacBook-Pro.local', + httpAddress: '127.0.0.1:9600', + alertStatus: 'Clear', + cpuUsage: '2.00%', + loadAverage: '4.76', + jvmHeapUsed: '30.00%', + eventsOut: '38.4k', + configReloadsSuccess: '0 successes', + configReloadsFailure: '0 failures', + version: '7.0.0-alpha1', + }, + ]; + + nodesAll.forEach((obj, index) => { + expect(nodesAll[index].id).to.be(tableData[index].id); + expect(nodesAll[index].httpAddress).to.be(tableData[index].httpAddress); + expect(nodesAll[index].alertStatus).to.be(tableData[index].alertStatus); + expect(nodesAll[index].cpuUsage).to.be(tableData[index].cpuUsage); + expect(nodesAll[index].loadAverage).to.be(tableData[index].loadAverage); + expect(nodesAll[index].jvmHeapUsed).to.be(tableData[index].jvmHeapUsed); + expect(nodesAll[index].eventsOut).to.be(tableData[index].eventsOut); + expect(nodesAll[index].configReloadsSuccess).to.be(tableData[index].configReloadsSuccess); + expect(nodesAll[index].configReloadsFailure).to.be(tableData[index].configReloadsFailure); + expect(nodesAll[index].version).to.be(tableData[index].version); + }); + }); + + it('should filter for non-existent node', async () => { + await nodes.setFilter('foobar'); + await nodes.assertNoData(); + await nodes.clearFilter(); + }); + + it('should filter for specific nodes', async () => { + await nodes.setFilter('sha'); + const rows = await nodes.getRows(); + expect(rows.length).to.be(2); + await nodes.clearFilter(); + }); + }); +} diff --git a/x-pack/test/functional/apps/monitoring/logstash/overview.js b/x-pack/test/functional/apps/monitoring/logstash/overview.js new file mode 100644 index 000000000000..593159ec6b26 --- /dev/null +++ b/x-pack/test/functional/apps/monitoring/logstash/overview.js @@ -0,0 +1,44 @@ +/* + * 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 { getLifecycleMethods } from '../_get_lifecycle_methods'; + +export default function ({ getService, getPageObjects }) { + const clusterOverview = getService('monitoringClusterOverview'); + const overview = getService('monitoringLogstashOverview'); + const logstashSummaryStatus = getService('monitoringLogstashSummaryStatus'); + + describe('Logstash overview', () => { + const { setup, tearDown } = getLifecycleMethods(getService, getPageObjects); + + before(async () => { + await setup('x-pack/test/functional/es_archives/monitoring/logstash_pipelines', { + from: 'Jan 22, 2018 @ 09:10:00.000', + to: 'Jan 22, 2018 @ 09:41:00.000', + }); + + await clusterOverview.closeAlertsModal(); + + // go to logstash overview + await clusterOverview.clickLsOverview(); + expect(await overview.isOnOverview()).to.be(true); + }); + + after(async () => { + await tearDown(); + }); + it('should have Logstash Cluster Summary Status showing correct info', async () => { + expect(await logstashSummaryStatus.getContent()).to.eql({ + eventsInTotal: 'Events Received\n117.9k', + eventsOutTotal: 'Events Emitted\n111.9k', + memoryUsed: 'Memory\n528.4 MB / 1.9 GB', + nodeCount: 'Nodes\n2', + }); + }); + }); +} diff --git a/x-pack/test/functional/apps/monitoring/logstash/overview_mb.js b/x-pack/test/functional/apps/monitoring/logstash/overview_mb.js new file mode 100644 index 000000000000..91faede36b1d --- /dev/null +++ b/x-pack/test/functional/apps/monitoring/logstash/overview_mb.js @@ -0,0 +1,44 @@ +/* + * 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 { getLifecycleMethods } from '../_get_lifecycle_methods'; + +export default function ({ getService, getPageObjects }) { + const clusterOverview = getService('monitoringClusterOverview'); + const overview = getService('monitoringLogstashOverview'); + const logstashSummaryStatus = getService('monitoringLogstashSummaryStatus'); + + describe('Logstash overview mb', () => { + const { setup, tearDown } = getLifecycleMethods(getService, getPageObjects); + + before(async () => { + await setup('x-pack/test/functional/es_archives/monitoring/logstash_pipelines_mb', { + from: 'Jan 22, 2018 @ 09:10:00.000', + to: 'Jan 22, 2018 @ 09:41:00.000', + }); + + await clusterOverview.closeAlertsModal(); + + // go to logstash overview + await clusterOverview.clickLsOverview(); + expect(await overview.isOnOverview()).to.be(true); + }); + + after(async () => { + await tearDown(); + }); + it('should have an Logstash Summary Status with correct info', async () => { + expect(await logstashSummaryStatus.getContent()).to.eql({ + eventsInTotal: 'Events Received\n117.9k', + eventsOutTotal: 'Events Emitted\n111.9k', + memoryUsed: 'Memory\n528.4 MB / 1.9 GB', + nodeCount: 'Nodes\n2', + }); + }); + }); +} diff --git a/x-pack/test/functional/services/index.ts b/x-pack/test/functional/services/index.ts index 3e69a5f43928..2f9259c16d4b 100644 --- a/x-pack/test/functional/services/index.ts +++ b/x-pack/test/functional/services/index.ts @@ -27,6 +27,9 @@ import { MonitoringBeatsListingProvider, MonitoringBeatDetailProvider, MonitoringBeatsSummaryStatusProvider, + MonitoringLogstashOverviewProvider, + MonitoringLogstashNodesProvider, + MonitoringLogstashNodeDetailProvider, MonitoringLogstashPipelinesProvider, MonitoringLogstashSummaryStatusProvider, MonitoringKibanaOverviewProvider, @@ -88,6 +91,9 @@ export const services = { monitoringBeatsListing: MonitoringBeatsListingProvider, monitoringBeatDetail: MonitoringBeatDetailProvider, monitoringBeatsSummaryStatus: MonitoringBeatsSummaryStatusProvider, + monitoringLogstashOverview: MonitoringLogstashOverviewProvider, + monitoringLogstashNodes: MonitoringLogstashNodesProvider, + monitoringLogstashNodeDetail: MonitoringLogstashNodeDetailProvider, monitoringLogstashPipelines: MonitoringLogstashPipelinesProvider, monitoringLogstashSummaryStatus: MonitoringLogstashSummaryStatusProvider, monitoringKibanaOverview: MonitoringKibanaOverviewProvider, diff --git a/x-pack/test/functional/services/monitoring/cluster_overview.js b/x-pack/test/functional/services/monitoring/cluster_overview.js index 215e92fa055b..835e566386e0 100644 --- a/x-pack/test/functional/services/monitoring/cluster_overview.js +++ b/x-pack/test/functional/services/monitoring/cluster_overview.js @@ -45,6 +45,7 @@ export function MonitoringClusterOverviewProvider({ getService }) { const SUBJ_LS_UPTIME = `${SUBJ_LS_PANEL} > lsUptime`; const SUBJ_LS_JVM_HEAP = `${SUBJ_LS_PANEL} > lsJvmHeap`; const SUBJ_LS_PIPELINES = `${SUBJ_LS_PANEL} > lsPipelines`; + const SUBJ_LS_OVERVIEW = `${SUBJ_LS_PANEL} > lsOverview`; const SUBJ_BEATS_PANEL = `clusterItemContainerBeats`; const SUBJ_BEATS_OVERVIEW = `${SUBJ_BEATS_PANEL} > beatsOverview`; @@ -179,6 +180,12 @@ export function MonitoringClusterOverviewProvider({ getService }) { getLsJvmHeap() { return testSubjects.getVisibleText(SUBJ_LS_JVM_HEAP); } + clickLsOverview() { + return testSubjects.click(SUBJ_LS_OVERVIEW); + } + clickLsNodes() { + return testSubjects.click(SUBJ_LS_NODES); + } getLsPipelines() { return testSubjects.getVisibleText(SUBJ_LS_PIPELINES); } diff --git a/x-pack/test/functional/services/monitoring/index.js b/x-pack/test/functional/services/monitoring/index.js index 2ca0e7fc920c..5d337dc6ca82 100644 --- a/x-pack/test/functional/services/monitoring/index.js +++ b/x-pack/test/functional/services/monitoring/index.js @@ -20,6 +20,9 @@ export { MonitoringBeatsOverviewProvider } from './beats_overview'; export { MonitoringBeatsListingProvider } from './beats_listing'; export { MonitoringBeatDetailProvider } from './beat_detail'; export { MonitoringBeatsSummaryStatusProvider } from './beats_summary_status'; +export { MonitoringLogstashOverviewProvider } from './logstash_overview'; +export { MonitoringLogstashNodesProvider } from './logstash_nodes'; +export { MonitoringLogstashNodeDetailProvider } from './logstash_node_detail'; export { MonitoringLogstashPipelinesProvider } from './logstash_pipelines'; export { MonitoringLogstashSummaryStatusProvider } from './logstash_summary_status'; export { MonitoringKibanaOverviewProvider } from './kibana_overview'; diff --git a/x-pack/test/functional/services/monitoring/logstash_node_detail.js b/x-pack/test/functional/services/monitoring/logstash_node_detail.js new file mode 100644 index 000000000000..42d32c0c1a2a --- /dev/null +++ b/x-pack/test/functional/services/monitoring/logstash_node_detail.js @@ -0,0 +1,42 @@ +/* + * 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 function MonitoringLogstashNodeDetailProvider({ getService }) { + const testSubjects = getService('testSubjects'); + + const SUBJ_SUMMARY = 'logstashDetailStatus'; + const SUBJ_SUMMARY_HTTP_ADDRESS = `${SUBJ_SUMMARY} > httpAddress`; + const SUBJ_SUMMARY_EVENTS_IN = `${SUBJ_SUMMARY} > eventsIn`; + const SUBJ_SUMMARY_EVENTS_OUT = `${SUBJ_SUMMARY} > eventsOut`; + const SUBJ_SUMMARY_NUM_RELOADS = `${SUBJ_SUMMARY} > numReloads`; + const SUBJ_SUMMARY_PIPELINE_WORKERS = `${SUBJ_SUMMARY} > pipelineWorkers`; + const SUBJ_SUMMARY_PIPELINE_BATCH_SIZE = `${SUBJ_SUMMARY} > pipelineBatchSize`; + const SUBJ_SUMMARY_VERSION = `${SUBJ_SUMMARY} > version`; + const SUBJ_SUMMARY_UPTIME = `${SUBJ_SUMMARY} > uptime`; + + return new (class LogstashNodeDetail { + async clickPipelines() { + return testSubjects.click('logstashNodeDetailPipelinesLink'); + } + async clickAdvanced() { + return testSubjects.click('logstashNodeDetailAdvancedLink'); + } + + async getSummary() { + return { + httpAddress: await testSubjects.getVisibleText(SUBJ_SUMMARY_HTTP_ADDRESS), + eventsIn: await testSubjects.getVisibleText(SUBJ_SUMMARY_EVENTS_IN), + eventsOut: await testSubjects.getVisibleText(SUBJ_SUMMARY_EVENTS_OUT), + numReloads: await testSubjects.getVisibleText(SUBJ_SUMMARY_NUM_RELOADS), + pipelineWorkers: await testSubjects.getVisibleText(SUBJ_SUMMARY_PIPELINE_WORKERS), + pipelineBatchSize: await testSubjects.getVisibleText(SUBJ_SUMMARY_PIPELINE_BATCH_SIZE), + version: await testSubjects.getVisibleText(SUBJ_SUMMARY_VERSION), + uptime: await testSubjects.getVisibleText(SUBJ_SUMMARY_UPTIME), + }; + } + })(); +} diff --git a/x-pack/test/functional/services/monitoring/logstash_nodes.js b/x-pack/test/functional/services/monitoring/logstash_nodes.js new file mode 100644 index 000000000000..2666cdc3d065 --- /dev/null +++ b/x-pack/test/functional/services/monitoring/logstash_nodes.js @@ -0,0 +1,102 @@ +/* + * 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 { range } from 'lodash'; +export function MonitoringLogstashNodesProvider({ getService, getPageObjects }) { + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + const PageObjects = getPageObjects(['monitoring']); + const find = getService('find'); + + const SUBJ_OVERVIEW_PAGE = 'logstashNodesPage'; + const SUBJ_TABLE_CONTAINER = 'logstashNodesTableContainer'; + const SUBJ_SEARCH_BAR = `${SUBJ_TABLE_CONTAINER} > monitoringTableToolBar`; + const SUBJ_TABLE_NO_DATA = `${SUBJ_TABLE_CONTAINER} > monitoringTableNoData`; + const SUBJ_NODE_NAME = `${SUBJ_TABLE_CONTAINER} > name`; + const SUBJ_NODE_ALERT_STATUS = `${SUBJ_TABLE_CONTAINER} > alertStatusText`; + const SUBJ_NODE_IP = `${SUBJ_TABLE_CONTAINER} > httpAddress`; + const SUBJ_NODE_CPU_USAGE = `${SUBJ_TABLE_CONTAINER} > cpuUsage`; + const SUBJ_NODE_LOAD_AVERAGE = `${SUBJ_TABLE_CONTAINER} > loadAverage`; + const SUBJ_NODE_JVM_HEAP_USED = `${SUBJ_TABLE_CONTAINER} > jvmHeapUsed`; + const SUBJ_NODE_EVENTS_OUT = `${SUBJ_TABLE_CONTAINER} > eventsOut`; + const SUBJ_NODE_CONFIG_RELOADS_SUCCESS = `${SUBJ_TABLE_CONTAINER} > configReloadsSuccess`; + const SUBJ_NODE_CONFIG_RELOADS_FAILURE = `${SUBJ_TABLE_CONTAINER} > configReloadsFailure`; + const SUBJ_NODE_VERSION = `${SUBJ_TABLE_CONTAINER} > version`; + + const SUBJ_NODE_LINK_PREFIX = `${SUBJ_TABLE_CONTAINER} > nodeLink-`; + + return new (class LogstashNodes { + async isOnNodesListing() { + const pageId = await retry.try(() => testSubjects.find(SUBJ_OVERVIEW_PAGE)); + return pageId !== null; + } + async clickRowByResolver(nodeResolver) { + await retry.waitForWithTimeout('redirection to node detail', 30000, async () => { + await testSubjects.click(SUBJ_NODE_LINK_PREFIX + nodeResolver, 5000); + return testSubjects.exists('logstashDetailStatus', { timeout: 5000 }); + }); + } + getRows() { + return PageObjects.monitoring.tableGetRowsFromContainer(SUBJ_TABLE_CONTAINER); + } + async setFilter(text) { + await PageObjects.monitoring.tableSetFilter(SUBJ_SEARCH_BAR, text); + await this.waitForTableToFinishLoading(); + } + + async clearFilter() { + await PageObjects.monitoring.tableClearFilter(SUBJ_SEARCH_BAR); + await this.waitForTableToFinishLoading(); + } + + assertNoData() { + return PageObjects.monitoring.assertTableNoData(SUBJ_TABLE_NO_DATA); + } + async waitForTableToFinishLoading() { + await retry.try(async () => { + await find.waitForDeletedByCssSelector('.euiBasicTable-loading', 5000); + }); + } + async getNodesAll() { + const name = await testSubjects.getVisibleTextAll(SUBJ_NODE_NAME); + const alertStatus = await testSubjects.getVisibleTextAll(SUBJ_NODE_ALERT_STATUS); + const httpAddress = await testSubjects.getVisibleTextAll(SUBJ_NODE_IP); + const cpuUsage = await testSubjects.getVisibleTextAll(SUBJ_NODE_CPU_USAGE); + const loadAverage = await testSubjects.getVisibleTextAll(SUBJ_NODE_LOAD_AVERAGE); + const jvmHeapUsed = await testSubjects.getVisibleTextAll(SUBJ_NODE_JVM_HEAP_USED); + const eventsOut = await testSubjects.getVisibleTextAll(SUBJ_NODE_EVENTS_OUT); + const configReloadsSuccess = await testSubjects.getVisibleTextAll( + SUBJ_NODE_CONFIG_RELOADS_SUCCESS + ); + const configReloadsFailure = await testSubjects.getVisibleTextAll( + SUBJ_NODE_CONFIG_RELOADS_FAILURE + ); + const version = await testSubjects.getVisibleTextAll(SUBJ_NODE_VERSION); + + // tuple-ize the icons and texts together into an array of objects + const tableRows = await this.getRows(); + const iterator = range(tableRows.length); + return iterator.reduce((all, current) => { + return [ + ...all, + { + id: name[current], + httpAddress: httpAddress[current], + alertStatus: alertStatus[current], + cpuUsage: cpuUsage[current], + loadAverage: loadAverage[current], + jvmHeapUsed: jvmHeapUsed[current], + eventsOut: eventsOut[current], + configReloadsSuccess: configReloadsSuccess[current], + configReloadsFailure: configReloadsFailure[current], + version: version[current], + }, + ]; + }, []); + } + })(); +} diff --git a/x-pack/test/functional/services/monitoring/logstash_overview.js b/x-pack/test/functional/services/monitoring/logstash_overview.js new file mode 100644 index 000000000000..55ac738c8ffe --- /dev/null +++ b/x-pack/test/functional/services/monitoring/logstash_overview.js @@ -0,0 +1,20 @@ +/* + * 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 function MonitoringLogstashOverviewProvider({ getService }) { + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + + const SUBJ_OVERVIEW_PAGE = 'logstashOverviewPage'; + + return new (class LogstashOverview { + async isOnOverview() { + const pageId = await retry.try(() => testSubjects.find(SUBJ_OVERVIEW_PAGE)); + return pageId !== null; + } + })(); +}