From 8a07023343c29b12e9a272836ada3db6b34249ea Mon Sep 17 00:00:00 2001 From: MadameSheema Date: Thu, 16 Jan 2020 12:31:46 +0100 Subject: [PATCH 01/11] [SIEM] Improves toggle column Cypress tests execution time (#54475) * refactor * replaces 'clearTimeline' for 'createNewTimeline' * fixes typecheck issue Co-authored-by: Elastic Machine --- .../smoke_tests/timeline/toggle_column.spec.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/toggle_column.spec.ts b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/toggle_column.spec.ts index 9a915b0e77d44..fbf75e8a854c6 100644 --- a/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/toggle_column.spec.ts +++ b/x-pack/legacy/plugins/siem/cypress/integration/smoke_tests/timeline/toggle_column.spec.ts @@ -6,15 +6,19 @@ import { drag, drop } from '../../lib/drag_n_drop/helpers'; import { populateTimeline } from '../../lib/fields_browser/helpers'; -import { toggleFirstTimelineEventDetails } from '../../lib/timeline/helpers'; +import { createNewTimeline, toggleFirstTimelineEventDetails } from '../../lib/timeline/helpers'; import { HOSTS_PAGE } from '../../lib/urls'; import { loginAndWaitForPage, DEFAULT_TIMEOUT } from '../../lib/util/helpers'; describe('toggle column in timeline', () => { - beforeEach(() => { + before(() => { loginAndWaitForPage(HOSTS_PAGE); }); + afterEach(() => { + createNewTimeline(); + }); + const timestampField = '@timestamp'; const idField = '_id'; From b06977f43f20b60328c23077c6a39036925a04db Mon Sep 17 00:00:00 2001 From: Daniil Suleiman <31325372+sulemanof@users.noreply.github.com> Date: Thu, 16 Jan 2020 15:38:26 +0300 Subject: [PATCH 02/11] Convert tests to jest in vis_type_timeseries/server folder (#54896) * Move vis_data/series tests to jest * Move tests in request_processors/series to jest * Move tests in vis_data to jest * Convert other tests to jest --- .../lib/vis_data/__tests__/fixture.json | 984 ----------------- .../fixtures/std_metric_fixture.json | 985 ------------------ .../__tests__/helpers/bucket_transform.js | 388 ------- ...on.js => build_processor_function.test.ts} | 38 +- ...unction.js => build_processor_function.ts} | 8 +- ....js => get_interval_and_timefield.test.js} | 11 +- .../vis_data/helpers/bucket_transform.test.js | 367 +++++++ .../get_agg_value.test.js} | 7 +- .../get_bucket_size.test.js} | 39 +- .../get_buckets_path.test.js} | 43 +- .../get_default_decoration.test.js} | 63 +- .../get_es_shard_timeout.test.js} | 7 +- .../get_last_metric.test.js} | 11 +- .../get_sibling_agg_value.test.js} | 19 +- .../get_splits.test.js} | 19 +- .../get_timerange.test.js} | 13 +- .../map_bucket.test.js} | 19 +- .../parse_settings.test.js} | 23 +- .../offset_time.js => offset_time.test.js} | 39 +- ...te_histogram.js => date_histogram.test.js} | 34 +- ...filter_ratios.js => filter_ratios.test.js} | 18 +- ...tric_buckets.js => metric_buckets.test.js} | 14 +- .../{__tests__/query.js => query.test.js} | 34 +- ...ing_buckets.js => sibling_buckets.test.js} | 14 +- ...rything.js => split_by_everything.test.js} | 16 +- ...t_by_filter.js => split_by_filter.test.js} | 22 +- ...by_filters.js => split_by_filters.test.js} | 22 +- ...lit_by_terms.js => split_by_terms.test.js} | 30 +- .../_series_agg.js => _series_agg.test.js} | 39 +- .../percentile.js => percentile.test.js} | 74 +- .../series_agg.js => series_agg.test.js} | 18 +- ...n_bands.js => std_deviation_bands.test.js} | 18 +- ...bling.js => std_deviation_sibling.test.js} | 18 +- .../std_metric.js => std_metric.test.js} | 46 +- .../std_sibling.js => std_sibling.test.js} | 24 +- .../time_shift.js => time_shift.test.js} | 32 +- ...est_body.js => build_request_body.test.ts} | 12 +- ..._request_body.js => build_request_body.ts} | 3 +- 38 files changed, 765 insertions(+), 2806 deletions(-) delete mode 100644 src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixture.json delete mode 100644 src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixtures/std_metric_fixture.json delete mode 100644 src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/bucket_transform.js rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/build_processor_function.js => build_processor_function.test.ts} (58%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{build_processor_function.js => build_processor_function.ts} (86%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/get_interval_and_timefield.js => get_interval_and_timefield.test.js} (79%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/helpers/get_agg_value.js => helpers/get_agg_value.test.js} (95%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/helpers/get_bucket_size.js => helpers/get_bucket_size.test.js} (54%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/helpers/get_buckets_path.js => helpers/get_buckets_path.test.js} (53%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/helpers/get_default_decoration.js => helpers/get_default_decoration.test.js} (51%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/helpers/get_es_shard_timeout.js => helpers/get_es_shard_timeout.test.js} (82%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/helpers/get_last_metric.js => helpers/get_last_metric.test.js} (76%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/helpers/get_sibling_agg_value.js => helpers/get_sibling_agg_value.test.js} (69%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/helpers/get_splits.js => helpers/get_splits.test.js} (90%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/helpers/get_timerange.js => helpers/get_timerange.test.js} (72%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/helpers/map_bucket.js => helpers/map_bucket.test.js} (72%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/helpers/parse_settings.js => helpers/parse_settings.test.js} (70%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/{__tests__/offset_time.js => offset_time.test.js} (64%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/{__tests__/date_histogram.js => date_histogram.test.js} (85%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/{__tests__/filter_ratios.js => filter_ratios.test.js} (92%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/{__tests__/metric_buckets.js => metric_buckets.test.js} (88%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/{__tests__/query.js => query.test.js} (91%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/{__tests__/sibling_buckets.js => sibling_buckets.test.js} (86%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/{__tests__/split_by_everything.js => split_by_everything.test.js} (83%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/{__tests__/split_by_filter.js => split_by_filter.test.js} (79%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/{__tests__/split_by_filters.js => split_by_filters.test.js} (85%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/{__tests__/split_by_terms.js => split_by_terms.test.js} (80%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/{__tests__/_series_agg.js => _series_agg.test.js} (68%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/{__tests__/percentile.js => percentile.test.js} (57%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/{__tests__/series_agg.js => series_agg.test.js} (88%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/{__tests__/std_deviation_bands.js => std_deviation_bands.test.js} (87%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/{__tests__/std_deviation_sibling.js => std_deviation_sibling.test.js} (87%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/{__tests__/std_metric.js => std_metric.test.js} (65%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/{__tests__/std_sibling.js => std_sibling.test.js} (82%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/{__tests__/time_shift.js => time_shift.test.js} (71%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/{__tests__/build_request_body.js => build_request_body.test.ts} (95%) rename src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/{build_request_body.js => build_request_body.ts} (95%) diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixture.json b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixture.json deleted file mode 100644 index 178704a36372d..0000000000000 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixture.json +++ /dev/null @@ -1,984 +0,0 @@ -{ - "_shards": { - "failed": 0, - "successful": 5, - "total": 5 - }, - "aggregations": { - "c9b5f9c0-e403-11e6-be91-6f7688e9fac7": { - "doc_count": 128145, - "timeseries": { - "buckets": [ - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.057 - }, - "doc_count": 368, - "key": 1485549090000, - "key_as_string": "2017-01-27T20:31:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.07466666666666667 - }, - "doc_count": 1106, - "key": 1485549120000, - "key_as_string": "2017-01-27T20:32:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.08033333333333335 - }, - "doc_count": 1107, - "key": 1485549150000, - "key_as_string": "2017-01-27T20:32:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.066 - }, - "doc_count": 1109, - "key": 1485549180000, - "key_as_string": "2017-01-27T20:33:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.05366666666666667 - }, - "doc_count": 1093, - "key": 1485549210000, - "key_as_string": "2017-01-27T20:33:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04533333333333334 - }, - "doc_count": 1086, - "key": 1485549240000, - "key_as_string": "2017-01-27T20:34:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037333333333333336 - }, - "doc_count": 1086, - "key": 1485549270000, - "key_as_string": "2017-01-27T20:34:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1090, - "key": 1485549300000, - "key_as_string": "2017-01-27T20:35:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036000000000000004 - }, - "doc_count": 1085, - "key": 1485549330000, - "key_as_string": "2017-01-27T20:35:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1082, - "key": 1485549360000, - "key_as_string": "2017-01-27T20:36:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1080, - "key": 1485549390000, - "key_as_string": "2017-01-27T20:36:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037000000000000005 - }, - "doc_count": 1082, - "key": 1485549420000, - "key_as_string": "2017-01-27T20:37:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036000000000000004 - }, - "doc_count": 1079, - "key": 1485549450000, - "key_as_string": "2017-01-27T20:37:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03233333333333333 - }, - "doc_count": 1080, - "key": 1485549480000, - "key_as_string": "2017-01-27T20:38:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1080, - "key": 1485549510000, - "key_as_string": "2017-01-27T20:38:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1082, - "key": 1485549540000, - "key_as_string": "2017-01-27T20:39:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.042666666666666665 - }, - "doc_count": 1079, - "key": 1485549570000, - "key_as_string": "2017-01-27T20:39:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1077, - "key": 1485549600000, - "key_as_string": "2017-01-27T20:40:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03833333333333334 - }, - "doc_count": 1075, - "key": 1485549630000, - "key_as_string": "2017-01-27T20:40:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1076, - "key": 1485549660000, - "key_as_string": "2017-01-27T20:41:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1076, - "key": 1485549690000, - "key_as_string": "2017-01-27T20:41:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1074, - "key": 1485549720000, - "key_as_string": "2017-01-27T20:42:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1072, - "key": 1485549750000, - "key_as_string": "2017-01-27T20:42:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1067, - "key": 1485549780000, - "key_as_string": "2017-01-27T20:43:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036000000000000004 - }, - "doc_count": 1065, - "key": 1485549810000, - "key_as_string": "2017-01-27T20:43:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1065, - "key": 1485549840000, - "key_as_string": "2017-01-27T20:44:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036333333333333336 - }, - "doc_count": 1062, - "key": 1485549870000, - "key_as_string": "2017-01-27T20:44:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1063, - "key": 1485549900000, - "key_as_string": "2017-01-27T20:45:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1065, - "key": 1485549930000, - "key_as_string": "2017-01-27T20:45:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1065, - "key": 1485549960000, - "key_as_string": "2017-01-27T20:46:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1069, - "key": 1485549990000, - "key_as_string": "2017-01-27T20:46:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1068, - "key": 1485550020000, - "key_as_string": "2017-01-27T20:47:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1068, - "key": 1485550050000, - "key_as_string": "2017-01-27T20:47:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1068, - "key": 1485550080000, - "key_as_string": "2017-01-27T20:48:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1074, - "key": 1485550110000, - "key_as_string": "2017-01-27T20:48:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1074, - "key": 1485550140000, - "key_as_string": "2017-01-27T20:49:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1074, - "key": 1485550170000, - "key_as_string": "2017-01-27T20:49:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1073, - "key": 1485550200000, - "key_as_string": "2017-01-27T20:50:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1077, - "key": 1485550230000, - "key_as_string": "2017-01-27T20:50:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03166666666666667 - }, - "doc_count": 1074, - "key": 1485550260000, - "key_as_string": "2017-01-27T20:51:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.031 - }, - "doc_count": 1074, - "key": 1485550290000, - "key_as_string": "2017-01-27T20:51:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1072, - "key": 1485550320000, - "key_as_string": "2017-01-27T20:52:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1073, - "key": 1485550350000, - "key_as_string": "2017-01-27T20:52:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1071, - "key": 1485550380000, - "key_as_string": "2017-01-27T20:53:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1071, - "key": 1485550410000, - "key_as_string": "2017-01-27T20:53:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03166666666666667 - }, - "doc_count": 1069, - "key": 1485550440000, - "key_as_string": "2017-01-27T20:54:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1069, - "key": 1485550470000, - "key_as_string": "2017-01-27T20:54:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.032 - }, - "doc_count": 1068, - "key": 1485550500000, - "key_as_string": "2017-01-27T20:55:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1067, - "key": 1485550530000, - "key_as_string": "2017-01-27T20:55:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03233333333333333 - }, - "doc_count": 1065, - "key": 1485550560000, - "key_as_string": "2017-01-27T20:56:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1069, - "key": 1485550590000, - "key_as_string": "2017-01-27T20:56:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03166666666666667 - }, - "doc_count": 1068, - "key": 1485550620000, - "key_as_string": "2017-01-27T20:57:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1068, - "key": 1485550650000, - "key_as_string": "2017-01-27T20:57:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1068, - "key": 1485550680000, - "key_as_string": "2017-01-27T20:58:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1071, - "key": 1485550710000, - "key_as_string": "2017-01-27T20:58:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1074, - "key": 1485550740000, - "key_as_string": "2017-01-27T20:59:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1074, - "key": 1485550770000, - "key_as_string": "2017-01-27T20:59:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04 - }, - "doc_count": 1074, - "key": 1485550800000, - "key_as_string": "2017-01-27T21:00:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.032 - }, - "doc_count": 1076, - "key": 1485550830000, - "key_as_string": "2017-01-27T21:00:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1078, - "key": 1485550860000, - "key_as_string": "2017-01-27T21:01:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1077, - "key": 1485550890000, - "key_as_string": "2017-01-27T21:01:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1071, - "key": 1485550920000, - "key_as_string": "2017-01-27T21:02:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1071, - "key": 1485550950000, - "key_as_string": "2017-01-27T21:02:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03566666666666667 - }, - "doc_count": 1073, - "key": 1485550980000, - "key_as_string": "2017-01-27T21:03:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1071, - "key": 1485551010000, - "key_as_string": "2017-01-27T21:03:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1069, - "key": 1485551040000, - "key_as_string": "2017-01-27T21:04:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03566666666666667 - }, - "doc_count": 1068, - "key": 1485551070000, - "key_as_string": "2017-01-27T21:04:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1075, - "key": 1485551100000, - "key_as_string": "2017-01-27T21:05:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1074, - "key": 1485551130000, - "key_as_string": "2017-01-27T21:05:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1073, - "key": 1485551160000, - "key_as_string": "2017-01-27T21:06:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1071, - "key": 1485551190000, - "key_as_string": "2017-01-27T21:06:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1075, - "key": 1485551220000, - "key_as_string": "2017-01-27T21:07:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1071, - "key": 1485551250000, - "key_as_string": "2017-01-27T21:07:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04733333333333334 - }, - "doc_count": 1081, - "key": 1485551280000, - "key_as_string": "2017-01-27T21:08:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.044333333333333336 - }, - "doc_count": 1078, - "key": 1485551310000, - "key_as_string": "2017-01-27T21:08:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037000000000000005 - }, - "doc_count": 1079, - "key": 1485551340000, - "key_as_string": "2017-01-27T21:09:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1077, - "key": 1485551370000, - "key_as_string": "2017-01-27T21:09:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03866666666666666 - }, - "doc_count": 1077, - "key": 1485551400000, - "key_as_string": "2017-01-27T21:10:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037666666666666675 - }, - "doc_count": 1075, - "key": 1485551430000, - "key_as_string": "2017-01-27T21:10:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.038000000000000006 - }, - "doc_count": 1078, - "key": 1485551460000, - "key_as_string": "2017-01-27T21:11:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037 - }, - "doc_count": 1074, - "key": 1485551490000, - "key_as_string": "2017-01-27T21:11:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036666666666666674 - }, - "doc_count": 1074, - "key": 1485551520000, - "key_as_string": "2017-01-27T21:12:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037333333333333336 - }, - "doc_count": 1076, - "key": 1485551550000, - "key_as_string": "2017-01-27T21:12:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03733333333333333 - }, - "doc_count": 1075, - "key": 1485551580000, - "key_as_string": "2017-01-27T21:13:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04533333333333334 - }, - "doc_count": 1077, - "key": 1485551610000, - "key_as_string": "2017-01-27T21:13:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.039 - }, - "doc_count": 1080, - "key": 1485551640000, - "key_as_string": "2017-01-27T21:14:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.057666666666666665 - }, - "doc_count": 1080, - "key": 1485551670000, - "key_as_string": "2017-01-27T21:14:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.045000000000000005 - }, - "doc_count": 1080, - "key": 1485551700000, - "key_as_string": "2017-01-27T21:15:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037666666666666675 - }, - "doc_count": 1080, - "key": 1485551730000, - "key_as_string": "2017-01-27T21:15:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1080, - "key": 1485551760000, - "key_as_string": "2017-01-27T21:16:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.038 - }, - "doc_count": 1080, - "key": 1485551790000, - "key_as_string": "2017-01-27T21:16:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1080, - "key": 1485551820000, - "key_as_string": "2017-01-27T21:17:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04966666666666667 - }, - "doc_count": 1080, - "key": 1485551850000, - "key_as_string": "2017-01-27T21:17:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1080, - "key": 1485551880000, - "key_as_string": "2017-01-27T21:18:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04 - }, - "doc_count": 1080, - "key": 1485551910000, - "key_as_string": "2017-01-27T21:18:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03766666666666666 - }, - "doc_count": 1080, - "key": 1485551940000, - "key_as_string": "2017-01-27T21:19:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1076, - "key": 1485551970000, - "key_as_string": "2017-01-27T21:19:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1077, - "key": 1485552000000, - "key_as_string": "2017-01-27T21:20:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1077, - "key": 1485552030000, - "key_as_string": "2017-01-27T21:20:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.029666666666666664 - }, - "doc_count": 1077, - "key": 1485552060000, - "key_as_string": "2017-01-27T21:21:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.02766666666666667 - }, - "doc_count": 1077, - "key": 1485552090000, - "key_as_string": "2017-01-27T21:21:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.028 - }, - "doc_count": 1077, - "key": 1485552120000, - "key_as_string": "2017-01-27T21:22:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.030666666666666665 - }, - "doc_count": 1077, - "key": 1485552150000, - "key_as_string": "2017-01-27T21:22:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03833333333333334 - }, - "doc_count": 1083, - "key": 1485552180000, - "key_as_string": "2017-01-27T21:23:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04966666666666667 - }, - "doc_count": 1083, - "key": 1485552210000, - "key_as_string": "2017-01-27T21:23:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.041 - }, - "doc_count": 1082, - "key": 1485552240000, - "key_as_string": "2017-01-27T21:24:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037333333333333336 - }, - "doc_count": 1087, - "key": 1485552270000, - "key_as_string": "2017-01-27T21:24:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.039 - }, - "doc_count": 1083, - "key": 1485552300000, - "key_as_string": "2017-01-27T21:25:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03933333333333333 - }, - "doc_count": 1083, - "key": 1485552330000, - "key_as_string": "2017-01-27T21:25:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037666666666666675 - }, - "doc_count": 1083, - "key": 1485552360000, - "key_as_string": "2017-01-27T21:26:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04033333333333333 - }, - "doc_count": 1083, - "key": 1485552390000, - "key_as_string": "2017-01-27T21:26:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03866666666666666 - }, - "doc_count": 1082, - "key": 1485552420000, - "key_as_string": "2017-01-27T21:27:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04033333333333334 - }, - "doc_count": 1083, - "key": 1485552450000, - "key_as_string": "2017-01-27T21:27:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04 - }, - "doc_count": 1083, - "key": 1485552480000, - "key_as_string": "2017-01-27T21:28:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04033333333333333 - }, - "doc_count": 1084, - "key": 1485552510000, - "key_as_string": "2017-01-27T21:28:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1083, - "key": 1485552540000, - "key_as_string": "2017-01-27T21:29:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03566666666666667 - }, - "doc_count": 1083, - "key": 1485552570000, - "key_as_string": "2017-01-27T21:29:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04466666666666667 - }, - "doc_count": 1083, - "key": 1485552600000, - "key_as_string": "2017-01-27T21:30:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03233333333333333 - }, - "doc_count": 1083, - "key": 1485552630000, - "key_as_string": "2017-01-27T21:30:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.0505 - }, - "doc_count": 722, - "key": 1485552660000, - "key_as_string": "2017-01-27T21:31:00.000Z" - } - ] - } - } - }, - "hits": { - "hits": [], - "max_score": 0, - "total": 128145 - }, - "status": 200, - "timed_out": false, - "took": 28 -} diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixtures/std_metric_fixture.json b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixtures/std_metric_fixture.json deleted file mode 100644 index d587e48b31881..0000000000000 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/fixtures/std_metric_fixture.json +++ /dev/null @@ -1,985 +0,0 @@ -{ - "_shards": { - "failed": 0, - "successful": 5, - "total": 5 - }, - "aggregations": { - "c9b5f9c0-e403-11e6-be91-6f7688e9fac7": { - "doc_count": 128145, - "timeseries": { - "buckets": [ - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.057 - }, - "doc_count": 368, - "key": 1485549090000, - "key_as_string": "2017-01-27T20:31:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.07466666666666667 - }, - "doc_count": 1106, - "key": 1485549120000, - "key_as_string": "2017-01-27T20:32:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.08033333333333335 - }, - "doc_count": 1107, - "key": 1485549150000, - "key_as_string": "2017-01-27T20:32:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.066 - }, - "doc_count": 1109, - "key": 1485549180000, - "key_as_string": "2017-01-27T20:33:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.05366666666666667 - }, - "doc_count": 1093, - "key": 1485549210000, - "key_as_string": "2017-01-27T20:33:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04533333333333334 - }, - "doc_count": 1086, - "key": 1485549240000, - "key_as_string": "2017-01-27T20:34:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037333333333333336 - }, - "doc_count": 1086, - "key": 1485549270000, - "key_as_string": "2017-01-27T20:34:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1090, - "key": 1485549300000, - "key_as_string": "2017-01-27T20:35:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036000000000000004 - }, - "doc_count": 1085, - "key": 1485549330000, - "key_as_string": "2017-01-27T20:35:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1082, - "key": 1485549360000, - "key_as_string": "2017-01-27T20:36:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1080, - "key": 1485549390000, - "key_as_string": "2017-01-27T20:36:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037000000000000005 - }, - "doc_count": 1082, - "key": 1485549420000, - "key_as_string": "2017-01-27T20:37:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036000000000000004 - }, - "doc_count": 1079, - "key": 1485549450000, - "key_as_string": "2017-01-27T20:37:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03233333333333333 - }, - "doc_count": 1080, - "key": 1485549480000, - "key_as_string": "2017-01-27T20:38:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1080, - "key": 1485549510000, - "key_as_string": "2017-01-27T20:38:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1082, - "key": 1485549540000, - "key_as_string": "2017-01-27T20:39:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.042666666666666665 - }, - "doc_count": 1079, - "key": 1485549570000, - "key_as_string": "2017-01-27T20:39:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1077, - "key": 1485549600000, - "key_as_string": "2017-01-27T20:40:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03833333333333334 - }, - "doc_count": 1075, - "key": 1485549630000, - "key_as_string": "2017-01-27T20:40:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1076, - "key": 1485549660000, - "key_as_string": "2017-01-27T20:41:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1076, - "key": 1485549690000, - "key_as_string": "2017-01-27T20:41:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1074, - "key": 1485549720000, - "key_as_string": "2017-01-27T20:42:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1072, - "key": 1485549750000, - "key_as_string": "2017-01-27T20:42:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1067, - "key": 1485549780000, - "key_as_string": "2017-01-27T20:43:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036000000000000004 - }, - "doc_count": 1065, - "key": 1485549810000, - "key_as_string": "2017-01-27T20:43:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1065, - "key": 1485549840000, - "key_as_string": "2017-01-27T20:44:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036333333333333336 - }, - "doc_count": 1062, - "key": 1485549870000, - "key_as_string": "2017-01-27T20:44:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1063, - "key": 1485549900000, - "key_as_string": "2017-01-27T20:45:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1065, - "key": 1485549930000, - "key_as_string": "2017-01-27T20:45:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1065, - "key": 1485549960000, - "key_as_string": "2017-01-27T20:46:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1069, - "key": 1485549990000, - "key_as_string": "2017-01-27T20:46:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1068, - "key": 1485550020000, - "key_as_string": "2017-01-27T20:47:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1068, - "key": 1485550050000, - "key_as_string": "2017-01-27T20:47:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1068, - "key": 1485550080000, - "key_as_string": "2017-01-27T20:48:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1074, - "key": 1485550110000, - "key_as_string": "2017-01-27T20:48:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1074, - "key": 1485550140000, - "key_as_string": "2017-01-27T20:49:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1074, - "key": 1485550170000, - "key_as_string": "2017-01-27T20:49:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1073, - "key": 1485550200000, - "key_as_string": "2017-01-27T20:50:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1077, - "key": 1485550230000, - "key_as_string": "2017-01-27T20:50:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03166666666666667 - }, - "doc_count": 1074, - "key": 1485550260000, - "key_as_string": "2017-01-27T20:51:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.031 - }, - "doc_count": 1074, - "key": 1485550290000, - "key_as_string": "2017-01-27T20:51:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1072, - "key": 1485550320000, - "key_as_string": "2017-01-27T20:52:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.033 - }, - "doc_count": 1073, - "key": 1485550350000, - "key_as_string": "2017-01-27T20:52:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1071, - "key": 1485550380000, - "key_as_string": "2017-01-27T20:53:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1071, - "key": 1485550410000, - "key_as_string": "2017-01-27T20:53:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03166666666666667 - }, - "doc_count": 1069, - "key": 1485550440000, - "key_as_string": "2017-01-27T20:54:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1069, - "key": 1485550470000, - "key_as_string": "2017-01-27T20:54:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.032 - }, - "doc_count": 1068, - "key": 1485550500000, - "key_as_string": "2017-01-27T20:55:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1067, - "key": 1485550530000, - "key_as_string": "2017-01-27T20:55:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03233333333333333 - }, - "doc_count": 1065, - "key": 1485550560000, - "key_as_string": "2017-01-27T20:56:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1069, - "key": 1485550590000, - "key_as_string": "2017-01-27T20:56:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03166666666666667 - }, - "doc_count": 1068, - "key": 1485550620000, - "key_as_string": "2017-01-27T20:57:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1068, - "key": 1485550650000, - "key_as_string": "2017-01-27T20:57:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1068, - "key": 1485550680000, - "key_as_string": "2017-01-27T20:58:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1071, - "key": 1485550710000, - "key_as_string": "2017-01-27T20:58:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1074, - "key": 1485550740000, - "key_as_string": "2017-01-27T20:59:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1074, - "key": 1485550770000, - "key_as_string": "2017-01-27T20:59:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04 - }, - "doc_count": 1074, - "key": 1485550800000, - "key_as_string": "2017-01-27T21:00:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.032 - }, - "doc_count": 1076, - "key": 1485550830000, - "key_as_string": "2017-01-27T21:00:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1078, - "key": 1485550860000, - "key_as_string": "2017-01-27T21:01:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1077, - "key": 1485550890000, - "key_as_string": "2017-01-27T21:01:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1071, - "key": 1485550920000, - "key_as_string": "2017-01-27T21:02:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1071, - "key": 1485550950000, - "key_as_string": "2017-01-27T21:02:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03566666666666667 - }, - "doc_count": 1073, - "key": 1485550980000, - "key_as_string": "2017-01-27T21:03:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1071, - "key": 1485551010000, - "key_as_string": "2017-01-27T21:03:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03466666666666667 - }, - "doc_count": 1069, - "key": 1485551040000, - "key_as_string": "2017-01-27T21:04:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03566666666666667 - }, - "doc_count": 1068, - "key": 1485551070000, - "key_as_string": "2017-01-27T21:04:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1075, - "key": 1485551100000, - "key_as_string": "2017-01-27T21:05:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1074, - "key": 1485551130000, - "key_as_string": "2017-01-27T21:05:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1073, - "key": 1485551160000, - "key_as_string": "2017-01-27T21:06:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1071, - "key": 1485551190000, - "key_as_string": "2017-01-27T21:06:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1075, - "key": 1485551220000, - "key_as_string": "2017-01-27T21:07:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03133333333333333 - }, - "doc_count": 1071, - "key": 1485551250000, - "key_as_string": "2017-01-27T21:07:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04733333333333334 - }, - "doc_count": 1081, - "key": 1485551280000, - "key_as_string": "2017-01-27T21:08:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.044333333333333336 - }, - "doc_count": 1078, - "key": 1485551310000, - "key_as_string": "2017-01-27T21:08:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037000000000000005 - }, - "doc_count": 1079, - "key": 1485551340000, - "key_as_string": "2017-01-27T21:09:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1077, - "key": 1485551370000, - "key_as_string": "2017-01-27T21:09:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03866666666666666 - }, - "doc_count": 1077, - "key": 1485551400000, - "key_as_string": "2017-01-27T21:10:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037666666666666675 - }, - "doc_count": 1075, - "key": 1485551430000, - "key_as_string": "2017-01-27T21:10:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.038000000000000006 - }, - "doc_count": 1078, - "key": 1485551460000, - "key_as_string": "2017-01-27T21:11:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037 - }, - "doc_count": 1074, - "key": 1485551490000, - "key_as_string": "2017-01-27T21:11:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.036666666666666674 - }, - "doc_count": 1074, - "key": 1485551520000, - "key_as_string": "2017-01-27T21:12:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037333333333333336 - }, - "doc_count": 1076, - "key": 1485551550000, - "key_as_string": "2017-01-27T21:12:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03733333333333333 - }, - "doc_count": 1075, - "key": 1485551580000, - "key_as_string": "2017-01-27T21:13:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04533333333333334 - }, - "doc_count": 1077, - "key": 1485551610000, - "key_as_string": "2017-01-27T21:13:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.039 - }, - "doc_count": 1080, - "key": 1485551640000, - "key_as_string": "2017-01-27T21:14:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.057666666666666665 - }, - "doc_count": 1080, - "key": 1485551670000, - "key_as_string": "2017-01-27T21:14:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.045000000000000005 - }, - "doc_count": 1080, - "key": 1485551700000, - "key_as_string": "2017-01-27T21:15:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037666666666666675 - }, - "doc_count": 1080, - "key": 1485551730000, - "key_as_string": "2017-01-27T21:15:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1080, - "key": 1485551760000, - "key_as_string": "2017-01-27T21:16:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.038 - }, - "doc_count": 1080, - "key": 1485551790000, - "key_as_string": "2017-01-27T21:16:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1080, - "key": 1485551820000, - "key_as_string": "2017-01-27T21:17:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04966666666666667 - }, - "doc_count": 1080, - "key": 1485551850000, - "key_as_string": "2017-01-27T21:17:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03266666666666667 - }, - "doc_count": 1080, - "key": 1485551880000, - "key_as_string": "2017-01-27T21:18:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04 - }, - "doc_count": 1080, - "key": 1485551910000, - "key_as_string": "2017-01-27T21:18:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03766666666666666 - }, - "doc_count": 1080, - "key": 1485551940000, - "key_as_string": "2017-01-27T21:19:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034 - }, - "doc_count": 1076, - "key": 1485551970000, - "key_as_string": "2017-01-27T21:19:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.034333333333333334 - }, - "doc_count": 1077, - "key": 1485552000000, - "key_as_string": "2017-01-27T21:20:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03366666666666667 - }, - "doc_count": 1077, - "key": 1485552030000, - "key_as_string": "2017-01-27T21:20:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.029666666666666664 - }, - "doc_count": 1077, - "key": 1485552060000, - "key_as_string": "2017-01-27T21:21:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.02766666666666667 - }, - "doc_count": 1077, - "key": 1485552090000, - "key_as_string": "2017-01-27T21:21:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.028 - }, - "doc_count": 1077, - "key": 1485552120000, - "key_as_string": "2017-01-27T21:22:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.030666666666666665 - }, - "doc_count": 1077, - "key": 1485552150000, - "key_as_string": "2017-01-27T21:22:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03833333333333334 - }, - "doc_count": 1083, - "key": 1485552180000, - "key_as_string": "2017-01-27T21:23:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04966666666666667 - }, - "doc_count": 1083, - "key": 1485552210000, - "key_as_string": "2017-01-27T21:23:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.041 - }, - "doc_count": 1082, - "key": 1485552240000, - "key_as_string": "2017-01-27T21:24:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037333333333333336 - }, - "doc_count": 1087, - "key": 1485552270000, - "key_as_string": "2017-01-27T21:24:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.039 - }, - "doc_count": 1083, - "key": 1485552300000, - "key_as_string": "2017-01-27T21:25:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03933333333333333 - }, - "doc_count": 1083, - "key": 1485552330000, - "key_as_string": "2017-01-27T21:25:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.037666666666666675 - }, - "doc_count": 1083, - "key": 1485552360000, - "key_as_string": "2017-01-27T21:26:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04033333333333333 - }, - "doc_count": 1083, - "key": 1485552390000, - "key_as_string": "2017-01-27T21:26:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03866666666666666 - }, - "doc_count": 1082, - "key": 1485552420000, - "key_as_string": "2017-01-27T21:27:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04033333333333334 - }, - "doc_count": 1083, - "key": 1485552450000, - "key_as_string": "2017-01-27T21:27:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04 - }, - "doc_count": 1083, - "key": 1485552480000, - "key_as_string": "2017-01-27T21:28:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04033333333333333 - }, - "doc_count": 1084, - "key": 1485552510000, - "key_as_string": "2017-01-27T21:28:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03333333333333333 - }, - "doc_count": 1083, - "key": 1485552540000, - "key_as_string": "2017-01-27T21:29:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03566666666666667 - }, - "doc_count": 1083, - "key": 1485552570000, - "key_as_string": "2017-01-27T21:29:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.04466666666666667 - }, - "doc_count": 1083, - "key": 1485552600000, - "key_as_string": "2017-01-27T21:30:00.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.03233333333333333 - }, - "doc_count": 1083, - "key": 1485552630000, - "key_as_string": "2017-01-27T21:30:30.000Z" - }, - { - "c9b5f9c1-e403-11e6-be91-6f7688e9fac7": { - "value": 0.0505 - }, - "doc_count": 722, - "key": 1485552660000, - "key_as_string": "2017-01-27T21:31:00.000Z" - } - ] - } - } - }, - "hits": { - "hits": [], - "max_score": 0, - "total": 128145 - }, - "status": 200, - "timed_out": false, - "took": 28 -} - diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/bucket_transform.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/bucket_transform.js deleted file mode 100644 index 1414435017c86..0000000000000 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/bucket_transform.js +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { expect } from 'chai'; -import { bucketTransform } from '../../helpers/bucket_transform'; - -describe('bucketTransform', () => { - describe('count', () => { - it('returns count agg', () => { - const metric = { id: 'test', type: 'count' }; - const fn = bucketTransform.count; - expect(fn(metric)).to.eql({ - bucket_script: { - buckets_path: { count: '_count' }, - script: { source: 'count * 1', lang: 'expression' }, - gap_policy: 'skip', - }, - }); - }); - }); - - describe('std metric', () => { - ['avg', 'max', 'min', 'sum', 'cardinality', 'value_count'].forEach(type => { - it(`returns ${type} agg`, () => { - const metric = { id: 'test', type: type, field: 'cpu.pct' }; - const fn = bucketTransform[type]; - const result = {}; - result[type] = { field: 'cpu.pct' }; - expect(fn(metric)).to.eql(result); - }); - }); - - it('throws error if type is missing', () => { - const run = () => bucketTransform.avg({ id: 'test', field: 'cpu.pct' }); - expect(run).to.throw(Error, 'Metric missing type'); - }); - - it('throws error if field is missing', () => { - const run = () => bucketTransform.avg({ id: 'test', type: 'avg' }); - expect(run).to.throw(Error, 'Metric missing field'); - }); - }); - - describe('extended stats', () => { - ['std_deviation', 'variance', 'sum_of_squares'].forEach(type => { - it(`returns ${type} agg`, () => { - const fn = bucketTransform[type]; - const metric = { id: 'test', type: type, field: 'cpu.pct' }; - expect(fn(metric)).to.eql({ extended_stats: { field: 'cpu.pct' } }); - }); - }); - - it('returns std_deviation agg with sigma', () => { - const fn = bucketTransform.std_deviation; - const metric = { - id: 'test', - type: 'std_deviation', - field: 'cpu.pct', - sigma: 2, - }; - expect(fn(metric)).to.eql({ - extended_stats: { field: 'cpu.pct', sigma: 2 }, - }); - }); - - it('throws error if type is missing', () => { - const run = () => bucketTransform.std_deviation({ id: 'test', field: 'cpu.pct' }); - expect(run).to.throw(Error, 'Metric missing type'); - }); - - it('throws error if field is missing', () => { - const run = () => bucketTransform.std_deviation({ id: 'test', type: 'avg' }); - expect(run).to.throw(Error, 'Metric missing field'); - }); - }); - - describe('percentiles', () => { - it('returns percentiles agg', () => { - const metric = { - id: 'test', - type: 'percentile', - field: 'cpu.pct', - percentiles: [ - { value: 50, mode: 'line' }, - { value: 10, mode: 'band', percentile: 90 }, - ], - }; - const fn = bucketTransform.percentile; - expect(fn(metric)).to.eql({ - percentiles: { - field: 'cpu.pct', - percents: [50, 10, 90], - }, - }); - }); - - it('define a default 0 value if it was not provided', () => { - const metric = { - id: 'test', - type: 'percentile', - field: 'cpu.pct', - percentiles: [ - { value: 50, mode: 'line' }, - { mode: 'line' }, - { value: undefined, mode: 'line' }, - { value: '', mode: 'line' }, - { value: null, mode: 'line' }, - { value: 0, mode: 'line' }, - ], - }; - expect(bucketTransform.percentile(metric)).to.eql({ - percentiles: { - field: 'cpu.pct', - percents: [50, 0, 0, 0, 0, 0], - }, - }); - }); - - it('throws error if type is missing', () => { - const run = () => - bucketTransform.percentile({ - id: 'test', - field: 'cpu.pct', - percentiles: [{ value: 50, mode: 'line' }], - }); - expect(run).to.throw(Error, 'Metric missing type'); - }); - - it('throws error if field is missing', () => { - const run = () => - bucketTransform.percentile({ - id: 'test', - type: 'avg', - percentiles: [{ value: 50, mode: 'line' }], - }); - expect(run).to.throw(Error, 'Metric missing field'); - }); - - it('throws error if percentiles is missing', () => { - const run = () => - bucketTransform.percentile({ - id: 'test', - type: 'avg', - field: 'cpu.pct', - }); - expect(run).to.throw(Error, 'Metric missing percentiles'); - }); - }); - - describe('derivative', () => { - it('returns derivative agg with defaults', () => { - const metric = { - id: '2', - type: 'derivative', - field: '1', - }; - const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.derivative; - expect(fn(metric, metrics, '10s')).is.eql({ - derivative: { - buckets_path: '1', - gap_policy: 'skip', - unit: '10s', - }, - }); - }); - - it('returns derivative agg with unit', () => { - const metric = { - id: '2', - type: 'derivative', - field: '1', - unit: '1s', - }; - const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.derivative; - expect(fn(metric, metrics, '10s')).is.eql({ - derivative: { - buckets_path: '1', - gap_policy: 'skip', - unit: '1s', - }, - }); - }); - - it('returns derivative agg with gap_policy', () => { - const metric = { - id: '2', - type: 'derivative', - field: '1', - gap_policy: 'zero_fill', - }; - const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.derivative; - expect(fn(metric, metrics, '10s')).is.eql({ - derivative: { - buckets_path: '1', - gap_policy: 'zero_fill', - unit: '10s', - }, - }); - }); - - it('throws error if type is missing', () => { - const run = () => bucketTransform.derivative({ id: 'test', field: 'cpu.pct' }); - expect(run).to.throw(Error, 'Metric missing type'); - }); - - it('throws error if field is missing', () => { - const run = () => bucketTransform.derivative({ id: 'test', type: 'derivative' }); - expect(run).to.throw(Error, 'Metric missing field'); - }); - }); - - describe('serial_diff', () => { - it('returns serial_diff agg with defaults', () => { - const metric = { - id: '2', - type: 'serial_diff', - field: '1', - }; - const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.serial_diff; - expect(fn(metric, metrics)).is.eql({ - serial_diff: { - buckets_path: '1', - gap_policy: 'skip', - lag: 1, - }, - }); - }); - - it('returns serial_diff agg with lag', () => { - const metric = { - id: '2', - type: 'serial_diff', - field: '1', - lag: 10, - }; - const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.serial_diff; - expect(fn(metric, metrics)).is.eql({ - serial_diff: { - buckets_path: '1', - gap_policy: 'skip', - lag: 10, - }, - }); - }); - - it('returns serial_diff agg with gap_policy', () => { - const metric = { - id: '2', - type: 'serial_diff', - field: '1', - gap_policy: 'zero_fill', - }; - const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.serial_diff; - expect(fn(metric, metrics)).is.eql({ - serial_diff: { - buckets_path: '1', - gap_policy: 'zero_fill', - lag: 1, - }, - }); - }); - - it('throws error if type is missing', () => { - const run = () => bucketTransform.serial_diff({ id: 'test', field: 'cpu.pct' }); - expect(run).to.throw(Error, 'Metric missing type'); - }); - - it('throws error if field is missing', () => { - const run = () => bucketTransform.serial_diff({ id: 'test', type: 'serial_diff' }); - expect(run).to.throw(Error, 'Metric missing field'); - }); - }); - - describe('cumulative_sum', () => { - it('returns cumulative_sum agg', () => { - const metric = { id: '2', type: 'cumulative_sum', field: '1' }; - const metrics = [{ id: '1', type: 'sum', field: 'cpu.pct' }, metric]; - const fn = bucketTransform.cumulative_sum; - expect(fn(metric, metrics, '10s')).is.eql({ - cumulative_sum: { buckets_path: '1' }, - }); - }); - - it('throws error if type is missing', () => { - const run = () => bucketTransform.cumulative_sum({ id: 'test', field: 'cpu.pct' }); - expect(run).to.throw(Error, 'Metric missing type'); - }); - - it('throws error if field is missing', () => { - const run = () => bucketTransform.cumulative_sum({ id: 'test', type: 'cumulative_sum' }); - expect(run).to.throw(Error, 'Metric missing field'); - }); - }); - - describe('calculation', () => { - it('returns calculation(bucket_script)', () => { - const metric = { - id: '2', - type: 'calculation', - script: 'params.idle != null ? 1 - params.idle : 0', - variables: [{ name: 'idle', field: '1' }], - }; - const metrics = [{ id: '1', type: 'avg', field: 'cpu.idle.pct' }, metric]; - const fn = bucketTransform.calculation; - expect(fn(metric, metrics, '10s')).is.eql({ - bucket_script: { - buckets_path: { - idle: '1', - }, - gap_policy: 'skip', - script: { - source: 'params.idle != null ? 1 - params.idle : 0', - lang: 'painless', - params: { - _interval: 10000, - }, - }, - }, - }); - }); - - it('throws error if variables is missing', () => { - const run = () => - bucketTransform.calculation({ - id: 'test', - type: 'calculation', - script: 'params.idle != null ? 1 - params.idle : null', - }); - expect(run).to.throw(Error, 'Metric missing variables'); - }); - - it('throws error if script is missing', () => { - const run = () => - bucketTransform.calculation({ - id: 'test', - type: 'calculation', - variables: [{ field: '1', name: 'idle' }], - }); - expect(run).to.throw(Error, 'Metric missing script'); - }); - }); - - describe('positive_only', () => { - it('returns bucket_script', () => { - const metric = { - id: '2', - type: 'positive_only', - field: '1', - }; - const metrics = [{ id: '1', type: 'avg', field: 'cpu.idle.pct' }, metric]; - const fn = bucketTransform.positive_only; - expect(fn(metric, metrics, '10s')).is.eql({ - bucket_script: { - buckets_path: { - value: '1', - }, - gap_policy: 'skip', - script: { - source: 'params.value > 0.0 ? params.value : 0.0', - lang: 'painless', - }, - }, - }); - }); - }); -}); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/build_processor_function.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.test.ts similarity index 58% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/build_processor_function.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.test.ts index 10ad9e467610e..cf5244f8e5a7d 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/build_processor_function.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.test.ts @@ -17,43 +17,41 @@ * under the License. */ -import sinon from 'sinon'; -import { expect } from 'chai'; -import { buildProcessorFunction } from '../build_processor_function'; +import { buildProcessorFunction } from './build_processor_function'; describe('buildProcessorFunction(chain, ...args)', () => { const req = {}; const panel = {}; const series = {}; - it('should call each processor', () => { - const first = sinon.spy(() => next => doc => next(doc)); - const second = sinon.spy(() => next => doc => next(doc)); + test('should call each processor', () => { + const first = jest.fn(() => (next: any) => (doc: any) => next(doc)); + const second = jest.fn(() => (next: any) => (doc: any) => next(doc)); buildProcessorFunction([first, second], req, panel, series); - expect(first.calledOnce).to.equal(true); - expect(second.calledOnce).to.equal(true); + expect(first.mock.calls.length).toEqual(1); + expect(second.mock.calls.length).toEqual(1); }); - it('should chain each processor', () => { - const first = sinon.spy(next => doc => next(doc)); - const second = sinon.spy(next => doc => next(doc)); + test('should chain each processor', () => { + const first = jest.fn(() => (next: any) => (doc: any) => next(doc)); + const second = jest.fn(() => (next: any) => (doc: any) => next(doc)); buildProcessorFunction([() => first, () => second], req, panel, series); - expect(first.calledOnce).to.equal(true); - expect(second.calledOnce).to.equal(true); + expect(first.mock.calls.length).toEqual(1); + expect(second.mock.calls.length).toEqual(1); }); - it('should next of each processor', () => { - const first = sinon.spy(); - const second = sinon.spy(); + test('should next of each processor', () => { + const first = jest.fn(); + const second = jest.fn(); const fn = buildProcessorFunction( [ - () => next => doc => { + () => (next: any) => (doc: any) => { first(); next(doc); }, - () => next => doc => { + () => (next: any) => (doc: any) => { second(); next(doc); }, @@ -63,7 +61,7 @@ describe('buildProcessorFunction(chain, ...args)', () => { series ); fn({}); - expect(first.calledOnce).to.equal(true); - expect(second.calledOnce).to.equal(true); + expect(first.mock.calls.length).toEqual(1); + expect(second.mock.calls.length).toEqual(1); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.ts similarity index 86% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.ts index 5896a089bafe2..b898f4dbf7a5e 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/build_processor_function.ts @@ -17,11 +17,9 @@ * under the License. */ -export function buildProcessorFunction(chain, ...args) { +export function buildProcessorFunction(chain: any[], ...args: any) { return chain.reduceRight( - (next, fn) => { - return fn(...args)(next); - }, - doc => doc + (next, fn) => fn(...args)(next), + (doc: any) => doc ); } diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/get_interval_and_timefield.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/get_interval_and_timefield.test.js similarity index 79% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/get_interval_and_timefield.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/get_interval_and_timefield.test.js index dc2c2b2cfb1f2..f3e15f2fc65b6 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/get_interval_and_timefield.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/get_interval_and_timefield.test.js @@ -17,27 +17,26 @@ * under the License. */ -import { expect } from 'chai'; -import { getIntervalAndTimefield } from '../get_interval_and_timefield'; +import { getIntervalAndTimefield } from './get_interval_and_timefield'; describe('getIntervalAndTimefield(panel, series)', () => { - it('returns the panel interval and timefield', () => { + test('returns the panel interval and timefield', () => { const panel = { time_field: '@timestamp', interval: 'auto' }; const series = {}; - expect(getIntervalAndTimefield(panel, series)).to.eql({ + expect(getIntervalAndTimefield(panel, series)).toEqual({ timeField: '@timestamp', interval: 'auto', }); }); - it('returns the series interval and timefield', () => { + test('returns the series interval and timefield', () => { const panel = { time_field: '@timestamp', interval: 'auto' }; const series = { override_index_pattern: true, series_interval: '1m', series_time_field: 'time', }; - expect(getIntervalAndTimefield(panel, series)).to.eql({ + expect(getIntervalAndTimefield(panel, series)).toEqual({ timeField: 'time', interval: '1m', }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/bucket_transform.test.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/bucket_transform.test.js index 3def18997863e..db0e8fa3d6bb9 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/bucket_transform.test.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/bucket_transform.test.js @@ -94,4 +94,371 @@ describe('src/legacy/core_plugins/metrics/server/lib/vis_data/helpers/bucket_tra }); }); }); + + describe('bucketTransform additional', () => { + describe('count', () => { + test('returns count agg', () => { + const metric = { id: 'test', type: 'count' }; + const fn = bucketTransform.count; + expect(fn(metric)).toEqual({ + bucket_script: { + buckets_path: { count: '_count' }, + script: { source: 'count * 1', lang: 'expression' }, + gap_policy: 'skip', + }, + }); + }); + }); + + describe('std metric', () => { + ['avg', 'max', 'min', 'sum', 'cardinality', 'value_count'].forEach(type => { + test(`returns ${type} agg`, () => { + const metric = { id: 'test', type: type, field: 'cpu.pct' }; + const fn = bucketTransform[type]; + const result = {}; + result[type] = { field: 'cpu.pct' }; + expect(fn(metric)).toEqual(result); + }); + }); + + test('throws error if type is missing', () => { + const run = () => bucketTransform.avg({ id: 'test', field: 'cpu.pct' }); + expect(run).toThrow(new Error('Metric missing type')); + }); + + test('throws error if field is missing', () => { + const run = () => bucketTransform.avg({ id: 'test', type: 'avg' }); + expect(run).toThrow(new Error('Metric missing field')); + }); + }); + + describe('extended stats', () => { + ['std_deviation', 'variance', 'sum_of_squares'].forEach(type => { + test(`returns ${type} agg`, () => { + const fn = bucketTransform[type]; + const metric = { id: 'test', type: type, field: 'cpu.pct' }; + expect(fn(metric)).toEqual({ extended_stats: { field: 'cpu.pct' } }); + }); + }); + + test('returns std_deviation agg with sigma', () => { + const fn = bucketTransform.std_deviation; + const metric = { + id: 'test', + type: 'std_deviation', + field: 'cpu.pct', + sigma: 2, + }; + expect(fn(metric)).toEqual({ + extended_stats: { field: 'cpu.pct', sigma: 2 }, + }); + }); + + test('throws error if type is missing', () => { + const run = () => bucketTransform.std_deviation({ id: 'test', field: 'cpu.pct' }); + expect(run).toThrow(new Error('Metric missing type')); + }); + + test('throws error if field is missing', () => { + const run = () => bucketTransform.std_deviation({ id: 'test', type: 'avg' }); + expect(run).toThrow(new Error('Metric missing field')); + }); + }); + + describe('percentiles', () => { + test('returns percentiles agg', () => { + const metric = { + id: 'test', + type: 'percentile', + field: 'cpu.pct', + percentiles: [ + { value: 50, mode: 'line' }, + { value: 10, mode: 'band', percentile: 90 }, + ], + }; + const fn = bucketTransform.percentile; + expect(fn(metric)).toEqual({ + percentiles: { + field: 'cpu.pct', + percents: [50, 10, 90], + }, + }); + }); + + test('define a default 0 value if it was not provided', () => { + const metric = { + id: 'test', + type: 'percentile', + field: 'cpu.pct', + percentiles: [ + { value: 50, mode: 'line' }, + { mode: 'line' }, + { value: undefined, mode: 'line' }, + { value: '', mode: 'line' }, + { value: null, mode: 'line' }, + { value: 0, mode: 'line' }, + ], + }; + expect(bucketTransform.percentile(metric)).toEqual({ + percentiles: { + field: 'cpu.pct', + percents: [50, 0, 0, 0, 0, 0], + }, + }); + }); + + test('throws error if type is missing', () => { + const run = () => + bucketTransform.percentile({ + id: 'test', + field: 'cpu.pct', + percentiles: [{ value: 50, mode: 'line' }], + }); + expect(run).toThrow(new Error('Metric missing type')); + }); + + test('throws error if field is missing', () => { + const run = () => + bucketTransform.percentile({ + id: 'test', + type: 'avg', + percentiles: [{ value: 50, mode: 'line' }], + }); + expect(run).toThrow(new Error('Metric missing field')); + }); + + test('throws error if percentiles is missing', () => { + const run = () => + bucketTransform.percentile({ + id: 'test', + type: 'avg', + field: 'cpu.pct', + }); + expect(run).toThrow(new Error('Metric missing percentiles')); + }); + }); + + describe('derivative', () => { + test('returns derivative agg with defaults', () => { + const metric = { + id: '2', + type: 'derivative', + field: '1', + }; + const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.derivative; + expect(fn(metric, metrics, '10s')).toEqual({ + derivative: { + buckets_path: '1', + gap_policy: 'skip', + unit: '10s', + }, + }); + }); + + test('returns derivative agg with unit', () => { + const metric = { + id: '2', + type: 'derivative', + field: '1', + unit: '1s', + }; + const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.derivative; + expect(fn(metric, metrics, '10s')).toEqual({ + derivative: { + buckets_path: '1', + gap_policy: 'skip', + unit: '1s', + }, + }); + }); + + test('returns derivative agg with gap_policy', () => { + const metric = { + id: '2', + type: 'derivative', + field: '1', + gap_policy: 'zero_fill', + }; + const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.derivative; + expect(fn(metric, metrics, '10s')).toEqual({ + derivative: { + buckets_path: '1', + gap_policy: 'zero_fill', + unit: '10s', + }, + }); + }); + + test('throws error if type is missing', () => { + const run = () => bucketTransform.derivative({ id: 'test', field: 'cpu.pct' }); + expect(run).toThrow(new Error('Metric missing type')); + }); + + test('throws error if field is missing', () => { + const run = () => bucketTransform.derivative({ id: 'test', type: 'derivative' }); + expect(run).toThrow(new Error('Metric missing field')); + }); + }); + + describe('serial_diff', () => { + test('returns serial_diff agg with defaults', () => { + const metric = { + id: '2', + type: 'serial_diff', + field: '1', + }; + const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.serial_diff; + expect(fn(metric, metrics)).toEqual({ + serial_diff: { + buckets_path: '1', + gap_policy: 'skip', + lag: 1, + }, + }); + }); + + test('returns serial_diff agg with lag', () => { + const metric = { + id: '2', + type: 'serial_diff', + field: '1', + lag: 10, + }; + const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.serial_diff; + expect(fn(metric, metrics)).toEqual({ + serial_diff: { + buckets_path: '1', + gap_policy: 'skip', + lag: 10, + }, + }); + }); + + test('returns serial_diff agg with gap_policy', () => { + const metric = { + id: '2', + type: 'serial_diff', + field: '1', + gap_policy: 'zero_fill', + }; + const metrics = [{ id: '1', type: 'max', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.serial_diff; + expect(fn(metric, metrics)).toEqual({ + serial_diff: { + buckets_path: '1', + gap_policy: 'zero_fill', + lag: 1, + }, + }); + }); + + test('throws error if type is missing', () => { + const run = () => bucketTransform.serial_diff({ id: 'test', field: 'cpu.pct' }); + expect(run).toThrow(new Error('Metric missing type')); + }); + + test('throws error if field is missing', () => { + const run = () => bucketTransform.serial_diff({ id: 'test', type: 'serial_diff' }); + expect(run).toThrow(new Error('Metric missing field')); + }); + }); + + describe('cumulative_sum', () => { + test('returns cumulative_sum agg', () => { + const metric = { id: '2', type: 'cumulative_sum', field: '1' }; + const metrics = [{ id: '1', type: 'sum', field: 'cpu.pct' }, metric]; + const fn = bucketTransform.cumulative_sum; + expect(fn(metric, metrics, '10s')).toEqual({ + cumulative_sum: { buckets_path: '1' }, + }); + }); + + test('throws error if type is missing', () => { + const run = () => bucketTransform.cumulative_sum({ id: 'test', field: 'cpu.pct' }); + expect(run).toThrow(new Error('Metric missing type')); + }); + + test('throws error if field is missing', () => { + const run = () => bucketTransform.cumulative_sum({ id: 'test', type: 'cumulative_sum' }); + expect(run).toThrow(new Error('Metric missing field')); + }); + }); + + describe('calculation', () => { + test('returns calculation(bucket_script)', () => { + const metric = { + id: '2', + type: 'calculation', + script: 'params.idle != null ? 1 - params.idle : 0', + variables: [{ name: 'idle', field: '1' }], + }; + const metrics = [{ id: '1', type: 'avg', field: 'cpu.idle.pct' }, metric]; + const fn = bucketTransform.calculation; + expect(fn(metric, metrics, '10s')).toEqual({ + bucket_script: { + buckets_path: { + idle: '1', + }, + gap_policy: 'skip', + script: { + source: 'params.idle != null ? 1 - params.idle : 0', + lang: 'painless', + params: { + _interval: 10000, + }, + }, + }, + }); + }); + + test('throws error if variables is missing', () => { + const run = () => + bucketTransform.calculation({ + id: 'test', + type: 'calculation', + script: 'params.idle != null ? 1 - params.idle : null', + }); + expect(run).toThrow(new Error('Metric missing variables')); + }); + + test('throws error if script is missing', () => { + const run = () => + bucketTransform.calculation({ + id: 'test', + type: 'calculation', + variables: [{ field: '1', name: 'idle' }], + }); + expect(run).toThrow(new Error('Metric missing script')); + }); + }); + + describe('positive_only', () => { + test('returns bucket_script', () => { + const metric = { + id: '2', + type: 'positive_only', + field: '1', + }; + const metrics = [{ id: '1', type: 'avg', field: 'cpu.idle.pct' }, metric]; + const fn = bucketTransform.positive_only; + expect(fn(metric, metrics, '10s')).toEqual({ + bucket_script: { + buckets_path: { + value: '1', + }, + gap_policy: 'skip', + script: { + source: 'params.value > 0.0 ? params.value : 0.0', + lang: 'painless', + }, + }, + }); + }); + }); + }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_agg_value.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_agg_value.test.js similarity index 95% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_agg_value.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_agg_value.test.js index 234953c8f4617..5f5e5ebafa560 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_agg_value.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_agg_value.test.js @@ -17,16 +17,15 @@ * under the License. */ -import { expect } from 'chai'; -import { getAggValue } from '../../helpers/get_agg_value'; +import { getAggValue } from './get_agg_value'; function testAgg(row, metric, expected) { let name = metric.type; if (metric.mode) name += `(${metric.mode})`; if (metric.percent) name += `(${metric.percent})`; - it(`it should return ${name}(${expected})`, () => { + test(`it should return ${name}(${expected})`, () => { const value = getAggValue(row, metric); - expect(value).to.eql(expected); + expect(value).toEqual(expected); }); } diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_bucket_size.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_bucket_size.test.js similarity index 54% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_bucket_size.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_bucket_size.test.js index e62cfff1083cf..99bef2de6b72d 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_bucket_size.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_bucket_size.test.js @@ -17,8 +17,7 @@ * under the License. */ -import { expect } from 'chai'; -import { getBucketSize } from '../../helpers/get_bucket_size'; +import { getBucketSize } from './get_bucket_size'; describe('getBucketSize', () => { const req = { @@ -30,39 +29,39 @@ describe('getBucketSize', () => { }, }; - it('returns auto calculated buckets', () => { + test('returns auto calculated buckets', () => { const result = getBucketSize(req, 'auto'); - expect(result).to.have.property('bucketSize', 30); - expect(result).to.have.property('intervalString', '30s'); + expect(result).toHaveProperty('bucketSize', 30); + expect(result).toHaveProperty('intervalString', '30s'); }); - it('returns overridden buckets (1s)', () => { + test('returns overridden buckets (1s)', () => { const result = getBucketSize(req, '1s'); - expect(result).to.have.property('bucketSize', 1); - expect(result).to.have.property('intervalString', '1s'); + expect(result).toHaveProperty('bucketSize', 1); + expect(result).toHaveProperty('intervalString', '1s'); }); - it('returns overridden buckets (10m)', () => { + test('returns overridden buckets (10m)', () => { const result = getBucketSize(req, '10m'); - expect(result).to.have.property('bucketSize', 600); - expect(result).to.have.property('intervalString', '10m'); + expect(result).toHaveProperty('bucketSize', 600); + expect(result).toHaveProperty('intervalString', '10m'); }); - it('returns overridden buckets (1d)', () => { + test('returns overridden buckets (1d)', () => { const result = getBucketSize(req, '1d'); - expect(result).to.have.property('bucketSize', 86400); - expect(result).to.have.property('intervalString', '1d'); + expect(result).toHaveProperty('bucketSize', 86400); + expect(result).toHaveProperty('intervalString', '1d'); }); - it('returns overridden buckets (>=2d)', () => { + test('returns overridden buckets (>=2d)', () => { const result = getBucketSize(req, '>=2d'); - expect(result).to.have.property('bucketSize', 86400 * 2); - expect(result).to.have.property('intervalString', '2d'); + expect(result).toHaveProperty('bucketSize', 86400 * 2); + expect(result).toHaveProperty('intervalString', '2d'); }); - it('returns overridden buckets (>=10s)', () => { + test('returns overridden buckets (>=10s)', () => { const result = getBucketSize(req, '>=10s'); - expect(result).to.have.property('bucketSize', 30); - expect(result).to.have.property('intervalString', '30s'); + expect(result).toHaveProperty('bucketSize', 30); + expect(result).toHaveProperty('intervalString', '30s'); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_buckets_path.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_buckets_path.test.js similarity index 53% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_buckets_path.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_buckets_path.test.js index f5c31fa8ba7ce..0a0e18a696588 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_buckets_path.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_buckets_path.test.js @@ -17,8 +17,7 @@ * under the License. */ -import { expect } from 'chai'; -import { getBucketsPath } from '../../helpers/get_buckets_path'; +import { getBucketsPath } from './get_buckets_path'; describe('getBucketsPath', () => { const metrics = [ @@ -33,43 +32,43 @@ describe('getBucketsPath', () => { { id: 9, type: 'max' }, ]; - it('return path for derivative', () => { - expect(getBucketsPath(1, metrics)).to.equal('1[normalized_value]'); + test('return path for derivative', () => { + expect(getBucketsPath(1, metrics)).toEqual('1[normalized_value]'); }); - it('return path for percentile(50)', () => { - expect(getBucketsPath(2, metrics)).to.equal('2[50.0]'); + test('return path for percentile(50)', () => { + expect(getBucketsPath(2, metrics)).toEqual('2[50.0]'); }); - it('return path for percentile(20.0)', () => { - expect(getBucketsPath(3, metrics)).to.equal('3[20.0]'); + test('return path for percentile(20.0)', () => { + expect(getBucketsPath(3, metrics)).toEqual('3[20.0]'); }); - it('return path for percentile(10.0) with alt id', () => { - expect(getBucketsPath('3[10.0]', metrics)).to.equal('3[10.0]'); + test('return path for percentile(10.0) with alt id', () => { + expect(getBucketsPath('3[10.0]', metrics)).toEqual('3[10.0]'); }); - it('return path for std_deviation(raw)', () => { - expect(getBucketsPath(4, metrics)).to.equal('4[std_deviation]'); + test('return path for std_deviation(raw)', () => { + expect(getBucketsPath(4, metrics)).toEqual('4[std_deviation]'); }); - it('return path for std_deviation(upper)', () => { - expect(getBucketsPath(5, metrics)).to.equal('5[std_upper]'); + test('return path for std_deviation(upper)', () => { + expect(getBucketsPath(5, metrics)).toEqual('5[std_upper]'); }); - it('return path for std_deviation(lower)', () => { - expect(getBucketsPath(6, metrics)).to.equal('6[std_lower]'); + test('return path for std_deviation(lower)', () => { + expect(getBucketsPath(6, metrics)).toEqual('6[std_lower]'); }); - it('return path for sum_of_squares', () => { - expect(getBucketsPath(7, metrics)).to.equal('7[sum_of_squares]'); + test('return path for sum_of_squares', () => { + expect(getBucketsPath(7, metrics)).toEqual('7[sum_of_squares]'); }); - it('return path for variance', () => { - expect(getBucketsPath(8, metrics)).to.equal('8[variance]'); + test('return path for variance', () => { + expect(getBucketsPath(8, metrics)).toEqual('8[variance]'); }); - it('return path for basic metric', () => { - expect(getBucketsPath(9, metrics)).to.equal('9'); + test('return path for basic metric', () => { + expect(getBucketsPath(9, metrics)).toEqual('9'); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_default_decoration.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_default_decoration.test.js similarity index 51% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_default_decoration.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_default_decoration.test.js index 5cc94dda6d21a..2529c8c649485 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_default_decoration.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_default_decoration.test.js @@ -17,44 +17,43 @@ * under the License. */ -import { expect } from 'chai'; -import { getDefaultDecoration } from '../../helpers/get_default_decoration'; +import { getDefaultDecoration } from './get_default_decoration'; describe('getDefaultDecoration', () => { describe('stack option', () => { - it('should set a stack option to none', () => { + test('should set a stack option to none', () => { const series = { id: 'test_id', stacked: 'none', }; - expect(getDefaultDecoration(series)).to.have.property('stack', 'none'); + expect(getDefaultDecoration(series)).toHaveProperty('stack', 'none'); }); - it('should set a stack option to stacked/percent', () => { + test('should set a stack option to stacked/percent', () => { const series = { stacked: 'stacked', id: 'test_id', }; - expect(getDefaultDecoration(series)).to.have.property('stack', 'stacked'); + expect(getDefaultDecoration(series)).toHaveProperty('stack', 'stacked'); series.stacked = 'percent'; - expect(getDefaultDecoration(series)).to.have.property('stack', 'percent'); + expect(getDefaultDecoration(series)).toHaveProperty('stack', 'percent'); }); - it('should set a stack option to stacked_within_series', () => { + test('should set a stack option to stacked_within_series', () => { const series = { stacked: 'stacked_within_series', id: 'test_id', }; - expect(getDefaultDecoration(series)).to.have.property('stack', 'stacked_within_series'); + expect(getDefaultDecoration(series)).toHaveProperty('stack', 'stacked_within_series'); }); }); describe('lines', () => { - it('return decoration for lines', () => { + test('return decoration for lines', () => { const series = { point_size: 10, chart_type: 'line', @@ -62,29 +61,29 @@ describe('getDefaultDecoration', () => { fill: 1, }; const result = getDefaultDecoration(series); - expect(result.lines).to.have.property('show', true); - expect(result.lines).to.have.property('fill', 1); - expect(result.lines).to.have.property('lineWidth', 10); - expect(result.points).to.have.property('show', true); - expect(result.points).to.have.property('radius', 1); - expect(result.points).to.have.property('lineWidth', 10); - expect(result.bars).to.have.property('show', false); - expect(result.bars).to.have.property('fill', 1); - expect(result.bars).to.have.property('lineWidth', 10); + expect(result.lines).toHaveProperty('show', true); + expect(result.lines).toHaveProperty('fill', 1); + expect(result.lines).toHaveProperty('lineWidth', 10); + expect(result.points).toHaveProperty('show', true); + expect(result.points).toHaveProperty('radius', 1); + expect(result.points).toHaveProperty('lineWidth', 10); + expect(result.bars).toHaveProperty('show', false); + expect(result.bars).toHaveProperty('fill', 1); + expect(result.bars).toHaveProperty('lineWidth', 10); }); - it('return decoration for lines without points', () => { + test('return decoration for lines without points', () => { const series = { chart_type: 'line', line_width: 10, fill: 1, }; const result = getDefaultDecoration(series); - expect(result.points).to.have.property('show', true); - expect(result.points).to.have.property('lineWidth', 10); + expect(result.points).toHaveProperty('show', true); + expect(result.points).toHaveProperty('lineWidth', 10); }); - it('return decoration for lines with points set to zero (off)', () => { + test('return decoration for lines with points set to zero (off)', () => { const series = { chart_type: 'line', line_width: 10, @@ -92,32 +91,32 @@ describe('getDefaultDecoration', () => { point_size: 0, }; const result = getDefaultDecoration(series); - expect(result.points).to.have.property('show', false); + expect(result.points).toHaveProperty('show', false); }); - it('return decoration for lines (off)', () => { + test('return decoration for lines (off)', () => { const series = { chart_type: 'line', line_width: 0, }; const result = getDefaultDecoration(series); - expect(result.lines).to.have.property('show', false); + expect(result.lines).toHaveProperty('show', false); }); }); describe('bars', () => { - it('return decoration for bars', () => { + test('return decoration for bars', () => { const series = { chart_type: 'bar', line_width: 10, fill: 1, }; const result = getDefaultDecoration(series); - expect(result.lines).to.have.property('show', false); - expect(result.points).to.have.property('show', false); - expect(result.bars).to.have.property('show', true); - expect(result.bars).to.have.property('fill', 1); - expect(result.bars).to.have.property('lineWidth', 10); + expect(result.lines).toHaveProperty('show', false); + expect(result.points).toHaveProperty('show', false); + expect(result.bars).toHaveProperty('show', true); + expect(result.bars).toHaveProperty('fill', 1); + expect(result.bars).toHaveProperty('lineWidth', 10); }); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_es_shard_timeout.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_es_shard_timeout.test.js similarity index 82% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_es_shard_timeout.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_es_shard_timeout.test.js index b19f6a3241597..13f62739a5485 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_es_shard_timeout.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_es_shard_timeout.test.js @@ -17,11 +17,10 @@ * under the License. */ -import { expect } from 'chai'; -import { getEsShardTimeout } from '../../helpers/get_es_shard_timeout'; +import { getEsShardTimeout } from './get_es_shard_timeout'; describe('getEsShardTimeout', () => { - it('should return the elasticsearch.shardTimeout', async () => { + test('should return the elasticsearch.shardTimeout', async () => { const req = { getEsShardTimeout: async () => { return 12345; @@ -30,6 +29,6 @@ describe('getEsShardTimeout', () => { const timeout = await getEsShardTimeout(req); - expect(timeout).to.equal(12345); + expect(timeout).toEqual(12345); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_last_metric.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_last_metric.test.js similarity index 76% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_last_metric.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_last_metric.test.js index be99f81dfccc4..42e6cc2c01836 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_last_metric.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_last_metric.test.js @@ -17,26 +17,25 @@ * under the License. */ -import { expect } from 'chai'; -import { getLastMetric } from '../../helpers/get_last_metric'; +import { getLastMetric } from './get_last_metric'; describe('getLastMetric(series)', () => { - it('returns the last metric', () => { + test('returns the last metric', () => { const series = { metrics: [ { id: 1, type: 'avg' }, { id: 2, type: 'moving_average' }, ], }; - expect(getLastMetric(series)).to.eql({ id: 2, type: 'moving_average' }); + expect(getLastMetric(series)).toEqual({ id: 2, type: 'moving_average' }); }); - it('returns the last metric that not a series_agg', () => { + test('returns the last metric that not a series_agg', () => { const series = { metrics: [ { id: 1, type: 'avg' }, { id: 2, type: 'series_agg' }, ], }; - expect(getLastMetric(series)).to.eql({ id: 1, type: 'avg' }); + expect(getLastMetric(series)).toEqual({ id: 1, type: 'avg' }); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_sibling_agg_value.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_sibling_agg_value.test.js similarity index 69% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_sibling_agg_value.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_sibling_agg_value.test.js index 68bfa77e25ea3..755568546949c 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_sibling_agg_value.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_sibling_agg_value.test.js @@ -17,8 +17,7 @@ * under the License. */ -import { expect } from 'chai'; -import { getSiblingAggValue } from '../../helpers/get_sibling_agg_value'; +import { getSiblingAggValue } from './get_sibling_agg_value'; describe('getSiblingAggValue', () => { const row = { @@ -32,23 +31,23 @@ describe('getSiblingAggValue', () => { }, }; - it('returns the value for std_deviation_bounds.upper', () => { + test('returns the value for std_deviation_bounds.upper', () => { const metric = { id: 'test', type: 'std_deviation_bucket', mode: 'upper' }; - expect(getSiblingAggValue(row, metric)).to.equal(2); + expect(getSiblingAggValue(row, metric)).toEqual(2); }); - it('returns the value for std_deviation_bounds.lower', () => { + test('returns the value for std_deviation_bounds.lower', () => { const metric = { id: 'test', type: 'std_deviation_bucket', mode: 'lower' }; - expect(getSiblingAggValue(row, metric)).to.equal(1); + expect(getSiblingAggValue(row, metric)).toEqual(1); }); - it('returns the value for std_deviation', () => { + test('returns the value for std_deviation', () => { const metric = { id: 'test', type: 'std_deviation_bucket', mode: 'raw' }; - expect(getSiblingAggValue(row, metric)).to.equal(1.5); + expect(getSiblingAggValue(row, metric)).toEqual(1.5); }); - it('returns the value for basic (max)', () => { + test('returns the value for basic (max)', () => { const metric = { id: 'test', type: 'max_bucket' }; - expect(getSiblingAggValue(row, metric)).to.equal(3); + expect(getSiblingAggValue(row, metric)).toEqual(3); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_splits.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js similarity index 90% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_splits.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js index 1057248d2f362..0874d944033f5 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_splits.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_splits.test.js @@ -17,11 +17,10 @@ * under the License. */ -import { expect } from 'chai'; -import { getSplits } from '../../helpers/get_splits'; +import { getSplits } from './get_splits'; describe('getSplits(resp, panel, series)', () => { - it('should return a splits for everything/filter group bys', () => { + test('should return a splits for everything/filter group bys', () => { const resp = { aggregations: { SERIES: { @@ -41,7 +40,7 @@ describe('getSplits(resp, panel, series)', () => { { id: 'SIBAGG', type: 'avg_bucket', field: 'AVG' }, ], }; - expect(getSplits(resp, panel, series)).to.eql([ + expect(getSplits(resp, panel, series)).toEqual([ { id: 'SERIES', label: 'Overall Average of Average of cpu', @@ -53,7 +52,7 @@ describe('getSplits(resp, panel, series)', () => { ]); }); - it('should return a splits for terms group bys for top_n', () => { + test('should return a splits for terms group bys for top_n', () => { const resp = { aggregations: { SERIES: { @@ -85,7 +84,7 @@ describe('getSplits(resp, panel, series)', () => { ], }; const panel = { type: 'top_n' }; - expect(getSplits(resp, panel, series)).to.eql([ + expect(getSplits(resp, panel, series)).toEqual([ { id: 'SERIES:example-01', key: 'example-01', @@ -107,7 +106,7 @@ describe('getSplits(resp, panel, series)', () => { ]); }); - it('should return a splits for terms group bys', () => { + test('should return a splits for terms group bys', () => { const resp = { aggregations: { SERIES: { @@ -139,7 +138,7 @@ describe('getSplits(resp, panel, series)', () => { ], }; const panel = { type: 'timeseries' }; - expect(getSplits(resp, panel, series)).to.eql([ + expect(getSplits(resp, panel, series)).toEqual([ { id: 'SERIES:example-01', key: 'example-01', @@ -161,7 +160,7 @@ describe('getSplits(resp, panel, series)', () => { ]); }); - it('should return a splits for filters group bys', () => { + test('should return a splits for filters group bys', () => { const resp = { aggregations: { SERIES: { @@ -188,7 +187,7 @@ describe('getSplits(resp, panel, series)', () => { metrics: [{ id: 'COUNT', type: 'count' }], }; const panel = { type: 'timeseries' }; - expect(getSplits(resp, panel, series)).to.eql([ + expect(getSplits(resp, panel, series)).toEqual([ { id: 'SERIES:filter-1', key: 'filter-1', diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_timerange.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_timerange.test.js similarity index 72% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_timerange.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_timerange.test.js index f79d1002b8546..1a1b12c651992 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/get_timerange.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/get_timerange.test.js @@ -17,12 +17,11 @@ * under the License. */ -import { expect } from 'chai'; -import { getTimerange } from '../../helpers/get_timerange'; +import { getTimerange } from './get_timerange'; import moment from 'moment'; describe('getTimerange(req)', () => { - it('should return a moment object for to and from', () => { + test('should return a moment object for to and from', () => { const req = { payload: { timerange: { @@ -32,9 +31,9 @@ describe('getTimerange(req)', () => { }, }; const { from, to } = getTimerange(req); - expect(moment.isMoment(from)).to.equal(true); - expect(moment.isMoment(to)).to.equal(true); - expect(moment.utc('2017-01-01T00:00:00Z').isSame(from)).to.equal(true); - expect(moment.utc('2017-01-01T01:00:00Z').isSame(to)).to.equal(true); + expect(moment.isMoment(from)).toEqual(true); + expect(moment.isMoment(to)).toEqual(true); + expect(moment.utc('2017-01-01T00:00:00Z').isSame(from)).toEqual(true); + expect(moment.utc('2017-01-01T01:00:00Z').isSame(to)).toEqual(true); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/map_bucket.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_bucket.test.js similarity index 72% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/map_bucket.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_bucket.test.js index e3223ef7b618f..0b007416681ee 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/map_bucket.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/map_bucket.test.js @@ -17,40 +17,39 @@ * under the License. */ -import { mapBucket } from '../../helpers/map_bucket'; -import { expect } from 'chai'; +import { mapBucket } from './map_bucket'; describe('mapBucket(metric)', () => { - it('returns bucket key and value for basic metric', () => { + test('returns bucket key and value for basic metric', () => { const metric = { id: 'AVG', type: 'avg' }; const bucket = { key: 1234, AVG: { value: 1 }, }; - expect(mapBucket(metric)(bucket)).to.eql([1234, 1]); + expect(mapBucket(metric)(bucket)).toEqual([1234, 1]); }); - it('returns bucket key and value for std_deviation', () => { + test('returns bucket key and value for std_deviation', () => { const metric = { id: 'STDDEV', type: 'std_deviation' }; const bucket = { key: 1234, STDDEV: { std_deviation: 1 }, }; - expect(mapBucket(metric)(bucket)).to.eql([1234, 1]); + expect(mapBucket(metric)(bucket)).toEqual([1234, 1]); }); - it('returns bucket key and value for percentiles', () => { + test('returns bucket key and value for percentiles', () => { const metric = { id: 'PCT', type: 'percentile', percent: 50 }; const bucket = { key: 1234, PCT: { values: { '50.0': 1 } }, }; - expect(mapBucket(metric)(bucket)).to.eql([1234, 1]); + expect(mapBucket(metric)(bucket)).toEqual([1234, 1]); }); - it('returns bucket key and value for derivative', () => { + test('returns bucket key and value for derivative', () => { const metric = { id: 'DERV', type: 'derivative', field: 'io', unit: '1s' }; const bucket = { key: 1234, DERV: { value: 100, normalized_value: 1 }, }; - expect(mapBucket(metric)(bucket)).to.eql([1234, 1]); + expect(mapBucket(metric)(bucket)).toEqual([1234, 1]); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/parse_settings.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/parse_settings.test.js similarity index 70% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/parse_settings.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/parse_settings.test.js index bf16b6e22e8ef..eab06cdccfa66 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/helpers/parse_settings.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/helpers/parse_settings.test.js @@ -17,41 +17,40 @@ * under the License. */ -import { expect } from 'chai'; -import { parseSettings } from '../../helpers/parse_settings'; +import { parseSettings } from './parse_settings'; describe('parseSettings', () => { - it('returns the true for "true"', () => { + test('returns the true for "true"', () => { const settings = 'pad=true'; - expect(parseSettings(settings)).to.eql({ + expect(parseSettings(settings)).toEqual({ pad: true, }); }); - it('returns the false for "false"', () => { + test('returns the false for "false"', () => { const settings = 'pad=false'; - expect(parseSettings(settings)).to.eql({ + expect(parseSettings(settings)).toEqual({ pad: false, }); }); - it('returns the true for 1', () => { + test('returns the true for 1', () => { const settings = 'pad=1'; - expect(parseSettings(settings)).to.eql({ + expect(parseSettings(settings)).toEqual({ pad: true, }); }); - it('returns the false for 0', () => { + test('returns the false for 0', () => { const settings = 'pad=0'; - expect(parseSettings(settings)).to.eql({ + expect(parseSettings(settings)).toEqual({ pad: false, }); }); - it('returns the settings as an object', () => { + test('returns the settings as an object', () => { const settings = 'alpha=0.9 beta=0.4 gamma=0.2 period=5 pad=false type=add'; - expect(parseSettings(settings)).to.eql({ + expect(parseSettings(settings)).toEqual({ alpha: 0.9, beta: 0.4, gamma: 0.2, diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/offset_time.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/offset_time.test.js similarity index 64% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/offset_time.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/offset_time.test.js index 55e43cf7bd8ce..b9b73002bafb3 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/__tests__/offset_time.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/offset_time.test.js @@ -17,12 +17,11 @@ * under the License. */ -import { expect } from 'chai'; import moment from 'moment'; -import { offsetTime } from '../offset_time'; +import { offsetTime } from './offset_time'; describe('offsetTime(req, by)', () => { - it('should return a moment object for to and from', () => { + test('should return a moment object for to and from', () => { const req = { payload: { timerange: { @@ -32,13 +31,13 @@ describe('offsetTime(req, by)', () => { }, }; const { from, to } = offsetTime(req, ''); - expect(moment.isMoment(from)).to.equal(true); - expect(moment.isMoment(to)).to.equal(true); - expect(moment.utc('2017-01-01T00:00:00Z').isSame(from)).to.equal(true); - expect(moment.utc('2017-01-01T01:00:00Z').isSame(to)).to.equal(true); + expect(moment.isMoment(from)).toBeTruthy(); + expect(moment.isMoment(to)).toBeTruthy(); + expect(moment.utc('2017-01-01T00:00:00Z').isSame(from)).toBeTruthy(); + expect(moment.utc('2017-01-01T01:00:00Z').isSame(to)).toBeTruthy(); }); - it('should return a moment object for to and from offset by 1 hour', () => { + test('should return a moment object for to and from offset by 1 hour', () => { const req = { payload: { timerange: { @@ -48,23 +47,23 @@ describe('offsetTime(req, by)', () => { }, }; const { from, to } = offsetTime(req, '1h'); - expect(moment.isMoment(from)).to.equal(true); - expect(moment.isMoment(to)).to.equal(true); + expect(moment.isMoment(from)).toBeTruthy(); + expect(moment.isMoment(to)).toBeTruthy(); expect( moment .utc('2017-01-01T00:00:00Z') .subtract(1, 'h') .isSame(from) - ).to.equal(true); + ).toBeTruthy(); expect( moment .utc('2017-01-01T01:00:00Z') .subtract(1, 'h') .isSame(to) - ).to.equal(true); + ).toBeTruthy(); }); - it('should return a moment object for to and from offset by -2 minute', () => { + test('should return a moment object for to and from offset by -2 minute', () => { const req = { payload: { timerange: { @@ -74,13 +73,13 @@ describe('offsetTime(req, by)', () => { }, }; const { from, to } = offsetTime(req, '-2m'); - expect(moment.isMoment(from)).to.equal(true); - expect(moment.isMoment(to)).to.equal(true); - expect(moment.utc('2017-01-10T01:02:00Z').isSame(from)).to.equal(true); - expect(moment.utc('2017-01-10T02:02:00Z').isSame(to)).to.equal(true); + expect(moment.isMoment(from)).toBeTruthy(); + expect(moment.isMoment(to)).toBeTruthy(); + expect(moment.utc('2017-01-10T01:02:00Z').isSame(from)).toBeTruthy(); + expect(moment.utc('2017-01-10T02:02:00Z').isSame(to)).toBeTruthy(); }); - it('should work when prefixing positive offsets with the plus sign', () => { + test('should work when prefixing positive offsets with the plus sign', () => { const req = { payload: { timerange: { @@ -92,7 +91,7 @@ describe('offsetTime(req, by)', () => { const { from: fromSigned, to: toSigned } = offsetTime(req, '+1m'); const { from, to } = offsetTime(req, '1m'); - expect(fromSigned.isSame(from)).to.equal(true); - expect(toSigned.isSame(to)).to.equal(true); + expect(fromSigned.isSame(from)).toBeTruthy(); + expect(toSigned.isSame(to)).toBeTruthy(); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/date_histogram.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js similarity index 85% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/date_histogram.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js index 40eaba621aabb..7f309b44d13f4 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/date_histogram.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/date_histogram.test.js @@ -17,10 +17,8 @@ * under the License. */ -import { expect } from 'chai'; -import sinon from 'sinon'; -import { DefaultSearchCapabilities } from '../../../../search_strategies/default_search_capabilities'; -import { dateHistogram } from '../date_histogram'; +import { DefaultSearchCapabilities } from '../../../search_strategies/default_search_capabilities'; +import { dateHistogram } from './date_histogram'; describe('dateHistogram(req, panel, series)', () => { let panel; @@ -54,18 +52,18 @@ describe('dateHistogram(req, panel, series)', () => { capabilities = new DefaultSearchCapabilities(req); }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); dateHistogram(req, panel, series, config, indexPatternObject, capabilities)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns valid date histogram', () => { + test('returns valid date histogram', () => { const next = doc => doc; const doc = dateHistogram(req, panel, series, config, indexPatternObject, capabilities)(next)( {} ); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { @@ -93,13 +91,13 @@ describe('dateHistogram(req, panel, series)', () => { }); }); - it('returns valid date histogram (offset by 1h)', () => { + test('returns valid date histogram (offset by 1h)', () => { series.offset_time = '1h'; const next = doc => doc; const doc = dateHistogram(req, panel, series, config, indexPatternObject, capabilities)(next)( {} ); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { @@ -127,7 +125,7 @@ describe('dateHistogram(req, panel, series)', () => { }); }); - it('returns valid date histogram with overridden index pattern', () => { + test('returns valid date histogram with overridden index pattern', () => { series.override_index_pattern = 1; series.series_index_pattern = '*'; series.series_time_field = 'timestamp'; @@ -136,7 +134,7 @@ describe('dateHistogram(req, panel, series)', () => { const doc = dateHistogram(req, panel, series, config, indexPatternObject, capabilities)(next)( {} ); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { @@ -165,7 +163,7 @@ describe('dateHistogram(req, panel, series)', () => { }); describe('dateHistogram for entire time range mode', () => { - it('should ignore entire range mode for timeseries', () => { + test('should ignore entire range mode for timeseries', () => { panel.time_range_mode = 'entire_time_range'; panel.type = 'timeseries'; @@ -174,18 +172,18 @@ describe('dateHistogram(req, panel, series)', () => { {} ); - expect(doc.aggs.test.aggs.timeseries.auto_date_histogram).to.eql(undefined); - expect(doc.aggs.test.aggs.timeseries.date_histogram).to.exist; + expect(doc.aggs.test.aggs.timeseries.auto_date_histogram).toBeUndefined(); + expect(doc.aggs.test.aggs.timeseries.date_histogram).toBeDefined(); }); - it('should returns valid date histogram for entire range mode', () => { + test('should returns valid date histogram for entire range mode', () => { panel.time_range_mode = 'entire_time_range'; const next = doc => doc; const doc = dateHistogram(req, panel, series, config, indexPatternObject, capabilities)(next)( {} ); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/filter_ratios.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js similarity index 92% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/filter_ratios.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js index 0449ee440da81..f3d25a8e44ba7 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/filter_ratios.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { ratios } from '../filter_ratios'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { ratios } from './filter_ratios'; describe('ratios(req, panel, series)', () => { let panel; @@ -55,16 +53,16 @@ describe('ratios(req, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); ratios(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns filter ratio aggs', () => { + test('returns filter ratio aggs', () => { const next = doc => doc; const doc = ratios(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { @@ -119,11 +117,11 @@ describe('ratios(req, panel, series)', () => { }); }); - it('returns empty object when field is not set', () => { + test('returns empty object when field is not set', () => { delete series.metrics[0].field; const next = doc => doc; const doc = ratios(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/metric_buckets.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.test.js similarity index 88% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/metric_buckets.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.test.js index 9393882f12b7e..eaf8ee1549f0b 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/metric_buckets.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/metric_buckets.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { metricBuckets } from '../metric_buckets'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { metricBuckets } from './metric_buckets'; describe('metricBuckets(req, panel, series)', () => { let panel; @@ -63,16 +61,16 @@ describe('metricBuckets(req, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); metricBuckets(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns metric aggs', () => { + test('returns metric aggs', () => { const next = doc => doc; const doc = metricBuckets(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/query.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/query.test.js similarity index 91% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/query.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/query.test.js index 2f2e5f46f834e..06da636f818d5 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/query.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/query.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { query } from '../query'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { query } from './query'; describe('query(req, panel, series)', () => { let panel; @@ -47,16 +45,16 @@ describe('query(req, panel, series)', () => { series = { id: 'test' }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); query(req, panel, series, config)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns doc with query for timerange', () => { + test('returns doc with query for timerange', () => { const next = doc => doc; const doc = query(req, panel, series, config)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { @@ -79,11 +77,11 @@ describe('query(req, panel, series)', () => { }); }); - it('returns doc with query for timerange (offset by 1h)', () => { + test('returns doc with query for timerange (offset by 1h)', () => { series.offset_time = '1h'; const next = doc => doc; const doc = query(req, panel, series, config)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { @@ -106,7 +104,7 @@ describe('query(req, panel, series)', () => { }); }); - it('returns doc with global query', () => { + test('returns doc with global query', () => { req.payload.filters = [ { bool: { @@ -122,7 +120,7 @@ describe('query(req, panel, series)', () => { ]; const next = doc => doc; const doc = query(req, panel, series, config)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { @@ -157,11 +155,11 @@ describe('query(req, panel, series)', () => { }); }); - it('returns doc with series filter', () => { + test('returns doc with series filter', () => { series.filter = { query: 'host:web-server', language: 'lucene' }; const next = doc => doc; const doc = query(req, panel, series, config)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { @@ -198,7 +196,7 @@ describe('query(req, panel, series)', () => { }, }); }); - it('returns doc with panel filter and global', () => { + test('returns doc with panel filter and global', () => { req.payload.filters = [ { bool: { @@ -215,7 +213,7 @@ describe('query(req, panel, series)', () => { panel.filter = { query: 'host:web-server', language: 'lucene' }; const next = doc => doc; const doc = query(req, panel, series, config)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { @@ -265,7 +263,7 @@ describe('query(req, panel, series)', () => { }); }); - it('returns doc with panel filter (ignoring globals)', () => { + test('returns doc with panel filter (ignoring globals)', () => { req.payload.filters = [ { bool: { @@ -283,7 +281,7 @@ describe('query(req, panel, series)', () => { panel.ignore_global_filter = true; const next = doc => doc; const doc = query(req, panel, series, config)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/sibling_buckets.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.test.js similarity index 86% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/sibling_buckets.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.test.js index 0f02c755cabcd..8e1c9b0f9ecd9 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/sibling_buckets.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/sibling_buckets.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { siblingBuckets } from '../sibling_buckets'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { siblingBuckets } from './sibling_buckets'; describe('siblingBuckets(req, panel, series)', () => { let panel; @@ -57,16 +55,16 @@ describe('siblingBuckets(req, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); siblingBuckets(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns sibling aggs', () => { + test('returns sibling aggs', () => { const next = doc => doc; const doc = siblingBuckets(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { aggs: { diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_everything.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_everything.test.js similarity index 83% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_everything.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_everything.test.js index 4e2775d3608e6..5c2468f6b7c35 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_everything.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_everything.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { splitByEverything } from '../split_by_everything'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { splitByEverything } from './split_by_everything'; describe('splitByEverything(req, panel, series)', () => { let panel; @@ -39,15 +37,15 @@ describe('splitByEverything(req, panel, series)', () => { }); it('calls next when finished', () => { - const next = sinon.spy(); + const next = jest.fn(); splitByEverything(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); it('returns a valid filter with match_all', () => { const next = doc => doc; const doc = splitByEverything(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { filter: { @@ -61,9 +59,9 @@ describe('splitByEverything(req, panel, series)', () => { it('calls next and does not add a filter', () => { series.split_mode = 'terms'; series.terms_field = 'host'; - const next = sinon.spy(doc => doc); + const next = jest.fn(doc => doc); const doc = splitByEverything(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); - expect(doc).to.eql({}); + expect(next.mock.calls.length).toEqual(1); + expect(doc).toEqual({}); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_filter.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_filter.test.js similarity index 79% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_filter.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_filter.test.js index 782310ba4d2bf..75ca782a6d7e7 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_filter.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_filter.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { splitByFilter } from '../split_by_filter'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { splitByFilter } from './split_by_filter'; describe('splitByFilter(req, panel, series)', () => { let panel; @@ -42,16 +40,16 @@ describe('splitByFilter(req, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); splitByFilter(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns a valid filter with a query_string', () => { + test('returns a valid filter with a query_string', () => { const next = doc => doc; const doc = splitByFilter(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { filter: { @@ -73,11 +71,11 @@ describe('splitByFilter(req, panel, series)', () => { }); }); - it('calls next and does not add a filter', () => { + test('calls next and does not add a filter', () => { series.split_mode = 'terms'; - const next = sinon.spy(doc => doc); + const next = jest.fn(doc => doc); const doc = splitByFilter(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); - expect(doc).to.eql({}); + expect(next.mock.calls.length).toEqual(1); + expect(doc).toEqual({}); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_filters.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_filters.test.js similarity index 85% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_filters.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_filters.test.js index 018cb4b003ecf..6108b2bf2cf2b 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_filters.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_filters.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { splitByFilters } from '../split_by_filters'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { splitByFilters } from './split_by_filters'; describe('splitByFilters(req, panel, series)', () => { let panel; @@ -58,16 +56,16 @@ describe('splitByFilters(req, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); splitByFilters(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns a valid terms agg', () => { + test('returns a valid terms agg', () => { const next = doc => doc; const doc = splitByFilters(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { filters: { @@ -107,11 +105,11 @@ describe('splitByFilters(req, panel, series)', () => { }); }); - it('calls next and does not add a terms agg', () => { + test('calls next and does not add a terms agg', () => { series.split_mode = 'everything'; - const next = sinon.spy(doc => doc); + const next = jest.fn(doc => doc); const doc = splitByFilters(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); - expect(doc).to.eql({}); + expect(next.mock.calls.length).toEqual(1); + expect(doc).toEqual({}); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_terms.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_terms.test.js similarity index 80% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_terms.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_terms.test.js index eb1a81baa7fc2..ff7139c380af9 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/__tests__/split_by_terms.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/request_processors/series/split_by_terms.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { splitByTerms } from '../split_by_terms'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { splitByTerms } from './split_by_terms'; describe('splitByTerms(req, panel, series)', () => { let panel; @@ -46,16 +44,16 @@ describe('splitByTerms(req, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); splitByTerms(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('returns a valid terms agg', () => { + test('returns a valid terms agg', () => { const next = doc => doc; const doc = splitByTerms(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { terms: { @@ -70,12 +68,12 @@ describe('splitByTerms(req, panel, series)', () => { }); }); - it('returns a valid terms agg sort by terms', () => { + test('returns a valid terms agg sort by terms', () => { const next = doc => doc; series.terms_order_by = '_key'; series.terms_direction = 'asc'; const doc = splitByTerms(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { terms: { @@ -90,11 +88,11 @@ describe('splitByTerms(req, panel, series)', () => { }); }); - it('returns a valid terms agg with custom sort', () => { + test('returns a valid terms agg with custom sort', () => { series.terms_order_by = 'avgmetric'; const next = doc => doc; const doc = splitByTerms(req, panel, series)(next)({}); - expect(doc).to.eql({ + expect(doc).toEqual({ aggs: { test: { terms: { @@ -116,11 +114,11 @@ describe('splitByTerms(req, panel, series)', () => { }); }); - it('calls next and does not add a terms agg', () => { + test('calls next and does not add a terms agg', () => { series.split_mode = 'everything'; - const next = sinon.spy(doc => doc); + const next = jest.fn(doc => doc); const doc = splitByTerms(req, panel, series)(next)({}); - expect(next.calledOnce).to.equal(true); - expect(doc).to.eql({}); + expect(next.mock.calls.length).toEqual(1); + expect(doc).toEqual({}); }); }); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/_series_agg.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/_series_agg.test.js similarity index 68% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/_series_agg.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/_series_agg.test.js index 582466f8eb9fd..22ea2c852e254 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/_series_agg.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/_series_agg.test.js @@ -17,8 +17,7 @@ * under the License. */ -import { expect } from 'chai'; -import { SeriesAgg as seriesAgg } from '../_series_agg'; +import { SeriesAgg as seriesAgg } from './_series_agg'; describe('seriesAgg', () => { const series = [ @@ -40,8 +39,8 @@ describe('seriesAgg', () => { ]; describe('basic', () => { - it('returns the series sum', () => { - expect(seriesAgg.sum(series)).to.eql([ + test('returns the series sum', () => { + expect(seriesAgg.sum(series)).toEqual([ [ [0, 8], [1, 4], @@ -50,8 +49,8 @@ describe('seriesAgg', () => { ]); }); - it('returns the series max', () => { - expect(seriesAgg.max(series)).to.eql([ + test('returns the series max', () => { + expect(seriesAgg.max(series)).toEqual([ [ [0, 4], [1, 2], @@ -60,8 +59,8 @@ describe('seriesAgg', () => { ]); }); - it('returns the series min', () => { - expect(seriesAgg.min(series)).to.eql([ + test('returns the series min', () => { + expect(seriesAgg.min(series)).toEqual([ [ [0, 2], [1, 1], @@ -70,8 +69,8 @@ describe('seriesAgg', () => { ]); }); - it('returns the series mean', () => { - expect(seriesAgg.mean(series)).to.eql([ + test('returns the series mean', () => { + expect(seriesAgg.mean(series)).toEqual([ [ [0, 8 / 3], [1, 4 / 3], @@ -82,8 +81,8 @@ describe('seriesAgg', () => { }); describe('overall', () => { - it('returns the series overall sum', () => { - expect(seriesAgg.overall_sum(series)).to.eql([ + test('returns the series overall sum', () => { + expect(seriesAgg.overall_sum(series)).toEqual([ [ [0, 21], [1, 21], @@ -92,8 +91,8 @@ describe('seriesAgg', () => { ]); }); - it('returns the series overall max', () => { - expect(seriesAgg.overall_max(series)).to.eql([ + test('returns the series overall max', () => { + expect(seriesAgg.overall_max(series)).toEqual([ [ [0, 4], [1, 4], @@ -102,8 +101,8 @@ describe('seriesAgg', () => { ]); }); - it('returns the series overall min', () => { - expect(seriesAgg.overall_min(series)).to.eql([ + test('returns the series overall min', () => { + expect(seriesAgg.overall_min(series)).toEqual([ [ [0, 1], [1, 1], @@ -112,9 +111,9 @@ describe('seriesAgg', () => { ]); }); - it('returns the series overall mean', () => { + test('returns the series overall mean', () => { const value = (8 + 4 + 9) / 3; - expect(seriesAgg.overall_avg(series)).to.eql([ + expect(seriesAgg.overall_avg(series)).toEqual([ [ [0, value], [1, value], @@ -125,8 +124,8 @@ describe('seriesAgg', () => { }); describe('cumulative sum', () => { - it('returns the series cumulative sum', () => { - expect(seriesAgg.cumulative_sum(series)).to.eql([ + test('returns the series cumulative sum', () => { + expect(seriesAgg.cumulative_sum(series)).toEqual([ [ [0, 8], [1, 12], diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/percentile.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.test.js similarity index 57% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/percentile.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.test.js index d40a75c903602..9cb08de8dad23 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/percentile.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/percentile.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { percentile } from '../percentile'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { percentile } from './percentile'; describe('percentile(resp, panel, series)', () => { let panel; @@ -82,72 +80,72 @@ describe('percentile(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); percentile(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('creates a series', () => { + test('creates a series', () => { const next = results => results; const results = percentile(resp, panel, series)(next)([]); - expect(results).to.have.length(3); + expect(results).toHaveLength(3); - expect(results[0]).to.have.property('id', 'test:10-90'); - expect(results[0]).to.have.property('color', 'rgb(255, 0, 0)'); - expect(results[0]).to.have.property('fillBetween', 'test:10-90:90'); - expect(results[0]).to.have.property('label', 'Percentile of cpu (10)'); - expect(results[0]).to.have.property('legend', false); - expect(results[0]).to.have.property('lines'); - expect(results[0].lines).to.eql({ + expect(results[0]).toHaveProperty('id', 'test:10-90'); + expect(results[0]).toHaveProperty('color', 'rgb(255, 0, 0)'); + expect(results[0]).toHaveProperty('fillBetween', 'test:10-90:90'); + expect(results[0]).toHaveProperty('label', 'Percentile of cpu (10)'); + expect(results[0]).toHaveProperty('legend', false); + expect(results[0]).toHaveProperty('lines'); + expect(results[0].lines).toEqual({ fill: 0.2, lineWidth: 0, show: true, }); - expect(results[0]).to.have.property('points'); - expect(results[0].points).to.eql({ show: false }); - expect(results[0].data).to.eql([ + expect(results[0]).toHaveProperty('points'); + expect(results[0].points).toEqual({ show: false }); + expect(results[0].data).toEqual([ [1, 1], [2, 1.2], ]); - expect(results[1]).to.have.property('id', 'test:10-90:90'); - expect(results[1]).to.have.property('color', 'rgb(255, 0, 0)'); - expect(results[1]).to.have.property('label', 'Percentile of cpu (10)'); - expect(results[1]).to.have.property('legend', false); - expect(results[1]).to.have.property('lines'); - expect(results[1].lines).to.eql({ + expect(results[1]).toHaveProperty('id', 'test:10-90:90'); + expect(results[1]).toHaveProperty('color', 'rgb(255, 0, 0)'); + expect(results[1]).toHaveProperty('label', 'Percentile of cpu (10)'); + expect(results[1]).toHaveProperty('legend', false); + expect(results[1]).toHaveProperty('lines'); + expect(results[1].lines).toEqual({ fill: false, lineWidth: 0, show: true, }); - expect(results[1]).to.have.property('points'); - expect(results[1].points).to.eql({ show: false }); - expect(results[1].data).to.eql([ + expect(results[1]).toHaveProperty('points'); + expect(results[1].points).toEqual({ show: false }); + expect(results[1].data).toEqual([ [1, 5], [2, 5.3], ]); - expect(results[2]).to.have.property('id', 'test:50'); - expect(results[2]).to.have.property('color', 'rgb(255, 0, 0)'); - expect(results[2]).to.have.property('label', 'Percentile of cpu (50)'); - expect(results[2]).to.have.property('stack', false); - expect(results[2]).to.have.property('lines'); - expect(results[2].lines).to.eql({ + expect(results[2]).toHaveProperty('id', 'test:50'); + expect(results[2]).toHaveProperty('color', 'rgb(255, 0, 0)'); + expect(results[2]).toHaveProperty('label', 'Percentile of cpu (50)'); + expect(results[2]).toHaveProperty('stack', false); + expect(results[2]).toHaveProperty('lines'); + expect(results[2].lines).toEqual({ fill: 0, lineWidth: 1, show: true, steps: false, }); - expect(results[2]).to.have.property('bars'); - expect(results[2].bars).to.eql({ + expect(results[2]).toHaveProperty('bars'); + expect(results[2].bars).toEqual({ fill: 0, lineWidth: 1, show: false, }); - expect(results[2]).to.have.property('points'); - expect(results[2].points).to.eql({ show: true, lineWidth: 1, radius: 1 }); - expect(results[2].data).to.eql([ + expect(results[2]).toHaveProperty('points'); + expect(results[2].points).toEqual({ show: true, lineWidth: 1, radius: 1 }); + expect(results[2].data).toEqual([ [1, 2.5], [2, 2.7], ]); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/series_agg.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.test.js similarity index 88% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/series_agg.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.test.js index 2391cd3bc7698..3e09c51d9184f 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/series_agg.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/series_agg.test.js @@ -17,10 +17,8 @@ * under the License. */ -import { seriesAgg } from '../series_agg'; -import { stdMetric } from '../std_metric'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { seriesAgg } from './series_agg'; +import { stdMetric } from './std_metric'; describe('seriesAgg(resp, panel, series)', () => { let panel; @@ -93,18 +91,18 @@ describe('seriesAgg(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); seriesAgg(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('creates a series', () => { + test('creates a series', () => { const next = seriesAgg(resp, panel, series)(results => results); const results = stdMetric(resp, panel, series)(next)([]); - expect(results).to.have.length(1); + expect(results).toHaveLength(1); - expect(results[0]).to.eql({ + expect(results[0]).toEqual({ id: 'test', color: '#F00', label: 'Total CPU', diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_deviation_bands.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.test.js similarity index 87% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_deviation_bands.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.test.js index 488ae4a8351b7..77949ff94dc4c 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_deviation_bands.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_bands.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { stdDeviationBands } from '../std_deviation_bands'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { stdDeviationBands } from './std_deviation_bands'; describe('stdDeviationBands(resp, panel, series)', () => { let panel; @@ -79,18 +77,18 @@ describe('stdDeviationBands(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); stdDeviationBands(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('creates a series', () => { + test('creates a series', () => { const next = results => results; const results = stdDeviationBands(resp, panel, series)(next)([]); - expect(results).to.have.length(2); + expect(results).toHaveLength(2); - expect(results[0]).to.eql({ + expect(results[0]).toEqual({ id: 'test:upper', label: 'Std. Deviation of cpu', color: 'rgb(255, 0, 0)', @@ -103,7 +101,7 @@ describe('stdDeviationBands(resp, panel, series)', () => { ], }); - expect(results[1]).to.eql({ + expect(results[1]).toEqual({ id: 'test:lower', color: 'rgb(255, 0, 0)', lines: { show: true, fill: false, lineWidth: 0 }, diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_deviation_sibling.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.test.js similarity index 87% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_deviation_sibling.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.test.js index 14c2c16ef728f..adc5a3a4a991b 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_deviation_sibling.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_deviation_sibling.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { stdDeviationSibling } from '../std_deviation_sibling'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { stdDeviationSibling } from './std_deviation_sibling'; describe('stdDeviationSibling(resp, panel, series)', () => { let panel; @@ -79,18 +77,18 @@ describe('stdDeviationSibling(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); stdDeviationSibling(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('creates a series', () => { + test('creates a series', () => { const next = results => results; const results = stdDeviationSibling(resp, panel, series)(next)([]); - expect(results).to.have.length(2); + expect(results).toHaveLength(2); - expect(results[0]).to.eql({ + expect(results[0]).toEqual({ id: 'test:lower', color: 'rgb(255, 0, 0)', lines: { show: true, fill: false, lineWidth: 0 }, @@ -101,7 +99,7 @@ describe('stdDeviationSibling(resp, panel, series)', () => { ], }); - expect(results[1]).to.eql({ + expect(results[1]).toEqual({ id: 'test:upper', label: 'Overall Std. Deviation of Average of cpu', color: 'rgb(255, 0, 0)', diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_metric.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.test.js similarity index 65% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_metric.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.test.js index 5039a406a6acc..6ddd6f907fa97 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_metric.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_metric.test.js @@ -17,9 +17,7 @@ * under the License. */ -import sinon from 'sinon'; -import { expect } from 'chai'; -import { stdMetric } from '../std_metric'; +import { stdMetric } from './std_metric'; describe('stdMetric(resp, panel, series)', () => { let panel; @@ -60,41 +58,41 @@ describe('stdMetric(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); stdMetric(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('calls next when finished (percentile)', () => { + test('calls next when finished (percentile)', () => { series.metrics[0].type = 'percentile'; - const next = sinon.spy(d => d); + const next = jest.fn(d => d); const results = stdMetric(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); - expect(results).to.have.length(0); + expect(next.mock.calls.length).toEqual(1); + expect(results).toHaveLength(0); }); - it('calls next when finished (std_deviation band)', () => { + test('calls next when finished (std_deviation band)', () => { series.metrics[0].type = 'std_deviation'; series.metrics[0].mode = 'band'; - const next = sinon.spy(d => d); + const next = jest.fn(d => d); const results = stdMetric(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); - expect(results).to.have.length(0); + expect(next.mock.calls.length).toEqual(1); + expect(results).toHaveLength(0); }); - it('creates a series', () => { + test('creates a series', () => { const next = results => results; const results = stdMetric(resp, panel, series)(next)([]); - expect(results).to.have.length(1); - expect(results[0]).to.have.property('color', 'rgb(255, 0, 0)'); - expect(results[0]).to.have.property('id', 'test'); - expect(results[0]).to.have.property('label', 'Average of cpu'); - expect(results[0]).to.have.property('lines'); - expect(results[0]).to.have.property('stack'); - expect(results[0]).to.have.property('bars'); - expect(results[0]).to.have.property('points'); - expect(results[0].data).to.eql([ + expect(results).toHaveLength(1); + expect(results[0]).toHaveProperty('color', 'rgb(255, 0, 0)'); + expect(results[0]).toHaveProperty('id', 'test'); + expect(results[0]).toHaveProperty('label', 'Average of cpu'); + expect(results[0]).toHaveProperty('lines'); + expect(results[0]).toHaveProperty('stack'); + expect(results[0]).toHaveProperty('bars'); + expect(results[0]).toHaveProperty('points'); + expect(results[0].data).toEqual([ [1, 1], [2, 2], ]); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_sibling.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.test.js similarity index 82% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_sibling.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.test.js index a243ad525332c..9ed60a6d16492 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/std_sibling.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/std_sibling.test.js @@ -17,9 +17,7 @@ * under the License. */ -import { stdSibling } from '../std_sibling'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { stdSibling } from './std_sibling'; describe('stdSibling(resp, panel, series)', () => { let panel; @@ -74,26 +72,26 @@ describe('stdSibling(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); stdSibling(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('calls next when std. deviation bands set', () => { + test('calls next when std. deviation bands set', () => { series.metrics[1].mode = 'band'; - const next = sinon.spy(results => results); + const next = jest.fn(results => results); const results = stdSibling(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); - expect(results).to.have.length(0); + expect(next.mock.calls.length).toEqual(1); + expect(results).toHaveLength(0); }); - it('creates a series', () => { + test('creates a series', () => { const next = results => results; const results = stdSibling(resp, panel, series)(next)([]); - expect(results).to.have.length(1); + expect(results).toHaveLength(1); - expect(results[0]).to.eql({ + expect(results[0]).toEqual({ id: 'test', label: 'Overall Std. Deviation of Average of cpu', color: 'rgb(255, 0, 0)', diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/time_shift.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js similarity index 71% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/time_shift.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js index 1e6da85f88164..7047c54fa1c0e 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/__tests__/time_shift.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/response_processors/series/time_shift.test.js @@ -17,10 +17,8 @@ * under the License. */ -import sinon from 'sinon'; -import { expect } from 'chai'; -import { timeShift } from '../time_shift'; -import { stdMetric } from '../std_metric'; +import { timeShift } from './time_shift'; +import { stdMetric } from './std_metric'; describe('timeShift(resp, panel, series)', () => { let panel; @@ -62,24 +60,24 @@ describe('timeShift(resp, panel, series)', () => { }; }); - it('calls next when finished', () => { - const next = sinon.spy(); + test('calls next when finished', () => { + const next = jest.fn(); timeShift(resp, panel, series)(next)([]); - expect(next.calledOnce).to.equal(true); + expect(next.mock.calls.length).toEqual(1); }); - it('creates a series', () => { + test('creates a series', () => { const next = timeShift(resp, panel, series)(results => results); const results = stdMetric(resp, panel, series)(next)([]); - expect(results).to.have.length(1); - expect(results[0]).to.have.property('color', 'rgb(255, 0, 0)'); - expect(results[0]).to.have.property('id', 'test'); - expect(results[0]).to.have.property('label', 'Average of cpu'); - expect(results[0]).to.have.property('lines'); - expect(results[0]).to.have.property('stack'); - expect(results[0]).to.have.property('bars'); - expect(results[0]).to.have.property('points'); - expect(results[0].data).to.eql([ + expect(results).toHaveLength(1); + expect(results[0]).toHaveProperty('color', 'rgb(255, 0, 0)'); + expect(results[0]).toHaveProperty('id', 'test'); + expect(results[0]).toHaveProperty('label', 'Average of cpu'); + expect(results[0]).toHaveProperty('lines'); + expect(results[0]).toHaveProperty('stack'); + expect(results[0]).toHaveProperty('bars'); + expect(results[0]).toHaveProperty('points'); + expect(results[0].data).toEqual([ [1483225200000 + 3600000, 1], [1483225210000 + 3600000, 2], ]); diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/__tests__/build_request_body.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts similarity index 95% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/__tests__/build_request_body.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts index f21bf3d197969..0c75e6ef1c5bd 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/__tests__/build_request_body.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.test.ts @@ -17,6 +17,8 @@ * under the License. */ +import { buildRequestBody } from './build_request_body'; + const body = JSON.parse(` { "filters": [ @@ -75,15 +77,11 @@ const body = JSON.parse(` } `); -import sinon from 'sinon'; -import { expect } from 'chai'; -import { buildRequestBody } from '../build_request_body'; - describe('buildRequestBody(req)', () => { - it('returns a valid body', () => { + test('returns a valid body', () => { const panel = body.panels[0]; const series = panel.series[0]; - const getValidTimeInterval = sinon.spy(() => '10s'); + const getValidTimeInterval = jest.fn(() => '10s'); const capabilities = { searchTimezone: 'UTC', getValidTimeInterval, @@ -102,7 +100,7 @@ describe('buildRequestBody(req)', () => { capabilities ); - expect(doc).to.eql({ + expect(doc).toEqual({ size: 0, query: { bool: { diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.js b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.ts similarity index 95% rename from src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.js rename to src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.ts index fe3137a8f86ba..85e1f8f7eb12b 100644 --- a/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.js +++ b/src/legacy/core_plugins/vis_type_timeseries/server/lib/vis_data/series/build_request_body.ts @@ -18,6 +18,7 @@ */ import { buildProcessorFunction } from '../build_processor_function'; +// @ts-ignore import { processors } from '../request_processors/series'; /** @@ -33,7 +34,7 @@ import { processors } from '../request_processors/series'; * ] * @returns {Object} doc - processed body */ -export function buildRequestBody(...args) { +export function buildRequestBody(...args: any[]) { const processor = buildProcessorFunction(processors, ...args); const doc = processor({}); return doc; From 2acb42662c7a3bc42434a6ca3b243592442c9220 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Thu, 16 Jan 2020 13:57:37 +0100 Subject: [PATCH 03/11] Upgrade io-ts after fix was merged and update use of some types (#55013) * Upgrade io-ts after fix was merged and update use of some types * Stricter checking against object keys --- .../constants/parameters_definition.tsx | 12 ++++-------- .../components/mappings_editor/lib/error_reporter.ts | 10 +++++----- .../mappings_editor/lib/mappings_validator.ts | 6 +++--- x-pack/package.json | 2 +- yarn.lock | 8 ++++---- 5 files changed, 17 insertions(+), 21 deletions(-) diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx index 581b1223b7892..1277568b71bbd 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/constants/parameters_definition.tsx @@ -100,14 +100,10 @@ const fielddataFrequencyFilterParam = { }, }, }, - schema: t.intersection([ - t.partial({ - min: t.number, - max: t.number, - min_segment_size: t.number, - }), - t.brand(t.UnknownRecord, (v: any): v is any => !Array.isArray(v), 'Array'), - ]), + schema: t.record( + t.union([t.literal('min'), t.literal('max'), t.literal('min_segment_size')]), + t.number + ), }; const analyzerValidations = [ diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/error_reporter.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/error_reporter.ts index 363ccfc2a5fab..e9beee1071597 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/error_reporter.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/error_reporter.ts @@ -3,14 +3,14 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { ValidationError, Validation } from 'io-ts'; +import { ValidationError } from 'io-ts'; import { fold } from 'fp-ts/lib/Either'; import { Reporter } from 'io-ts/lib/Reporter'; export type ReporterResult = Array<{ path: string[]; message: string }>; -export const failure = (validation: any): ReporterResult => { - return validation.map((e: ValidationError) => { +const failure = (validation: ValidationError[]): ReporterResult => { + return validation.map(e => { const path: string[] = []; let validationName = ''; @@ -37,6 +37,6 @@ export const failure = (validation: any): ReporterResult => { const empty: never[] = []; const success = () => empty; -export const ErrorReporter: Reporter = { - report: (validation: Validation) => fold(failure, success)(validation as any), +export const errorReporter: Reporter = { + report: fold(failure, success), }; diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts index 990d5ec961a6f..fff735da2e758 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/lib/mappings_validator.ts @@ -8,7 +8,7 @@ import * as t from 'io-ts'; import { ordString } from 'fp-ts/lib/Ord'; import { toArray } from 'fp-ts/lib/Set'; import { isLeft, isRight } from 'fp-ts/lib/Either'; -import { ErrorReporter } from './error_reporter'; +import { errorReporter } from './error_reporter'; import { ALL_DATA_TYPES, PARAMETERS_DEFINITION } from '../constants'; import { FieldMeta } from '../types'; import { getFieldMeta } from '../lib'; @@ -218,7 +218,7 @@ const mappingsConfigurationSchemaKeys = Object.keys(mappingsConfigurationSchema. const validateMappingsConfiguration = ( mappingsConfiguration: any ): { value: any; errors: MappingsValidationError[] } => { - // Array to keep track of invalid configuration parameters. + // Set to keep track of invalid configuration parameters. const configurationRemoved: Set = new Set(); let copyOfMappingsConfig = { ...mappingsConfiguration }; @@ -228,7 +228,7 @@ const validateMappingsConfiguration = ( /** * To keep the logic simple we will strip out the parameters that contain errors */ - const errors = ErrorReporter.report(result); + const errors = errorReporter.report(result); errors.forEach(error => { const configurationName = error.path[0]; configurationRemoved.add(configurationName); diff --git a/x-pack/package.json b/x-pack/package.json index 84f15d3d38828..bd43d19135aab 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -252,7 +252,7 @@ "immer": "^1.5.0", "inline-style": "^2.0.0", "intl": "^1.2.5", - "io-ts": "^2.0.1", + "io-ts": "^2.0.5", "isbinaryfile": "4.0.2", "joi": "^13.5.2", "jquery": "^3.4.1", diff --git a/yarn.lock b/yarn.lock index 587af6ba2e99d..ce222e727d08e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16849,10 +16849,10 @@ invert-kv@^2.0.0: resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== -io-ts@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.0.1.tgz#1261c12f915c2f48d16393a36966636b48a45aa1" - integrity sha512-RezD+WcCfW4VkMkEcQWL/Nmy/nqsWTvTYg7oUmTGzglvSSV2P9h2z1PVeREPFf0GWNzruYleAt1XCMQZSg1xxQ== +io-ts@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.0.5.tgz#e6e3db9df8b047f9cbd6b69e7d2ad3e6437a0b13" + integrity sha512-pL7uUptryanI5Glv+GUv7xh+aLBjxGEDmLwmEYNSx0yOD3djK0Nw5Bt0N6BAkv9LadOUU7QKpRsLcqnTh3UlLA== ip-regex@^2.1.0: version "2.1.0" From 5c19c82d4a3368f21bc0c2410329f93a648784ac Mon Sep 17 00:00:00 2001 From: Vadim Dalecky Date: Thu, 16 Jan 2020 05:33:52 -0800 Subject: [PATCH 04/11] bfetch (2) (#53711) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 🎸 implement ItemBuffer * test: 💍 add tests for ItemBuffer * feat: 🎸 add TimedItemBuffer * test: 💍 add TimedItemBuffer tests * feat: 🎸 add createBatchedFunction * chore: 🤖 save wip on higher level batching * test: 💍 add createBatchedFunction tests * feat: 🎸 implement createStreamingBatchedFunction() method * refactor: 💡 rename "data" key to "result" * feat: 🎸 return error in "error" key in legacy protocol * feat: 🎸 add server-side to Expressions plugin * refactor: 💡 move interpreter server-side registries to NP * feat: 🎸 implement bfetch.addBatchProcessingRoute * feat: 🎸 improve streaming and batching func to pass request * feat: 🎸 initial setup of new expressions batching endpoint * feat: 🎸 expose bfetch.batchedFunction() function * feat: 🎸 add of() function of() function awaits a promise and converts it to a 3-tuple representing its state. * refactor: 💡 move normalizeError() to /common * feat: 🎸 improve createStreamingBatchedFunction() function * refactor: 💡 move GET /api/interpreter/fns to the New Platform * feat: 🎸 move batched_fetch to the New Platform * feat: 🎸 implement legacy interpreter batching on server in NP * feat: 🎸 switch legacy interpreter server functions to NP * chore: 🤖 remove unused import * fix: 🐛 correct expressions mocks * test: 💍 fix batching tests after refactor * test: 💍 stub bfetch plugin explorer * test: 💍 add routing and app structure to bfetch_explorer * test: 💍 add server-side to bfetch_explorer * test: 💍 create component in bfetch_explorer * test: 💍 improve bfetch_explorer * test: 💍 add demo to bfetch_explorer * test: 💍 by default redirect to first bfetch_explorer example * test: 💍 add error example to bfetch_explorer * docs: ✏️ improve bfetch docs * docs: ✏️ improve bfetch server-side docs * chore: 🤖 address self-review comments * fix: 🐛 use new core ES data client, remove unuseed import * fix: 🐛 remove unused interface import * Update examples/bfetch_explorer/public/components/count_until/index.tsx Co-Authored-By: Lukas Olson * Update examples/bfetch_explorer/public/components/double_integers/index.tsx Co-Authored-By: Lukas Olson * Update src/plugins/bfetch/common/buffer/item_buffer.ts Co-Authored-By: Lukas Olson * Update src/plugins/kibana_utils/common/of.ts Co-Authored-By: Lukas Olson * docs: ✏️ add batchedFunction params to README * refactor: 💡 rename onflush to onFlush * feat: 🎸 make maxItemAge optional in TimedItemBuffer * refactor: 💡 remove promise from fetchStreaming * test: 💍 add bfetch_explorer functional tests * test: 💍 rename test plugin to kbn_tp_bfetch_explorer * fix: 🐛 use stream instead of removed promise * fix: 🐛 use correct tsconfig.json in bfetch test plugin * feat: 🎸 add kbn_tp_bfetch_explorer server-side files to tsconfi Co-authored-by: Lukas Olson Co-authored-by: Elastic Machine --- examples/README.md | 1 - examples/bfetch_explorer/kibana.json | 10 + examples/bfetch_explorer/package.json | 17 + .../public/components/count_until/index.tsx | 93 ++++ .../components/double_integers/index.tsx | 105 ++++ .../public/components/page/index.tsx | 51 ++ .../public/containers/app/index.tsx | 48 ++ .../app/pages/page_count_until/index.tsx | 45 ++ .../app/pages/page_double_integers/index.tsx | 45 ++ .../public/containers/app/sidebar/index.tsx | 54 ++ .../bfetch_explorer/public/hooks/use_deps.ts | 23 + .../bfetch_explorer/public/index.ts | 5 +- examples/bfetch_explorer/public/mount.tsx | 47 ++ examples/bfetch_explorer/public/plugin.tsx | 55 ++ examples/bfetch_explorer/public/routes.tsx | 59 ++ .../bfetch_explorer/server}/index.ts | 6 +- examples/bfetch_explorer/server/plugin.ts | 68 +++ examples/bfetch_explorer/tsconfig.json | 15 + src/legacy/core_plugins/interpreter/init.ts | 33 +- .../load_legacy_server_function_wrappers.ts | 60 +- .../public/registries.karma_mock.ts | 1 + .../server/lib/__tests__/create_handlers.ts | 65 --- .../server/routes/server_functions.ts | 166 ------ src/plugins/bfetch/README.md | 49 +- src/plugins/bfetch/common/batch.ts | 32 ++ .../common/buffer/create_batched_function.ts | 49 ++ src/plugins/bfetch/common/buffer/index.ts | 22 + .../bfetch/common/buffer/item_buffer.ts | 81 +++ .../tests/create_batched_function.test.ts | 75 +++ .../common/buffer/tests/item_buffer.test.ts | 23 + .../buffer/tests/run_item_buffer_tests.ts | 239 ++++++++ .../buffer/tests/timed_item_buffer.test.ts | 104 ++++ .../bfetch/common/buffer/timed_item_buffer.ts | 58 ++ src/plugins/bfetch/common/index.ts | 2 + src/plugins/bfetch/common/streaming/types.ts | 2 +- src/plugins/bfetch/common/util/index.ts | 1 + .../bfetch/common/util/normalize_error.ts} | 28 +- src/plugins/bfetch/docs/browser/reference.md | 31 +- src/plugins/bfetch/docs/server/reference.md | 54 ++ .../create_streaming_batched_function.test.ts | 521 ++++++++++++++++++ .../create_streaming_batched_function.ts | 140 +++++ src/plugins/bfetch/public/index.ts | 3 +- src/plugins/bfetch/public/mocks.ts | 4 +- src/plugins/bfetch/public/plugin.ts | 32 +- .../public/streaming/fetch_streaming.test.ts | 19 +- .../public/streaming/fetch_streaming.ts | 8 - src/plugins/bfetch/server/index.ts | 2 +- src/plugins/bfetch/server/mocks.ts | 3 +- src/plugins/bfetch/server/plugin.ts | 87 ++- .../server/streaming/create_ndjson_stream.ts | 2 +- src/plugins/expressions/common/type.ts | 10 +- src/plugins/expressions/kibana.json | 3 +- .../expressions/public}/batched_fetch.test.ts | 2 +- .../expressions/public}/batched_fetch.ts | 16 +- src/plugins/expressions/public/mocks.tsx | 4 + src/plugins/expressions/public/plugin.ts | 33 +- src/plugins/expressions/server/index.ts | 27 + src/plugins/expressions/server/legacy.ts | 135 +++++ src/plugins/expressions/server/mocks.ts | 73 +++ src/plugins/expressions/server/plugin.ts | 77 +++ src/plugins/kibana_utils/common/index.ts | 1 + src/plugins/kibana_utils/common/of.test.ts | 63 +++ src/plugins/kibana_utils/common/of.ts | 37 ++ src/plugins/kibana_utils/public/index.ts | 2 +- test/plugin_functional/config.js | 1 + .../kbn_tp_bfetch_explorer/kibana.json | 10 + .../kbn_tp_bfetch_explorer/package.json | 17 + .../kbn_tp_bfetch_explorer/public/index.ts | 20 + .../kbn_tp_bfetch_explorer/server/index.ts | 20 + .../kbn_tp_bfetch_explorer/tsconfig.json | 21 + .../bfetch_explorer/batched_function.ts | 93 ++++ .../test_suites/bfetch_explorer/index.ts | 36 ++ 72 files changed, 3044 insertions(+), 400 deletions(-) create mode 100644 examples/bfetch_explorer/kibana.json create mode 100644 examples/bfetch_explorer/package.json create mode 100644 examples/bfetch_explorer/public/components/count_until/index.tsx create mode 100644 examples/bfetch_explorer/public/components/double_integers/index.tsx create mode 100644 examples/bfetch_explorer/public/components/page/index.tsx create mode 100644 examples/bfetch_explorer/public/containers/app/index.tsx create mode 100644 examples/bfetch_explorer/public/containers/app/pages/page_count_until/index.tsx create mode 100644 examples/bfetch_explorer/public/containers/app/pages/page_double_integers/index.tsx create mode 100644 examples/bfetch_explorer/public/containers/app/sidebar/index.tsx create mode 100644 examples/bfetch_explorer/public/hooks/use_deps.ts rename src/legacy/core_plugins/interpreter/public/canvas/consts.ts => examples/bfetch_explorer/public/index.ts (86%) create mode 100644 examples/bfetch_explorer/public/mount.tsx create mode 100644 examples/bfetch_explorer/public/plugin.tsx create mode 100644 examples/bfetch_explorer/public/routes.tsx rename {src/legacy/core_plugins/interpreter/server/routes => examples/bfetch_explorer/server}/index.ts (85%) create mode 100644 examples/bfetch_explorer/server/plugin.ts create mode 100644 examples/bfetch_explorer/tsconfig.json delete mode 100644 src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.ts delete mode 100644 src/legacy/core_plugins/interpreter/server/routes/server_functions.ts create mode 100644 src/plugins/bfetch/common/batch.ts create mode 100644 src/plugins/bfetch/common/buffer/create_batched_function.ts create mode 100644 src/plugins/bfetch/common/buffer/index.ts create mode 100644 src/plugins/bfetch/common/buffer/item_buffer.ts create mode 100644 src/plugins/bfetch/common/buffer/tests/create_batched_function.test.ts create mode 100644 src/plugins/bfetch/common/buffer/tests/item_buffer.test.ts create mode 100644 src/plugins/bfetch/common/buffer/tests/run_item_buffer_tests.ts create mode 100644 src/plugins/bfetch/common/buffer/tests/timed_item_buffer.test.ts create mode 100644 src/plugins/bfetch/common/buffer/timed_item_buffer.ts rename src/{legacy/core_plugins/interpreter/server/lib/create_handlers.ts => plugins/bfetch/common/util/normalize_error.ts} (62%) create mode 100644 src/plugins/bfetch/docs/server/reference.md create mode 100644 src/plugins/bfetch/public/batching/create_streaming_batched_function.test.ts create mode 100644 src/plugins/bfetch/public/batching/create_streaming_batched_function.ts rename src/{legacy/core_plugins/interpreter/public/canvas => plugins/expressions/public}/batched_fetch.test.ts (97%) rename src/{legacy/core_plugins/interpreter/public/canvas => plugins/expressions/public}/batched_fetch.ts (87%) create mode 100644 src/plugins/expressions/server/index.ts create mode 100644 src/plugins/expressions/server/legacy.ts create mode 100644 src/plugins/expressions/server/mocks.ts create mode 100644 src/plugins/expressions/server/plugin.ts create mode 100644 src/plugins/kibana_utils/common/of.test.ts create mode 100644 src/plugins/kibana_utils/common/of.ts create mode 100644 test/plugin_functional/plugins/kbn_tp_bfetch_explorer/kibana.json create mode 100644 test/plugin_functional/plugins/kbn_tp_bfetch_explorer/package.json create mode 100644 test/plugin_functional/plugins/kbn_tp_bfetch_explorer/public/index.ts create mode 100644 test/plugin_functional/plugins/kbn_tp_bfetch_explorer/server/index.ts create mode 100644 test/plugin_functional/plugins/kbn_tp_bfetch_explorer/tsconfig.json create mode 100644 test/plugin_functional/test_suites/bfetch_explorer/batched_function.ts create mode 100644 test/plugin_functional/test_suites/bfetch_explorer/index.ts diff --git a/examples/README.md b/examples/README.md index 7cade0b35f820..2b214a8d1eb52 100644 --- a/examples/README.md +++ b/examples/README.md @@ -5,4 +5,3 @@ This folder contains example plugins. To run the plugins in this folder, use th ``` yarn start --run-examples ``` - diff --git a/examples/bfetch_explorer/kibana.json b/examples/bfetch_explorer/kibana.json new file mode 100644 index 0000000000000..cbdd9be0e658c --- /dev/null +++ b/examples/bfetch_explorer/kibana.json @@ -0,0 +1,10 @@ +{ + "id": "bfetchExplorer", + "version": "0.0.1", + "kibanaVersion": "kibana", + "configPath": ["bfetch_explorer"], + "server": true, + "ui": true, + "requiredPlugins": ["bfetch"], + "optionalPlugins": [] +} diff --git a/examples/bfetch_explorer/package.json b/examples/bfetch_explorer/package.json new file mode 100644 index 0000000000000..ea5a1b1848613 --- /dev/null +++ b/examples/bfetch_explorer/package.json @@ -0,0 +1,17 @@ +{ + "name": "bfetch_explorer", + "version": "1.0.0", + "main": "target/examples/bfetch_explorer", + "kibana": { + "version": "kibana", + "templateVersion": "1.0.0" + }, + "license": "Apache-2.0", + "scripts": { + "kbn": "node ../../scripts/kbn.js", + "build": "rm -rf './target' && tsc" + }, + "devDependencies": { + "typescript": "3.7.2" + } +} diff --git a/examples/bfetch_explorer/public/components/count_until/index.tsx b/examples/bfetch_explorer/public/components/count_until/index.tsx new file mode 100644 index 0000000000000..ce48ce9dfe61f --- /dev/null +++ b/examples/bfetch_explorer/public/components/count_until/index.tsx @@ -0,0 +1,93 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useState } from 'react'; +import useMountedState from 'react-use/lib/useMountedState'; +import useList from 'react-use/lib/useList'; +import { EuiForm, EuiSpacer, EuiFieldNumber, EuiFormRow, EuiButton } from '@elastic/eui'; +import { BfetchPublicSetup } from '../../../../../src/plugins/bfetch/public'; + +export interface Props { + fetchStreaming: BfetchPublicSetup['fetchStreaming']; +} + +export const CountUntil: React.FC = ({ fetchStreaming }) => { + const isMounted = useMountedState(); + const [data, setData] = useState(5); + const [showingResults, setShowingResults] = useState(false); + const [results, { push: pushResult, clear: clearList }] = useList([]); + const [completed, setCompleted] = useState(false); + const [error, setError] = useState(null); + + const handleSubmit = () => { + setShowingResults(true); + const { stream } = fetchStreaming({ + url: '/bfetch_explorer/count', + body: JSON.stringify({ data }), + }); + stream.subscribe({ + next: (next: string) => { + if (!isMounted()) return; + pushResult(next); + }, + error: (nextError: any) => { + if (!isMounted()) return; + setError(nextError); + }, + complete: () => { + if (!isMounted()) return; + setCompleted(true); + }, + }); + }; + + const handleReset = () => { + setShowingResults(false); + clearList(); + setError(null); + setCompleted(false); + }; + + if (showingResults) { + return ( + +
{JSON.stringify(error || results, null, 4)}
+ + + Reset + +
+ ); + } + + return ( + + + setData(Number(e.target.value))} + /> + + + Start + + + ); +}; diff --git a/examples/bfetch_explorer/public/components/double_integers/index.tsx b/examples/bfetch_explorer/public/components/double_integers/index.tsx new file mode 100644 index 0000000000000..d8fbe33ec73be --- /dev/null +++ b/examples/bfetch_explorer/public/components/double_integers/index.tsx @@ -0,0 +1,105 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useState } from 'react'; +import useMountedState from 'react-use/lib/useMountedState'; +import useList from 'react-use/lib/useList'; +import useCounter from 'react-use/lib/useCounter'; +import { EuiForm, EuiSpacer, EuiTextArea, EuiFormRow, EuiButton } from '@elastic/eui'; +import { ExplorerService } from '../../plugin'; + +interface ResultItem { + num: number; + result?: { + num: number; + }; + error?: any; +} + +const defaultNumbers = [2000, 300, -1, 1000].join('\n'); + +export interface Props { + double: ExplorerService['double']; +} + +export const DoubleIntegers: React.FC = ({ double }) => { + const isMounted = useMountedState(); + const [numbers, setNumbers] = useState(defaultNumbers); + const [showingResults, setShowingResults] = useState(false); + const [numberOfResultsAwaiting, counter] = useCounter(0); + const [results, { push: pushResult, clear: clearList }] = useList([]); + + const handleSubmit = () => { + setShowingResults(true); + const nums = numbers + .split('\n') + .map(num => num.trim()) + .filter(Boolean) + .map(Number); + counter.set(nums.length); + nums.forEach(num => { + double({ num }).then( + result => { + if (!isMounted()) return; + counter.dec(); + pushResult({ num, result }); + }, + error => { + if (!isMounted()) return; + counter.dec(); + pushResult({ num, error }); + } + ); + }); + }; + + const handleReset = () => { + setShowingResults(false); + counter.reset(); + clearList(); + }; + + if (showingResults) { + return ( + +
{JSON.stringify(results, null, 4)}
+ + + Reset + +
+ ); + } + + return ( + + + setNumbers(e.target.value)} + /> + + + Send + + + ); +}; diff --git a/examples/bfetch_explorer/public/components/page/index.tsx b/examples/bfetch_explorer/public/components/page/index.tsx new file mode 100644 index 0000000000000..0e7855178a884 --- /dev/null +++ b/examples/bfetch_explorer/public/components/page/index.tsx @@ -0,0 +1,51 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from 'react'; +import { + EuiPageBody, + EuiPageContent, + EuiPageContentBody, + EuiPageHeader, + EuiPageHeaderSection, + EuiTitle, +} from '@elastic/eui'; + +export interface PageProps { + title?: React.ReactNode; +} + +export const Page: React.FC = ({ title = 'Untitled', children }) => { + return ( + + + + +

{title}

+
+
+
+ + + {children} + + +
+ ); +}; diff --git a/examples/bfetch_explorer/public/containers/app/index.tsx b/examples/bfetch_explorer/public/containers/app/index.tsx new file mode 100644 index 0000000000000..a448c9e4f3a6a --- /dev/null +++ b/examples/bfetch_explorer/public/containers/app/index.tsx @@ -0,0 +1,48 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom'; +import { EuiPage } from '@elastic/eui'; +import { useDeps } from '../../hooks/use_deps'; +import { Sidebar } from './sidebar'; +import { routes } from '../../routes'; + +export const App: React.FC = () => { + const { appBasePath } = useDeps(); + + const routeElements: React.ReactElement[] = []; + for (const { items } of routes) { + for (const { id, component } of items) { + routeElements.push( component} />); + } + } + + return ( + + + + + {routeElements} + + + + + ); +}; diff --git a/examples/bfetch_explorer/public/containers/app/pages/page_count_until/index.tsx b/examples/bfetch_explorer/public/containers/app/pages/page_count_until/index.tsx new file mode 100644 index 0000000000000..7b4eac6eea44c --- /dev/null +++ b/examples/bfetch_explorer/public/containers/app/pages/page_count_until/index.tsx @@ -0,0 +1,45 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from 'react'; +import { EuiPanel, EuiText } from '@elastic/eui'; +import { CountUntil } from '../../../../components/count_until'; +import { Page } from '../../../../components/page'; +import { useDeps } from '../../../../hooks/use_deps'; + +// eslint-disable-next-line +export interface Props {} + +export const PageCountUntil: React.FC = () => { + const { plugins } = useDeps(); + + return ( + + + This demo sends a single number N using fetchStreaming to the server. The + server will stream back N number of messages with 1 second delay each containing a number + from 1 to N, after which it will close the stream. + +
+ + + +
+ ); +}; diff --git a/examples/bfetch_explorer/public/containers/app/pages/page_double_integers/index.tsx b/examples/bfetch_explorer/public/containers/app/pages/page_double_integers/index.tsx new file mode 100644 index 0000000000000..7bd5feb836674 --- /dev/null +++ b/examples/bfetch_explorer/public/containers/app/pages/page_double_integers/index.tsx @@ -0,0 +1,45 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from 'react'; +import { EuiPanel, EuiText } from '@elastic/eui'; +import { DoubleIntegers } from '../../../../components/double_integers'; +import { Page } from '../../../../components/page'; +import { useDeps } from '../../../../hooks/use_deps'; + +// eslint-disable-next-line +export interface Props {} + +export const PageDoubleIntegers: React.FC = () => { + const { explorer } = useDeps(); + + return ( + + + Below is a list of numbers in milliseconds. They are sent as a batch to the server. For each + number server waits given number of milliseconds then doubles the number and streams it + back. + +
+ + + +
+ ); +}; diff --git a/examples/bfetch_explorer/public/containers/app/sidebar/index.tsx b/examples/bfetch_explorer/public/containers/app/sidebar/index.tsx new file mode 100644 index 0000000000000..cc50698e05908 --- /dev/null +++ b/examples/bfetch_explorer/public/containers/app/sidebar/index.tsx @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { EuiPageSideBar, EuiSideNav } from '@elastic/eui'; +import { useHistory } from 'react-router-dom'; +import { routes } from '../../../routes'; + +// eslint-disable-next-line +interface SidebarProps {} + +export const Sidebar: React.FC = () => { + const history = useHistory(); + + return ( + + ({ + id, + name: title, + isSelected: true, + items: items.map(route => ({ + id: route.id, + name: route.title, + onClick: () => history.push(`/${route.id}`), + 'data-test-subj': route.id, + })), + })), + }, + ]} + /> + + ); +}; diff --git a/examples/bfetch_explorer/public/hooks/use_deps.ts b/examples/bfetch_explorer/public/hooks/use_deps.ts new file mode 100644 index 0000000000000..c68b4e759c21c --- /dev/null +++ b/examples/bfetch_explorer/public/hooks/use_deps.ts @@ -0,0 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { useKibana } from '../../../../src/plugins/kibana_react/public'; +import { BfetchDeps } from '../mount'; + +export const useDeps = () => useKibana().services as BfetchDeps; diff --git a/src/legacy/core_plugins/interpreter/public/canvas/consts.ts b/examples/bfetch_explorer/public/index.ts similarity index 86% rename from src/legacy/core_plugins/interpreter/public/canvas/consts.ts rename to examples/bfetch_explorer/public/index.ts index 2600ada36afdc..76d0a1d1c6334 100644 --- a/src/legacy/core_plugins/interpreter/public/canvas/consts.ts +++ b/examples/bfetch_explorer/public/index.ts @@ -17,5 +17,6 @@ * under the License. */ -// The server endpoint for retrieiving and running Canvas functions. -export const FUNCTIONS_URL = '/api/interpreter/fns'; +import { BfetchExplorerPlugin } from './plugin'; + +export const plugin = () => new BfetchExplorerPlugin(); diff --git a/examples/bfetch_explorer/public/mount.tsx b/examples/bfetch_explorer/public/mount.tsx new file mode 100644 index 0000000000000..5ad53ef4a1988 --- /dev/null +++ b/examples/bfetch_explorer/public/mount.tsx @@ -0,0 +1,47 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import { CoreSetup, CoreStart, AppMountParameters } from 'kibana/public'; +import { KibanaContextProvider } from '../../../src/plugins/kibana_react/public'; +import { BfetchExplorerStartPlugins, ExplorerService } from './plugin'; +import { App } from './containers/app'; + +export interface BfetchDeps { + appBasePath: string; + core: CoreStart; + plugins: BfetchExplorerStartPlugins; + explorer: ExplorerService; +} + +export const mount = ( + coreSetup: CoreSetup, + explorer: ExplorerService +) => async ({ appBasePath, element }: AppMountParameters) => { + const [core, plugins] = await coreSetup.getStartServices(); + const deps: BfetchDeps = { appBasePath, core, plugins, explorer }; + const reactElement = ( + + + + ); + render(reactElement, element); + return () => unmountComponentAtNode(element); +}; diff --git a/examples/bfetch_explorer/public/plugin.tsx b/examples/bfetch_explorer/public/plugin.tsx new file mode 100644 index 0000000000000..3155354c91fd4 --- /dev/null +++ b/examples/bfetch_explorer/public/plugin.tsx @@ -0,0 +1,55 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Plugin, CoreSetup } from 'kibana/public'; +import { BfetchPublicSetup, BfetchPublicStart } from '../../../src/plugins/bfetch/public'; +import { mount } from './mount'; + +export interface ExplorerService { + double: (number: { num: number }) => Promise<{ num: number }>; +} + +export interface BfetchExplorerSetupPlugins { + bfetch: BfetchPublicSetup; +} + +export interface BfetchExplorerStartPlugins { + bfetch: BfetchPublicStart; +} + +export class BfetchExplorerPlugin implements Plugin { + public setup(core: CoreSetup, plugins: BfetchExplorerSetupPlugins) { + const double = plugins.bfetch.batchedFunction<{ num: number }, { num: number }>({ + url: '/bfetch_explorer/double', + }); + + const explorer: ExplorerService = { + double, + }; + + core.application.register({ + id: 'bfetch-explorer', + title: 'bfetch explorer', + mount: mount(core, explorer), + }); + } + + public start() {} + public stop() {} +} diff --git a/examples/bfetch_explorer/public/routes.tsx b/examples/bfetch_explorer/public/routes.tsx new file mode 100644 index 0000000000000..2008811d75795 --- /dev/null +++ b/examples/bfetch_explorer/public/routes.tsx @@ -0,0 +1,59 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { PageDoubleIntegers } from './containers/app/pages/page_double_integers'; +import { PageCountUntil } from './containers/app/pages/page_count_until'; + +interface RouteSectionDef { + title: string; + id: string; + items: RouteDef[]; +} + +interface RouteDef { + title: string; + id: string; + component: React.ReactNode; +} + +export const routes: RouteSectionDef[] = [ + { + title: 'fetchStreaming', + id: 'fetchStreaming', + items: [ + { + title: 'Count until', + id: 'count-until', + component: , + }, + ], + }, + { + title: 'batchedFunction', + id: 'batchedFunction', + items: [ + { + title: 'Double integers', + id: 'double-integers', + component: , + }, + ], + }, +]; diff --git a/src/legacy/core_plugins/interpreter/server/routes/index.ts b/examples/bfetch_explorer/server/index.ts similarity index 85% rename from src/legacy/core_plugins/interpreter/server/routes/index.ts rename to examples/bfetch_explorer/server/index.ts index 50385147dd38e..76d0a1d1c6334 100644 --- a/src/legacy/core_plugins/interpreter/server/routes/index.ts +++ b/examples/bfetch_explorer/server/index.ts @@ -17,8 +17,6 @@ * under the License. */ -import { registerServerFunctions } from './server_functions'; +import { BfetchExplorerPlugin } from './plugin'; -export function routes(server: any) { - registerServerFunctions(server); -} +export const plugin = () => new BfetchExplorerPlugin(); diff --git a/examples/bfetch_explorer/server/plugin.ts b/examples/bfetch_explorer/server/plugin.ts new file mode 100644 index 0000000000000..bf3b7f50ca6c8 --- /dev/null +++ b/examples/bfetch_explorer/server/plugin.ts @@ -0,0 +1,68 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Subject } from 'rxjs'; +import { Plugin, CoreSetup, CoreStart } from '../../../src/core/server'; +import { BfetchServerSetup, BfetchServerStart } from '../../../src/plugins/bfetch/server'; + +export interface BfetchExplorerSetupPlugins { + bfetch: BfetchServerSetup; +} + +export interface BfetchExplorerStartPlugins { + bfetch: BfetchServerStart; +} + +export class BfetchExplorerPlugin implements Plugin { + public setup(core: CoreSetup, plugins: BfetchExplorerSetupPlugins) { + plugins.bfetch.addStreamingResponseRoute('/bfetch_explorer/count', () => ({ + getResponseStream: ({ data }: any) => { + const subject = new Subject(); + const countTo = Number(data); + for (let cnt = 1; cnt <= countTo; cnt++) { + setTimeout(() => { + subject.next(String(cnt)); + }, cnt * 1000); + } + setTimeout(() => { + subject.complete(); + }, countTo * 1000); + return subject; + }, + })); + + plugins.bfetch.addBatchProcessingRoute<{ num: number }, { num: number }>( + '/bfetch_explorer/double', + () => ({ + onBatchItem: async ({ num }) => { + // Validate inputs. + if (num < 0) throw new Error('Invalid number'); + // Wait number of specified milliseconds. + await new Promise(r => setTimeout(r, num)); + // Double the number and send it back. + return { num: 2 * num }; + }, + }) + ); + } + + public start(core: CoreStart, plugins: BfetchExplorerStartPlugins) {} + + public stop() {} +} diff --git a/examples/bfetch_explorer/tsconfig.json b/examples/bfetch_explorer/tsconfig.json new file mode 100644 index 0000000000000..d508076b33199 --- /dev/null +++ b/examples/bfetch_explorer/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true + }, + "include": [ + "index.ts", + "public/**/*.ts", + "public/**/*.tsx", + "server/**/*.ts", + "../../typings/**/*", + ], + "exclude": [] +} diff --git a/src/legacy/core_plugins/interpreter/init.ts b/src/legacy/core_plugins/interpreter/init.ts index 768d76fbf744e..46da1539afadb 100644 --- a/src/legacy/core_plugins/interpreter/init.ts +++ b/src/legacy/core_plugins/interpreter/init.ts @@ -22,35 +22,10 @@ // @ts-ignore import { register, registryFactory, Registry, Fn } from '@kbn/interpreter/common'; -// @ts-ignore -import { routes } from './server/routes'; - -import { typeSpecs as types, Type } from '../../../plugins/expressions/common'; import { Legacy } from '../../../../kibana'; -export class TypesRegistry extends Registry { - wrapper(obj: any) { - return new (Type as any)(obj); - } -} - -export class FunctionsRegistry extends Registry { - wrapper(obj: any) { - return new Fn(obj); - } -} - -export const registries = { - types: new TypesRegistry(), - serverFunctions: new FunctionsRegistry(), -}; - export async function init(server: Legacy.Server /* options */) { server.injectUiAppVars('canvas', () => { - register(registries, { - types, - }); - const config = server.config(); const basePath = config.get('server.basePath'); const reportingBrowserType = (() => { @@ -63,7 +38,9 @@ export async function init(server: Legacy.Server /* options */) { return { kbnIndex: config.get('kibana.index'), - serverFunctions: registries.serverFunctions.toArray(), + serverFunctions: (server.newPlatform.setup.plugins.expressions as any).__LEGACY + .registries() + .serverFunctions.toArray(), basePath, reportingBrowserType, }; @@ -71,7 +48,5 @@ export async function init(server: Legacy.Server /* options */) { // Expose server.plugins.interpreter.register(specs) and // server.plugins.interpreter.registries() (a getter). - server.expose(registryFactory(registries)); - - routes(server); + server.expose((server.newPlatform.setup.plugins.expressions as any).__LEGACY); } diff --git a/src/legacy/core_plugins/interpreter/public/canvas/load_legacy_server_function_wrappers.ts b/src/legacy/core_plugins/interpreter/public/canvas/load_legacy_server_function_wrappers.ts index 2c2f79b3d6f51..fed157846a1a1 100644 --- a/src/legacy/core_plugins/interpreter/public/canvas/load_legacy_server_function_wrappers.ts +++ b/src/legacy/core_plugins/interpreter/public/canvas/load_legacy_server_function_wrappers.ts @@ -28,62 +28,6 @@ * server side, it should be respective function's internal implementation detail. */ -import { get, identity } from 'lodash'; -// @ts-ignore -import { npSetup, npStart } from 'ui/new_platform'; -import { FUNCTIONS_URL } from './consts'; -import { batchedFetch } from './batched_fetch'; +import { npSetup } from 'ui/new_platform'; -export function getType(node: any) { - if (node == null) return 'null'; - if (typeof node === 'object') { - if (!node.type) throw new Error('Objects must have a type property'); - return node.type; - } - return typeof node; -} - -export function serializeProvider(types: any) { - return { - serialize: provider('serialize'), - deserialize: provider('deserialize'), - }; - - function provider(key: any) { - return (context: any) => { - const type = getType(context); - const typeDef = types[type]; - const fn: any = get(typeDef, key) || identity; - return fn(context); - }; - } -} - -let cached: Promise | null = null; - -export const loadLegacyServerFunctionWrappers = async () => { - if (!cached) { - cached = (async () => { - const serverFunctionList = await npSetup.core.http.get(FUNCTIONS_URL); - const types = npSetup.plugins.expressions.__LEGACY.types.toJS(); - const { serialize } = serializeProvider(types); - const batch = batchedFetch({ - fetchStreaming: npStart.plugins.bfetch.fetchStreaming, - serialize, - }); - - // For every sever-side function, register a client-side - // function that matches its definition, but which simply - // calls the server-side function endpoint. - Object.keys(serverFunctionList).forEach(functionName => { - const fn = () => ({ - ...serverFunctionList[functionName], - fn: (context: any, args: any) => batch({ functionName, args, context }), - }); - npSetup.plugins.expressions.registerFunction(fn); - }); - })(); - } - - return cached; -}; +export const { loadLegacyServerFunctionWrappers } = npSetup.plugins.expressions.__LEGACY; diff --git a/src/legacy/core_plugins/interpreter/public/registries.karma_mock.ts b/src/legacy/core_plugins/interpreter/public/registries.karma_mock.ts index 66c51167c7b59..0f37f33cc1b13 100644 --- a/src/legacy/core_plugins/interpreter/public/registries.karma_mock.ts +++ b/src/legacy/core_plugins/interpreter/public/registries.karma_mock.ts @@ -26,6 +26,7 @@ export const registries = { browserFunctions: functionsRegistry, renderers: renderersRegistry, types: typesRegistry, + loadLegacyServerFunctionWrappers: () => Promise.resolve(), }; const resetRegistry = (registry: any) => { diff --git a/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.ts b/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.ts deleted file mode 100644 index 0088663080774..0000000000000 --- a/src/legacy/core_plugins/interpreter/server/lib/__tests__/create_handlers.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { createHandlers } from '../create_handlers'; - -const mockRequest = { - headers: 'i can haz headers', -}; - -const mockServer = { - plugins: { - elasticsearch: { - getCluster: () => ({ - callWithRequest: (...args: any) => Promise.resolve(args), - }), - }, - }, - config: () => ({ - has: () => false, - get: (val: any) => val, - }), - info: { - uri: 'serveruri', - }, -}; - -describe('server createHandlers', () => { - it('provides helper methods and properties', () => { - const handlers = createHandlers(mockRequest, mockServer); - - expect(handlers).to.have.property('environment', 'server'); - expect(handlers).to.have.property('serverUri'); - expect(handlers).to.have.property('elasticsearchClient'); - }); - - describe('elasticsearchClient', () => { - it('executes callWithRequest', async () => { - const handlers = createHandlers(mockRequest, mockServer); - const [request, endpoint, payload] = await handlers.elasticsearchClient( - 'endpoint', - 'payload' - ); - expect(request).to.equal(mockRequest); - expect(endpoint).to.equal('endpoint'); - expect(payload).to.equal('payload'); - }); - }); -}); diff --git a/src/legacy/core_plugins/interpreter/server/routes/server_functions.ts b/src/legacy/core_plugins/interpreter/server/routes/server_functions.ts deleted file mode 100644 index e03ad361b5555..0000000000000 --- a/src/legacy/core_plugins/interpreter/server/routes/server_functions.ts +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Boom from 'boom'; -import Joi from 'joi'; -import { serializeProvider } from '../../../../../plugins/expressions/common'; -import { createHandlers } from '../lib/create_handlers'; - -const API_ROUTE = '/api/interpreter'; - -/** - * Register the Canvas function endopints. - * - * @param {*} server - The Kibana server - */ -export function registerServerFunctions(server: any) { - getServerFunctions(server); - runServerFunctions(server); -} - -/** - * Register the endpoint that executes a batch of functions, and sends the result back as a single response. - * - * @param {*} server - The Kibana server - */ -function runServerFunctions(server: any) { - server.route({ - method: 'POST', - path: `${API_ROUTE}/fns`, - options: { - payload: { - allow: 'application/json', - maxBytes: 26214400, // 25MB payload limit - }, - validate: { - payload: Joi.object({ - functions: Joi.array() - .items( - Joi.object().keys({ - id: Joi.number().required(), - functionName: Joi.string().required(), - args: Joi.object().default({}), - context: Joi.any().default(null), - }) - ) - .required(), - }).required(), - }, - }, - async handler(req: any) { - const handlers = await createHandlers(req, server); - const { functions } = req.payload; - - // Grab the raw Node response object. - const res = req.raw.res; - - // Tell Hapi not to manage the response https://github.com/hapijs/hapi/issues/3884 - req._isReplied = true; - - // Send the initial headers. - res.writeHead(200, { - 'Content-Type': 'application/x-ndjson', - Connection: 'keep-alive', - 'Transfer-Encoding': 'chunked', - 'Cache-Control': 'no-cache', - }); - - // Write a length-delimited response - const streamResult = (result: any) => { - res.write(JSON.stringify(result) + '\n'); - }; - - // Tries to run an interpreter function, and ensures a consistent error payload on failure. - const tryFunction = async (id: any, fnCall: any) => { - try { - const result = await runFunction(server, handlers, fnCall); - - if (typeof result === 'undefined') { - return batchError(id, `Function ${fnCall.functionName} did not return anything.`); - } - - return { id, statusCode: 200, result }; - } catch (err) { - if (Boom.isBoom(err)) { - return batchError(id, err.output.payload, (err as any).statusCode); - } else if (err instanceof Error) { - return batchError(id, err.message); - } - - server.log(['interpreter', 'error'], err); - return batchError(id, 'See server logs for details.'); - } - }; - - // Process each function individually, and stream the responses back to the client - await Promise.all( - functions.map(({ id, ...fnCall }: any) => tryFunction(id, fnCall).then(streamResult)) - ); - - // All of the responses have been written, so we can close the response. - res.end(); - }, - }); -} - -/** - * A helper function for bundling up errors. - */ -function batchError(id: any, message: any, statusCode = 500) { - return { - id, - statusCode, - result: { statusCode, message }, - }; -} - -/** - * Register the endpoint that returns the list of server-only functions. - * @param {*} server - The Kibana server - */ -function getServerFunctions(server: any) { - server.route({ - method: 'GET', - path: `${API_ROUTE}/fns`, - handler() { - return server.plugins.interpreter.registries().serverFunctions.toJS(); - }, - }); -} - -/** - * Run a single Canvas function. - * - * @param {*} server - The Kibana server object - * @param {*} handlers - The Canvas handlers - * @param {*} fnCall - Describes the function being run `{ functionName, args, context }` - */ -async function runFunction(server: any, handlers: any, fnCall: any) { - const registries = server.plugins.interpreter.registries(); - const { functionName, args, context } = fnCall; - const types = registries.types.toJS(); - const { deserialize } = serializeProvider(types); - const fnDef = registries.serverFunctions.toJS()[functionName]; - - if (!fnDef) { - throw Boom.notFound(`Function "${functionName}" could not be found.`); - } - - return fnDef.fn(deserialize(context), args, handlers); -} diff --git a/src/plugins/bfetch/README.md b/src/plugins/bfetch/README.md index 9c18720e30d96..9ed90a4de306e 100644 --- a/src/plugins/bfetch/README.md +++ b/src/plugins/bfetch/README.md @@ -3,7 +3,54 @@ `bfetch` allows to batch HTTP requests and streams responses back. +# Example + +We will create a batch processing endpoint that receives a number then doubles it +and streams it back. We will also consider the number to be time in milliseconds +and before streaming the number back the server will wait for the specified number of +milliseconds. + +To do that, first create server-side batch processing route using [`addBatchProcessingRoute`](./docs/server/reference.md#addBatchProcessingRoute). + +```ts +plugins.bfetch.addBatchProcessingRoute<{ num: number }, { num: number }>( + '/my-plugin/double', + () => ({ + onBatchItem: async ({ num }) => { + // Validate inputs. + if (num < 0) throw new Error('Invalid number'); + // Wait number of specified milliseconds. + await new Promise(r => setTimeout(r, num)); + // Double the number and send it back. + return { num: 2 * num }; + }, + }) +); +``` + +Now on client-side create `double` function using [`batchedFunction`](./docs/browser/reference.md#batchedFunction). +The newly created `double` function can be called many times and it +will package individual calls into batches and send them to the server. + +```ts +const double = plugins.bfetch.batchedFunction<{ num: number }, { num: number }>({ + url: '/my-plugin/double', +}); +``` + +Note: the created `double` must accept a single object argument (`{ num: number }` in this case) +and it will return a promise that resolves into an object, too (also `{ num: number }` in this case). + +Use the `double` function. + +```ts +double({ num: 1 }).then(console.log, console.error); // { num: 2 } +double({ num: 2 }).then(console.log, console.error); // { num: 4 } +double({ num: 3 }).then(console.log, console.error); // { num: 6 } +``` + + ## Reference - [Browser](./docs/browser/reference.md) -- Server +- [Server](./docs/server/reference.md) diff --git a/src/plugins/bfetch/common/batch.ts b/src/plugins/bfetch/common/batch.ts new file mode 100644 index 0000000000000..6fd2c7e35ed91 --- /dev/null +++ b/src/plugins/bfetch/common/batch.ts @@ -0,0 +1,32 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export interface ErrorLike { + message: string; +} + +export interface BatchRequestData { + batch: Item[]; +} + +export interface BatchResponseItem { + id: number; + result?: Result; + error?: Error; +} diff --git a/src/plugins/bfetch/common/buffer/create_batched_function.ts b/src/plugins/bfetch/common/buffer/create_batched_function.ts new file mode 100644 index 0000000000000..24f28659863a7 --- /dev/null +++ b/src/plugins/bfetch/common/buffer/create_batched_function.ts @@ -0,0 +1,49 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ItemBufferParams } from './item_buffer'; +import { TimedItemBufferParams, TimedItemBuffer } from './timed_item_buffer'; + +type Fn = (...args: any) => any; + +export interface BatchedFunctionParams { + onCall: (...args: Parameters) => [ReturnType, BatchEntry]; + onBatch: (items: BatchEntry[]) => void; + flushOnMaxItems?: ItemBufferParams['flushOnMaxItems']; + maxItemAge?: TimedItemBufferParams['maxItemAge']; +} + +export const createBatchedFunction = ( + params: BatchedFunctionParams +): [Func, TimedItemBuffer] => { + const { onCall, onBatch, maxItemAge = 10, flushOnMaxItems = 25 } = params; + const buffer = new TimedItemBuffer({ + onFlush: onBatch, + maxItemAge, + flushOnMaxItems, + }); + + const fn: Func = ((...args) => { + const [result, batchEntry] = onCall(...args); + buffer.write(batchEntry); + return result; + }) as Func; + + return [fn, buffer]; +}; diff --git a/src/plugins/bfetch/common/buffer/index.ts b/src/plugins/bfetch/common/buffer/index.ts new file mode 100644 index 0000000000000..33bc52733289b --- /dev/null +++ b/src/plugins/bfetch/common/buffer/index.ts @@ -0,0 +1,22 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './item_buffer'; +export * from './timed_item_buffer'; +export * from './create_batched_function'; diff --git a/src/plugins/bfetch/common/buffer/item_buffer.ts b/src/plugins/bfetch/common/buffer/item_buffer.ts new file mode 100644 index 0000000000000..663aa5d7b0b7f --- /dev/null +++ b/src/plugins/bfetch/common/buffer/item_buffer.ts @@ -0,0 +1,81 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export interface ItemBufferParams { + /** + * Flushes buffer automatically if number of items in the buffer reaches + * this number. Omit it or set to `Infinity` to never flush on max buffer + * size automatically. + */ + flushOnMaxItems?: number; + + /** + * Callback that is called every time buffer is flushed. It receives a single + * argument which is a list of all buffered items. If `.flush()` is called + * when buffer is empty, `.onflush` is called with empty array. + */ + onFlush: (items: Item[]) => void; +} + +/** + * A simple buffer that collects items. Can be cleared or flushed; and can + * automatically flush when specified number of items is reached. + */ +export class ItemBuffer { + private list: Item[] = []; + + constructor(public readonly params: ItemBufferParams) {} + + /** + * Get current buffer size. + */ + public get length(): number { + return this.list.length; + } + + /** + * Add item to the buffer. + */ + public write(item: Item) { + this.list.push(item); + + const { flushOnMaxItems } = this.params; + if (flushOnMaxItems) { + if (this.list.length >= flushOnMaxItems) { + this.flush(); + } + } + } + + /** + * Remove all items from the buffer. + */ + public clear() { + this.list = []; + } + + /** + * Call `.onflush` method and clear buffer. + */ + public flush() { + let list; + [list, this.list] = [this.list, []]; + this.params.onFlush(list); + } +} diff --git a/src/plugins/bfetch/common/buffer/tests/create_batched_function.test.ts b/src/plugins/bfetch/common/buffer/tests/create_batched_function.test.ts new file mode 100644 index 0000000000000..5b145a2523070 --- /dev/null +++ b/src/plugins/bfetch/common/buffer/tests/create_batched_function.test.ts @@ -0,0 +1,75 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createBatchedFunction } from '../create_batched_function'; + +describe('createBatchedFunction', () => { + test('calls onCall every time fn is called, calls onBatch once flushOnMaxItems reached', async () => { + const onBatch = jest.fn(); + const onCall = jest.fn(() => [1, 2] as any); + const [fn] = createBatchedFunction({ + onBatch, + onCall, + flushOnMaxItems: 2, + maxItemAge: 10, + }); + + expect(onCall).toHaveBeenCalledTimes(0); + expect(onBatch).toHaveBeenCalledTimes(0); + + fn(123); + + expect(onCall).toHaveBeenCalledTimes(1); + expect(onCall).toHaveBeenCalledWith(123); + expect(onBatch).toHaveBeenCalledTimes(0); + + fn(456); + + expect(onCall).toHaveBeenCalledTimes(2); + expect(onCall).toHaveBeenCalledWith(456); + expect(onBatch).toHaveBeenCalledTimes(1); + expect(onBatch).toHaveBeenCalledWith([2, 2]); + }); + + test('calls onBatch once timeout is reached', async () => { + const onBatch = jest.fn(); + const onCall = jest.fn(() => [4, 3] as any); + const [fn] = createBatchedFunction({ + onBatch, + onCall, + flushOnMaxItems: 2, + maxItemAge: 10, + }); + + expect(onCall).toHaveBeenCalledTimes(0); + expect(onBatch).toHaveBeenCalledTimes(0); + + fn(123); + + expect(onCall).toHaveBeenCalledTimes(1); + expect(onCall).toHaveBeenCalledWith(123); + expect(onBatch).toHaveBeenCalledTimes(0); + + await new Promise(r => setTimeout(r, 15)); + + expect(onCall).toHaveBeenCalledTimes(1); + expect(onBatch).toHaveBeenCalledTimes(1); + expect(onBatch).toHaveBeenCalledWith([3]); + }); +}); diff --git a/src/plugins/bfetch/common/buffer/tests/item_buffer.test.ts b/src/plugins/bfetch/common/buffer/tests/item_buffer.test.ts new file mode 100644 index 0000000000000..a921fa8e589a3 --- /dev/null +++ b/src/plugins/bfetch/common/buffer/tests/item_buffer.test.ts @@ -0,0 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ItemBuffer } from '../item_buffer'; +import { runItemBufferTests } from './run_item_buffer_tests'; + +runItemBufferTests(ItemBuffer); diff --git a/src/plugins/bfetch/common/buffer/tests/run_item_buffer_tests.ts b/src/plugins/bfetch/common/buffer/tests/run_item_buffer_tests.ts new file mode 100644 index 0000000000000..b3ba9375448dc --- /dev/null +++ b/src/plugins/bfetch/common/buffer/tests/run_item_buffer_tests.ts @@ -0,0 +1,239 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ItemBuffer, ItemBufferParams } from '../item_buffer'; + +export const runItemBufferTests = ( + Buffer: new >(params: Params) => ItemBuffer +) => { + describe('ItemBuffer', () => { + test('can create with or without optional "flushOnMaxItems" param', () => { + new Buffer({ + onFlush: () => {}, + }); + + new Buffer({ + onFlush: () => {}, + flushOnMaxItems: 123, + }); + }); + + test('can add items to the buffer', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + buf.write('a'); + buf.write('b'); + buf.write('c'); + }); + + test('returns number of items in the buffer', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + expect(buf.length).toBe(0); + buf.write('a'); + expect(buf.length).toBe(1); + buf.write('b'); + expect(buf.length).toBe(2); + buf.write('c'); + expect(buf.length).toBe(3); + }); + + test('returns correct number of items after .clear() was called', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + expect(buf.length).toBe(0); + buf.write('a'); + expect(buf.length).toBe(1); + buf.clear(); + buf.write('b'); + expect(buf.length).toBe(1); + buf.write('c'); + expect(buf.length).toBe(2); + }); + + test('returns correct number of items after .flush() was called', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + expect(buf.length).toBe(0); + buf.write('a'); + expect(buf.length).toBe(1); + buf.flush(); + buf.write('b'); + expect(buf.length).toBe(1); + buf.write('c'); + expect(buf.length).toBe(2); + }); + + test('can flush buffer and receive items in chronological order', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + buf.write('a'); + buf.write('b'); + buf.write('c'); + + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(1); + expect(onFlush.mock.calls[0][0]).toEqual(['a', 'b', 'c']); + }); + + test('clears buffer after flush', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + buf.write('a'); + buf.write('b'); + buf.write('c'); + + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(1); + expect(onFlush.mock.calls[0][0]).toEqual(['a', 'b', 'c']); + + buf.write('d'); + + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(2); + expect(onFlush.mock.calls[1][0]).toEqual(['d']); + }); + + test('can call .flush() any time as many times as needed', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + buf.flush(); + buf.write(123); + buf.flush(); + buf.flush(); + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(4); + expect(onFlush.mock.calls[0][0]).toEqual([]); + expect(onFlush.mock.calls[1][0]).toEqual([123]); + expect(onFlush.mock.calls[2][0]).toEqual([]); + expect(onFlush.mock.calls[3][0]).toEqual([]); + }); + + test('calling .clear() before .flush() cases to return empty list', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + buf.write(1); + buf.write(2); + buf.clear(); + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(1); + expect(onFlush.mock.calls[0][0]).toEqual([]); + }); + + test('can call .clear() any time as many times as needed', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + }); + + buf.clear(); + buf.flush(); + buf.write(123); + buf.clear(); + buf.flush(); + buf.clear(); + buf.clear(); + buf.flush(); + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(4); + expect(onFlush.mock.calls[0][0]).toEqual([]); + expect(onFlush.mock.calls[1][0]).toEqual([]); + expect(onFlush.mock.calls[2][0]).toEqual([]); + expect(onFlush.mock.calls[3][0]).toEqual([]); + }); + + describe('when `flushOnMaxItems` is set', () => { + test('does not flush automatically before `flushOnMaxItems` is reached', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + flushOnMaxItems: 2, + }); + + buf.write(1); + + expect(onFlush).toHaveBeenCalledTimes(0); + }); + + test('automatically flushes buffer when `flushOnMaxItems` is reached', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + flushOnMaxItems: 2, + }); + + buf.write(1); + buf.write(2); + + expect(onFlush).toHaveBeenCalledTimes(1); + expect(onFlush.mock.calls[0][0]).toEqual([1, 2]); + }); + + test('flushes again when `flushOnMaxItems` limit is reached the second time', () => { + const onFlush = jest.fn(); + const buf = new Buffer({ + onFlush, + flushOnMaxItems: 2, + }); + + buf.write(1); + buf.write(2); + buf.write(3); + buf.write(4); + buf.write(5); + buf.flush(); + + expect(onFlush).toHaveBeenCalledTimes(3); + expect(onFlush.mock.calls[0][0]).toEqual([1, 2]); + expect(onFlush.mock.calls[1][0]).toEqual([3, 4]); + expect(onFlush.mock.calls[2][0]).toEqual([5]); + }); + }); + }); +}; diff --git a/src/plugins/bfetch/common/buffer/tests/timed_item_buffer.test.ts b/src/plugins/bfetch/common/buffer/tests/timed_item_buffer.test.ts new file mode 100644 index 0000000000000..c1c6a8f187a44 --- /dev/null +++ b/src/plugins/bfetch/common/buffer/tests/timed_item_buffer.test.ts @@ -0,0 +1,104 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { TimedItemBuffer } from '../timed_item_buffer'; +import { runItemBufferTests } from './run_item_buffer_tests'; + +describe('TimedItemBuffer', () => { + runItemBufferTests(TimedItemBuffer); + + test('does not do unnecessary flushes', async () => { + const onFlush = jest.fn(); + const buf = new TimedItemBuffer({ + onFlush, + maxItemAge: 3, + }); + + expect(onFlush).toHaveBeenCalledTimes(0); + buf.write(0); + expect(onFlush).toHaveBeenCalledTimes(0); + buf.flush(); + expect(onFlush).toHaveBeenCalledTimes(1); + }); + + test('does not do extra flush after timeout if buffer was flushed during timeout wait', async () => { + const onFlush = jest.fn(); + const buf = new TimedItemBuffer({ + onFlush, + maxItemAge: 10, + }); + + buf.write(0); + await new Promise(r => setTimeout(r, 3)); + buf.flush(); + await new Promise(r => setTimeout(r, 11)); + + expect(onFlush).toHaveBeenCalledTimes(1); + }); + + test('flushes buffer automatically after timeout reached', async () => { + const onFlush = jest.fn(); + const buf = new TimedItemBuffer({ + onFlush, + maxItemAge: 2, + }); + + buf.write(1); + buf.write(2); + expect(onFlush).toHaveBeenCalledTimes(0); + + await new Promise(r => setTimeout(r, 3)); + expect(onFlush).toHaveBeenCalledTimes(1); + expect(onFlush).toHaveBeenCalledWith([1, 2]); + }); + + test('does not call flush after timeout if flush was triggered because buffer size reached', async () => { + const onFlush = jest.fn(); + const buf = new TimedItemBuffer({ + onFlush, + flushOnMaxItems: 2, + maxItemAge: 2, + }); + + buf.write(1); + buf.write(2); + + expect(onFlush).toHaveBeenCalledTimes(1); + await new Promise(r => setTimeout(r, 3)); + expect(onFlush).toHaveBeenCalledTimes(1); + }); + + test('does not automatically flush if `.clear()` was called', async () => { + const onFlush = jest.fn(); + const buf = new TimedItemBuffer({ + onFlush, + flushOnMaxItems: 25, + maxItemAge: 5, + }); + + buf.write(1); + buf.write(2); + await new Promise(r => setImmediate(r)); + buf.clear(); + + expect(onFlush).toHaveBeenCalledTimes(0); + await new Promise(r => setTimeout(r, 6)); + expect(onFlush).toHaveBeenCalledTimes(0); + }); +}); diff --git a/src/plugins/bfetch/common/buffer/timed_item_buffer.ts b/src/plugins/bfetch/common/buffer/timed_item_buffer.ts new file mode 100644 index 0000000000000..8d0f9e4856f8c --- /dev/null +++ b/src/plugins/bfetch/common/buffer/timed_item_buffer.ts @@ -0,0 +1,58 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ItemBuffer, ItemBufferParams } from './item_buffer'; + +export interface TimedItemBufferParams extends ItemBufferParams { + /** + * Flushes buffer when oldest item reaches age specified by this parameter, + * in milliseconds. + */ + maxItemAge?: number; +} + +export class TimedItemBuffer extends ItemBuffer { + private timer: any; + + constructor(public readonly params: TimedItemBufferParams) { + super(params); + } + + public write(item: Item) { + super.write(item); + + if (this.params.maxItemAge && this.length === 1) { + this.timer = setTimeout(this.onTimeout, this.params.maxItemAge); + } + } + + public clear() { + clearTimeout(this.timer); + super.clear(); + } + + public flush() { + clearTimeout(this.timer); + super.flush(); + } + + private onTimeout = () => { + this.flush(); + }; +} diff --git a/src/plugins/bfetch/common/index.ts b/src/plugins/bfetch/common/index.ts index afa73ade80084..085b8e7c58a67 100644 --- a/src/plugins/bfetch/common/index.ts +++ b/src/plugins/bfetch/common/index.ts @@ -19,3 +19,5 @@ export * from './util'; export * from './streaming'; +export * from './buffer'; +export * from './batch'; diff --git a/src/plugins/bfetch/common/streaming/types.ts b/src/plugins/bfetch/common/streaming/types.ts index 1ee92edbc89ff..197ee9a52ff01 100644 --- a/src/plugins/bfetch/common/streaming/types.ts +++ b/src/plugins/bfetch/common/streaming/types.ts @@ -20,5 +20,5 @@ import { Observable } from 'rxjs'; export interface StreamingResponseHandler { - onRequest(payload: Payload): Observable; + getResponseStream(payload: Payload): Observable; } diff --git a/src/plugins/bfetch/common/util/index.ts b/src/plugins/bfetch/common/util/index.ts index 02843af9b4350..b5d1fcabbcd85 100644 --- a/src/plugins/bfetch/common/util/index.ts +++ b/src/plugins/bfetch/common/util/index.ts @@ -17,4 +17,5 @@ * under the License. */ +export * from './normalize_error'; export * from './remove_leading_slash'; diff --git a/src/legacy/core_plugins/interpreter/server/lib/create_handlers.ts b/src/plugins/bfetch/common/util/normalize_error.ts similarity index 62% rename from src/legacy/core_plugins/interpreter/server/lib/create_handlers.ts rename to src/plugins/bfetch/common/util/normalize_error.ts index 6e295d0aecaa5..c2ee3d83f5eb5 100644 --- a/src/legacy/core_plugins/interpreter/server/lib/create_handlers.ts +++ b/src/plugins/bfetch/common/util/normalize_error.ts @@ -17,16 +17,24 @@ * under the License. */ -export const createHandlers = (request: any, server: any) => { - const { callWithRequest } = server.plugins.elasticsearch.getCluster('data'); - const config = server.config(); +import { ErrorLike } from '../batch'; +export const normalizeError = (err: any): E => { + if (!err) { + return { + message: 'Unknown error.', + } as E; + } + if (err instanceof Error) { + return { message: err.message } as E; + } + if (typeof err === 'object') { + return { + ...err, + message: err.message || 'Unknown error.', + } as E; + } return { - environment: 'server', - serverUri: - config.has('server.rewriteBasePath') && config.get('server.rewriteBasePath') - ? `${server.info.uri}${config.get('server.basePath')}` - : server.info.uri, - elasticsearchClient: async (...args: any) => callWithRequest(request, ...args), - }; + message: String(err), + } as E; }; diff --git a/src/plugins/bfetch/docs/browser/reference.md b/src/plugins/bfetch/docs/browser/reference.md index 47a67c08a4c1f..444b1aa08a98e 100644 --- a/src/plugins/bfetch/docs/browser/reference.md +++ b/src/plugins/bfetch/docs/browser/reference.md @@ -1,8 +1,37 @@ # `bfetch` browser reference +- [`batchedFunction`](#batchedFunction) - [`fetchStreaming`](#fetchStreaming) +## `batchedFunction` + +Creates a function that will buffer its calls (until timeout—10ms default— or capacity reached—25 default) +and send all calls in one batch to the specified endpoint. The endpoint is expected +to stream results back in ND-JSON format using `Transfer-Encoding: chunked`, which is +implemented by `addBatchProcessingRoute` server-side method of `bfetch` plugin. + +The created function is expected to be called with a single object argument and will +return a promise that will resolve to an object. + +```ts +const fn = bfetch.batchedFunction({ url: '/my-plugin/something' }); + +const result = await fn({ foo: 'bar' }); +``` + +Options: + +- `url` — URL endpoint that will receive a batch of requests. This endpoint is expected + to receive batch as a serialized JSON array. It should stream responses back + in ND-JSON format using `Transfer-Encoding: chunked` HTTP/1 streaming. +- `fetchStreaming` — The instance of `fetchStreaming` function that will perform ND-JSON handling. + There should be a version of this function available in setup contract of `bfetch` plugin. +- `flushOnMaxItems` — The maximum size of function call buffer before sending the batch request. +- `maxItemAge` — The maximum timeout in milliseconds of the oldest item in the batch + before sending the batch request. + + ## `fetchStreaming` Executes an HTTP request and expects that server streams back results using @@ -12,4 +41,4 @@ HTTP/1 `Transfer-Encoding: chunked`. const { stream } = bfetch.fetchStreaming({ url: 'http://elastic.co' }); stream.subscribe(value => {}); -``` \ No newline at end of file +``` diff --git a/src/plugins/bfetch/docs/server/reference.md b/src/plugins/bfetch/docs/server/reference.md new file mode 100644 index 0000000000000..424532a50b817 --- /dev/null +++ b/src/plugins/bfetch/docs/server/reference.md @@ -0,0 +1,54 @@ +# `bfetch` server reference + +- [`addBatchProcessingRoute`](#addBatchProcessingRoute) +- [`addStreamingResponseRoute`](#addStreamingResponseRoute) + + +## `addBatchProcessingRoute` + +Sets up a server endpoint that expects to work with [`batchedFunction`](../browser/reference.md#batchedFunction). +The endpoint receives a batch of requests, processes each request and streams results +back immediately as they become available. You only need to implement the +processing of each request (`onBatchItem` function), everything else is handled. + +`onBatchItem` function is called for each individual request in the batch. +`onBatchItem` function receives a single object argument which is the payload +of one request; and it must return a promise that resolves to an object, too. +`onBatchItem` function is allowed to throw, in that case the error will be forwarded +to the browser only to the individual request, the rest of the batch will still continue +executing. + +```ts +plugins.bfetch.addBatchProcessingRoute( + '/my-plugin/double', + request => ({ + onBatchItem: async (payload) => { + // ... + return {}; + }, + }) +); +``` + +`request` is the `KibanaRequest` object. `addBatchProcessingRoute` together with `batchedFunction` +ensure that errors are handled and that all items in the batch get executed. + + +## `addStreamingResponseRoute` + +`addStreamingResponseRoute` is a lower-level interface that receives and `payload` +message returns and observable which results are streamed back as ND-JSON messages +until the observable completes. `addStreamingResponseRoute` does not know about the +type of the messages, it does not handle errors, and it does not have a concept of +batch size—observable can stream any number of messages until it completes. + +```ts +plugins.bfetch.addStreamingResponseRoute('/my-plugin/foo', request => ({ + getResponseStream: (payload) => { + const subject = new Subject(); + setTimeout(() => { subject.next('123'); }, 100); + setTimeout(() => { subject.complete(); }, 200); + return subject; + }, +})); +``` diff --git a/src/plugins/bfetch/public/batching/create_streaming_batched_function.test.ts b/src/plugins/bfetch/public/batching/create_streaming_batched_function.test.ts new file mode 100644 index 0000000000000..064b791327e69 --- /dev/null +++ b/src/plugins/bfetch/public/batching/create_streaming_batched_function.test.ts @@ -0,0 +1,521 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createStreamingBatchedFunction } from './create_streaming_batched_function'; +import { fetchStreaming as fetchStreamingReal } from '../streaming/fetch_streaming'; +import { defer, of } from '../../../kibana_utils/public'; +import { Subject } from 'rxjs'; + +const getPromiseState = (promise: Promise): Promise<'resolved' | 'rejected' | 'pending'> => + Promise.race<'resolved' | 'rejected' | 'pending'>([ + new Promise(resolve => + promise.then( + () => resolve('resolved'), + () => resolve('rejected') + ) + ), + new Promise<'pending'>(resolve => resolve()).then(() => 'pending'), + ]); + +const isPending = (promise: Promise): Promise => + getPromiseState(promise).then(state => state === 'pending'); + +const setup = () => { + const xhr = ({} as unknown) as XMLHttpRequest; + const { promise, resolve, reject } = defer(); + const stream = new Subject(); + + const fetchStreaming = (jest.fn(() => ({ + xhr, + promise, + stream, + })) as unknown) as jest.SpyInstance & typeof fetchStreamingReal; + + return { + fetchStreaming, + xhr, + promise, + resolve, + reject, + stream, + }; +}; + +describe('createStreamingBatchedFunction()', () => { + test('returns a function', () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + }); + expect(typeof fn).toBe('function'); + }); + + test('returned function is async', () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + }); + const res = fn({}); + expect(typeof res.then).toBe('function'); + }); + + describe('when timeout is reached', () => { + test('dispatches batch', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + expect(fetchStreaming).toHaveBeenCalledTimes(0); + fn({ foo: 'bar' }); + expect(fetchStreaming).toHaveBeenCalledTimes(0); + fn({ baz: 'quix' }); + expect(fetchStreaming).toHaveBeenCalledTimes(0); + + await new Promise(r => setTimeout(r, 6)); + expect(fetchStreaming).toHaveBeenCalledTimes(1); + }); + + test('does nothing is buffer is empty', async () => { + const { fetchStreaming } = setup(); + createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + expect(fetchStreaming).toHaveBeenCalledTimes(0); + await new Promise(r => setTimeout(r, 6)); + expect(fetchStreaming).toHaveBeenCalledTimes(0); + }); + + test('sends POST request to correct endpoint', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + fn({ foo: 'bar' }); + await new Promise(r => setTimeout(r, 6)); + + expect(fetchStreaming.mock.calls[0][0]).toMatchObject({ + url: '/test', + method: 'POST', + }); + }); + + test('collects calls into an array batch ordered by in same order as calls', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + fn({ foo: 'bar' }); + fn({ baz: 'quix' }); + + await new Promise(r => setTimeout(r, 6)); + const { body } = fetchStreaming.mock.calls[0][0]; + expect(JSON.parse(body)).toEqual({ + batch: [{ foo: 'bar' }, { baz: 'quix' }], + }); + }); + }); + + describe('when buffer becomes full', () => { + test('dispatches batch request', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + expect(fetchStreaming).toHaveBeenCalledTimes(0); + fn({ foo: 'bar' }); + expect(fetchStreaming).toHaveBeenCalledTimes(0); + fn({ baz: 'quix' }); + expect(fetchStreaming).toHaveBeenCalledTimes(0); + fn({ full: 'yep' }); + expect(fetchStreaming).toHaveBeenCalledTimes(1); + }); + + test('sends POST request to correct endpoint with items in array batched sorted in call order', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + fn({ a: '1' }); + fn({ b: '2' }); + fn({ c: '3' }); + + expect(fetchStreaming.mock.calls[0][0]).toMatchObject({ + url: '/test', + method: 'POST', + }); + const { body } = fetchStreaming.mock.calls[0][0]; + expect(JSON.parse(body)).toEqual({ + batch: [{ a: '1' }, { b: '2' }, { c: '3' }], + }); + }); + + test('dispatches batch on full buffer and also on timeout', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + fn({ a: '1' }); + fn({ b: '2' }); + fn({ c: '3' }); + expect(fetchStreaming).toHaveBeenCalledTimes(1); + fn({ d: '4' }); + await new Promise(r => setTimeout(r, 6)); + expect(fetchStreaming).toHaveBeenCalledTimes(2); + }); + }); + + describe('when receiving results', () => { + test('does not resolve call promises until request finishes', async () => { + const { fetchStreaming } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = fn({ a: '1' }); + const promise2 = fn({ b: '2' }); + await new Promise(r => setTimeout(r, 6)); + + expect(await isPending(promise1)).toBe(true); + expect(await isPending(promise2)).toBe(true); + }); + + test('resolves only promise of result that was streamed back', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = fn({ a: '1' }); + const promise2 = fn({ b: '2' }); + const promise3 = fn({ c: '3' }); + await new Promise(r => setTimeout(r, 6)); + + expect(await isPending(promise1)).toBe(true); + expect(await isPending(promise2)).toBe(true); + expect(await isPending(promise3)).toBe(true); + + stream.next( + JSON.stringify({ + id: 1, + result: { foo: 'bar' }, + }) + '\n' + ); + + expect(await isPending(promise1)).toBe(true); + expect(await isPending(promise2)).toBe(false); + expect(await isPending(promise3)).toBe(true); + + stream.next( + JSON.stringify({ + id: 0, + result: { foo: 'bar 2' }, + }) + '\n' + ); + + expect(await isPending(promise1)).toBe(false); + expect(await isPending(promise2)).toBe(false); + expect(await isPending(promise3)).toBe(true); + }); + + test('resolves each promise with correct data', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = fn({ a: '1' }); + const promise2 = fn({ b: '2' }); + const promise3 = fn({ c: '3' }); + await new Promise(r => setTimeout(r, 6)); + + stream.next( + JSON.stringify({ + id: 1, + result: { foo: 'bar' }, + }) + '\n' + ); + stream.next( + JSON.stringify({ + id: 2, + result: { foo: 'bar 2' }, + }) + '\n' + ); + + expect(await isPending(promise1)).toBe(true); + expect(await isPending(promise2)).toBe(false); + expect(await isPending(promise3)).toBe(false); + expect(await promise2).toEqual({ foo: 'bar' }); + expect(await promise3).toEqual({ foo: 'bar 2' }); + }); + + test('rejects promise on error response', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise = fn({ a: '1' }); + await new Promise(r => setTimeout(r, 6)); + + expect(await isPending(promise)).toBe(true); + + stream.next( + JSON.stringify({ + id: 0, + error: { message: 'oops' }, + }) + '\n' + ); + + expect(await isPending(promise)).toBe(false); + const [, error] = await of(promise); + expect(error).toEqual({ + message: 'oops', + }); + }); + + test('resolves successful requests even after rejected ones', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = of(fn({ a: '1' })); + const promise2 = of(fn({ a: '2' })); + const promise3 = of(fn({ a: '3' })); + + await new Promise(r => setTimeout(r, 6)); + + stream.next( + JSON.stringify({ + id: 2, + result: { b: '3' }, + }) + '\n' + ); + + await new Promise(r => setTimeout(r, 1)); + + stream.next( + JSON.stringify({ + id: 1, + error: { b: '2' }, + }) + '\n' + ); + + await new Promise(r => setTimeout(r, 1)); + + stream.next( + JSON.stringify({ + id: 0, + result: { b: '1' }, + }) + '\n' + ); + + await new Promise(r => setTimeout(r, 1)); + + const [result1] = await promise1; + const [, error2] = await promise2; + const [result3] = await promise3; + + expect(result1).toEqual({ b: '1' }); + expect(error2).toEqual({ b: '2' }); + expect(result3).toEqual({ b: '3' }); + }); + + describe('when stream closes prematurely', () => { + test('rejects pending promises with CONNECTION error code', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = of(fn({ a: '1' })); + const promise2 = of(fn({ a: '2' })); + + await new Promise(r => setTimeout(r, 6)); + + stream.complete(); + + await new Promise(r => setTimeout(r, 1)); + + const [, error1] = await promise1; + const [, error2] = await promise2; + expect(error1).toMatchObject({ + message: 'Connection terminated prematurely.', + code: 'CONNECTION', + }); + expect(error2).toMatchObject({ + message: 'Connection terminated prematurely.', + code: 'CONNECTION', + }); + }); + + test('rejects with CONNECTION error only pending promises', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = of(fn({ a: '1' })); + const promise2 = of(fn({ a: '2' })); + + await new Promise(r => setTimeout(r, 6)); + + stream.next( + JSON.stringify({ + id: 1, + result: { b: '1' }, + }) + '\n' + ); + stream.complete(); + + await new Promise(r => setTimeout(r, 1)); + + const [, error1] = await promise1; + const [result1] = await promise2; + expect(error1).toMatchObject({ + message: 'Connection terminated prematurely.', + code: 'CONNECTION', + }); + expect(result1).toMatchObject({ + b: '1', + }); + }); + }); + + describe('when stream errors', () => { + test('rejects pending promises with STREAM error code', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = of(fn({ a: '1' })); + const promise2 = of(fn({ a: '2' })); + + await new Promise(r => setTimeout(r, 6)); + + stream.error({ + message: 'something went wrong', + }); + + await new Promise(r => setTimeout(r, 1)); + + const [, error1] = await promise1; + const [, error2] = await promise2; + expect(error1).toMatchObject({ + message: 'something went wrong', + code: 'STREAM', + }); + expect(error2).toMatchObject({ + message: 'something went wrong', + code: 'STREAM', + }); + }); + + test('rejects with STREAM error only pending promises', async () => { + const { fetchStreaming, stream } = setup(); + const fn = createStreamingBatchedFunction({ + url: '/test', + fetchStreaming, + maxItemAge: 5, + flushOnMaxItems: 3, + }); + + const promise1 = of(fn({ a: '1' })); + const promise2 = of(fn({ a: '2' })); + + await new Promise(r => setTimeout(r, 6)); + + stream.next( + JSON.stringify({ + id: 1, + result: { b: '1' }, + }) + '\n' + ); + stream.error('oops'); + + await new Promise(r => setTimeout(r, 1)); + + const [, error1] = await promise1; + const [result1] = await promise2; + expect(error1).toMatchObject({ + message: 'oops', + code: 'STREAM', + }); + expect(result1).toMatchObject({ + b: '1', + }); + }); + }); + }); +}); diff --git a/src/plugins/bfetch/public/batching/create_streaming_batched_function.ts b/src/plugins/bfetch/public/batching/create_streaming_batched_function.ts new file mode 100644 index 0000000000000..07d5724a2520d --- /dev/null +++ b/src/plugins/bfetch/public/batching/create_streaming_batched_function.ts @@ -0,0 +1,140 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { defer, Defer } from '../../../kibana_utils/public'; +import { + ItemBufferParams, + TimedItemBufferParams, + createBatchedFunction, + BatchResponseItem, + ErrorLike, +} from '../../common'; +import { fetchStreaming, split } from '../streaming'; +import { normalizeError } from '../../common'; + +export interface BatchItem { + payload: Payload; + future: Defer; +} + +export type BatchedFunc = (payload: Payload) => Promise; + +export interface BatchedFunctionProtocolError extends ErrorLike { + code: string; +} + +export interface StreamingBatchedFunctionParams { + /** + * URL endpoint that will receive a batch of requests. This endpoint is expected + * to receive batch as a serialized JSON array. It should stream responses back + * in ND-JSON format using `Transfer-Encoding: chunked` HTTP/1 streaming. + */ + url: string; + + /** + * The instance of `fetchStreaming` function that will perform ND-JSON handling. + * There should be a version of this function available in setup contract of `bfetch` + * plugin. + */ + fetchStreaming?: typeof fetchStreaming; + + /** + * The maximum size of function call buffer before sending the batch request. + */ + flushOnMaxItems?: ItemBufferParams['flushOnMaxItems']; + + /** + * The maximum timeout in milliseconds of the oldest item in the batch + * before sending the batch request. + */ + maxItemAge?: TimedItemBufferParams['maxItemAge']; +} + +/** + * Returns a function that does not execute immediately but buffers the call internally until + * `params.flushOnMaxItems` is reached or after `params.maxItemAge` timeout in milliseconds is reached. Once + * one of those thresholds is reached all buffered calls are sent in one batch to the + * server using `params.fetchStreaming` in a POST request. Responses are streamed back + * and each batch item is resolved once corresponding response is received. + */ +export const createStreamingBatchedFunction = ( + params: StreamingBatchedFunctionParams +): BatchedFunc => { + const { + url, + fetchStreaming: fetchStreamingInjected = fetchStreaming, + flushOnMaxItems = 25, + maxItemAge = 10, + } = params; + const [fn] = createBatchedFunction, BatchItem>({ + onCall: (payload: Payload) => { + const future = defer(); + const entry: BatchItem = { + payload, + future, + }; + return [future.promise, entry]; + }, + onBatch: async items => { + try { + let responsesReceived = 0; + const batch = items.map(({ payload }) => payload); + const { stream } = fetchStreamingInjected({ + url, + body: JSON.stringify({ batch }), + method: 'POST', + }); + stream.pipe(split('\n')).subscribe({ + next: (json: string) => { + const response = JSON.parse(json) as BatchResponseItem; + if (response.error) { + responsesReceived++; + items[response.id].future.reject(response.error); + } else if (response.result) { + responsesReceived++; + items[response.id].future.resolve(response.result); + } + }, + error: error => { + const normalizedError = normalizeError(error); + normalizedError.code = 'STREAM'; + for (const { future } of items) future.reject(normalizedError); + }, + complete: () => { + const streamTerminatedPrematurely = responsesReceived !== items.length; + if (streamTerminatedPrematurely) { + const error: BatchedFunctionProtocolError = { + message: 'Connection terminated prematurely.', + code: 'CONNECTION', + }; + for (const { future } of items) future.reject(error); + } + }, + }); + await stream.toPromise(); + } catch (error) { + for (const item of items) item.future.reject(error); + } + }, + flushOnMaxItems, + maxItemAge, + }); + + return fn; +}; diff --git a/src/plugins/bfetch/public/index.ts b/src/plugins/bfetch/public/index.ts index a57dd77fe7e67..8707e5a438159 100644 --- a/src/plugins/bfetch/public/index.ts +++ b/src/plugins/bfetch/public/index.ts @@ -20,7 +20,8 @@ import { PluginInitializerContext } from '../../../core/public'; import { BfetchPublicPlugin } from './plugin'; -export { BfetchPublicSetup, BfetchPublicStart, BfetchPublicApi } from './plugin'; +export { BfetchPublicSetup, BfetchPublicStart, BfetchPublicContract } from './plugin'; +export { split } from './streaming'; export function plugin(initializerContext: PluginInitializerContext) { return new BfetchPublicPlugin(initializerContext); diff --git a/src/plugins/bfetch/public/mocks.ts b/src/plugins/bfetch/public/mocks.ts index e8caf5c9cb739..f457b9ae5d671 100644 --- a/src/plugins/bfetch/public/mocks.ts +++ b/src/plugins/bfetch/public/mocks.ts @@ -27,6 +27,7 @@ export type Start = jest.Mocked; const createSetupContract = (): Setup => { const setupContract: Setup = { fetchStreaming: jest.fn(), + batchedFunction: jest.fn(), }; return setupContract; }; @@ -34,6 +35,7 @@ const createSetupContract = (): Setup => { const createStartContract = (): Start => { const startContract: Start = { fetchStreaming: jest.fn(), + batchedFunction: jest.fn(), }; return startContract; @@ -56,7 +58,7 @@ const createPlugin = async () => { }; }; -export const uiActionsPluginMock = { +export const bfetchPluginMock = { createSetupContract, createStartContract, createPlugin, diff --git a/src/plugins/bfetch/public/plugin.ts b/src/plugins/bfetch/public/plugin.ts index db18a15afa1e7..783c448c567e5 100644 --- a/src/plugins/bfetch/public/plugin.ts +++ b/src/plugins/bfetch/public/plugin.ts @@ -20,6 +20,11 @@ import { CoreStart, PluginInitializerContext, CoreSetup, Plugin } from 'src/core/public'; import { fetchStreaming as fetchStreamingStatic, FetchStreamingParams } from './streaming'; import { removeLeadingSlash } from '../common'; +import { + createStreamingBatchedFunction, + BatchedFunc, + StreamingBatchedFunctionParams, +} from './batching/create_streaming_batched_function'; // eslint-disable-next-line export interface BfetchPublicSetupDependencies {} @@ -27,12 +32,15 @@ export interface BfetchPublicSetupDependencies {} // eslint-disable-next-line export interface BfetchPublicStartDependencies {} -export interface BfetchPublicApi { +export interface BfetchPublicContract { fetchStreaming: (params: FetchStreamingParams) => ReturnType; + batchedFunction: ( + params: StreamingBatchedFunctionParams + ) => BatchedFunc; } -export type BfetchPublicSetup = BfetchPublicApi; -export type BfetchPublicStart = BfetchPublicApi; +export type BfetchPublicSetup = BfetchPublicContract; +export type BfetchPublicStart = BfetchPublicContract; export class BfetchPublicPlugin implements @@ -42,7 +50,7 @@ export class BfetchPublicPlugin BfetchPublicSetupDependencies, BfetchPublicStartDependencies > { - private api!: BfetchPublicApi; + private contract!: BfetchPublicContract; constructor(private readonly initializerContext: PluginInitializerContext) {} @@ -51,16 +59,18 @@ export class BfetchPublicPlugin const basePath = core.http.basePath.get(); const fetchStreaming = this.fetchStreaming(version, basePath); + const batchedFunction = this.batchedFunction(fetchStreaming); - this.api = { + this.contract = { fetchStreaming, + batchedFunction, }; - return this.api; + return this.contract; } public start(core: CoreStart, plugins: BfetchPublicStartDependencies): BfetchPublicStart { - return this.api; + return this.contract; } public stop() {} @@ -78,4 +88,12 @@ export class BfetchPublicPlugin ...(params.headers || {}), }, }); + + private batchedFunction = ( + fetchStreaming: BfetchPublicContract['fetchStreaming'] + ): BfetchPublicContract['batchedFunction'] => params => + createStreamingBatchedFunction({ + ...params, + fetchStreaming: params.fetchStreaming || fetchStreaming, + }); } diff --git a/src/plugins/bfetch/public/streaming/fetch_streaming.test.ts b/src/plugins/bfetch/public/streaming/fetch_streaming.test.ts index e59af71cb76bc..7845616026ea1 100644 --- a/src/plugins/bfetch/public/streaming/fetch_streaming.test.ts +++ b/src/plugins/bfetch/public/streaming/fetch_streaming.test.ts @@ -36,14 +36,6 @@ test('returns XHR request', () => { expect(typeof xhr.readyState).toBe('number'); }); -test('returns promise', () => { - setup(); - const { promise } = fetchStreaming({ - url: 'http://example.com', - }); - expect(typeof promise.then).toBe('function'); -}); - test('returns stream', () => { setup(); const { stream } = fetchStreaming({ @@ -54,12 +46,12 @@ test('returns stream', () => { test('promise resolves when request completes', async () => { const env = setup(); - const { promise } = fetchStreaming({ + const { stream } = fetchStreaming({ url: 'http://example.com', }); let resolved = false; - promise.then(() => (resolved = true)); + stream.toPromise().then(() => (resolved = true)); await tick(); expect(resolved).toBe(false); @@ -142,12 +134,12 @@ test('completes stream observable when request finishes', async () => { test('promise throws when request errors', async () => { const env = setup(); - const { promise } = fetchStreaming({ + const { stream } = fetchStreaming({ url: 'http://example.com', }); const spy = jest.fn(); - promise.catch(spy); + stream.toPromise().catch(spy); await tick(); expect(spy).toHaveBeenCalledTimes(0); @@ -168,12 +160,11 @@ test('promise throws when request errors', async () => { test('stream observable errors when request errors', async () => { const env = setup(); - const { promise, stream } = fetchStreaming({ + const { stream } = fetchStreaming({ url: 'http://example.com', }); const spy = jest.fn(); - promise.catch(() => {}); stream.subscribe({ error: spy, }); diff --git a/src/plugins/bfetch/public/streaming/fetch_streaming.ts b/src/plugins/bfetch/public/streaming/fetch_streaming.ts index 44a3693e7010b..899e8a1824a41 100644 --- a/src/plugins/bfetch/public/streaming/fetch_streaming.ts +++ b/src/plugins/bfetch/public/streaming/fetch_streaming.ts @@ -17,7 +17,6 @@ * under the License. */ -import { defer } from '../../../kibana_utils/common'; import { fromStreamingXhr } from './from_streaming_xhr'; export interface FetchStreamingParams { @@ -38,7 +37,6 @@ export function fetchStreaming({ body = '', }: FetchStreamingParams) { const xhr = new window.XMLHttpRequest(); - const { promise, resolve, reject } = defer(); // Begin the request xhr.open(method, url); @@ -49,17 +47,11 @@ export function fetchStreaming({ const stream = fromStreamingXhr(xhr); - stream.subscribe({ - complete: () => resolve(), - error: error => reject(error), - }); - // Send the payload to the server xhr.send(body); return { xhr, - promise, stream, }; } diff --git a/src/plugins/bfetch/server/index.ts b/src/plugins/bfetch/server/index.ts index f1a3f7fd44cf6..06b7c793c537e 100644 --- a/src/plugins/bfetch/server/index.ts +++ b/src/plugins/bfetch/server/index.ts @@ -20,7 +20,7 @@ import { PluginInitializerContext } from '../../../core/server'; import { BfetchServerPlugin } from './plugin'; -export { BfetchServerSetup, BfetchServerStart } from './plugin'; +export { BfetchServerSetup, BfetchServerStart, BatchProcessingRouteParams } from './plugin'; export function plugin(initializerContext: PluginInitializerContext) { return new BfetchServerPlugin(initializerContext); diff --git a/src/plugins/bfetch/server/mocks.ts b/src/plugins/bfetch/server/mocks.ts index 8ec68650a60dc..e0a76ba8da325 100644 --- a/src/plugins/bfetch/server/mocks.ts +++ b/src/plugins/bfetch/server/mocks.ts @@ -26,6 +26,7 @@ export type Start = jest.Mocked; const createSetupContract = (): Setup => { const setupContract: Setup = { + addBatchProcessingRoute: jest.fn(), addStreamingResponseRoute: jest.fn(), }; return setupContract; @@ -54,7 +55,7 @@ const createPlugin = async () => { }; }; -export const uiActionsPluginMock = { +export const bfetchPluginMock = { createSetupContract, createStartContract, createPlugin, diff --git a/src/plugins/bfetch/server/plugin.ts b/src/plugins/bfetch/server/plugin.ts index 75baeafc17669..fd1fe009e93ae 100644 --- a/src/plugins/bfetch/server/plugin.ts +++ b/src/plugins/bfetch/server/plugin.ts @@ -17,9 +17,24 @@ * under the License. */ -import { CoreStart, PluginInitializerContext, CoreSetup, Plugin, Logger } from 'src/core/server'; +import { + CoreStart, + PluginInitializerContext, + CoreSetup, + Plugin, + Logger, + KibanaRequest, +} from 'src/core/server'; import { schema } from '@kbn/config-schema'; -import { StreamingResponseHandler, removeLeadingSlash } from '../common'; +import { Subject } from 'rxjs'; +import { + StreamingResponseHandler, + BatchRequestData, + BatchResponseItem, + ErrorLike, + removeLeadingSlash, + normalizeError, +} from '../common'; import { createNDJSONStream } from './streaming'; // eslint-disable-next-line @@ -28,8 +43,19 @@ export interface BfetchServerSetupDependencies {} // eslint-disable-next-line export interface BfetchServerStartDependencies {} +export interface BatchProcessingRouteParams { + onBatchItem: (data: BatchItemData) => Promise; +} + export interface BfetchServerSetup { - addStreamingResponseRoute: (path: string, handler: StreamingResponseHandler) => void; + addBatchProcessingRoute: ( + path: string, + handler: (request: KibanaRequest) => BatchProcessingRouteParams + ) => void; + addStreamingResponseRoute: ( + path: string, + params: (request: KibanaRequest) => StreamingResponseHandler + ) => void; } // eslint-disable-next-line @@ -49,8 +75,10 @@ export class BfetchServerPlugin const logger = this.initializerContext.logger.get(); const router = core.http.createRouter(); const addStreamingResponseRoute = this.addStreamingResponseRoute({ router, logger }); + const addBatchProcessingRoute = this.addBatchProcessingRoute(addStreamingResponseRoute); return { + addBatchProcessingRoute, addStreamingResponseRoute, }; } @@ -76,17 +104,56 @@ export class BfetchServerPlugin }, }, async (context, request, response) => { + const handlerInstance = handler(request); const data = request.body; + const headers = { + 'Content-Type': 'application/x-ndjson', + Connection: 'keep-alive', + 'Transfer-Encoding': 'chunked', + 'Cache-Control': 'no-cache', + }; return response.ok({ - headers: { - 'Content-Type': 'application/x-ndjson', - Connection: 'keep-alive', - 'Transfer-Encoding': 'chunked', - 'Cache-Control': 'no-cache', - }, - body: createNDJSONStream(data, handler, logger), + headers, + body: createNDJSONStream(data, handlerInstance, logger), }); } ); }; + + private addBatchProcessingRoute = ( + addStreamingResponseRoute: BfetchServerSetup['addStreamingResponseRoute'] + ): BfetchServerSetup['addBatchProcessingRoute'] => < + BatchItemData extends object, + BatchItemResult extends object, + E extends ErrorLike = ErrorLike + >( + path: string, + handler: (request: KibanaRequest) => BatchProcessingRouteParams + ) => { + addStreamingResponseRoute< + BatchRequestData, + BatchResponseItem + >(path, request => { + const handlerInstance = handler(request); + return { + getResponseStream: ({ batch }) => { + const subject = new Subject>(); + let cnt = batch.length; + batch.forEach(async (batchItem, id) => { + try { + const result = await handlerInstance.onBatchItem(batchItem); + subject.next({ id, result }); + } catch (err) { + const error = normalizeError(err); + subject.next({ id, error }); + } finally { + cnt--; + if (!cnt) subject.complete(); + } + }); + return subject; + }, + }; + }); + }; } diff --git a/src/plugins/bfetch/server/streaming/create_ndjson_stream.ts b/src/plugins/bfetch/server/streaming/create_ndjson_stream.ts index b1f39f4acbcb5..82fe31906e8bf 100644 --- a/src/plugins/bfetch/server/streaming/create_ndjson_stream.ts +++ b/src/plugins/bfetch/server/streaming/create_ndjson_stream.ts @@ -29,7 +29,7 @@ export const createNDJSONStream = ( logger: Logger ): Stream => { const stream = new PassThrough(); - const results = handler.onRequest(payload); + const results = handler.getResponseStream(payload); results.subscribe({ next: (message: Response) => { diff --git a/src/plugins/expressions/common/type.ts b/src/plugins/expressions/common/type.ts index de9c43d01a0aa..c9daed9b6785a 100644 --- a/src/plugins/expressions/common/type.ts +++ b/src/plugins/expressions/common/type.ts @@ -30,11 +30,6 @@ export function getType(node: any) { } export function serializeProvider(types: any) { - return { - serialize: provider('serialize'), - deserialize: provider('deserialize'), - }; - function provider(key: any) { return (context: any) => { const type = getType(context); @@ -43,6 +38,11 @@ export function serializeProvider(types: any) { return fn(context); }; } + + return { + serialize: provider('serialize'), + deserialize: provider('deserialize'), + }; } export class Type { diff --git a/src/plugins/expressions/kibana.json b/src/plugins/expressions/kibana.json index ec87b56f3745e..cba693dd4bc20 100644 --- a/src/plugins/expressions/kibana.json +++ b/src/plugins/expressions/kibana.json @@ -1,9 +1,10 @@ { "id": "expressions", "version": "kibana", - "server": false, + "server": true, "ui": true, "requiredPlugins": [ + "bfetch", "inspector" ] } diff --git a/src/legacy/core_plugins/interpreter/public/canvas/batched_fetch.test.ts b/src/plugins/expressions/public/batched_fetch.test.ts similarity index 97% rename from src/legacy/core_plugins/interpreter/public/canvas/batched_fetch.test.ts rename to src/plugins/expressions/public/batched_fetch.test.ts index 3da15cf54cda0..7273be872a725 100644 --- a/src/legacy/core_plugins/interpreter/public/canvas/batched_fetch.test.ts +++ b/src/plugins/expressions/public/batched_fetch.test.ts @@ -18,7 +18,7 @@ */ import { batchedFetch, Request } from './batched_fetch'; -import { defer } from '../../../../../plugins/kibana_utils/public'; +import { defer } from '../../kibana_utils/public'; import { Subject } from 'rxjs'; const serialize = (o: any) => JSON.stringify(o); diff --git a/src/legacy/core_plugins/interpreter/public/canvas/batched_fetch.ts b/src/plugins/expressions/public/batched_fetch.ts similarity index 87% rename from src/legacy/core_plugins/interpreter/public/canvas/batched_fetch.ts rename to src/plugins/expressions/public/batched_fetch.ts index 717a87fc90f9f..6a155b7d42b72 100644 --- a/src/legacy/core_plugins/interpreter/public/canvas/batched_fetch.ts +++ b/src/plugins/expressions/public/batched_fetch.ts @@ -20,13 +20,11 @@ import _ from 'lodash'; import { filter, map } from 'rxjs/operators'; // eslint-disable-next-line -import { split } from '../../../../../plugins/bfetch/public/streaming'; -import { BfetchPublicApi } from '../../../../../plugins/bfetch/public'; -import { defer } from '../../../../../plugins/kibana_utils/public'; -import { FUNCTIONS_URL } from './consts'; +import { split, BfetchPublicContract } from '../../bfetch/public'; +import { defer } from '../../kibana_utils/public'; export interface Options { - fetchStreaming: BfetchPublicApi['fetchStreaming']; + fetchStreaming: BfetchPublicContract['fetchStreaming']; serialize: any; ms?: number; } @@ -111,9 +109,9 @@ export function batchedFetch({ fetchStreaming, serialize, ms = 10 }: Options) { * Runs the specified batch of functions on the server, then resolves * the related promises. */ -async function processBatch(fetchStreaming: BfetchPublicApi['fetchStreaming'], batch: Batch) { - const { stream, promise } = fetchStreaming({ - url: FUNCTIONS_URL, +async function processBatch(fetchStreaming: BfetchPublicContract['fetchStreaming'], batch: Batch) { + const { stream } = fetchStreaming({ + url: `/api/interpreter/fns`, body: JSON.stringify({ functions: Object.values(batch).map(({ request }) => request), }), @@ -137,7 +135,7 @@ async function processBatch(fetchStreaming: BfetchPublicApi['fetchStreaming'], b }); try { - await promise; + await stream.toPromise(); } catch (error) { Object.values(batch).forEach(({ future }) => { future.reject(error); diff --git a/src/plugins/expressions/public/mocks.tsx b/src/plugins/expressions/public/mocks.tsx index 089c324677712..a3476a24dd7ed 100644 --- a/src/plugins/expressions/public/mocks.tsx +++ b/src/plugins/expressions/public/mocks.tsx @@ -23,6 +23,7 @@ import { ExpressionsSetup, ExpressionsStart, plugin as pluginInitializer } from /* eslint-disable */ import { coreMock } from '../../../core/public/mocks'; import { inspectorPluginMock } from '../../inspector/public/mocks'; +import { bfetchPluginMock } from '../../bfetch/public/mocks'; /* eslint-enable */ export type Setup = jest.Mocked; @@ -48,6 +49,7 @@ const createSetupContract = (): Setup => { interpretAst: () => {}, }, }), + loadLegacyServerFunctionWrappers: () => Promise.resolve(), }, }; return setupContract; @@ -71,6 +73,7 @@ const createPlugin = async () => { const coreStart = coreMock.createStart(); const plugin = pluginInitializer(pluginInitializerContext); const setup = await plugin.setup(coreSetup, { + bfetch: bfetchPluginMock.createSetupContract(), inspector: inspectorPluginMock.createSetupContract(), }); @@ -82,6 +85,7 @@ const createPlugin = async () => { setup, doStart: async () => await plugin.start(coreStart, { + bfetch: bfetchPluginMock.createStartContract(), inspector: inspectorPluginMock.createStartContract(), }), }; diff --git a/src/plugins/expressions/public/plugin.ts b/src/plugins/expressions/public/plugin.ts index 11f804464704e..2ba10be76cd92 100644 --- a/src/plugins/expressions/public/plugin.ts +++ b/src/plugins/expressions/public/plugin.ts @@ -20,6 +20,7 @@ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public'; import { ExpressionInterpretWithHandlers, ExpressionExecutor } from './types'; import { FunctionsRegistry, RenderFunctionsRegistry, TypesRegistry } from './registries'; +import { BfetchPublicSetup, BfetchPublicStart } from '../../bfetch/public'; import { Setup as InspectorSetup, Start as InspectorStart } from '../../inspector/public'; import { setCoreStart, @@ -58,12 +59,15 @@ import { ExpressionLoader, loader } from './loader'; import { ExpressionDataHandler, execute } from './execute'; import { render, ExpressionRenderHandler } from './render'; import { AnyExpressionFunction, AnyExpressionType } from '../common/types'; +import { serializeProvider } from '../common'; export interface ExpressionsSetupDeps { + bfetch: BfetchPublicSetup; inspector: InspectorSetup; } export interface ExpressionsStartDeps { + bfetch: BfetchPublicStart; inspector: InspectorStart; } @@ -76,6 +80,7 @@ export interface ExpressionsSetup { renderers: RenderFunctionsRegistry; types: TypesRegistry; getExecutor: () => ExpressionExecutor; + loadLegacyServerFunctionWrappers: () => Promise; }; } @@ -98,7 +103,7 @@ export class ExpressionsPublicPlugin constructor(initializerContext: PluginInitializerContext) {} - public setup(core: CoreSetup, { inspector }: ExpressionsSetupDeps): ExpressionsSetup { + public setup(core: CoreSetup, { inspector, bfetch }: ExpressionsSetupDeps): ExpressionsSetup { const { functions, renderers, types } = this; setRenderersRegistry(renderers); @@ -146,6 +151,31 @@ export class ExpressionsPublicPlugin setInterpreter(getExecutor().interpreter); + let cached: Promise | null = null; + const loadLegacyServerFunctionWrappers = async () => { + if (!cached) { + cached = (async () => { + const serverFunctionList = await core.http.get(`/api/interpreter/fns`); + const batchedFunction = bfetch.batchedFunction({ url: `/api/interpreter/fns` }); + const { serialize } = serializeProvider(types.toJS()); + + // For every sever-side function, register a client-side + // function that matches its definition, but which simply + // calls the server-side function endpoint. + Object.keys(serverFunctionList).forEach(functionName => { + const fn = () => ({ + ...serverFunctionList[functionName], + fn: (context: any, args: any) => { + return batchedFunction({ functionName, args, context: serialize(context) }); + }, + }); + registerFunction(fn); + }); + })(); + } + return cached; + }; + const setup: ExpressionsSetup = { registerFunction, registerRenderer: (renderer: any) => { @@ -159,6 +189,7 @@ export class ExpressionsPublicPlugin renderers, types, getExecutor, + loadLegacyServerFunctionWrappers, }, }; diff --git a/src/plugins/expressions/server/index.ts b/src/plugins/expressions/server/index.ts new file mode 100644 index 0000000000000..6718602ccdef5 --- /dev/null +++ b/src/plugins/expressions/server/index.ts @@ -0,0 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { PluginInitializerContext } from '../../../core/server'; +import { ExpressionsServerPlugin } from './plugin'; + +export { ExpressionsServerSetup, ExpressionsServerStart } from './plugin'; + +export function plugin(initializerContext: PluginInitializerContext) { + return new ExpressionsServerPlugin(initializerContext); +} diff --git a/src/plugins/expressions/server/legacy.ts b/src/plugins/expressions/server/legacy.ts new file mode 100644 index 0000000000000..54e2a5a387342 --- /dev/null +++ b/src/plugins/expressions/server/legacy.ts @@ -0,0 +1,135 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* eslint-disable max-classes-per-file */ + +// TODO: Remove this file once https://github.com/elastic/kibana/issues/46906 is complete. + +// @ts-ignore +import { register, registryFactory, Registry, Fn } from '@kbn/interpreter/common'; + +import Boom from 'boom'; +import { schema } from '@kbn/config-schema'; +import { CoreSetup, Logger } from 'src/core/server'; +import { ExpressionsServerSetupDependencies } from './plugin'; +import { typeSpecs as types, Type } from '../common'; +import { serializeProvider } from '../common'; + +export class TypesRegistry extends Registry { + wrapper(obj: any) { + return new (Type as any)(obj); + } +} + +export class FunctionsRegistry extends Registry { + wrapper(obj: any) { + return new Fn(obj); + } +} + +export const registries = { + types: new TypesRegistry(), + serverFunctions: new FunctionsRegistry(), +}; + +export interface LegacyInterpreterServerApi { + registries(): typeof registries; + register(specs: Record): typeof registries; +} + +export const createLegacyServerInterpreterApi = (): LegacyInterpreterServerApi => { + const api = registryFactory(registries); + + register(registries, { + types, + }); + + return api; +}; + +export const createLegacyServerEndpoints = ( + api: LegacyInterpreterServerApi, + logger: Logger, + core: CoreSetup, + plugins: ExpressionsServerSetupDependencies +) => { + const router = core.http.createRouter(); + + /** + * Register the endpoint that returns the list of server-only functions. + */ + router.get( + { + path: `/api/interpreter/fns`, + validate: { + body: schema.any(), + }, + }, + async (context, request, response) => { + const functions = api.registries().serverFunctions.toJS(); + const body = JSON.stringify(functions); + return response.ok({ + body, + }); + } + ); + + /** + * Run a single Canvas function. + * + * @param {*} server - The Kibana server object + * @param {*} handlers - The Canvas handlers + * @param {*} fnCall - Describes the function being run `{ functionName, args, context }` + */ + async function runFunction(handlers: any, fnCall: any) { + const { functionName, args, context } = fnCall; + const { deserialize } = serializeProvider(registries.types.toJS()); + const fnDef = registries.serverFunctions.toJS()[functionName]; + if (!fnDef) throw Boom.notFound(`Function "${functionName}" could not be found.`); + const deserialized = deserialize(context); + const result = fnDef.fn(deserialized, args, handlers); + return result; + } + + /** + * Register an endpoint that executes a batch of functions, and streams the + * results back using ND-JSON. + */ + plugins.bfetch.addBatchProcessingRoute(`/api/interpreter/fns`, request => { + const scopedClient = core.elasticsearch.dataClient.asScoped(request); + const handlers = { + environment: 'server', + elasticsearchClient: async ( + endpoint: string, + clientParams: Record = {}, + options?: any + ) => scopedClient.callAsCurrentUser(endpoint, clientParams, options), + }; + + return { + onBatchItem: async (fnCall: any) => { + const result = await runFunction(handlers, fnCall); + if (typeof result === 'undefined') { + throw new Error(`Function ${fnCall.functionName} did not return anything.`); + } + return result; + }, + }; + }); +}; diff --git a/src/plugins/expressions/server/mocks.ts b/src/plugins/expressions/server/mocks.ts new file mode 100644 index 0000000000000..4510ae6dc0b4a --- /dev/null +++ b/src/plugins/expressions/server/mocks.ts @@ -0,0 +1,73 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { ExpressionsServerSetup, ExpressionsServerStart } from '.'; +import { plugin as pluginInitializer } from '.'; +import { coreMock } from '../../../core/server/mocks'; + +/* eslint-disable */ +import { bfetchPluginMock } from '../../bfetch/server/mocks'; +/* eslint-enable */ + +export type Setup = jest.Mocked; +export type Start = jest.Mocked; + +const createSetupContract = (): Setup => { + const setupContract: Setup = { + __LEGACY: { + register: jest.fn(), + registries: jest.fn(), + }, + }; + return setupContract; +}; + +const createStartContract = (): Start => { + const startContract: Start = {}; + + return startContract; +}; + +const createPlugin = async () => { + const pluginInitializerContext = coreMock.createPluginInitializerContext(); + const coreSetup = coreMock.createSetup(); + const coreStart = coreMock.createStart(); + const plugin = pluginInitializer(pluginInitializerContext); + const setup = await plugin.setup(coreSetup, { + bfetch: bfetchPluginMock.createSetupContract(), + }); + + return { + pluginInitializerContext, + coreSetup, + coreStart, + plugin, + setup, + doStart: async () => + await plugin.start(coreStart, { + bfetch: bfetchPluginMock.createStartContract(), + }), + }; +}; + +export const expressionsPluginMock = { + createSetupContract, + createStartContract, + createPlugin, +}; diff --git a/src/plugins/expressions/server/plugin.ts b/src/plugins/expressions/server/plugin.ts new file mode 100644 index 0000000000000..84c780b5ca226 --- /dev/null +++ b/src/plugins/expressions/server/plugin.ts @@ -0,0 +1,77 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreStart, PluginInitializerContext, CoreSetup, Plugin } from 'src/core/server'; +import { BfetchServerSetup, BfetchServerStart } from '../../bfetch/server'; +import { + LegacyInterpreterServerApi, + createLegacyServerInterpreterApi, + createLegacyServerEndpoints, +} from './legacy'; + +// eslint-disable-next-line +export interface ExpressionsServerSetupDependencies { + bfetch: BfetchServerSetup; +} + +// eslint-disable-next-line +export interface ExpressionsServerStartDependencies { + bfetch: BfetchServerStart; +} + +export interface ExpressionsServerSetup { + __LEGACY: LegacyInterpreterServerApi; +} + +// eslint-disable-next-line +export interface ExpressionsServerStart {} + +export class ExpressionsServerPlugin + implements + Plugin< + ExpressionsServerSetup, + ExpressionsServerStart, + ExpressionsServerSetupDependencies, + ExpressionsServerStartDependencies + > { + constructor(private readonly initializerContext: PluginInitializerContext) {} + + public setup( + core: CoreSetup, + plugins: ExpressionsServerSetupDependencies + ): ExpressionsServerSetup { + const logger = this.initializerContext.logger.get(); + + const legacyApi = createLegacyServerInterpreterApi(); + createLegacyServerEndpoints(legacyApi, logger, core, plugins); + + return { + __LEGACY: legacyApi, + }; + } + + public start( + core: CoreStart, + plugins: ExpressionsServerStartDependencies + ): ExpressionsServerStart { + return {}; + } + + public stop() {} +} diff --git a/src/plugins/kibana_utils/common/index.ts b/src/plugins/kibana_utils/common/index.ts index eb3bb96c8e874..bfb45b88964d8 100644 --- a/src/plugins/kibana_utils/common/index.ts +++ b/src/plugins/kibana_utils/common/index.ts @@ -18,4 +18,5 @@ */ export * from './defer'; +export * from './of'; export { distinctUntilChangedWithInitialValue } from './distinct_until_changed_with_initial_value'; diff --git a/src/plugins/kibana_utils/common/of.test.ts b/src/plugins/kibana_utils/common/of.test.ts new file mode 100644 index 0000000000000..6c3f0ec1592bd --- /dev/null +++ b/src/plugins/kibana_utils/common/of.test.ts @@ -0,0 +1,63 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { of } from './of'; + +describe('of()', () => { + describe('when promise resolves', () => { + const promise = new Promise(resolve => resolve()).then(() => 123); + + test('first member of 3-tuple is the promise value', async () => { + const [result] = await of(promise); + expect(result).toBe(123); + }); + + test('second member of 3-tuple is undefined', async () => { + const [, error] = await of(promise); + expect(error).toBe(undefined); + }); + + test('third, flag member, of 3-tuple is true', async () => { + const [, , resolved] = await of(promise); + expect(resolved).toBe(true); + }); + }); + + describe('when promise rejects', () => { + const promise = new Promise(resolve => resolve()).then(() => { + // eslint-disable-next-line no-throw-literal + throw 123; + }); + + test('first member of 3-tuple is undefined', async () => { + const [result] = await of(promise); + expect(result).toBe(undefined); + }); + + test('second member of 3-tuple is thrown error', async () => { + const [, error] = await of(promise); + expect(error).toBe(123); + }); + + test('third, flag member, of 3-tuple is false', async () => { + const [, , resolved] = await of(promise); + expect(resolved).toBe(false); + }); + }); +}); diff --git a/src/plugins/kibana_utils/common/of.ts b/src/plugins/kibana_utils/common/of.ts new file mode 100644 index 0000000000000..fa0ec8b0ce306 --- /dev/null +++ b/src/plugins/kibana_utils/common/of.ts @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Given a promise awaits it and returns a 3-tuple, with the following members: + * + * - First entry is either the resolved value of the promise or `undefined`. + * - Second entry is either the error thrown by promise or `undefined`. + * - Third entry is a boolean, truthy if promise was resolved and falsy if rejected. + * + * @param promise Promise to convert to 3-tuple. + */ +export const of = async ( + promise: Promise +): Promise<[T | undefined, E | undefined, boolean]> => { + try { + return [await promise, undefined, true]; + } catch (error) { + return [undefined, error, false]; + } +}; diff --git a/src/plugins/kibana_utils/public/index.ts b/src/plugins/kibana_utils/public/index.ts index 0ba444c4e9395..fa58a61e51232 100644 --- a/src/plugins/kibana_utils/public/index.ts +++ b/src/plugins/kibana_utils/public/index.ts @@ -17,7 +17,7 @@ * under the License. */ -export { defer } from '../common'; +export { defer, Defer, of } from '../common'; export * from './core'; export * from './errors'; export * from './field_mapping'; diff --git a/test/plugin_functional/config.js b/test/plugin_functional/config.js index e9a4f3bcc4b1a..e63054f1b6912 100644 --- a/test/plugin_functional/config.js +++ b/test/plugin_functional/config.js @@ -38,6 +38,7 @@ export default async function({ readConfigFile }) { require.resolve('./test_suites/embeddable_explorer'), require.resolve('./test_suites/core_plugins'), require.resolve('./test_suites/management'), + require.resolve('./test_suites/bfetch_explorer'), ], services: { ...functionalConfig.get('services'), diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/kibana.json b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/kibana.json new file mode 100644 index 0000000000000..1acc7df871c94 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/kibana.json @@ -0,0 +1,10 @@ +{ + "id": "kbn_tp_bfetch_explorer", + "version": "0.0.1", + "kibanaVersion": "kibana", + "configPath": ["kbn_tp_bfetch_explorer"], + "server": true, + "ui": true, + "requiredPlugins": ["bfetch"], + "optionalPlugins": [] +} diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/package.json b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/package.json new file mode 100644 index 0000000000000..e396489a1ffc4 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/package.json @@ -0,0 +1,17 @@ +{ + "name": "kbn_tp_bfetch_explorer", + "version": "1.0.0", + "main": "target/examples/kbn_tp_bfetch_explorer", + "kibana": { + "version": "kibana", + "templateVersion": "1.0.0" + }, + "license": "Apache-2.0", + "scripts": { + "kbn": "node ../../scripts/kbn.js", + "build": "rm -rf './target' && tsc" + }, + "devDependencies": { + "typescript": "3.7.2" + } +} diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/public/index.ts b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/public/index.ts new file mode 100644 index 0000000000000..547dfe2aa38d2 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/public/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from '../../../../../examples/bfetch_explorer/public'; diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/server/index.ts b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/server/index.ts new file mode 100644 index 0000000000000..b4370eb53311e --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/server/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from '../../../../../examples/bfetch_explorer/server'; diff --git a/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/tsconfig.json b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/tsconfig.json new file mode 100644 index 0000000000000..994f81e396763 --- /dev/null +++ b/test/plugin_functional/plugins/kbn_tp_bfetch_explorer/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true, + "types": [ + "node", + "jest", + "react" + ] + }, + "include": [ + "index.ts", + "public/**/*.ts", + "public/**/*.tsx", + "server/**/*.ts", + "server/**/*.tsx", + "../../../../typings/**/*", + ], + "exclude": [] +} diff --git a/test/plugin_functional/test_suites/bfetch_explorer/batched_function.ts b/test/plugin_functional/test_suites/bfetch_explorer/batched_function.ts new file mode 100644 index 0000000000000..cb2a0b41694c2 --- /dev/null +++ b/test/plugin_functional/test_suites/bfetch_explorer/batched_function.ts @@ -0,0 +1,93 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../functional/ftr_provider_context'; + +export default function({ getService }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const appsMenu = getService('appsMenu'); + + describe('batchedFunction', () => { + beforeEach(async () => { + await appsMenu.clickLink('bfetch explorer'); + await testSubjects.click('count-until'); + await testSubjects.click('double-integers'); + }); + + it('executes all requests in a batch', async () => { + const form = await testSubjects.find('DoubleIntegers'); + const btn = await form.findByCssSelector('button'); + await btn.click(); + await new Promise(r => setTimeout(r, 4000)); + const pre = await form.findByCssSelector('pre'); + const text = await pre.getVisibleText(); + const json = JSON.parse(text); + + expect(json).to.eql([ + { + num: -1, + error: { + message: 'Invalid number', + }, + }, + { + num: 300, + result: { + num: 600, + }, + }, + { + num: 1000, + result: { + num: 2000, + }, + }, + { + num: 2000, + result: { + num: 4000, + }, + }, + ]); + }); + + it('streams results back', async () => { + const form = await testSubjects.find('DoubleIntegers'); + const btn = await form.findByCssSelector('button'); + await btn.click(); + + await new Promise(r => setTimeout(r, 500)); + const pre = await form.findByCssSelector('pre'); + + const text1 = await pre.getVisibleText(); + const json1 = JSON.parse(text1); + + expect(json1.length > 0).to.be(true); + expect(json1.length < 4).to.be(true); + + await new Promise(r => setTimeout(r, 3500)); + + const text2 = await pre.getVisibleText(); + const json2 = JSON.parse(text2); + + expect(json2.length).to.be(4); + }); + }); +} diff --git a/test/plugin_functional/test_suites/bfetch_explorer/index.ts b/test/plugin_functional/test_suites/bfetch_explorer/index.ts new file mode 100644 index 0000000000000..54f127d6de89a --- /dev/null +++ b/test/plugin_functional/test_suites/bfetch_explorer/index.ts @@ -0,0 +1,36 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { FtrProviderContext } from '../../../functional/ftr_provider_context'; + +export default function({ getService, getPageObjects, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const appsMenu = getService('appsMenu'); + const PageObjects = getPageObjects(['common', 'header']); + + describe('bfetch explorer', function() { + before(async () => { + await browser.setWindowSize(1300, 900); + await PageObjects.common.navigateToApp('settings'); + await appsMenu.clickLink('bfetch explorer'); + }); + + loadTestFile(require.resolve('./batched_function')); + }); +} From 3b8398fb1f21fbb7e9647310287836411b4f2b3f Mon Sep 17 00:00:00 2001 From: Peter Pisljar Date: Thu, 16 Jan 2020 08:52:36 -0500 Subject: [PATCH 05/11] making visualization expression function and renderer np_ready (#51966) --- .../visualizations/public/legacy_imports.ts | 2 ++ .../{ => np_ready/public}/expressions/vis.js | 5 +++-- .../expressions/visualization_function.ts | 16 ++++------------ .../expressions/visualization_renderer.tsx | 6 +++--- .../public/np_ready/public/plugin.ts | 7 +++++-- .../public/np_ready/public/services.ts | 6 +++++- 6 files changed, 22 insertions(+), 20 deletions(-) rename src/legacy/core_plugins/visualizations/public/{ => np_ready/public}/expressions/vis.js (96%) rename src/legacy/core_plugins/visualizations/public/{ => np_ready/public}/expressions/visualization_function.ts (87%) rename src/legacy/core_plugins/visualizations/public/{ => np_ready/public}/expressions/visualization_renderer.tsx (92%) diff --git a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts index 92d8ac2c7db3a..e10cbe9aefea6 100644 --- a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts +++ b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts @@ -27,4 +27,6 @@ export { } from '../../../ui/public/agg_types/buckets/date_histogram'; export { createFormat } from '../../../ui/public/visualize/loader/pipeline_helpers/utilities'; export { I18nContext } from '../../../ui/public/i18n'; +import chrome from '../../../ui/public/chrome'; +export { chrome as legacyChrome }; import '../../../ui/public/directives/bind'; diff --git a/src/legacy/core_plugins/visualizations/public/expressions/vis.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.js similarity index 96% rename from src/legacy/core_plugins/visualizations/public/expressions/vis.js rename to src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.js index cbadfd9da3788..81224b65f7786 100644 --- a/src/legacy/core_plugins/visualizations/public/expressions/vis.js +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.js @@ -29,8 +29,9 @@ import { EventEmitter } from 'events'; import _ from 'lodash'; -import { PersistedState } from '../../../../ui/public/persisted_state'; -import { getTypes } from '../np_ready/public/services'; +import { PersistedState } from '../../../legacy_imports'; + +import { getTypes } from '../services'; export class Vis extends EventEmitter { constructor(visState = { type: 'histogram' }) { diff --git a/src/legacy/core_plugins/visualizations/public/expressions/visualization_function.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_function.ts similarity index 87% rename from src/legacy/core_plugins/visualizations/public/expressions/visualization_function.ts rename to src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_function.ts index 37b437c1c2dd6..24eb974f6edee 100644 --- a/src/legacy/core_plugins/visualizations/public/expressions/visualization_function.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_function.ts @@ -19,13 +19,10 @@ import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; -import chrome from 'ui/chrome'; -import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter'; -import { PersistedState } from 'ui/persisted_state'; import { VisResponseValue } from 'src/plugins/visualizations/public'; import { ExpressionFunction, Render } from 'src/plugins/expressions/public'; -import { npStart } from 'ui/new_platform'; -import { getTypes } from '../np_ready/public/services'; +import { PersistedState } from '../../../legacy_imports'; +import { getTypes, getIndexPatterns, getFilterManager } from '../services'; interface Arguments { index?: string | null; @@ -90,15 +87,10 @@ export const visualization = (): ExpressionFunctionVisualization => ({ }, }, async fn(context, args, handlers) { - const $injector = await chrome.dangerouslyGetActiveInjector(); - const Private = $injector.get('Private') as any; - const indexPatterns = npStart.plugins.data.indexPatterns; - const queryFilter = Private(FilterBarQueryFilterProvider); - const visConfigParams = args.visConfig ? JSON.parse(args.visConfig) : {}; const schemas = args.schemas ? JSON.parse(args.schemas) : {}; const visType = getTypes().get(args.type || 'histogram') as any; - const indexPattern = args.index ? await indexPatterns.get(args.index) : null; + const indexPattern = args.index ? await getIndexPatterns().get(args.index) : null; const uiStateParams = args.uiState ? JSON.parse(args.uiState) : {}; const uiState = new PersistedState(uiStateParams); @@ -114,7 +106,7 @@ export const visualization = (): ExpressionFunctionVisualization => ({ filters: get(context, 'filters', null), uiState, inspectorAdapters: handlers.inspectorAdapters, - queryFilter, + queryFilter: getFilterManager(), forceFetch: true, }); } diff --git a/src/legacy/core_plugins/visualizations/public/expressions/visualization_renderer.tsx b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_renderer.tsx similarity index 92% rename from src/legacy/core_plugins/visualizations/public/expressions/visualization_renderer.tsx rename to src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_renderer.tsx index 5f894c7eb60e3..2a12884ecf7c8 100644 --- a/src/legacy/core_plugins/visualizations/public/expressions/visualization_renderer.tsx +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_renderer.tsx @@ -17,12 +17,12 @@ * under the License. */ -import chrome from 'ui/chrome'; import React from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; +import { legacyChrome } from '../../../legacy_imports'; // @ts-ignore import { Vis } from './vis'; -import { Visualization } from '../np_ready/public/components'; +import { Visualization } from '../components'; export const visualization = () => ({ name: 'visualization', @@ -31,7 +31,7 @@ export const visualization = () => ({ render: async (domNode: HTMLElement, config: any, handlers: any) => { const { visData, visConfig, params } = config; const visType = config.visType || visConfig.type; - const $injector = await chrome.dangerouslyGetActiveInjector(); + const $injector = await legacyChrome.dangerouslyGetActiveInjector(); const $rootScope = $injector.get('$rootScope') as any; if (handlers.vis) { diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts index 7584556324e8b..cfd22f88167c5 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public'; import { TypesService, TypesSetup, TypesStart } from './types'; import { @@ -27,13 +28,14 @@ import { setIndexPatterns, setSavedObjects, setUsageCollector, + setFilterManager, } from './services'; import { VisualizeEmbeddableFactory } from '../../embeddable/visualize_embeddable_factory'; import { VISUALIZE_EMBEDDABLE_TYPE } from '../../embeddable'; import { ExpressionsSetup } from '../../../../../../plugins/expressions/public'; import { IEmbeddableSetup } from '../../../../../../plugins/embeddable/public'; -import { visualization as visualizationFunction } from '../../expressions/visualization_function'; -import { visualization as visualizationRenderer } from '../../expressions/visualization_renderer'; +import { visualization as visualizationFunction } from './expressions/visualization_function'; +import { visualization as visualizationRenderer } from './expressions/visualization_renderer'; import { DataPublicPluginStart } from '../../../../../../plugins/data/public'; import { UsageCollectionSetup } from '../../../../../../plugins/usage_collection/public'; /** @@ -106,6 +108,7 @@ export class VisualizationsPlugin setHttp(core.http); setSavedObjects(core.savedObjects); setIndexPatterns(data.indexPatterns); + setFilterManager(data.query.filterManager); return { types, diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts index 4b426fee6c7da..433c5c7b6df0d 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts @@ -26,7 +26,7 @@ import { } from 'src/core/public'; import { TypesStart } from './types'; import { createGetterSetter } from '../../../../../../plugins/kibana_utils/public'; -import { IndexPatternsContract } from '../../../../../../plugins/data/public'; +import { FilterManager, IndexPatternsContract } from '../../../../../../plugins/data/public'; import { UsageCollectionSetup } from '../../../../../../plugins/usage_collection/public'; export const [getUISettings, setUISettings] = createGetterSetter('UISettings'); @@ -43,6 +43,10 @@ export const [getTypes, setTypes] = createGetterSetter('Types'); export const [getI18n, setI18n] = createGetterSetter('I18n'); +export const [getFilterManager, setFilterManager] = createGetterSetter( + 'FilterManager' +); + export const [getIndexPatterns, setIndexPatterns] = createGetterSetter( 'IndexPatterns' ); From 3419b06ee3bbbdfd581ec98b7ccbd1c45ef29ac4 Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Thu, 16 Jan 2020 14:19:34 +0000 Subject: [PATCH 06/11] [ML] Fixes empty table header cell and duplicate ID accessibility issues (#54917) * [ML] Fixes empty table header cell and duplicate ID accessibility issues * [ML] Fix anomalies table columns test --- .../anomalies_table/anomalies_table.test.js | 3 -- .../anomalies_table_columns.js | 14 ++++++- .../components/anomalies_table/links_menu.js | 1 - .../components/analytics_list/columns.tsx | 12 ++++++ .../components/jobs_list/jobs_list.js | 37 ++++++++++++++++--- .../components/transform_list/columns.tsx | 12 ++++++ 6 files changed, 68 insertions(+), 11 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.test.js b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.test.js index b40808d51dd66..206b9e01bab8c 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.test.js +++ b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.test.js @@ -63,9 +63,6 @@ describe('AnomaliesTable', () => { expect(columns).toEqual( expect.arrayContaining([ - expect.objectContaining({ - name: '', - }), expect.objectContaining({ name: 'time', }), diff --git a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js index 5454911673fe2..58f1214c11e10 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js +++ b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js @@ -4,12 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiButtonIcon, EuiLink } from '@elastic/eui'; +import { EuiButtonIcon, EuiLink, EuiScreenReaderOnly } from '@elastic/eui'; import React from 'react'; import _ from 'lodash'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { formatHumanReadableDate, @@ -65,7 +66,16 @@ export function getColumns( ) { const columns = [ { - name: '', + name: ( + +

+ +

+
+ ), render: item => ( toggleRow(item)} diff --git a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js index 8cbee27bdd9a8..074a584f3a136 100644 --- a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js +++ b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/links_menu.js @@ -479,7 +479,6 @@ export const LinksMenu = injectI18n( return ( +

+ +

+ + ), align: RIGHT_ALIGNMENT, width: '40px', isExpander: true, diff --git a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js index 818f1b79b3143..7a6a1c22e39c5 100644 --- a/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js +++ b/x-pack/legacy/plugins/ml/public/application/jobs/jobs_list/components/jobs_list/jobs_list.js @@ -16,8 +16,8 @@ import { JobDescription } from './job_description'; import { JobIcon } from '../../../../components/job_message_icon'; import { getJobIdUrl } from '../utils'; -import { EuiBadge, EuiBasicTable, EuiButtonIcon, EuiLink } from '@elastic/eui'; -import { injectI18n } from '@kbn/i18n/react'; +import { EuiBadge, EuiBasicTable, EuiButtonIcon, EuiLink, EuiScreenReaderOnly } from '@elastic/eui'; +import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; const PAGE_SIZE = 10; @@ -124,7 +124,16 @@ class JobsListUI extends Component { // be updated if we move to always using props for width. const columns = [ { - name: '', + name: ( + +

+ +

+
+ ), render: item => ( this.toggleRow(item)} @@ -167,7 +176,16 @@ class JobsListUI extends Component { }, { field: 'auditMessage', - name: '', + name: ( + +

+ +

+
+ ), render: item => , }, { @@ -272,7 +290,16 @@ class JobsListUI extends Component { width: '15%', }); columns.push({ - name: '', + name: ( + +

+ +

+
+ ), actions: actionsMenuContent( this.props.showEditJobFlyout, this.props.showDeleteJobModal, diff --git a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx index ebe4f7efda055..e2f92e0acd645 100644 --- a/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx +++ b/x-pack/legacy/plugins/transform/public/app/sections/transform_management/components/transform_list/columns.tsx @@ -6,12 +6,14 @@ import React, { Fragment } from 'react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { EuiBadge, EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiProgress, + EuiScreenReaderOnly, EuiText, EuiToolTip, RIGHT_ALIGNMENT, @@ -98,6 +100,16 @@ export const getColumns = ( ActionsColumnType ] = [ { + name: ( + +

+ +

+
+ ), align: RIGHT_ALIGNMENT, width: '40px', isExpander: true, From c8c03e4e8504f348de29683c8365e5ea1f2e3dcb Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 16 Jan 2020 15:41:29 +0100 Subject: [PATCH 07/11] Fix double fetch errors (#54701) --- .../kibana/public/discover/np_ready/angular/discover.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js index 78ac99567d10e..2927565e61dce 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js @@ -826,9 +826,14 @@ function discoverController( }; $scope.updateQueryAndFetch = function({ query, dateRange }) { + const oldDateRange = timefilter.getTime(); timefilter.setTime(dateRange); $state.query = query; - $scope.fetch(); + // storing the updated timerange in the state will trigger a fetch + // call automatically, so only trigger fetch in case this is a refresh call (no changes in parameters). + if (_.isEqual(oldDateRange, dateRange)) { + $scope.fetch(); + } }; function onResults(resp) { From 0d19b38f1892f4c0459c0bb9cc06cf8692cadec7 Mon Sep 17 00:00:00 2001 From: Joe Portner <5295965+jportner@users.noreply.github.com> Date: Thu, 16 Jan 2020 09:46:45 -0500 Subject: [PATCH 08/11] Document mutual TLS authentication (PKI) between Kibana and Elasticsearch (#54940) --- .../images/mutual-tls-role-mapping.png | Bin 0 -> 470103 bytes .../elasticsearch-mutual-tls.asciidoc | 120 ++++++++++++++++++ docs/user/security/securing-kibana.asciidoc | 3 + 3 files changed, 123 insertions(+) create mode 100644 docs/user/security/images/mutual-tls-role-mapping.png create mode 100644 docs/user/security/securing-communications/elasticsearch-mutual-tls.asciidoc diff --git a/docs/user/security/images/mutual-tls-role-mapping.png b/docs/user/security/images/mutual-tls-role-mapping.png new file mode 100644 index 0000000000000000000000000000000000000000..d95ce41e130c21df2530868efbb47e5b327c2206 GIT binary patch literal 470103 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 z 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%0Dr6e?0|$*U;kB`(VFX*LlZQp!PRIYE)%+7 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 TLS with {es} +++++ + +In a standard Transport Layer Security (TLS/SSL) configuration, the server presents a signed certificate to authenticate itself to the +client. In a mutual TLS configuration, the client also presents a signed certificate to authenticate itself to the server. + +When {security} is enabled on your cluster, each request that {kib} makes to {es} must be authenticated. Most requests made through {kib} to +{es} are authenticated by using the credentials of the logged-in user. There are, however, a few internal requests that the {kib} server +needs to make to the {es} cluster. For this reason, you must configure credentials for the {kib} server to use for those requests. + +If {kib} has `elasticsearch.username` and `elasticsearch.password` configured, it will attempt to use these to authenticate to {es} via the +{ref}/native-realm.html[Native realm]. However, {kib} also supports mutual TLS authentication with {es} via a {ref}/pki-realm.html[Public +Key Infrastructure (PKI) realm]. To do so, {es} needs to verify the signature on the {kib} client certificate, and it also needs to map the +certificate's distinguished name (DN) to the appropriate `kibana_system` role. + +NOTE: Using a PKI realm is a gold feature. For a comparison of the Elastic license levels, see https://www.elastic.co/subscriptions[the +subscription page]. + +To configure {kib} and {es} to use mutual TLS authentication: + +. <> with a username and password. + +. <>. At a minimum, this requires a server certificate for {es}. + +. Create a client certificate and private key for {kib} to use when connecting to {es}. ++ +-- +NOTE: This is not the same as the <> that {kib} will present to web browsers. + +You may choose to generate a certificate and private key using {ref}/certutil.html[the {es} certutil tool]. At this point, you will have +already set up a certificate authority (CA) to sign the {es} server certificate. You may choose to use the same CA to sign the {kib} client +certificate. You would do this like so: + +[source,sh] +-------------------------------------------------------------------------------- +bin/elasticsearch-certutil cert -ca elastic-stack-ca.p12 -name kibana-client +-------------------------------------------------------------------------------- + +This will generate a certificate and private key in a PKCS #12 keystore named `kibana-client.p12`. The certificate has a Common Name (CN) of +"kibana-client". + +You will also need to use the CA certificate when setting up the PKI realm in {es}. While you could use the CA keystore in the above example +for this purpose, it is bad practice to expose the CA's private key in such a manner. Instead, you can extract the CA certificate (without +its private key) like so: + +[source,sh] +-------------------------------------------------------------------------------- +openssl pkcs12 -in kibana-client.p12 -cacerts -nokeys -out ca.crt +-------------------------------------------------------------------------------- +-- + +. Configure a PKI realm and a Native realm in your {es} cluster: ++ +-- +By default, {es} provides a Native realm. However, to support both a PKI realm (for {kib}) and a Native realm (for end users), you must +configure each realm in `elasticsearch.yml`: + +[source,yaml] +-------------------------------------------------------------------------------- +xpack.security.authc.realms.pki.realm1.order: 1 +xpack.security.authc.realms.pki.realm1.certificate_authorities: "/path/to/ca.crt" +xpack.security.authc.realms.native.realm2.order: 2 +-------------------------------------------------------------------------------- + +-- + +. Configure your {es} cluster to request client certificates: ++ +-- +By default, {es} will not request a client certificate when establishing a TLS connection. To change this, you must set up optional client +certificate authentication in `elasticsearch.yml`: + +[source,yaml] +-------------------------------------------------------------------------------- +xpack.security.http.ssl.client_authentication: "optional" +-------------------------------------------------------------------------------- +-- + +. Restart your {es} cluster. + +. Use {kib} to create a <> for your new client certificate: ++ +-- +This role mapping will assign the `kibana_system` role to any user that matches the included mapping rule, which is set to equal the client +certificate's DN attribute: + +[role="screenshot"] +image:user/security/images/mutual-tls-role-mapping.png["Role mapping for the {kib} client certificate"] +-- + +. Configure {kib} to use the client certificate: ++ +-- +Assuming you used the {es} certutil tool to generate a certificate and private key in a PKCS #12 keystore, add the following values to +`kibana.yml`: + +[source,yaml] +-------------------------------------------------------------------------------- +elasticsearch.ssl.keystore.path: "/path/to/kibana-client.p12" +elasticsearch.ssl.keystore.password: "decryption password" +-------------------------------------------------------------------------------- + +The decryption password should match what you entered when prompted by the {es} certutil tool. + +You must also remove the `elasticsearch.username` and `elasticsearch.password` values from the configuration file. Otherwise, {kib} will +attempt to use those to authenticate via the Native realm. + +TIP: Alternatively, {kib} also supports using a client certificate and private key in PEM format with the `elasticsearch.ssl.certificate` +and `elasticsearch.ssl.key` settings. For more information, see <>. +-- + +. Restart {kib}. + +NOTE: The steps above enable {kib} to authenticate to {es} using a certificate. However, end users will only be able to authenticate to +{kib} with a username and password. To allow end users to authenticate to {kib} using certificates, see <>. diff --git a/docs/user/security/securing-kibana.asciidoc b/docs/user/security/securing-kibana.asciidoc index a68a2ee285ee3..2d07b57bfabe1 100644 --- a/docs/user/security/securing-kibana.asciidoc +++ b/docs/user/security/securing-kibana.asciidoc @@ -88,6 +88,8 @@ xpack.security.session.lifespan: "8h" . Optional: <>. +. Optional: <>. + . Restart {kib}. . [[kibana-roles]]Choose an authentication mechanism and grant users the privileges they need to @@ -141,4 +143,5 @@ NOTE: This must be a user who has been assigned < Date: Thu, 16 Jan 2020 09:27:07 -0600 Subject: [PATCH 09/11] [APM] Storybook support (#54970) Add Storybook with help from changes in #43529. We still need to do some work around having mocks for hooks and HTTP requests but the basics are there. --- src/dev/storybook/aliases.ts | 1 + .../PlatinumLicensePrompt.stories.tsx | 33 +++++++++++++++++++ x-pack/legacy/plugins/apm/readme.md | 7 +++- .../legacy/plugins/apm/scripts/storybook.js | 15 +++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.stories.tsx create mode 100644 x-pack/legacy/plugins/apm/scripts/storybook.js diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts index 8213bdeeea2da..1dce53b6c2a84 100644 --- a/src/dev/storybook/aliases.ts +++ b/src/dev/storybook/aliases.ts @@ -18,6 +18,7 @@ */ export const storybookAliases = { + apm: 'x-pack/legacy/plugins/apm/scripts/storybook.js', canvas: 'x-pack/legacy/plugins/canvas/scripts/storybook_new.js', embeddable: 'src/plugins/embeddable/scripts/storybook.js', infra: 'x-pack/legacy/plugins/infra/scripts/storybook.js', diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.stories.tsx b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.stories.tsx new file mode 100644 index 0000000000000..80281c1a0a8fc --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/PlatinumLicensePrompt.stories.tsx @@ -0,0 +1,33 @@ +/* + * 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 { storiesOf } from '@storybook/react'; +import React from 'react'; +import { PlatinumLicensePrompt } from './PlatinumLicensePrompt'; +import { + ApmPluginContext, + ApmPluginContextValue +} from '../../../context/ApmPluginContext'; + +storiesOf('app/ServiceMap/PlatinumLicensePrompt', module).add( + 'example', + () => { + const contextMock = ({ + core: { http: { basePath: { prepend: () => {} } } } + } as unknown) as ApmPluginContextValue; + + return ( + + + + ); + }, + { + info: { + source: false + } + } +); diff --git a/x-pack/legacy/plugins/apm/readme.md b/x-pack/legacy/plugins/apm/readme.md index 6b21f08b7695e..2106243d12aea 100644 --- a/x-pack/legacy/plugins/apm/readme.md +++ b/x-pack/legacy/plugins/apm/readme.md @@ -40,7 +40,6 @@ For testing purposes APM uses 3 custom users: **kibana_write_user** Apps: read/write. Indices: None - To create the users with the correct roles run the following script: ```sh @@ -88,6 +87,12 @@ yarn prettier "./x-pack/legacy/plugins/apm/**/*.{tsx,ts,js}" --write yarn eslint ./x-pack/legacy/plugins/apm --fix ``` +#### Storybook + +Start the [Storybook](https://storybook.js.org/) development environment with +`yarn storybook apm`. All files with a .stories.tsx extension will be loaded. +You can access the development environment at http://localhost:9001. + #### Further resources - [Cypress integration tests](cypress/README.md) diff --git a/x-pack/legacy/plugins/apm/scripts/storybook.js b/x-pack/legacy/plugins/apm/scripts/storybook.js new file mode 100644 index 0000000000000..846ee1f301e30 --- /dev/null +++ b/x-pack/legacy/plugins/apm/scripts/storybook.js @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { join } from 'path'; + +// eslint-disable-next-line +require('@kbn/storybook').runStorybookCli({ + name: 'apm', + storyGlobs: [ + join(__dirname, '..', 'public', 'components', '**', '*.stories.tsx') + ] +}); From b9814bfb76c046ef930a976f25f342062334a84a Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Thu, 16 Jan 2020 10:32:27 -0500 Subject: [PATCH 10/11] [ML] DF Analytics Outlier detection results: improve handling of text fields (#55002) * add keyword suffix to fieldName when both text and keyword * update exploration jest test --- .../exploration/exploration.test.tsx | 6 ++- .../components/exploration/exploration.tsx | 51 +++++++++++++++++-- .../exploration/use_explore_data.ts | 17 +++---- 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.test.tsx b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.test.tsx index 92f438459128e..013ea8ddc78a5 100644 --- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.test.tsx +++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.test.tsx @@ -7,6 +7,8 @@ import { shallow } from 'enzyme'; import React from 'react'; import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common'; +import { KibanaContext } from '../../../../../contexts/kibana'; +import { kibanaContextValueMock } from '../../../../../contexts/kibana/__mocks__/kibana_context_value'; jest.mock('../../../../../contexts/ui/use_ui_chrome_context'); jest.mock('ui/new_platform'); @@ -22,7 +24,9 @@ jest.mock('react', () => { describe('Data Frame Analytics: ', () => { test('Minimal initialization', () => { const wrapper = shallow( - + + + ); // Without the jobConfig being loaded, the component will just return empty. expect(wrapper.text()).toMatch(''); diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx index 9691a0706121c..098f8f07bee44 100644 --- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx +++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx @@ -55,6 +55,7 @@ import { SEARCH_SIZE, defaultSearchQuery, } from '../../../../common'; +import { isKeywordAndTextType } from '../../../../common/fields'; import { getOutlierScoreFieldName } from './common'; import { useExploreData, TableItem } from './use_explore_data'; @@ -64,6 +65,10 @@ import { } from '../../../analytics_management/components/analytics_list/common'; import { getTaskStateBadge } from '../../../analytics_management/components/analytics_list/columns'; import { SavedSearchQuery } from '../../../../../contexts/kibana'; +import { getIndexPatternIdFromName } from '../../../../../util/index_utils'; +import { IIndexPattern } from '../../../../../../../../../../../src/plugins/data/common/index_patterns'; +import { newJobCapsService } from '../../../../../services/new_job_capabilities_service'; +import { useKibanaContext } from '../../../../../contexts/kibana'; const FEATURE_INFLUENCE = 'feature_influence'; @@ -110,6 +115,19 @@ export const Exploration: FC = React.memo(({ jobId, jobStatus }) => { const [searchError, setSearchError] = useState(undefined); const [searchString, setSearchString] = useState(undefined); + const kibanaContext = useKibanaContext(); + + const initializeJobCapsService = async () => { + if (jobConfig !== undefined) { + const sourceIndex = jobConfig.source.index[0]; + const indexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex; + const indexPattern: IIndexPattern = await kibanaContext.indexPatterns.get(indexPatternId); + if (indexPattern !== undefined) { + await newJobCapsService.initializeFromIndexPattern(indexPattern, false, false); + } + } + }; + useEffect(() => { (async function() { const analyticsConfigs: GetDataFrameAnalyticsResponse = await ml.dataFrameAnalytics.getDataFrameAnalytics( @@ -124,6 +142,10 @@ export const Exploration: FC = React.memo(({ jobId, jobStatus }) => { })(); }, []); + useEffect(() => { + initializeJobCapsService(); + }, [jobConfig && jobConfig.id]); + const [selectedFields, setSelectedFields] = useState([] as EsFieldName[]); const [isColumnsPopoverVisible, setColumnsPopoverVisible] = useState(false); @@ -293,10 +315,16 @@ export const Exploration: FC = React.memo(({ jobId, jobStatus }) => { if (jobConfig !== undefined) { const outlierScoreFieldName = getOutlierScoreFieldName(jobConfig); const outlierScoreFieldSelected = selectedFields.includes(outlierScoreFieldName); + let requiresKeyword = false; const field = outlierScoreFieldSelected ? outlierScoreFieldName : selectedFields[0]; const direction = outlierScoreFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC; - loadExploreData({ field, direction, searchQuery }); + + if (outlierScoreFieldSelected === false) { + requiresKeyword = isKeywordAndTextType(field); + } + + loadExploreData({ field, direction, searchQuery, requiresKeyword }); } }, [JSON.stringify(searchQuery)]); @@ -307,10 +335,16 @@ export const Exploration: FC = React.memo(({ jobId, jobStatus }) => { if (jobConfig !== undefined && columns.length > 0 && !selectedFields.includes(sortField)) { const outlierScoreFieldName = getOutlierScoreFieldName(jobConfig); const outlierScoreFieldSelected = selectedFields.includes(outlierScoreFieldName); + let requiresKeyword = false; const field = outlierScoreFieldSelected ? outlierScoreFieldName : selectedFields[0]; const direction = outlierScoreFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC; - loadExploreData({ field, direction, searchQuery }); + + if (outlierScoreFieldSelected === false) { + requiresKeyword = isKeywordAndTextType(field); + } + + loadExploreData({ field, direction, searchQuery, requiresKeyword }); return; } }, [jobConfig, columns.length, sortField, sortDirection, tableItems.length]); @@ -334,8 +368,17 @@ export const Exploration: FC = React.memo(({ jobId, jobStatus }) => { setPageIndex(index); setPageSize(size); - if (sort.field !== sortField || sort.direction !== sortDirection) { - loadExploreData({ ...sort, searchQuery }); + if ( + (sort.field !== sortField || sort.direction !== sortDirection) && + jobConfig !== undefined + ) { + const outlierScoreFieldName = getOutlierScoreFieldName(jobConfig); + let requiresKeyword = false; + + if (outlierScoreFieldName !== sort.field) { + requiresKeyword = isKeywordAndTextType(sort.field); + } + loadExploreData({ ...sort, searchQuery, requiresKeyword }); } }; } diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts index e76cbaa463f1d..24cc8d000de7e 100644 --- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts +++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/use_explore_data.ts @@ -23,18 +23,12 @@ import { defaultSearchQuery, SearchQuery, } from '../../../../common'; +import { LoadExploreDataArg } from '../../../../common/analytics'; import { getOutlierScoreFieldName } from './common'; -import { SavedSearchQuery } from '../../../../../contexts/kibana'; export type TableItem = Record; -interface LoadExploreDataArg { - field: string; - direction: SortDirection; - searchQuery: SavedSearchQuery; -} - export interface UseExploreDataReturnType { errorMessage: string; loadExploreData: (arg: LoadExploreDataArg) => void; @@ -55,7 +49,12 @@ export const useExploreData = ( const [sortField, setSortField] = useState(''); const [sortDirection, setSortDirection] = useState(SORT_DIRECTION.ASC); - const loadExploreData = async ({ field, direction, searchQuery }: LoadExploreDataArg) => { + const loadExploreData = async ({ + field, + direction, + searchQuery, + requiresKeyword, + }: LoadExploreDataArg) => { if (jobConfig !== undefined) { setErrorMessage(''); setStatus(INDEX_STATUS.LOADING); @@ -70,7 +69,7 @@ export const useExploreData = ( if (field !== undefined) { body.sort = [ { - [field]: { + [`${field}${requiresKeyword ? '.keyword' : ''}`]: { order: direction, }, }, From 6658412bad4e05b68500992dad9f17d8b58d5426 Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Thu, 16 Jan 2020 10:38:54 -0500 Subject: [PATCH 11/11] [Mappings editor] Add missing period to load JSON copy (#54959) --- .../components/load_mappings/load_mappings_provider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx index 9402a64b22dde..a55bd96dce3d0 100644 --- a/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx +++ b/x-pack/legacy/plugins/index_management/public/app/components/mappings_editor/components/load_mappings/load_mappings_provider.tsx @@ -234,7 +234,7 @@ export const LoadMappingsProvider = ({ onJson, children }: Props) => { mappings, }}