')
.attr('ng-controller', 'KbnTableVisController')
@@ -162,7 +157,7 @@ describe('Table Vis - Controller', async function () {
it('sets the sort on the scope when it is passed as a vis param', async function () {
const sortObj = {
columnIndex: 1,
- direction: 'asc',
+ direction: 'asc'
};
const vis = new OneRangeVis({ sort: sortObj });
initController(vis);
@@ -186,6 +181,7 @@ describe('Table Vis - Controller', async function () {
});
it('passes partialRows:true to tabify based on the vis params', function () {
+
const vis = new OneRangeVis({ showPartialRows: true });
initController(vis);
@@ -193,6 +189,7 @@ describe('Table Vis - Controller', async function () {
});
it('passes partialRows:false to tabify based on the vis params', function () {
+
const vis = new OneRangeVis({ showPartialRows: false });
initController(vis);
diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js
index 8521ee729f313..b0476ae224866 100644
--- a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js
+++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table.js
@@ -31,9 +31,10 @@ import { round } from 'lodash';
import { VisFactoryProvider } from 'ui/vis/vis_factory';
import { createTableVisTypeDefinition } from '../../table_vis_type';
-import { setup } from '../../../../visualizations/public/np_ready/public/legacy';
+import { visualizations } from '../../../../visualizations/public';
describe('Table Vis - AggTable Directive', function () {
+
let $rootScope;
let $compile;
let Vis;
@@ -50,21 +51,19 @@ describe('Table Vis - AggTable Directive', function () {
const vis2 = new Vis(indexPattern, {
type: 'table',
params: {
- showMetricsAtAllLevels: true,
+ showMetricsAtAllLevels: true
},
aggs: [
{ type: 'avg', schema: 'metric', params: { field: 'bytes' } },
{ type: 'terms', schema: 'bucket', params: { field: 'extension' } },
{ type: 'terms', schema: 'bucket', params: { field: 'geo.src' } },
- { type: 'terms', schema: 'bucket', params: { field: 'machine.os' } },
- ],
+ { type: 'terms', schema: 'bucket', params: { field: 'machine.os' } }
+ ]
});
vis2.aggs.aggs.forEach(function (agg, i) {
agg.id = 'agg_' + (i + 1);
});
- tabifiedData.threeTermBuckets = tabifyAggResponse(vis2.aggs, fixtures.threeTermBuckets, {
- metricsAtAllLevels: true,
- });
+ tabifiedData.threeTermBuckets = tabifyAggResponse(vis2.aggs, fixtures.threeTermBuckets, { metricsAtAllLevels: true });
const vis3 = new Vis(indexPattern, {
type: 'table',
@@ -72,54 +71,41 @@ describe('Table Vis - AggTable Directive', function () {
{ type: 'avg', schema: 'metric', params: { field: 'bytes' } },
{ type: 'min', schema: 'metric', params: { field: '@timestamp' } },
{ type: 'terms', schema: 'bucket', params: { field: 'extension' } },
- {
- type: 'date_histogram',
- schema: 'bucket',
- params: { field: '@timestamp', interval: 'd' },
- },
- {
- type: 'derivative',
- schema: 'metric',
- params: { metricAgg: 'custom', customMetric: { id: '5-orderAgg', type: 'count' } },
- },
- {
- type: 'top_hits',
- schema: 'metric',
- params: { field: 'bytes', aggregate: { val: 'min' }, size: 1 },
- },
- ],
+ { type: 'date_histogram', schema: 'bucket', params: { field: '@timestamp', interval: 'd' } },
+ { type: 'derivative', schema: 'metric',
+ params: { metricAgg: 'custom', customMetric: { id: '5-orderAgg', type: 'count' } } },
+ { type: 'top_hits', schema: 'metric', params: { field: 'bytes', aggregate: { val: 'min' }, size: 1 } }
+ ]
});
vis3.aggs.aggs.forEach(function (agg, i) {
agg.id = 'agg_' + (i + 1);
});
- tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative = tabifyAggResponse(
- vis3.aggs,
- fixtures.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative
- );
+ tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative =
+ tabifyAggResponse(vis3.aggs, fixtures.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative);
};
beforeEach(ngMock.module('kibana'));
- beforeEach(
- ngMock.inject(function ($injector, Private, config) {
- legacyDependencies = {
- // eslint-disable-next-line new-cap
- createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization,
- };
+ beforeEach(ngMock.inject(function ($injector, Private, config) {
+ legacyDependencies = {
+ // eslint-disable-next-line new-cap
+ createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization
+ };
- setup.types.registerVisualization(() => createTableVisTypeDefinition(legacyDependencies));
+ visualizations.types.VisTypesRegistryProvider.register(() =>
+ createTableVisTypeDefinition(legacyDependencies)
+ );
- tableAggResponse = legacyResponseHandlerProvider().handler;
- indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
- Vis = Private(VisProvider);
- settings = config;
+ tableAggResponse = legacyResponseHandlerProvider().handler;
+ indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
+ Vis = Private(VisProvider);
+ settings = config;
- $rootScope = $injector.get('$rootScope');
- $compile = $injector.get('$compile');
+ $rootScope = $injector.get('$rootScope');
+ $compile = $injector.get('$compile');
- init();
- })
- );
+ init();
+ }));
let $scope;
beforeEach(function () {
@@ -129,16 +115,12 @@ describe('Table Vis - AggTable Directive', function () {
$scope.$destroy();
});
+
it('renders a simple response properly', async function () {
- $scope.dimensions = {
- metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }],
- buckets: [],
- };
+ $scope.dimensions = { metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], buckets: [] };
$scope.table = (await tableAggResponse(tabifiedData.metricOnly, $scope.dimensions)).tables[0];
- const $el = $compile('
')(
- $scope
- );
+ const $el = $compile('
')($scope);
$scope.$digest();
expect($el.find('tbody').length).to.be(1);
@@ -149,9 +131,7 @@ describe('Table Vis - AggTable Directive', function () {
it('renders nothing if the table is empty', function () {
$scope.dimensions = {};
$scope.table = null;
- const $el = $compile('
')(
- $scope
- );
+ const $el = $compile('
')($scope);
$scope.$digest();
expect($el.find('tbody').length).to.be(0);
@@ -159,21 +139,10 @@ describe('Table Vis - AggTable Directive', function () {
it('renders a complex response properly', async function () {
$scope.dimensions = {
- buckets: [
- { accessor: 0, params: {} },
- { accessor: 2, params: {} },
- { accessor: 4, params: {} },
- ],
- metrics: [
- { accessor: 1, params: {} },
- { accessor: 3, params: {} },
- { accessor: 5, params: {} },
- ],
+ buckets: [{ accessor: 0, params: {} }, { accessor: 2, params: {} }, { accessor: 4, params: {} }],
+ metrics: [{ accessor: 1, params: {} }, { accessor: 3, params: {} }, { accessor: 5, params: {} }]
};
- $scope.table = (await tableAggResponse(
- tabifiedData.threeTermBuckets,
- $scope.dimensions
- )).tables[0];
+ $scope.table = (await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions)).tables[0];
const $el = $('
');
$compile($el)($scope);
$scope.$digest();
@@ -196,9 +165,7 @@ describe('Table Vis - AggTable Directive', function () {
expect($cells.length).to.be(6);
const txts = $cells.map(function () {
- return $(this)
- .text()
- .trim();
+ return $(this).text().trim();
});
// two character country code
@@ -217,6 +184,7 @@ describe('Table Vis - AggTable Directive', function () {
describe('renders totals row', function () {
async function totalsRowTest(totalFunc, expected) {
+
function setDefaultTimezone() {
moment.tz.setDefault(settings.get('dateFormat:tz'));
}
@@ -229,18 +197,15 @@ describe('Table Vis - AggTable Directive', function () {
buckets: [
{ accessor: 0, params: {} },
{ accessor: 1, format: { id: 'date', params: { pattern: 'YYYY-MM-DD' } } },
- ],
- metrics: [
+ ], metrics: [
{ accessor: 2, format: { id: 'number' } },
{ accessor: 3, format: { id: 'date' } },
{ accessor: 4, format: { id: 'number' } },
{ accessor: 5, format: { id: 'number' } },
- ],
+ ]
};
const response = await tableAggResponse(
- tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative,
- $scope.dimensions
- );
+ tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative, $scope.dimensions);
$scope.table = response.tables[0];
$scope.showTotal = true;
$scope.totalFunc = totalFunc;
@@ -261,11 +226,7 @@ describe('Table Vis - AggTable Directive', function () {
expect($cells.length).to.be(6);
for (let i = 0; i < 6; i++) {
- expect(
- $($cells[i])
- .text()
- .trim()
- ).to.be(expected[i]);
+ expect($($cells[i]).text().trim()).to.be(expected[i]);
}
settings.set('dateFormat:tz', oldTimezoneSetting);
off();
@@ -280,7 +241,7 @@ describe('Table Vis - AggTable Directive', function () {
'9,283',
'Sep 28, 2014 @ 00:00:00.000',
'1',
- '11',
+ '11'
]);
});
it('as max', async function () {
@@ -290,22 +251,34 @@ describe('Table Vis - AggTable Directive', function () {
'220,943',
'Oct 3, 2014 @ 00:00:00.000',
'239',
- '837',
+ '837'
]);
});
it('as avg', async function () {
- await totalsRowTest('avg', ['', '', '87,221.5', '', '64.667', '206.833']);
+ await totalsRowTest('avg', [
+ '',
+ '',
+ '87,221.5',
+ '',
+ '64.667',
+ '206.833'
+ ]);
});
it('as sum', async function () {
- await totalsRowTest('sum', ['', '', '1,569,987', '', '1,164', '3,723']);
+ await totalsRowTest('sum', [
+ '',
+ '',
+ '1,569,987',
+ '',
+ '1,164',
+ '3,723'
+ ]);
});
});
describe('aggTable.toCsv()', function () {
it('escapes rows and columns properly', function () {
- const $el = $compile('
')(
- $scope
- );
+ const $el = $compile('
')($scope);
$scope.$digest();
const $tableScope = $el.isolateScope();
@@ -316,35 +289,25 @@ describe('Table Vis - AggTable Directive', function () {
{ id: 'b', name: 'two' },
{ id: 'c', name: 'with double-quotes(")' },
],
- rows: [{ a: 1, b: 2, c: '"foobar"' }],
+ rows: [
+ { a: 1, b: 2, c: '"foobar"' },
+ ],
};
expect(aggTable.toCsv()).to.be(
- 'one,two,"with double-quotes("")"' + '\r\n' + '1,2,"""foobar"""' + '\r\n'
+ 'one,two,"with double-quotes("")"' + '\r\n' +
+ '1,2,"""foobar"""' + '\r\n'
);
});
it('exports rows and columns properly', async function () {
$scope.dimensions = {
- buckets: [
- { accessor: 0, params: {} },
- { accessor: 2, params: {} },
- { accessor: 4, params: {} },
- ],
- metrics: [
- { accessor: 1, params: {} },
- { accessor: 3, params: {} },
- { accessor: 5, params: {} },
- ],
+ buckets: [{ accessor: 0, params: {} }, { accessor: 2, params: {} }, { accessor: 4, params: {} }],
+ metrics: [{ accessor: 1, params: {} }, { accessor: 3, params: {} }, { accessor: 5, params: {} }]
};
- $scope.table = (await tableAggResponse(
- tabifiedData.threeTermBuckets,
- $scope.dimensions
- )).tables[0];
+ $scope.table = (await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions)).tables[0];
- const $el = $compile('
')(
- $scope
- );
+ const $el = $compile('
')($scope);
$scope.$digest();
const $tableScope = $el.isolateScope();
@@ -353,56 +316,30 @@ describe('Table Vis - AggTable Directive', function () {
const raw = aggTable.toCsv(false);
expect(raw).to.be(
- '"extension: Descending","Average bytes","geo.src: Descending","Average bytes","machine.os: Descending","Average bytes"' +
- '\r\n' +
- 'png,IT,win,412032,9299,0' +
- '\r\n' +
- 'png,IT,mac,412032,9299,9299' +
- '\r\n' +
- 'png,US,linux,412032,8293,3992' +
- '\r\n' +
- 'png,US,mac,412032,8293,3029' +
- '\r\n' +
- 'css,MX,win,412032,9299,4992' +
- '\r\n' +
- 'css,MX,mac,412032,9299,5892' +
- '\r\n' +
- 'css,US,linux,412032,8293,3992' +
- '\r\n' +
- 'css,US,mac,412032,8293,3029' +
- '\r\n' +
- 'html,CN,win,412032,9299,4992' +
- '\r\n' +
- 'html,CN,mac,412032,9299,5892' +
- '\r\n' +
- 'html,FR,win,412032,8293,3992' +
- '\r\n' +
- 'html,FR,mac,412032,8293,3029' +
- '\r\n'
+ '"extension: Descending","Average bytes","geo.src: Descending","Average bytes","machine.os: Descending","Average bytes"' + '\r\n' +
+ 'png,IT,win,412032,9299,0' + '\r\n' +
+ 'png,IT,mac,412032,9299,9299' + '\r\n' +
+ 'png,US,linux,412032,8293,3992' + '\r\n' +
+ 'png,US,mac,412032,8293,3029' + '\r\n' +
+ 'css,MX,win,412032,9299,4992' + '\r\n' +
+ 'css,MX,mac,412032,9299,5892' + '\r\n' +
+ 'css,US,linux,412032,8293,3992' + '\r\n' +
+ 'css,US,mac,412032,8293,3029' + '\r\n' +
+ 'html,CN,win,412032,9299,4992' + '\r\n' +
+ 'html,CN,mac,412032,9299,5892' + '\r\n' +
+ 'html,FR,win,412032,8293,3992' + '\r\n' +
+ 'html,FR,mac,412032,8293,3029' + '\r\n'
);
});
it('exports formatted rows and columns properly', async function () {
$scope.dimensions = {
- buckets: [
- { accessor: 0, params: {} },
- { accessor: 2, params: {} },
- { accessor: 4, params: {} },
- ],
- metrics: [
- { accessor: 1, params: {} },
- { accessor: 3, params: {} },
- { accessor: 5, params: {} },
- ],
+ buckets: [{ accessor: 0, params: {} }, { accessor: 2, params: {} }, { accessor: 4, params: {} }],
+ metrics: [{ accessor: 1, params: {} }, { accessor: 3, params: {} }, { accessor: 5, params: {} }]
};
- $scope.table = (await tableAggResponse(
- tabifiedData.threeTermBuckets,
- $scope.dimensions
- )).tables[0];
+ $scope.table = (await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions)).tables[0];
- const $el = $compile('
')(
- $scope
- );
+ const $el = $compile('
')($scope);
$scope.$digest();
const $tableScope = $el.isolateScope();
@@ -414,32 +351,19 @@ describe('Table Vis - AggTable Directive', function () {
const formatted = aggTable.toCsv(true);
expect(formatted).to.be(
- '"extension: Descending","Average bytes","geo.src: Descending","Average bytes","machine.os: Descending","Average bytes"' +
- '\r\n' +
- '"png_formatted",IT,win,412032,9299,0' +
- '\r\n' +
- '"png_formatted",IT,mac,412032,9299,9299' +
- '\r\n' +
- '"png_formatted",US,linux,412032,8293,3992' +
- '\r\n' +
- '"png_formatted",US,mac,412032,8293,3029' +
- '\r\n' +
- '"css_formatted",MX,win,412032,9299,4992' +
- '\r\n' +
- '"css_formatted",MX,mac,412032,9299,5892' +
- '\r\n' +
- '"css_formatted",US,linux,412032,8293,3992' +
- '\r\n' +
- '"css_formatted",US,mac,412032,8293,3029' +
- '\r\n' +
- '"html_formatted",CN,win,412032,9299,4992' +
- '\r\n' +
- '"html_formatted",CN,mac,412032,9299,5892' +
- '\r\n' +
- '"html_formatted",FR,win,412032,8293,3992' +
- '\r\n' +
- '"html_formatted",FR,mac,412032,8293,3029' +
- '\r\n'
+ '"extension: Descending","Average bytes","geo.src: Descending","Average bytes","machine.os: Descending","Average bytes"' + '\r\n' +
+ '"png_formatted",IT,win,412032,9299,0' + '\r\n' +
+ '"png_formatted",IT,mac,412032,9299,9299' + '\r\n' +
+ '"png_formatted",US,linux,412032,8293,3992' + '\r\n' +
+ '"png_formatted",US,mac,412032,8293,3029' + '\r\n' +
+ '"css_formatted",MX,win,412032,9299,4992' + '\r\n' +
+ '"css_formatted",MX,mac,412032,9299,5892' + '\r\n' +
+ '"css_formatted",US,linux,412032,8293,3992' + '\r\n' +
+ '"css_formatted",US,mac,412032,8293,3029' + '\r\n' +
+ '"html_formatted",CN,win,412032,9299,4992' + '\r\n' +
+ '"html_formatted",CN,mac,412032,9299,5892' + '\r\n' +
+ '"html_formatted",FR,win,412032,8293,3992' + '\r\n' +
+ '"html_formatted",FR,mac,412032,8293,3029' + '\r\n'
);
});
});
@@ -528,7 +452,9 @@ describe('Table Vis - AggTable Directive', function () {
{ id: 'b', name: 'two' },
{ id: 'c', name: 'with double-quotes(")' },
],
- rows: [{ a: 1, b: 2, c: '"foobar"' }],
+ rows: [
+ { a: 1, b: 2, c: '"foobar"' },
+ ],
};
aggTable.csv.filename = 'somefilename.csv';
@@ -538,26 +464,25 @@ describe('Table Vis - AggTable Directive', function () {
const call = saveAs.getCall(0);
expect(call.args[0]).to.be.a(FakeBlob);
expect(call.args[0].slices).to.eql([
- 'one,two,"with double-quotes("")"' + '\r\n' + '1,2,"""foobar"""' + '\r\n',
+ 'one,two,"with double-quotes("")"' + '\r\n' +
+ '1,2,"""foobar"""' + '\r\n'
]);
expect(call.args[0].opts).to.eql({
- type: 'text/plain;charset=utf-8',
+ type: 'text/plain;charset=utf-8'
});
expect(call.args[1]).to.be('somefilename.csv');
});
it('should use the export-title attribute', function () {
const expected = 'export file name';
- const $el = $compile(
- `
`
- )($scope);
+ const $el = $compile(``)($scope);
$scope.$digest();
const $tableScope = $el.isolateScope();
const aggTable = $tableScope.aggTable;
$tableScope.table = {
columns: [],
- rows: [],
+ rows: []
};
$tableScope.exportTitle = expected;
$scope.$digest();
diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js
index 7998a92a4759f..5b9974d6ff4d5 100644
--- a/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js
+++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/__tests__/agg_table_group.js
@@ -28,7 +28,7 @@ import { tabifyAggResponse } from 'ui/agg_response/tabify';
import { VisFactoryProvider } from 'ui/vis/vis_factory';
import { createTableVisTypeDefinition } from '../../table_vis_type';
-import { setup } from '../../../../visualizations/public/np_ready/public/legacy';
+import { visualizations } from '../../../../visualizations/public';
describe('Table Vis - AggTableGroup Directive', function () {
let $rootScope;
@@ -49,8 +49,8 @@ describe('Table Vis - AggTableGroup Directive', function () {
{ type: 'avg', schema: 'metric', params: { field: 'bytes' } },
{ type: 'terms', schema: 'split', params: { field: 'extension' } },
{ type: 'terms', schema: 'segment', params: { field: 'geo.src' } },
- { type: 'terms', schema: 'segment', params: { field: 'machine.os' } },
- ],
+ { type: 'terms', schema: 'segment', params: { field: 'machine.os' } }
+ ]
});
vis2.aggs.aggs.forEach(function (agg, i) {
agg.id = 'agg_' + (i + 1);
@@ -59,25 +59,25 @@ describe('Table Vis - AggTableGroup Directive', function () {
};
beforeEach(ngMock.module('kibana'));
- beforeEach(
- ngMock.inject(function ($injector, Private) {
- legacyDependencies = {
- // eslint-disable-next-line new-cap
- createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization,
- };
+ beforeEach(ngMock.inject(function ($injector, Private) {
+ legacyDependencies = {
+ // eslint-disable-next-line new-cap
+ createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization
+ };
- setup.types.registerVisualization(() => createTableVisTypeDefinition(legacyDependencies));
+ visualizations.types.VisTypesRegistryProvider.register(() =>
+ createTableVisTypeDefinition(legacyDependencies)
+ );
- tableAggResponse = legacyResponseHandlerProvider().handler;
- indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
- Vis = Private(VisProvider);
+ tableAggResponse = legacyResponseHandlerProvider().handler;
+ indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
+ Vis = Private(VisProvider);
- $rootScope = $injector.get('$rootScope');
- $compile = $injector.get('$compile');
+ $rootScope = $injector.get('$rootScope');
+ $compile = $injector.get('$compile');
- init();
- })
- );
+ init();
+ }));
let $scope;
beforeEach(function () {
@@ -88,18 +88,13 @@ describe('Table Vis - AggTableGroup Directive', function () {
});
it('renders a simple split response properly', async function () {
- $scope.dimensions = {
- metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }],
- buckets: [],
- };
+ $scope.dimensions = { metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], buckets: [] };
$scope.group = await tableAggResponse(tabifiedData.metricOnly, $scope.dimensions);
$scope.sort = {
columnIndex: null,
- direction: null,
+ direction: null
};
- const $el = $(
- ''
- );
+ const $el = $('');
$compile($el)($scope);
$scope.$digest();
@@ -109,12 +104,10 @@ describe('Table Vis - AggTableGroup Directive', function () {
});
it('renders nothing if the table list is empty', function () {
- const $el = $(
- ''
- );
+ const $el = $('');
$scope.group = {
- tables: [],
+ tables: []
};
$compile($el)($scope);
@@ -128,19 +121,10 @@ describe('Table Vis - AggTableGroup Directive', function () {
$scope.dimensions = {
splitRow: [{ accessor: 0, params: {} }],
buckets: [{ accessor: 2, params: {} }, { accessor: 4, params: {} }],
- metrics: [
- { accessor: 1, params: {} },
- { accessor: 3, params: {} },
- { accessor: 5, params: {} },
- ],
+ metrics: [{ accessor: 1, params: {} }, { accessor: 3, params: {} }, { accessor: 5, params: {} }]
};
- const group = ($scope.group = await tableAggResponse(
- tabifiedData.threeTermBuckets,
- $scope.dimensions
- ));
- const $el = $(
- ''
- );
+ const group = $scope.group = await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions);
+ const $el = $('');
$compile($el)($scope);
$scope.$digest();
diff --git a/src/legacy/core_plugins/vis_type_table/public/legacy.ts b/src/legacy/core_plugins/vis_type_table/public/legacy.ts
index 8139a70552c48..fded5690a362d 100644
--- a/src/legacy/core_plugins/vis_type_table/public/legacy.ts
+++ b/src/legacy/core_plugins/vis_type_table/public/legacy.ts
@@ -22,11 +22,11 @@ import { npSetup, npStart } from 'ui/new_platform';
import { plugin } from '.';
import { TablePluginSetupDependencies } from './plugin';
-import { setup as setupVisualizations } from '../../visualizations/public/np_ready/public/legacy';
+import { visualizations } from '../../visualizations/public';
import { LegacyDependenciesPlugin } from './shim';
const plugins: Readonly = {
- visualizations: setupVisualizations,
+ visualizations,
data: npSetup.plugins.data,
// Temporary solution
diff --git a/src/legacy/core_plugins/vis_type_table/public/plugin.ts b/src/legacy/core_plugins/vis_type_table/public/plugin.ts
index 6a39e8079a9fd..21b6e21d6d639 100644
--- a/src/legacy/core_plugins/vis_type_table/public/plugin.ts
+++ b/src/legacy/core_plugins/vis_type_table/public/plugin.ts
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { VisualizationsSetup } from '../../visualizations/public/np_ready/public';
+import { VisualizationsSetup } from '../../visualizations/public';
import { Plugin as DataPublicPlugin } from '../../../../plugins/data/public';
import {
@@ -63,7 +63,7 @@ export class TableVisPlugin implements Plugin, void> {
data.expressions.registerFunction(createTableVisFn);
- visualizations.types.registerVisualization(() =>
+ visualizations.types.VisTypesRegistryProvider.register(() =>
createTableVisTypeDefinition(visualizationDependencies)
);
}
diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts b/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts
index 6a5e06b6e6978..01b2d99ce509c 100644
--- a/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts
+++ b/src/legacy/core_plugins/vis_type_tagcloud/public/legacy.ts
@@ -20,12 +20,12 @@
import { PluginInitializerContext } from 'kibana/public';
import { npSetup, npStart } from 'ui/new_platform';
-import { setup as setupVisualizations } from '../../visualizations/public/np_ready/public/legacy';
+import { visualizations } from '../../visualizations/public';
import { TagCloudPluginSetupDependencies } from './plugin';
import { plugin } from '.';
const plugins: Readonly = {
- visualizations: setupVisualizations,
+ visualizations,
data: npSetup.plugins.data,
};
diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/plugin.ts b/src/legacy/core_plugins/vis_type_tagcloud/public/plugin.ts
index e13e9896e3940..e7f633b4af377 100644
--- a/src/legacy/core_plugins/vis_type_tagcloud/public/plugin.ts
+++ b/src/legacy/core_plugins/vis_type_tagcloud/public/plugin.ts
@@ -19,7 +19,7 @@
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../../core/public';
import { Plugin as DataPublicPlugin } from '../../../../plugins/data/public';
-import { VisualizationsSetup } from '../../visualizations/public/np_ready/public';
+import { VisualizationsSetup } from '../../visualizations/public';
import { createTagCloudFn } from './tag_cloud_fn';
import { createTagCloudTypeDefinition } from './tag_cloud_type';
@@ -40,7 +40,7 @@ export class TagCloudPlugin implements Plugin {
public setup(core: CoreSetup, { data, visualizations }: TagCloudPluginSetupDependencies) {
data.expressions.registerFunction(createTagCloudFn);
- visualizations.types.registerVisualization(createTagCloudTypeDefinition);
+ visualizations.types.VisTypesRegistryProvider.register(createTagCloudTypeDefinition);
}
public start(core: CoreStart) {
diff --git a/src/legacy/core_plugins/vis_type_tagcloud/public/tag_cloud_type.ts b/src/legacy/core_plugins/vis_type_tagcloud/public/tag_cloud_type.ts
index 421821d93b045..0b4d90522cc44 100644
--- a/src/legacy/core_plugins/vis_type_tagcloud/public/tag_cloud_type.ts
+++ b/src/legacy/core_plugins/vis_type_tagcloud/public/tag_cloud_type.ts
@@ -23,7 +23,7 @@ import { Status } from 'ui/vis/update_status';
import { Schemas } from 'ui/vis/editors/default/schemas';
import { TagCloudOptions } from './components/tag_cloud_options';
-import { visFactory } from '../../visualizations/public/np_ready/public';
+import { visFactory } from '../../visualizations/public';
// @ts-ignore
import { TagCloudVisualization } from './components/tag_cloud_visualization';
diff --git a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js
index 012f144983e98..681f4486a02d7 100644
--- a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js
+++ b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js
@@ -41,10 +41,10 @@ import vegaMapImage256 from './vega_map_image_256.png';
import { VegaParser } from '../data_model/vega_parser';
import { SearchCache } from '../data_model/search_cache';
-import { setup } from '../../../visualizations/public/np_ready/public/legacy';
+import { visualizations } from '../../../visualizations/public';
import { createVegaTypeDefinition } from '../vega_type';
-const THRESHOLD = 0.1;
+const THRESHOLD = 0.10;
const PIXEL_DIFF = 30;
describe('VegaVisualizations', () => {
@@ -57,24 +57,22 @@ describe('VegaVisualizations', () => {
let vegaVisualizationDependencies;
beforeEach(ngMock.module('kibana'));
- beforeEach(
- ngMock.inject((Private, $injector) => {
- vegaVisualizationDependencies = {
- es: $injector.get('es'),
- serviceSettings: $injector.get('serviceSettings'),
- uiSettings: $injector.get('config'),
- };
+ beforeEach(ngMock.inject((Private, $injector) => {
+ vegaVisualizationDependencies = {
+ es: $injector.get('es'),
+ serviceSettings: $injector.get('serviceSettings'),
+ uiSettings: $injector.get('config'),
+ };
- setup.types.registerVisualization(() =>
- createVegaTypeDefinition(vegaVisualizationDependencies)
- );
+ visualizations.types.VisTypesRegistryProvider.register(() =>
+ createVegaTypeDefinition(vegaVisualizationDependencies)
+ );
- Vis = Private(visModule.VisProvider);
+ Vis = Private(visModule.VisProvider);
- VegaVisualization = createVegaVisualization(vegaVisualizationDependencies);
- indexPattern = Private(LogstashIndexPatternStubProvider);
- })
- );
+ VegaVisualization = createVegaVisualization(vegaVisualizationDependencies);
+ indexPattern = Private(LogstashIndexPatternStubProvider);
+ }));
describe('VegaVisualization - basics', () => {
beforeEach(async function () {
@@ -107,12 +105,15 @@ describe('VegaVisualizations', () => {
await vegaVis.render(vegaParser, vis.params, { resize: true });
const mismatchedPixels2 = await compareImage(vegaliteImage256);
expect(mismatchedPixels2).to.be.lessThan(PIXEL_DIFF);
+
} finally {
vegaVis.destroy();
}
+
});
it('should show vega graph', async function () {
+
let vegaVis;
try {
vegaVis = new VegaVisualization(domNode, vis);
@@ -126,16 +127,20 @@ describe('VegaVisualizations', () => {
} finally {
vegaVis.destroy();
}
+
});
it('should show vegatooltip on mouseover over a vega graph', async () => {
+
let vegaVis;
try {
+
vegaVis = new VegaVisualization(domNode, vis);
const vegaParser = new VegaParser(vegaTooltipGraph, new SearchCache());
await vegaParser.parseAsync();
await vegaVis.render(vegaParser, vis.params, { data: true });
+
const $el = $(domNode);
const offset = $el.offset();
@@ -155,24 +160,27 @@ describe('VegaVisualizations', () => {
expect(tooltip).to.be.ok();
expect(tooltip.innerHTML).to.be(
'This is a long title
' +
- '' +
- '| fieldA: | value of fld1 |
' +
- '| fld2: | 42 |
' +
- '
'
- );
+ '' +
+ '| fieldA: | value of fld1 |
' +
+ '| fld2: | 42 |
' +
+ '
');
vegaVis.destroy();
tooltip = document.getElementById('vega-kibana-tooltip');
expect(tooltip).to.not.be.ok();
+
} finally {
vegaVis.destroy();
}
+
});
it('should show vega blank rectangle on top of a map (vegamap)', async () => {
+
let vegaVis;
try {
+
vegaVis = new VegaVisualization(domNode, vis);
const vegaParser = new VegaParser(vegaMapGraph, new SearchCache());
await vegaParser.parseAsync();
@@ -183,17 +191,19 @@ describe('VegaVisualizations', () => {
await vegaVis.render(vegaParser, vis.params, { data: true });
const mismatchedPixels = await compareImage(vegaMapImage256);
expect(mismatchedPixels).to.be.lessThan(PIXEL_DIFF);
+
} finally {
vegaVis.destroy();
}
+
});
it('should add a small subpixel value to the height of the canvas to avoid getting it set to 0', async () => {
let vegaVis;
try {
+
vegaVis = new VegaVisualization(domNode, vis);
- const vegaParser = new VegaParser(
- `{
+ const vegaParser = new VegaParser(`{
"$schema": "https://vega.github.io/schema/vega/v3.json",
"marks": [
{
@@ -212,9 +222,7 @@ describe('VegaVisualizations', () => {
}
}
]
- }`,
- new SearchCache()
- );
+ }`, new SearchCache());
await vegaParser.parseAsync();
domNode.style.width = '256px';
@@ -232,8 +240,10 @@ describe('VegaVisualizations', () => {
vegaVis.destroy();
}
});
+
});
+
async function compareImage(expectedImageSource) {
const elementList = domNode.querySelectorAll('canvas');
expect(elementList.length).to.equal(1);
@@ -257,4 +267,5 @@ describe('VegaVisualizations', () => {
domNode.innerHTML = '';
document.body.removeChild(domNode);
}
+
});
diff --git a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts
index 15cf97beb5717..5136046b31a97 100644
--- a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts
+++ b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts
@@ -20,13 +20,13 @@
import { PluginInitializerContext } from 'kibana/public';
import { npSetup, npStart } from 'ui/new_platform';
-import { setup as setupVisualizations } from '../../visualizations/public/np_ready/public/legacy';
+import { visualizations } from '../../visualizations/public';
import { VegaPluginSetupDependencies } from './plugin';
import { LegacyDependenciesPlugin } from './shim';
import { plugin } from '.';
const plugins: Readonly = {
- visualizations: setupVisualizations,
+ visualizations,
data: npSetup.plugins.data,
// Temporary solution
diff --git a/src/legacy/core_plugins/vis_type_vega/public/plugin.ts b/src/legacy/core_plugins/vis_type_vega/public/plugin.ts
index b2a6fade883ca..039ef49cb2289 100644
--- a/src/legacy/core_plugins/vis_type_vega/public/plugin.ts
+++ b/src/legacy/core_plugins/vis_type_vega/public/plugin.ts
@@ -25,7 +25,7 @@ import {
} from '../../../../core/public';
import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim';
import { Plugin as DataPublicPlugin } from '../../../../plugins/data/public';
-import { VisualizationsSetup } from '../../visualizations/public/np_ready/public';
+import { VisualizationsSetup } from '../../visualizations/public';
import { createVegaFn } from './vega_fn';
import { createVegaTypeDefinition } from './vega_type';
@@ -61,7 +61,7 @@ export class VegaPlugin implements Plugin, void> {
data.expressions.registerFunction(() => createVegaFn(visualizationDependencies));
- visualizations.types.registerVisualization(() =>
+ visualizations.types.VisTypesRegistryProvider.register(() =>
createVegaTypeDefinition(visualizationDependencies)
);
}
diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts b/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts
index 22a71bd999d54..a930e369c3e1c 100644
--- a/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts
+++ b/src/legacy/core_plugins/vis_type_vega/public/vega_request_handler.ts
@@ -17,8 +17,7 @@
* under the License.
*/
import { Filter } from '@kbn/es-query';
-import { timefilter } from 'ui/timefilter';
-import { TimeRange } from 'src/plugins/data/public';
+import { timefilter, TimeRange } from 'ui/timefilter';
import { Query } from 'src/legacy/core_plugins/data/public';
// @ts-ignore
diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_type.ts b/src/legacy/core_plugins/vis_type_vega/public/vega_type.ts
index d1f04c794e3c6..6ffcd8867ffea 100644
--- a/src/legacy/core_plugins/vis_type_vega/public/vega_type.ts
+++ b/src/legacy/core_plugins/vis_type_vega/public/vega_type.ts
@@ -25,7 +25,7 @@ import { DefaultEditorSize } from 'ui/vis/editor_size';
import { defaultFeedbackMessage } from 'ui/vis/default_feedback_message';
import vegaEditorTemplate from './vega_editor_template.html';
-import { visFactory } from '../../visualizations/public/np_ready/public';
+import { visFactory } from '../../visualizations/public';
import { VegaVisualizationDependencies } from './plugin';
import { createVegaRequestHandler } from './vega_request_handler';
diff --git a/src/legacy/core_plugins/visualizations/index.ts b/src/legacy/core_plugins/visualizations/index.ts
index 3642071667f48..bb9ef1588bdc2 100644
--- a/src/legacy/core_plugins/visualizations/index.ts
+++ b/src/legacy/core_plugins/visualizations/index.ts
@@ -25,7 +25,7 @@ export default function VisualizationsPlugin(kibana: any) {
const config: Legacy.PluginSpecOptions = {
id: 'visualizations',
require: ['data'],
- publicDir: resolve(__dirname, 'public/np_ready/public'),
+ publicDir: resolve(__dirname, 'public'),
config: (Joi: any) => {
return Joi.object({
enabled: Joi.boolean().default(true),
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/filters/filters_service.ts b/src/legacy/core_plugins/visualizations/public/filters/filters_service.ts
similarity index 87%
rename from src/legacy/core_plugins/visualizations/public/np_ready/public/filters/filters_service.ts
rename to src/legacy/core_plugins/visualizations/public/filters/filters_service.ts
index 51709f365dbbd..60c26d7cbdc1d 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/filters/filters_service.ts
+++ b/src/legacy/core_plugins/visualizations/public/filters/filters_service.ts
@@ -17,10 +17,8 @@
* under the License.
*/
-interface SetupDependecies {
- VisFiltersProvider: any;
- createFilter: any;
-}
+// @ts-ignore
+import { VisFiltersProvider, createFilter } from 'ui/vis/vis_filters';
/**
* Vis Filters Service
@@ -28,7 +26,7 @@ interface SetupDependecies {
* @internal
*/
export class FiltersService {
- public setup({ VisFiltersProvider, createFilter }: SetupDependecies) {
+ public setup() {
return {
VisFiltersProvider,
createFilter,
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/filters/index.ts b/src/legacy/core_plugins/visualizations/public/filters/index.ts
similarity index 100%
rename from src/legacy/core_plugins/visualizations/public/np_ready/public/filters/index.ts
rename to src/legacy/core_plugins/visualizations/public/filters/index.ts
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts b/src/legacy/core_plugins/visualizations/public/index.ts
similarity index 53%
rename from src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts
rename to src/legacy/core_plugins/visualizations/public/index.ts
index d38acaa3cf3f2..10fef3112335b 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts
+++ b/src/legacy/core_plugins/visualizations/public/index.ts
@@ -17,11 +17,43 @@
* under the License.
*/
-import { PluginInitializerContext } from 'src/core/public';
-import { VisualizationsPublicPlugin, Setup } from './plugin';
+import { FiltersService, FiltersSetup } from './filters';
+import { TypesService, TypesSetup } from './types';
+
+class VisualizationsPlugin {
+ private readonly filters: FiltersService;
+ private readonly types: TypesService;
+
+ constructor() {
+ this.filters = new FiltersService();
+ this.types = new TypesService();
+ }
+
+ public setup() {
+ return {
+ filters: this.filters.setup(),
+ types: this.types.setup(),
+ };
+ }
+
+ public stop() {
+ this.filters.stop();
+ this.types.stop();
+ }
+}
+
+/**
+ * We export visualizations here so that users importing from 'plugins/visualizations'
+ * will automatically receive the response value of the `setup` contract, mimicking
+ * the data that will eventually be injected by the new platform.
+ */
+export const visualizations = new VisualizationsPlugin().setup();
/** @public */
-export type VisualizationsSetup = Setup;
+export interface VisualizationsSetup {
+ filters: FiltersSetup;
+ types: TypesSetup;
+}
/** @public types */
export {
@@ -37,9 +69,3 @@ export {
VisTypesRegistry,
Status,
} from './types';
-
-export function plugin(initializerContext: PluginInitializerContext) {
- return new VisualizationsPublicPlugin(initializerContext);
-}
-
-export { VisualizationsPublicPlugin as Plugin };
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/kibana.json b/src/legacy/core_plugins/visualizations/public/np_ready/kibana.json
deleted file mode 100644
index 8ecf3dfce6e94..0000000000000
--- a/src/legacy/core_plugins/visualizations/public/np_ready/kibana.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "id": "visualizations",
- "version": "kibana",
- "requiredPlugins": [
- ],
- "server": false,
- "ui": true
- }
-
\ No newline at end of file
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy.ts
deleted file mode 100644
index 04a49294bd0c6..0000000000000
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy.ts
+++ /dev/null
@@ -1,50 +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.
- */
-/* eslint-disable @kbn/eslint/no-restricted-paths */
-import { npSetup, npStart } from 'ui/new_platform';
-// @ts-ignore
-import { VisFiltersProvider, createFilter } from 'ui/vis/vis_filters';
-// @ts-ignore
-import { defaultFeedbackMessage } from 'ui/vis/default_feedback_message';
-// @ts-ignore
-import { VisProvider as Vis } from 'ui/vis/index.js';
-// @ts-ignore
-import { VisFactoryProvider } from 'ui/vis/vis_factory';
-import { VisTypesRegistryProvider } from 'ui/registry/vis_types';
-/* eslint-enable @kbn/eslint/no-restricted-paths */
-
-import { visTypeAliasRegistry } from './types/vis_type_alias_registry';
-
-import { plugin } from '.';
-
-const pluginInstance = plugin({} as any);
-
-export const setup = pluginInstance.setup(npSetup.core, {
- __LEGACY: {
- VisFiltersProvider,
- createFilter,
-
- Vis,
- VisFactoryProvider,
- VisTypesRegistryProvider,
- defaultFeedbackMessage,
- visTypeAliasRegistry,
- },
-});
-export const start = pluginInstance.start(npStart.core);
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts
deleted file mode 100644
index df5e4d25dedcc..0000000000000
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts
+++ /dev/null
@@ -1,92 +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.
- */
-
-/* eslint-disable @kbn/eslint/no-restricted-paths */
-jest.mock('ui/vis/vis_filters');
-jest.mock('ui/vis/default_feedback_message');
-jest.mock('ui/vis/index.js');
-jest.mock('ui/vis/vis_factory');
-jest.mock('ui/registry/vis_types');
-// @ts-ignore
-import { VisFiltersProvider, createFilter } from 'ui/vis/vis_filters';
-// @ts-ignore
-import { defaultFeedbackMessage } from 'ui/vis/default_feedback_message';
-// @ts-ignore
-import { VisProvider as Vis } from 'ui/vis/index.js';
-// @ts-ignore
-import { VisFactoryProvider } from 'ui/vis/vis_factory';
-import { VisTypesRegistryProvider } from 'ui/registry/vis_types';
-/* eslint-enable @kbn/eslint/no-restricted-paths */
-jest.mock('./types/vis_type_alias_registry');
-import { visTypeAliasRegistry } from './types/vis_type_alias_registry';
-
-import { Plugin } from '.';
-import { coreMock } from '../../../../../../core/public/mocks';
-
-export type Setup = jest.Mocked>;
-export type Start = jest.Mocked>;
-
-const createSetupContract = (): Setup => ({
- filters: {
- VisFiltersProvider: jest.fn(),
- createFilter: jest.fn(),
- },
- types: {
- Vis,
- VisFactoryProvider: jest.fn(),
- registerVisualization: jest.fn(),
- defaultFeedbackMessage,
- visTypeAliasRegistry: {
- add: jest.fn(),
- get: jest.fn(),
- },
- },
-});
-
-const createStartContract = (): Start => {};
-
-const createInstance = () => {
- const plugin = new Plugin({} as any);
-
- const setup = plugin.setup(coreMock.createSetup(), {
- __LEGACY: {
- VisFiltersProvider,
- createFilter,
-
- Vis,
- VisFactoryProvider,
- VisTypesRegistryProvider,
- defaultFeedbackMessage,
- visTypeAliasRegistry,
- },
- });
- const doStart = () => plugin.start(coreMock.createStart());
-
- return {
- plugin,
- setup,
- doStart,
- };
-};
-
-export const visualizationsPluginMock = {
- createSetupContract,
- createStartContract,
- createInstance,
-};
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
deleted file mode 100644
index abf5974b77532..0000000000000
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts
+++ /dev/null
@@ -1,88 +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 { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public';
-
-import { FiltersService, FiltersSetup } from './filters';
-import { TypesService, TypesSetup } from './types';
-import { VisTypeAliasRegistry } from './types/vis_type_alias_registry';
-
-interface SetupDependencies {
- __LEGACY: {
- VisFiltersProvider: any;
- createFilter: any;
-
- Vis: any;
- VisFactoryProvider: any;
- VisTypesRegistryProvider: any;
- defaultFeedbackMessage: any;
- visTypeAliasRegistry: VisTypeAliasRegistry;
- };
-}
-
-export interface Setup {
- filters: FiltersSetup;
- types: TypesSetup;
-}
-
-export type Start = void;
-
-export class VisualizationsPublicPlugin implements Plugin {
- private readonly filters: FiltersService;
- private readonly types: TypesService;
-
- constructor(initializerContext: PluginInitializerContext) {
- this.filters = new FiltersService();
- this.types = new TypesService();
- }
-
- public setup(core: CoreSetup, { __LEGACY }: SetupDependencies) {
- const {
- VisFiltersProvider,
- createFilter,
- Vis,
- VisFactoryProvider,
- VisTypesRegistryProvider,
- defaultFeedbackMessage,
- visTypeAliasRegistry,
- } = __LEGACY;
-
- return {
- filters: this.filters.setup({
- VisFiltersProvider,
- createFilter,
- }),
- types: this.types.setup({
- Vis,
- VisFactoryProvider,
- VisTypesRegistryProvider,
- defaultFeedbackMessage,
- visTypeAliasRegistry,
- }),
- };
- }
-
- public start(core: CoreStart) {
- // Do nothing yet...
- }
-
- public stop() {
- this.filters.stop();
- this.types.stop();
- }
-}
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/types/index.ts b/src/legacy/core_plugins/visualizations/public/types/index.ts
similarity index 100%
rename from src/legacy/core_plugins/visualizations/public/np_ready/public/types/index.ts
rename to src/legacy/core_plugins/visualizations/public/types/index.ts
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/types/types_service.ts b/src/legacy/core_plugins/visualizations/public/types/types_service.ts
similarity index 72%
rename from src/legacy/core_plugins/visualizations/public/np_ready/public/types/types_service.ts
rename to src/legacy/core_plugins/visualizations/public/types/types_service.ts
index 28574917ba1bb..cb5328812b406 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/types/types_service.ts
+++ b/src/legacy/core_plugins/visualizations/public/types/types_service.ts
@@ -17,23 +17,18 @@
* under the License.
*/
-/* eslint-disable @kbn/eslint/no-restricted-paths */
// @ts-ignore
-import { visFactory } from 'ui/vis/vis_factory';
+import { defaultFeedbackMessage } from 'ui/vis/default_feedback_message';
+// @ts-ignore
+import { VisProvider as Vis } from 'ui/vis/index.js';
+// @ts-ignore
+import { VisFactoryProvider, visFactory } from 'ui/vis/vis_factory';
// @ts-ignore
import { DefaultEditorSize } from 'ui/vis/editor_size';
+import { VisTypesRegistryProvider } from 'ui/registry/vis_types';
import * as types from 'ui/vis/vis';
-/* eslint-enable @kbn/eslint/no-restricted-paths */
-import { VisTypeAliasRegistry, VisTypeAlias } from './vis_type_alias_registry';
-
-interface SetupDependencies {
- Vis: any;
- VisFactoryProvider: any;
- VisTypesRegistryProvider: any;
- defaultFeedbackMessage: any;
- visTypeAliasRegistry: VisTypeAliasRegistry;
-}
+import { visTypeAliasRegistry, VisTypeAlias } from './vis_type_alias_registry';
/**
* Vis Types Service
@@ -41,19 +36,11 @@ interface SetupDependencies {
* @internal
*/
export class TypesService {
- public setup({
- Vis,
- VisFactoryProvider,
- VisTypesRegistryProvider,
- defaultFeedbackMessage,
- visTypeAliasRegistry,
- }: SetupDependencies) {
+ public setup() {
return {
Vis,
VisFactoryProvider,
- registerVisualization: (registerFn: () => any) => {
- VisTypesRegistryProvider.register(registerFn);
- },
+ VisTypesRegistryProvider,
defaultFeedbackMessage, // make default in base vis type, or move?
visTypeAliasRegistry,
};
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/types/vis_type_alias_registry.ts b/src/legacy/core_plugins/visualizations/public/types/vis_type_alias_registry.ts
similarity index 90%
rename from src/legacy/core_plugins/visualizations/public/np_ready/public/types/vis_type_alias_registry.ts
rename to src/legacy/core_plugins/visualizations/public/types/vis_type_alias_registry.ts
index eb84f93a0d3ba..91040cf966567 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/types/vis_type_alias_registry.ts
+++ b/src/legacy/core_plugins/visualizations/public/types/vis_type_alias_registry.ts
@@ -52,12 +52,7 @@ export interface VisTypeAlias {
const registry: VisTypeAlias[] = [];
-export interface VisTypeAliasRegistry {
- get: () => VisTypeAlias[];
- add: (newVisTypeAlias: VisTypeAlias) => void;
-}
-
-export const visTypeAliasRegistry: VisTypeAliasRegistry = {
+export const visTypeAliasRegistry = {
get: () => [...registry],
add: (newVisTypeAlias: VisTypeAlias) => {
if (registry.find(visTypeAlias => visTypeAlias.name === newVisTypeAlias.name)) {
diff --git a/src/legacy/ui/field_formats/__tests__/field_format.js b/src/legacy/ui/field_formats/__tests__/field_format.js
new file mode 100644
index 0000000000000..bf8ff9f33b18c
--- /dev/null
+++ b/src/legacy/ui/field_formats/__tests__/field_format.js
@@ -0,0 +1,180 @@
+/*
+ * 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 _ from 'lodash';
+import expect from '@kbn/expect';
+import { asPrettyString } from '../../../core_plugins/kibana/common/utils/as_pretty_string';
+import { FieldFormat } from '../field_format';
+
+describe('FieldFormat class', function () {
+
+ let TestFormat;
+
+ beforeEach(function () {
+ TestFormat = class _TestFormat extends FieldFormat {
+ static id = 'test-format';
+ static title = 'Test Format';
+ _convert(val) {
+ return asPrettyString(val);
+ }
+ };
+ });
+
+ describe('params', function () {
+ it('accepts its params via the constructor', function () {
+ const f = new TestFormat({ foo: 'bar' });
+ expect(f.param('foo')).to.be('bar');
+ });
+
+ it('allows reading a clone of the params', function () {
+ const params = { foo: 'bar' };
+ const f = new TestFormat(params);
+ const output = f.params();
+ expect(output).to.eql(params);
+ expect(output).to.not.be(params);
+ });
+ });
+
+ describe('type', function () {
+ it('links the constructor class to instances as the `type`', function () {
+ const f = new TestFormat();
+ expect(f.type).to.be(TestFormat);
+ });
+ });
+
+ describe('toJSON', function () {
+ it('serializes to a version a basic id and param pair', function () {
+ const f = new TestFormat({ foo: 'bar' });
+ const ser = JSON.parse(JSON.stringify(f));
+ expect(ser).to.eql({ id: 'test-format', params: { foo: 'bar' } });
+ });
+
+ it('removes param values that match the defaults', function () {
+ TestFormat.prototype.getParamDefaults = function () {
+ return { foo: 'bar' };
+ };
+
+ const f = new TestFormat({ foo: 'bar', baz: 'bar' });
+ const ser = JSON.parse(JSON.stringify(f));
+ expect(ser.params).to.eql({ baz: 'bar' });
+ });
+
+ it('removes the params entirely if they are empty', function () {
+ const f = new TestFormat();
+ const ser = JSON.parse(JSON.stringify(f));
+ expect(ser).to.not.have.property('params');
+ });
+ });
+
+ describe('converters', function () {
+ describe('#getConverterFor', function () {
+ it('returns a converter for a specific content type', function () {
+ const f = new TestFormat();
+ expect(f.getConverterFor('html')()).to.be.a('string');
+ expect(f.getConverterFor('text')()).to.be.a('string');
+ });
+ });
+
+ describe('#_convert, the instance method or methods used to format values', function () {
+ it('can be a function, which gets converted to a text and html converter', function () {
+ TestFormat.prototype._convert = function () {
+ return 'formatted';
+ };
+
+ const f = new TestFormat();
+ const text = f.getConverterFor('text');
+ const html = f.getConverterFor('html');
+ expect(text).to.not.be(html);
+ expect(text('formatted')).to.be('formatted');
+ expect(html('formatted')).to.be('formatted');
+ });
+
+ it('can be an object, with separate text and html converter', function () {
+ TestFormat.prototype._convert = {
+ text: _.constant('formatted text'),
+ html: _.constant('formatted html'),
+ };
+
+ const f = new TestFormat();
+ const text = f.getConverterFor('text');
+ const html = f.getConverterFor('html');
+ expect(text).to.not.be(html);
+ expect(text('formatted text')).to.be('formatted text');
+ expect(html('formatted html')).to.be('formatted html');
+ });
+
+ it('does not escape the output of the text converter', function () {
+ TestFormat.prototype._convert = _.constant('');
+ const f = new TestFormat();
+ expect(f.convert('', 'text')).to.contain('<');
+ });
+
+ it('does escape the output of the text converter if used in an html context', function () {
+ TestFormat.prototype._convert = _.constant('');
+ const f = new TestFormat();
+ expect(_.trimRight(_.trimLeft(f.convert('', 'html'), ''), ''))
+ .to.not.contain('<');
+ });
+
+ it('does not escape the output of an html specific converter', function () {
+ TestFormat.prototype._convert = {
+ text: _.constant('
'),
+ html: _.constant('
'),
+ };
+
+ const f = new TestFormat();
+ expect(f.convert('', 'text')).to.be('
');
+ expect(f.convert('', 'html')).to.be('
');
+ });
+ });
+
+ describe('#convert', function () {
+ it('formats a value, defaulting to text content type', function () {
+ TestFormat.prototype._convert = {
+ text: _.constant('text'),
+ html: _.constant('html'),
+ };
+
+ const f = new TestFormat();
+ expect(f.convert('val')).to.be('text');
+ });
+
+ it('formats a value as html, when specified via second param', function () {
+ TestFormat.prototype._convert = {
+ text: _.constant('text'),
+ html: _.constant('html'),
+ };
+
+ const f = new TestFormat();
+ expect(f.convert('val', 'html')).to.be('html');
+ });
+
+ it('formats a value as " - " when no value is specified', function () {
+ const f = new TestFormat();
+ expect(f.convert()).to.be(' - ');
+ });
+
+ it('formats a list of values as text', function () {
+ const f = new TestFormat();
+ expect(f.convert(['one', 'two', 'three'])).to.be('["one","two","three"]');
+ });
+ });
+
+ });
+});
diff --git a/src/legacy/ui/field_formats/__tests__/field_formats_mixin.js b/src/legacy/ui/field_formats/__tests__/field_formats_mixin.js
new file mode 100644
index 0000000000000..8f513fe28c98b
--- /dev/null
+++ b/src/legacy/ui/field_formats/__tests__/field_formats_mixin.js
@@ -0,0 +1,83 @@
+/*
+ * 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 sinon from 'sinon';
+
+import { FieldFormat } from '../field_format';
+import * as FieldFormatsServiceNS from '../field_formats_service';
+import { fieldFormatsMixin } from '../field_formats_mixin';
+
+describe('server.registerFieldFormat(createFormat)', () => {
+ const sandbox = sinon.createSandbox();
+
+ let registerFieldFormat;
+ let fieldFormatServiceFactory;
+ const serverMock = { decorate() {} };
+ beforeEach(async () => {
+ sandbox.stub(serverMock);
+ await fieldFormatsMixin({}, serverMock);
+ [[,, fieldFormatServiceFactory], [,, registerFieldFormat]] = serverMock.decorate.args;
+ });
+
+ afterEach(() => sandbox.restore());
+
+ it('throws if createFormat is not a function', () => {
+ expect(() => registerFieldFormat()).to.throwError(error => {
+ expect(error.message).to.match(/createFormat is not a function/i);
+ });
+ });
+
+ it('calls the createFormat() function with the FieldFormat class', () => {
+ const createFormat = sinon.stub();
+ registerFieldFormat(createFormat);
+ sinon.assert.calledOnce(createFormat);
+ sinon.assert.calledWithExactly(createFormat, sinon.match.same(FieldFormat));
+ });
+
+ it('passes the returned class to the FieldFormatsService', async () => {
+ const { FieldFormatsService: ActualFFS } = FieldFormatsServiceNS;
+ sandbox.stub(FieldFormatsServiceNS, 'FieldFormatsService').callsFake((...args) => {
+ return new ActualFFS(...args);
+ });
+
+ const { FieldFormatsService } = FieldFormatsServiceNS;
+ class FooFormat {
+ static id = 'foo'
+ }
+ registerFieldFormat(() => FooFormat);
+
+ const fieldFormats = await fieldFormatServiceFactory({
+ getAll: () => ({}),
+ getDefaults: () => ({})
+ });
+
+ sinon.assert.calledOnce(FieldFormatsService);
+ sinon.assert.calledWithExactly(
+ FieldFormatsService,
+ // array of fieldFormat classes
+ [sinon.match.same(FooFormat)],
+ // getConfig() function
+ sinon.match.func
+ );
+
+ const format = fieldFormats.getInstance({ id: 'foo' });
+ expect(format).to.be.a(FooFormat);
+ });
+});
diff --git a/src/legacy/ui/field_formats/__tests__/field_formats_service.js b/src/legacy/ui/field_formats/__tests__/field_formats_service.js
new file mode 100644
index 0000000000000..9ae80462c2a07
--- /dev/null
+++ b/src/legacy/ui/field_formats/__tests__/field_formats_service.js
@@ -0,0 +1,52 @@
+/*
+ * 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 { FieldFormat } from '../field_format';
+import { FieldFormatsService } from '../field_formats_service';
+import { createNumberFormat } from '../../../core_plugins/kibana/common/field_formats/types/number';
+
+describe('FieldFormatsService', function () {
+
+ const config = {};
+ config['format:defaultTypeMap'] = {
+ 'number': { 'id': 'number', 'params': {} },
+ '_default_': { 'id': 'string', 'params': {} }
+ };
+ config['format:number:defaultPattern'] = '0,0.[000]';
+ const getConfig = (key) => config[key];
+ const fieldFormatClasses = [createNumberFormat(FieldFormat)];
+
+ let fieldFormats;
+ beforeEach(function () {
+ fieldFormats = new FieldFormatsService(fieldFormatClasses, getConfig);
+ });
+
+ it('FieldFormats are accessible via getType method', function () {
+ const Type = fieldFormats.getType('number');
+ expect(Type.id).to.be('number');
+ });
+
+ it('getDefaultInstance returns default FieldFormat instance for fieldType', function () {
+ const instance = fieldFormats.getDefaultInstance('number', getConfig);
+ expect(instance.type.id).to.be('number');
+ expect(instance.convert('0.33333')).to.be('0.333');
+ });
+
+});
diff --git a/src/legacy/ui/field_formats/content_types.js b/src/legacy/ui/field_formats/content_types.js
new file mode 100644
index 0000000000000..39a5cac7b9027
--- /dev/null
+++ b/src/legacy/ui/field_formats/content_types.js
@@ -0,0 +1,84 @@
+/*
+ * 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 _ from 'lodash';
+import { asPrettyString } from '../../core_plugins/kibana/common/utils/as_pretty_string';
+import { getHighlightHtml } from '../../core_plugins/kibana/common/highlight/highlight_html';
+
+const types = {
+ html: function (format, convert) {
+ function recurse(value, field, hit, meta) {
+ if (value == null) {
+ return asPrettyString(value);
+ }
+
+ if (!value || typeof value.map !== 'function') {
+ return convert.call(format, value, field, hit, meta);
+ }
+
+ const subVals = value.map(v => {
+ return recurse(v, field, hit, meta);
+ });
+ const useMultiLine = subVals.some(sub => {
+ return sub.indexOf('\n') > -1;
+ });
+
+ return subVals.join(',' + (useMultiLine ? '\n' : ' '));
+ }
+
+ return function (...args) {
+ return `${recurse(...args)}`;
+ };
+ },
+
+ text: function (format, convert) {
+ return function recurse(value) {
+ if (!value || typeof value.map !== 'function') {
+ return convert.call(format, value);
+ }
+
+ // format a list of values. In text contexts we just use JSON encoding
+ return JSON.stringify(value.map(recurse));
+ };
+ }
+};
+
+function fallbackText(value) {
+ return asPrettyString(value);
+}
+
+function fallbackHtml(value, field, hit) {
+ const formatted = _.escape(this.convert(value, 'text'));
+
+ if (!hit || !hit.highlight || !hit.highlight[field.name]) {
+ return formatted;
+ } else {
+ return getHighlightHtml(formatted, hit.highlight[field.name]);
+ }
+}
+
+export function contentTypesSetup(format) {
+ const src = format._convert || {};
+ const converters = format._convert = {};
+
+ converters.text = types.text(format, src.text || fallbackText);
+ converters.html = types.html(format, src.html || fallbackHtml);
+
+ return format._convert;
+}
diff --git a/src/legacy/ui/field_formats/content_types/html_content_type.ts b/src/legacy/ui/field_formats/content_types/html_content_type.ts
deleted file mode 100644
index 21cdb21d16895..0000000000000
--- a/src/legacy/ui/field_formats/content_types/html_content_type.ts
+++ /dev/null
@@ -1,76 +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 { escape, isFunction } from 'lodash';
-import { FieldFormatConvert, IFieldFormat, HtmlConventTypeConvert } from '../types';
-
-// @ts-ignore
-import { asPrettyString } from '../../../core_plugins/kibana/common/utils/as_pretty_string';
-// @ts-ignore
-import { getHighlightHtml } from '../../../core_plugins/kibana/common/highlight/highlight_html';
-
-const CONTEXT_TYPE = 'html';
-
-const getConvertFn = (
- format: IFieldFormat,
- fieldFormatConvert: FieldFormatConvert
-): HtmlConventTypeConvert => {
- const fallbackHtml: HtmlConventTypeConvert = (value, field, hit) => {
- const formatted = escape(format.convert(value, 'text'));
-
- return !field || !hit || !hit.highlight || !hit.highlight[field.name]
- ? formatted
- : getHighlightHtml(formatted, hit.highlight[field.name]);
- };
-
- return (fieldFormatConvert[CONTEXT_TYPE] || fallbackHtml) as HtmlConventTypeConvert;
-};
-
-export const setup = (
- format: IFieldFormat,
- fieldFormatConvert: FieldFormatConvert
-): FieldFormatConvert => {
- const convert = getConvertFn(format, fieldFormatConvert);
-
- const recurse: HtmlConventTypeConvert = (value, field, hit, meta) => {
- if (value == null) {
- return asPrettyString(value);
- }
-
- if (!value || !isFunction(value.map)) {
- return convert.call(format, value, field, hit, meta);
- }
-
- const subValues = value.map((v: any) => {
- return recurse(v, field, hit, meta);
- });
- const useMultiLine = subValues.some((sub: any) => {
- return sub.indexOf('\n') > -1;
- });
-
- return subValues.join(',' + (useMultiLine ? '\n' : ' '));
- };
-
- const wrap: HtmlConventTypeConvert = (value, field, hit, meta) => {
- return `${recurse(value, field, hit, meta)}`;
- };
-
- return {
- [CONTEXT_TYPE]: wrap,
- };
-};
diff --git a/src/legacy/ui/field_formats/content_types/index.ts b/src/legacy/ui/field_formats/content_types/index.ts
deleted file mode 100644
index b5d98a7bc8393..0000000000000
--- a/src/legacy/ui/field_formats/content_types/index.ts
+++ /dev/null
@@ -1,21 +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.
- */
-
-export { setup as textContentTypeSetup } from './text_content_type';
-export { setup as htmlContentTypeSetup } from './html_content_type';
diff --git a/src/legacy/ui/field_formats/content_types/text_content_type.ts b/src/legacy/ui/field_formats/content_types/text_content_type.ts
deleted file mode 100644
index 0a6983f8f1a87..0000000000000
--- a/src/legacy/ui/field_formats/content_types/text_content_type.ts
+++ /dev/null
@@ -1,47 +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 { isFunction } from 'lodash';
-import { IFieldFormat, FieldFormatConvert, TextContextTypeConvert } from '../types';
-
-// @ts-ignore
-import { asPrettyString } from '../../../core_plugins/kibana/common/utils/as_pretty_string';
-
-const CONTEXT_TYPE = 'text';
-
-const getConvertFn = (fieldFormatConvert: FieldFormatConvert): TextContextTypeConvert =>
- (fieldFormatConvert[CONTEXT_TYPE] || asPrettyString) as TextContextTypeConvert;
-
-export const setup = (
- format: IFieldFormat,
- fieldFormatConvert: FieldFormatConvert
-): FieldFormatConvert => {
- const convert = getConvertFn(fieldFormatConvert);
-
- const recurse: TextContextTypeConvert = value => {
- if (!value || !isFunction(value.map)) {
- return convert.call(format, value);
- }
-
- // format a list of values. In text contexts we just use JSON encoding
- return JSON.stringify(value.map(recurse));
- };
-
- return { [CONTEXT_TYPE]: recurse };
-};
diff --git a/src/legacy/ui/field_formats/field_format.js b/src/legacy/ui/field_formats/field_format.js
new file mode 100644
index 0000000000000..21e4946a86b48
--- /dev/null
+++ b/src/legacy/ui/field_formats/field_format.js
@@ -0,0 +1,123 @@
+/*
+ * 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 _ from 'lodash';
+import { contentTypesSetup } from './content_types';
+
+export function FieldFormat(params) {
+ // give the constructor a more appropriate name
+ this.type = this.constructor;
+
+ // keep the params and defaults separate
+ this._params = params || {};
+
+ // one content type, so assume text
+ if (_.isFunction(this._convert)) {
+ this._convert = { text: this._convert };
+ }
+
+ contentTypesSetup(this);
+}
+
+FieldFormat.from = function (converter) {
+ class FieldFormatFromConverter extends FieldFormat {}
+ FieldFormatFromConverter.prototype._convert = converter;
+ return FieldFormatFromConverter;
+};
+
+/**
+ * Convert a raw value to a formated string
+ * @param {any} value
+ * @param {string} [contentType=text] - optional content type, the only two contentTypes
+ * currently supported are "html" and "text", which helps
+ * formatters adjust to different contexts
+ * @return {string} - the formatted string, which is assumed to be html, safe for
+ * injecting into the DOM or a DOM attribute
+ */
+FieldFormat.prototype.convert = function (value, contentType) {
+ return this.getConverterFor(contentType)(value);
+};
+
+/**
+ * Get a convert function that is bound to a specific contentType
+ * @param {string} [contentType=text]
+ * @return {function} - a bound converter function
+ */
+FieldFormat.prototype.getConverterFor = function (contentType) {
+ return this._convert[contentType || 'text'];
+};
+
+/**
+ * Get parameter defaults
+ * @return {object} - parameter defaults
+ */
+FieldFormat.prototype.getParamDefaults = function () {
+ return {};
+};
+
+/**
+ * Get the value of a param. This value may be a default value.
+ *
+ * @param {string} name - the param name to fetch
+ * @return {any}
+ */
+FieldFormat.prototype.param = function (name) {
+ const val = this._params[name];
+ if (val || val === false || val === 0) {
+ // truthy, false, or 0 are fine
+ // '', NaN, null, undefined, etc are not
+ return val;
+ }
+
+ return this.getParamDefaults()[name];
+};
+
+/**
+ * Get all of the params in a single object
+ * @return {object}
+ */
+FieldFormat.prototype.params = function () {
+ return _.cloneDeep(_.defaults({}, this._params, this.getParamDefaults()));
+};
+
+/**
+ * serialize this format to a simple POJO, with only the params
+ * that are not default
+ *
+ * @return {object}
+ */
+FieldFormat.prototype.toJSON = function () {
+ const type = this.type;
+ const defaults = this.getParamDefaults();
+
+ let params = _.transform(this._params, function (uniqParams, val, param) {
+ if (val !== defaults[param]) {
+ uniqParams[param] = val;
+ }
+ }, {});
+
+ if (!_.size(params)) {
+ params = undefined;
+ }
+
+ return {
+ id: type.id,
+ params: params
+ };
+};
diff --git a/src/legacy/ui/field_formats/field_format.test.ts b/src/legacy/ui/field_formats/field_format.test.ts
deleted file mode 100644
index 05912d5b5f4a8..0000000000000
--- a/src/legacy/ui/field_formats/field_format.test.ts
+++ /dev/null
@@ -1,187 +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 { constant, trimRight, trimLeft, get } from 'lodash';
-import { FieldFormat } from './field_format';
-import { FieldFormatConvert } from './types';
-
-// @ts-ignore
-import { asPrettyString } from '../../core_plugins/kibana/common/utils/as_pretty_string';
-
-const getTestFormat = (
- _convert: FieldFormatConvert = {
- text: (val: string) => asPrettyString(val),
- },
- _params?: any
-) =>
- new (class TestFormat extends FieldFormat {
- static id = 'test-format';
- static title = 'Test Format';
-
- public get _convert() {
- return _convert;
- }
- })(_params);
-
-describe('FieldFormat class', () => {
- describe('params', () => {
- test('accepts its params via the constructor', () => {
- const f = getTestFormat(undefined, { foo: 'bar' });
- const fooParam = f.param('foo');
-
- expect(fooParam).toBe('bar');
- });
-
- test('allows reading a clone of the params', () => {
- const params = { foo: 'bar' };
- const f = getTestFormat(undefined, params);
- const output = f.params();
-
- expect(output).toEqual(params);
- expect(output).not.toBe(params);
- });
- });
-
- describe('type', () => {
- test('links the constructor class to instances as the `type`', () => {
- const f = getTestFormat();
-
- expect(get(f.type, 'id')).toBe('test-format');
- expect(get(f.type, 'title')).toBe('Test Format');
- });
- });
-
- describe('toJSON', () => {
- it('serializes to a version a basic id and param pair', () => {
- const f = getTestFormat(undefined, { foo: 'bar' });
- const ser = JSON.parse(JSON.stringify(f));
-
- expect(ser).toEqual({ id: 'test-format', params: { foo: 'bar' } });
- });
-
- it('removes the params entirely if they are empty', () => {
- const f = getTestFormat();
- const ser = JSON.parse(JSON.stringify(f));
-
- expect(ser).not.toHaveProperty('params');
- });
- });
-
- describe('converters', () => {
- describe('#getConverterFor', () => {
- it('returns a converter for a specific content type', () => {
- const f = getTestFormat();
- const htmlConverter = f.getConverterFor('html');
- const textConverter = f.getConverterFor('text');
-
- expect(htmlConverter && typeof htmlConverter('')).toBe('string');
- expect(textConverter && typeof textConverter('')).toBe('string');
- });
- });
-
- describe('#_convert, the instance method or methods used to format values', () => {
- it('can be a function, which gets converted to a text and html converter', () => {
- const f = getTestFormat({
- text: () => 'formatted',
- });
- const text = f.getConverterFor('text');
- const html = f.getConverterFor('html');
-
- expect(text).not.toBe(html);
- expect(text && text('formatted')).toBe('formatted');
- expect(html && html('formatted')).toBe('formatted');
- });
-
- it('can be an object, with separate text and html converter', () => {
- const f = getTestFormat({
- text: constant('formatted text'),
- html: constant('formatted html'),
- });
- const text = f.getConverterFor('text');
- const html = f.getConverterFor('html');
-
- expect(text).not.toBe(html);
- expect(text && text('formatted text')).toBe('formatted text');
- expect(html && html('formatted html')).toBe('formatted html');
- });
-
- it('does not escape the output of the text converter', () => {
- const f = getTestFormat({
- text: constant(''),
- });
-
- expect(f.convert('', 'text')).toContain('<');
- });
-
- it('does escape the output of the text converter if used in an html context', () => {
- const f = getTestFormat({
- text: constant(''),
- });
-
- const expected = trimRight(
- trimLeft(f.convert('', 'html'), ''),
- ''
- );
-
- expect(expected).not.toContain('<');
- });
-
- it('does not escape the output of an html specific converter', function() {
- const f = getTestFormat({
- text: constant('
'),
- html: constant('
'),
- });
- expect(f.convert('', 'text')).toBe('
');
- expect(f.convert('', 'html')).toBe('
');
- });
- });
-
- describe('#convert', () => {
- it('formats a value, defaulting to text content type', () => {
- const f = getTestFormat({
- text: constant('text'),
- html: constant('html'),
- });
-
- expect(f.convert('val')).toBe('text');
- });
-
- it('formats a value as html, when specified via second param', () => {
- const f = getTestFormat({
- text: constant('text'),
- html: constant('html'),
- });
-
- expect(f.convert('val', 'html')).toBe('html');
- });
-
- it('formats a value as " - " when no value is specified', () => {
- const f = getTestFormat();
-
- expect(f.convert(undefined)).toBe(' - ');
- });
-
- it('formats a list of values as text', () => {
- const f = getTestFormat();
-
- expect(f.convert(['one', 'two', 'three'])).toBe('["one","two","three"]');
- });
- });
- });
-});
diff --git a/src/legacy/ui/field_formats/field_format.ts b/src/legacy/ui/field_formats/field_format.ts
deleted file mode 100644
index 226631660b8a0..0000000000000
--- a/src/legacy/ui/field_formats/field_format.ts
+++ /dev/null
@@ -1,191 +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 { isFunction, transform, size, cloneDeep, get, defaults } from 'lodash';
-import { createCustomFieldFormat } from './converters/custom';
-import { ContentType, FieldFormatConvert, FieldFormatConvertFunction } from './types';
-
-import { htmlContentTypeSetup, textContentTypeSetup } from './content_types';
-
-const DEFAULT_CONTEXT_TYPE = 'text';
-
-export abstract class FieldFormat {
- /**
- * @property {string} - Field Format Id
- * @static
- * @public
- */
- static id: string;
- /**
- * @property {string} - Field Format Title
- * @static
- * @public
- */
- static title: string;
-
- /**
- * @property {string} - Field Format Type
- * @private
- */
- static fieldType: string;
-
- /**
- * @property {FieldFormatConvert}
- * @private
- */
- _convert: FieldFormatConvert = FieldFormat.setupContentType(this, get(this, '_convert', {}));
-
- /**
- * @property {Function} - ref to child class
- * @private
- */
- type: any = this.constructor;
-
- constructor(public _params: any = {}) {}
-
- /**
- * Convert a raw value to a formatted string
- * @param {any} value
- * @param {string} [contentType=text] - optional content type, the only two contentTypes
- * currently supported are "html" and "text", which helps
- * formatters adjust to different contexts
- * @return {string} - the formatted string, which is assumed to be html, safe for
- * injecting into the DOM or a DOM attribute
- * @public
- */
- convert(value: any, contentType: ContentType = DEFAULT_CONTEXT_TYPE): string {
- const converter = this.getConverterFor(contentType);
-
- if (converter) {
- return converter.call(this, value);
- }
-
- return value;
- }
-
- /**
- * Get a convert function that is bound to a specific contentType
- * @param {string} [contentType=text]
- * @return {function} - a bound converter function
- * @public
- */
- getConverterFor(
- contentType: ContentType = DEFAULT_CONTEXT_TYPE
- ): FieldFormatConvertFunction | null {
- if (this._convert) {
- return this._convert[contentType];
- }
-
- return null;
- }
-
- /**
- * Get parameter defaults
- * @return {object} - parameter defaults
- * @public
- */
- getParamDefaults(): Record {
- return {};
- }
-
- /**
- * Get the value of a param. This value may be a default value.
- *
- * @param {string} name - the param name to fetch
- * @return {any}
- * @public
- */
- param(name: string): any {
- const val = get(this._params, name);
-
- if (val || val === false || val === 0) {
- // truthy, false, or 0 are fine
- // '', NaN, null, undefined, etc are not
- return val;
- }
-
- return get(this.getParamDefaults(), name);
- }
-
- /**
- * Get all of the params in a single object
- * @return {object}
- * @public
- */
- params(): Record {
- return cloneDeep(defaults({}, this._params, this.getParamDefaults()));
- }
-
- /**
- * Serialize this format to a simple POJO, with only the params
- * that are not default
- *
- * @return {object}
- * @public
- */
- toJSON() {
- const id = get(this.type, 'id');
- const defaultsParams = this.getParamDefaults() || {};
-
- const params = transform(
- this._params,
- (uniqParams, val, param) => {
- if (param && val !== get(defaultsParams, param)) {
- uniqParams[param] = val;
- }
- },
- {}
- );
-
- return {
- id,
- params: size(params) ? params : undefined,
- };
- }
-
- static from(convertFn: FieldFormatConvertFunction) {
- return createCustomFieldFormat(FieldFormat.toConvertObject(convertFn));
- }
-
- private static setupContentType(
- fieldFormat: IFieldFormat,
- convert: FieldFormatConvert | FieldFormatConvertFunction
- ): FieldFormatConvert {
- const convertObject = FieldFormat.toConvertObject(convert);
-
- return {
- ...textContentTypeSetup(fieldFormat, convertObject),
- ...htmlContentTypeSetup(fieldFormat, convertObject),
- };
- }
-
- private static toConvertObject(
- convert: FieldFormatConvert | FieldFormatConvertFunction
- ): FieldFormatConvert {
- if (isFunction(convert)) {
- return {
- [DEFAULT_CONTEXT_TYPE]: convert,
- };
- }
- return convert;
- }
-}
-
-export type FieldFormatConvert = { [key: string]: Function } | FieldFormatConvertFunction;
-export type IFieldFormat = PublicMethodsOf;
diff --git a/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts b/src/legacy/ui/field_formats/field_formats_mixin.js
similarity index 72%
rename from src/legacy/ui/field_formats/mixin/field_formats_mixin.ts
rename to src/legacy/ui/field_formats/field_formats_mixin.js
index 6f20ab8cdf51f..76c72102ebff7 100644
--- a/src/legacy/ui/field_formats/mixin/field_formats_mixin.ts
+++ b/src/legacy/ui/field_formats/field_formats_mixin.js
@@ -17,29 +17,27 @@
* under the License.
*/
-import { has } from 'lodash';
-import { Legacy } from 'kibana';
+import _ from 'lodash';
import { FieldFormatsService } from './field_formats_service';
-import { FieldFormat } from '../field_format';
+import { FieldFormat } from './field_format';
-export function fieldFormatsMixin(kbnServer: any, server: Legacy.Server) {
- const fieldFormatClasses: FieldFormat[] = [];
+export function fieldFormatsMixin(kbnServer, server) {
+ const fieldFormatClasses = [];
// for use outside of the request context, for special cases
- server.decorate('server', 'fieldFormatServiceFactory', async function(uiSettings) {
+ server.decorate('server', 'fieldFormatServiceFactory', async function (uiSettings) {
const uiConfigs = await uiSettings.getAll();
const uiSettingDefaults = await uiSettings.getDefaults();
- Object.keys(uiSettingDefaults).forEach(key => {
- if (has(uiConfigs, key) && uiSettingDefaults[key].type === 'json') {
+ Object.keys(uiSettingDefaults).forEach((key) => {
+ if (_.has(uiConfigs, key) && uiSettingDefaults[key].type === 'json') {
uiConfigs[key] = JSON.parse(uiConfigs[key]);
}
});
- const getConfig = (key: string) => uiConfigs[key];
-
+ const getConfig = (key) => uiConfigs[key];
return new FieldFormatsService(fieldFormatClasses, getConfig);
});
- server.decorate('server', 'registerFieldFormat', createFormat => {
+ server.decorate('server', 'registerFieldFormat', (createFormat) => {
fieldFormatClasses.push(createFormat(FieldFormat));
});
}
diff --git a/src/legacy/ui/field_formats/mixin/field_formats_service.ts b/src/legacy/ui/field_formats/field_formats_service.js
similarity index 66%
rename from src/legacy/ui/field_formats/mixin/field_formats_service.ts
rename to src/legacy/ui/field_formats/field_formats_service.js
index 779157f5c418b..9584f78046c35 100644
--- a/src/legacy/ui/field_formats/mixin/field_formats_service.ts
+++ b/src/legacy/ui/field_formats/field_formats_service.js
@@ -17,20 +17,11 @@
* under the License.
*/
-import { indexBy, Dictionary } from 'lodash';
-import { FieldFormat } from '../field_format';
-
-interface FieldFormatConfig {
- id: string;
- params?: Record;
-}
+import _ from 'lodash';
export class FieldFormatsService {
- getConfig: any;
- _fieldFormats: Dictionary;
-
- constructor(fieldFormatClasses: FieldFormat[], getConfig: Function) {
- this._fieldFormats = indexBy(fieldFormatClasses, 'id');
+ constructor(fieldFormatClasses, getConfig) {
+ this._fieldFormats = _.indexBy(fieldFormatClasses, 'id');
this.getConfig = getConfig;
}
@@ -39,9 +30,9 @@ export class FieldFormatsService {
* using the format:defaultTypeMap config map
*
* @param {String} fieldType - the field type
- * @return {FieldFormatConfig}
+ * @return {String}
*/
- getDefaultConfig(fieldType: string): FieldFormatConfig {
+ getDefaultConfig(fieldType) {
const defaultMap = this.getConfig('format:defaultTypeMap');
return defaultMap[fieldType] || defaultMap._default_;
}
@@ -52,19 +43,21 @@ export class FieldFormatsService {
* @param {String} fieldType
* @return {FieldFormat}
*/
- getDefaultInstance(fieldType: string): FieldFormat {
- return this.getInstance(this.getDefaultConfig(fieldType));
+ getDefaultInstance(fieldType) {
+ const conf = this.getDefaultConfig(fieldType);
+ const FieldFormat = this._fieldFormats[conf.id];
+ return new FieldFormat(conf.params, this.getConfig);
}
/**
* Get the fieldFormat instance for a field format configuration.
*
- * @param {FieldFormatConfig} field format config
+ * @param {Object} conf:id, conf:params
* @return {FieldFormat}
*/
- getInstance(conf: FieldFormatConfig): FieldFormat {
- // @ts-ignore
- return new this._fieldFormats[conf.id](conf.params, this.getConfig);
+ getInstance(conf) {
+ const FieldFormat = this._fieldFormats[conf.id];
+ return new FieldFormat(conf.params, this.getConfig);
}
/**
@@ -73,7 +66,7 @@ export class FieldFormatsService {
* @param {String} fieldFormatId - the FieldFormat id
* @return {FieldFormat}
*/
- getType(fieldFormatId: string): any {
+ getType(fieldFormatId) {
return this._fieldFormats[fieldFormatId];
}
}
diff --git a/src/legacy/ui/field_formats/index.ts b/src/legacy/ui/field_formats/index.js
similarity index 92%
rename from src/legacy/ui/field_formats/index.ts
rename to src/legacy/ui/field_formats/index.js
index cb15ba7a6b0ae..1bbad4800a363 100644
--- a/src/legacy/ui/field_formats/index.ts
+++ b/src/legacy/ui/field_formats/index.js
@@ -17,5 +17,5 @@
* under the License.
*/
-export { fieldFormatsMixin } from './mixin/field_formats_mixin';
+export { fieldFormatsMixin } from './field_formats_mixin';
export { FieldFormat } from './field_format';
diff --git a/src/legacy/ui/field_formats/mixin/field_formats_service.test.ts b/src/legacy/ui/field_formats/mixin/field_formats_service.test.ts
deleted file mode 100644
index 32f1579510c64..0000000000000
--- a/src/legacy/ui/field_formats/mixin/field_formats_service.test.ts
+++ /dev/null
@@ -1,59 +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 { FieldFormat } from '../field_format';
-import { FieldFormatsService } from './field_formats_service';
-
-// @ts-ignore
-import { createNumberFormat } from '../../../core_plugins/kibana/common/field_formats/types/number';
-
-const getConfig = (key: string) => {
- switch (key) {
- case 'format:defaultTypeMap':
- return {
- number: { id: 'number', params: {} },
- _default_: { id: 'string', params: {} },
- };
- case 'format:number:defaultPattern':
- return '0,0.[000]';
- }
-};
-
-describe('FieldFormatsService', function() {
- let fieldFormatsService: FieldFormatsService;
-
- beforeEach(function() {
- const fieldFormatClasses = [createNumberFormat(FieldFormat)];
-
- fieldFormatsService = new FieldFormatsService(fieldFormatClasses, getConfig);
- });
-
- test('FieldFormats are accessible via getType method', function() {
- const Type = fieldFormatsService.getType('number');
-
- expect(Type.id).toBe('number');
- });
-
- test('getDefaultInstance returns default FieldFormat instance for fieldType', function() {
- const instance = fieldFormatsService.getDefaultInstance('number');
-
- expect(instance.type.id).toBe('number');
- expect(instance.convert('0.33333')).toBe('0.333');
- });
-});
diff --git a/src/legacy/ui/field_formats/types.ts b/src/legacy/ui/field_formats/types.ts
deleted file mode 100644
index f5238422020c2..0000000000000
--- a/src/legacy/ui/field_formats/types.ts
+++ /dev/null
@@ -1,45 +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 { Field } from '../../core_plugins/data/public/index_patterns';
-
-/** @public **/
-export type ContentType = 'html' | 'text';
-
-/** @public **/
-export { IFieldFormat } from './field_format';
-
-/** @internal **/
-export type HtmlConventTypeConvert = (
- value: any,
- field?: Field,
- hit?: Record,
- meta?: any
-) => string;
-
-/** @internal **/
-export type TextContextTypeConvert = (value: any) => string;
-
-/** @internal **/
-export type FieldFormatConvertFunction = HtmlConventTypeConvert | TextContextTypeConvert;
-
-/** @internal **/
-export interface FieldFormatConvert {
- [key: string]: FieldFormatConvertFunction;
-}
diff --git a/src/legacy/ui/public/_index.scss b/src/legacy/ui/public/_index.scss
index e7d85b8cc3f8e..1c3a9c006acfd 100644
--- a/src/legacy/ui/public/_index.scss
+++ b/src/legacy/ui/public/_index.scss
@@ -19,7 +19,6 @@
@import './exit_full_screen/index';
@import './field_editor/index';
@import './notify/index';
-@import './saved_objects/index';
@import './share/index';
@import './style_compile/index';
diff --git a/src/legacy/ui/public/chrome/chrome.js b/src/legacy/ui/public/chrome/chrome.js
index a5a0521013a6e..8f58da9107673 100644
--- a/src/legacy/ui/public/chrome/chrome.js
+++ b/src/legacy/ui/public/chrome/chrome.js
@@ -95,6 +95,7 @@ const waitForBootstrap = new Promise(resolve => {
document.body.setAttribute('id', `${internals.app.id}-app`);
chrome.setupAngular();
+ // targetDomElement.setAttribute('id', 'kibana-body');
targetDomElement.setAttribute('kbn-chrome', 'true');
targetDomElement.setAttribute('ng-class', '{ \'hidden-chrome\': !chrome.getVisible() }');
targetDomElement.className = 'app-wrapper';
diff --git a/src/legacy/ui/public/chrome/directives/kbn_chrome.js b/src/legacy/ui/public/chrome/directives/kbn_chrome.js
index 755cb8b42d363..d81a1ceb5f288 100644
--- a/src/legacy/ui/public/chrome/directives/kbn_chrome.js
+++ b/src/legacy/ui/public/chrome/directives/kbn_chrome.js
@@ -77,21 +77,15 @@ export function kbnChromeProvider(chrome, internals) {
// Non-scope based code (e.g., React)
// Banners
- const bannerListContainer = document.getElementById('globalBannerList');
- // Banners not supported in New Platform yet
- // https://github.com/elastic/kibana/issues/41986
- if (bannerListContainer) {
- ReactDOM.render(
-
-
- ,
- bannerListContainer
- );
- }
-
+ ReactDOM.render(
+
+
+ ,
+ document.getElementById('globalBannerList')
+ );
return chrome;
}
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/__snapshots__/string.test.js.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/__snapshots__/string.test.js.snap
index 5561fbec68b3b..1b48a8e6a7250 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/__snapshots__/string.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/__snapshots__/string.test.js.snap
@@ -58,10 +58,6 @@ exports[`StringFormatEditor should render normally 1`] = `
"input": "SGVsbG8gd29ybGQ=",
"output": "SGVSBG8GD29YBGQ=",
},
- Object {
- "input": "%EC%95%88%EB%85%95%20%ED%82%A4%EB%B0%94%EB%82%98",
- "output": "%EC%95%88%EB%85%95%20%ED%82%A4%EB%B0%94%EB%82%98",
- },
]
}
/>
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/string.js b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/string.js
index 9aacc7899afee..8d3c1d9fca1c8 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/string.js
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/string.js
@@ -44,8 +44,7 @@ export class StringFormatEditor extends DefaultFormatEditor {
'STAY CALM!',
'com.organizations.project.ClassName',
'hostname.net',
- 'SGVsbG8gd29ybGQ=',
- '%EC%95%88%EB%85%95%20%ED%82%A4%EB%B0%94%EB%82%98'
+ 'SGVsbG8gd29ybGQ='
];
}
diff --git a/src/legacy/ui/public/legacy_compat/angular_config.tsx b/src/legacy/ui/public/legacy_compat/angular_config.tsx
index 28d57e9f8e8c9..1e22003b32833 100644
--- a/src/legacy/ui/public/legacy_compat/angular_config.tsx
+++ b/src/legacy/ui/public/legacy_compat/angular_config.tsx
@@ -33,7 +33,7 @@ import * as Rx from 'rxjs';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { CoreStart, LegacyCoreStart } from 'kibana/public';
+import { InternalCoreStart } from 'kibana/public';
import { fatalError } from 'ui/notify';
import { capabilities } from 'ui/capabilities';
@@ -77,7 +77,7 @@ export const configureAppAngularModule = (angularModule: IModule) => {
.run($setupUrlOverflowHandling(newPlatform));
};
-const getEsUrl = (newPlatform: CoreStart) => {
+const getEsUrl = (newPlatform: InternalCoreStart) => {
const a = document.createElement('a');
a.href = newPlatform.http.basePath.prepend('/elasticsearch');
const protocolPort = /https/.test(a.protocol) ? 443 : 80;
@@ -90,7 +90,7 @@ const getEsUrl = (newPlatform: CoreStart) => {
};
};
-const setupCompileProvider = (newPlatform: LegacyCoreStart) => (
+const setupCompileProvider = (newPlatform: InternalCoreStart) => (
$compileProvider: ICompileProvider
) => {
if (!newPlatform.injectedMetadata.getLegacyMetadata().devMode) {
@@ -98,7 +98,7 @@ const setupCompileProvider = (newPlatform: LegacyCoreStart) => (
}
};
-const setupLocationProvider = (newPlatform: CoreStart) => (
+const setupLocationProvider = (newPlatform: InternalCoreStart) => (
$locationProvider: ILocationProvider
) => {
$locationProvider.html5Mode({
@@ -110,7 +110,7 @@ const setupLocationProvider = (newPlatform: CoreStart) => (
$locationProvider.hashPrefix('');
};
-export const $setupXsrfRequestInterceptor = (newPlatform: LegacyCoreStart) => {
+export const $setupXsrfRequestInterceptor = (newPlatform: InternalCoreStart) => {
const version = newPlatform.injectedMetadata.getLegacyMetadata().version;
// Configure jQuery prefilter
@@ -145,7 +145,7 @@ export const $setupXsrfRequestInterceptor = (newPlatform: LegacyCoreStart) => {
* @param {HttpService} $http
* @return {undefined}
*/
-const capture$httpLoadingCount = (newPlatform: CoreStart) => (
+const capture$httpLoadingCount = (newPlatform: InternalCoreStart) => (
$rootScope: IRootScopeService,
$http: IHttpService
) => {
@@ -166,7 +166,7 @@ const capture$httpLoadingCount = (newPlatform: CoreStart) => (
* lets us integrate with the angular router so that we can automatically clear
* the breadcrumbs if we switch to a Kibana app that does not use breadcrumbs correctly
*/
-const $setupBreadcrumbsAutoClear = (newPlatform: CoreStart) => (
+const $setupBreadcrumbsAutoClear = (newPlatform: InternalCoreStart) => (
$rootScope: IRootScopeService,
$injector: any
) => {
@@ -213,7 +213,7 @@ const $setupBreadcrumbsAutoClear = (newPlatform: CoreStart) => (
* lets us integrate with the angular router so that we can automatically clear
* the badge if we switch to a Kibana app that does not use the badge correctly
*/
-const $setupBadgeAutoClear = (newPlatform: CoreStart) => (
+const $setupBadgeAutoClear = (newPlatform: InternalCoreStart) => (
$rootScope: IRootScopeService,
$injector: any
) => {
@@ -253,7 +253,7 @@ const $setupBadgeAutoClear = (newPlatform: CoreStart) => (
* the helpExtension if we switch to a Kibana app that does not set its own
* helpExtension
*/
-const $setupHelpExtensionAutoClear = (newPlatform: CoreStart) => (
+const $setupHelpExtensionAutoClear = (newPlatform: InternalCoreStart) => (
$rootScope: IRootScopeService,
$injector: any
) => {
@@ -285,7 +285,7 @@ const $setupHelpExtensionAutoClear = (newPlatform: CoreStart) => (
});
};
-const $setupUrlOverflowHandling = (newPlatform: CoreStart) => (
+const $setupUrlOverflowHandling = (newPlatform: InternalCoreStart) => (
$location: ILocationService,
$rootScope: IRootScopeService,
Private: any,
diff --git a/src/legacy/ui/public/new_platform/new_platform.ts b/src/legacy/ui/public/new_platform/new_platform.ts
index 4f55349e3efe2..5e0eb2feeb450 100644
--- a/src/legacy/ui/public/new_platform/new_platform.ts
+++ b/src/legacy/ui/public/new_platform/new_platform.ts
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { LegacyCoreSetup, LegacyCoreStart } from '../../../../core/public';
+import { InternalCoreSetup, InternalCoreStart } from '../../../../core/public';
import { Plugin as DataPlugin } from '../../../../plugins/data/public';
import {
Setup as InspectorSetup,
@@ -34,12 +34,12 @@ export interface PluginsStart {
}
export const npSetup = {
- core: (null as unknown) as LegacyCoreSetup,
+ core: (null as unknown) as InternalCoreSetup,
plugins: {} as PluginsSetup,
};
export const npStart = {
- core: (null as unknown) as LegacyCoreStart,
+ core: (null as unknown) as InternalCoreStart,
plugins: {} as PluginsStart,
};
@@ -48,18 +48,18 @@ export const npStart = {
* @internal
*/
export function __reset__() {
- npSetup.core = (null as unknown) as LegacyCoreSetup;
+ npSetup.core = (null as unknown) as InternalCoreSetup;
npSetup.plugins = {} as any;
- npStart.core = (null as unknown) as LegacyCoreStart;
+ npStart.core = (null as unknown) as InternalCoreStart;
npStart.plugins = {} as any;
}
-export function __setup__(coreSetup: LegacyCoreSetup, plugins: PluginsSetup) {
+export function __setup__(coreSetup: InternalCoreSetup, plugins: PluginsSetup) {
npSetup.core = coreSetup;
npSetup.plugins = plugins;
}
-export function __start__(coreStart: LegacyCoreStart, plugins: PluginsStart) {
+export function __start__(coreStart: InternalCoreStart, plugins: PluginsStart) {
npStart.core = coreStart;
npStart.plugins = plugins;
}
diff --git a/src/legacy/ui/public/saved_objects/_index.scss b/src/legacy/ui/public/saved_objects/_index.scss
deleted file mode 100644
index 50a192b6a7b17..0000000000000
--- a/src/legacy/ui/public/saved_objects/_index.scss
+++ /dev/null
@@ -1 +0,0 @@
-@import '../../../../plugins/kibana_react/public/saved_objects/index';
diff --git a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.js
similarity index 52%
rename from src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx
rename to src/legacy/ui/public/saved_objects/show_saved_object_save_modal.js
index 6aea3c72e0c34..bd2fbba3aa145 100644
--- a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx
+++ b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.js
@@ -21,25 +21,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { I18nContext } from 'ui/i18n';
-/**
- * Represents the result of trying to persist the saved object.
- * Contains `error` prop if something unexpected happened (e.g. network error).
- * Contains an `id` if persisting was successful. If `id` and
- * `error` are undefined, persisting was not successful, but the
- * modal can still recover (e.g. the name of the saved object was already taken).
- */
-export type SaveResult = { id?: string } | { error: Error };
-
-function isSuccess(result: SaveResult): result is { id?: string } {
- return 'id' in result;
-}
-
-interface MinimalSaveModalProps {
- onSave: (...args: any[]) => Promise;
- onClose: () => void;
-}
-
-export function showSaveModal(saveModal: React.ReactElement) {
+export function showSaveModal(saveModal) {
const container = document.createElement('div');
const closeModal = () => {
ReactDOM.unmountComponentAtNode(container);
@@ -48,19 +30,21 @@ export function showSaveModal(saveModal: React.ReactElement {
- const response = await onSave(...args);
- // close modal if we either hit an error or the saved object got an id
- if (Boolean(isSuccess(response) ? response.id : response.error)) {
- closeModal();
- }
- return response;
+ const onSaveConfirmed = (...args) => {
+ onSave(...args).then(({ id, error }) => {
+ if (id || error) {
+ closeModal();
+ }
+ });
};
document.body.appendChild(container);
- const element = React.cloneElement(saveModal, {
- onSave: onSaveConfirmed,
- onClose: closeModal,
- });
+ const element = React.cloneElement(
+ saveModal,
+ {
+ onSave: onSaveConfirmed,
+ onClose: closeModal
+ }
+ );
ReactDOM.render({element}, container);
}
diff --git a/src/legacy/core_plugins/data/public/timefilter/get_time.test.ts b/src/legacy/ui/public/timefilter/get_time.test.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/get_time.test.ts
rename to src/legacy/ui/public/timefilter/get_time.test.ts
diff --git a/src/legacy/core_plugins/data/public/timefilter/get_time.ts b/src/legacy/ui/public/timefilter/get_time.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/get_time.ts
rename to src/legacy/ui/public/timefilter/get_time.ts
diff --git a/src/legacy/ui/public/timefilter/index.ts b/src/legacy/ui/public/timefilter/index.ts
index 34f2a367a217c..5f5fcf6b19c7f 100644
--- a/src/legacy/ui/public/timefilter/index.ts
+++ b/src/legacy/ui/public/timefilter/index.ts
@@ -17,16 +17,8 @@
* under the License.
*/
-import uiRoutes from 'ui/routes';
-import { registerTimefilterWithGlobalState, getTimefilterConfig } from './setup_router';
-import { Timefilter, TimeHistory } from '../../../core_plugins/data/public/timefilter';
+export { TimeRange, RefreshInterval } from '../../../../plugins/data/public';
-const config = getTimefilterConfig();
-
-export { Timefilter, TimeHistory, getTime } from '../../../core_plugins/data/public/timefilter';
-export const timeHistory = new TimeHistory();
-export const timefilter = new Timefilter(config, timeHistory);
-
-uiRoutes.addSetupWork((globalState, $rootScope) => {
- return registerTimefilterWithGlobalState(timefilter, globalState, $rootScope);
-});
+export { timefilter, Timefilter, registerTimefilterWithGlobalState } from './timefilter';
+export { timeHistory, TimeHistory } from './time_history';
+export { getTime } from './get_time';
diff --git a/src/legacy/core_plugins/data/public/timefilter/lib/diff_time_picker_vals.test.ts b/src/legacy/ui/public/timefilter/lib/diff_time_picker_vals.test.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/lib/diff_time_picker_vals.test.ts
rename to src/legacy/ui/public/timefilter/lib/diff_time_picker_vals.test.ts
diff --git a/src/legacy/core_plugins/data/public/timefilter/lib/diff_time_picker_vals.ts b/src/legacy/ui/public/timefilter/lib/diff_time_picker_vals.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/lib/diff_time_picker_vals.ts
rename to src/legacy/ui/public/timefilter/lib/diff_time_picker_vals.ts
diff --git a/src/legacy/core_plugins/data/public/timefilter/lib/parse_querystring.ts b/src/legacy/ui/public/timefilter/lib/parse_querystring.ts
similarity index 100%
rename from src/legacy/core_plugins/data/public/timefilter/lib/parse_querystring.ts
rename to src/legacy/ui/public/timefilter/lib/parse_querystring.ts
diff --git a/src/legacy/ui/public/timefilter/setup_router.ts b/src/legacy/ui/public/timefilter/setup_router.ts
deleted file mode 100644
index cbd03df455da3..0000000000000
--- a/src/legacy/ui/public/timefilter/setup_router.ts
+++ /dev/null
@@ -1,89 +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 _ from 'lodash';
-import { IScope } from 'angular';
-import moment from 'moment';
-import { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
-import chrome from 'ui/chrome';
-import { RefreshInterval, TimeRange } from 'src/plugins/data/public';
-import { Timefilter } from '../../../core_plugins/data/public/timefilter';
-
-// TODO
-// remove everything underneath once globalState is no longer an angular service
-// and listener can be registered without angular.
-function convertISO8601(stringTime: string): string {
- const obj = moment(stringTime, 'YYYY-MM-DDTHH:mm:ss.SSSZ', true);
- return obj.isValid() ? obj.toString() : stringTime;
-}
-
-export function getTimefilterConfig() {
- const settings = chrome.getUiSettingsClient();
- return {
- timeDefaults: settings.get('timepicker:timeDefaults'),
- refreshIntervalDefaults: settings.get('timepicker:refreshIntervalDefaults'),
- };
-}
-
-// Currently some parts of Kibana (index patterns, timefilter) rely on addSetupWork in the uiRouter
-// and require it to be executed to properly function.
-// This function is exposed for applications that do not use uiRoutes like APM
-// Kibana issue https://github.com/elastic/kibana/issues/19110 tracks the removal of this dependency on uiRouter
-export const registerTimefilterWithGlobalState = _.once(
- (timefilter: Timefilter, globalState: any, $rootScope: IScope) => {
- // settings have to be re-fetched here, to make sure that settings changed by overrideLocalDefault are taken into account.
- const config = getTimefilterConfig();
- timefilter.setTime(_.defaults(globalState.time || {}, config.timeDefaults));
- timefilter.setRefreshInterval(
- _.defaults(globalState.refreshInterval || {}, config.refreshIntervalDefaults)
- );
-
- globalState.on('fetch_with_changes', () => {
- // clone and default to {} in one
- const newTime: TimeRange = _.defaults({}, globalState.time, config.timeDefaults);
- const newRefreshInterval: RefreshInterval = _.defaults(
- {},
- globalState.refreshInterval,
- config.refreshIntervalDefaults
- );
-
- if (newTime) {
- if (newTime.to) newTime.to = convertISO8601(newTime.to);
- if (newTime.from) newTime.from = convertISO8601(newTime.from);
- }
-
- timefilter.setTime(newTime);
- timefilter.setRefreshInterval(newRefreshInterval);
- });
-
- const updateGlobalStateWithTime = () => {
- globalState.time = timefilter.getTime();
- globalState.refreshInterval = timefilter.getRefreshInterval();
- globalState.save();
- };
-
- subscribeWithScope($rootScope, timefilter.getRefreshIntervalUpdate$(), {
- next: updateGlobalStateWithTime,
- });
-
- subscribeWithScope($rootScope, timefilter.getTimeUpdate$(), {
- next: updateGlobalStateWithTime,
- });
- }
-);
diff --git a/src/legacy/core_plugins/data/public/timefilter/time_history.ts b/src/legacy/ui/public/timefilter/time_history.ts
similarity index 94%
rename from src/legacy/core_plugins/data/public/timefilter/time_history.ts
rename to src/legacy/ui/public/timefilter/time_history.ts
index 98e759fb27a9d..66957ec5987c9 100644
--- a/src/legacy/core_plugins/data/public/timefilter/time_history.ts
+++ b/src/legacy/ui/public/timefilter/time_history.ts
@@ -19,7 +19,7 @@
import moment from 'moment';
import { TimeRange } from 'src/plugins/data/public';
-import { PersistedLog } from 'ui/persisted_log';
+import { PersistedLog } from '../persisted_log';
export class TimeHistory {
private history: PersistedLog;
@@ -52,3 +52,5 @@ export class TimeHistory {
return this.history.get();
}
}
+
+export const timeHistory = new TimeHistory();
diff --git a/src/legacy/core_plugins/data/public/timefilter/timefilter.test.mocks.ts b/src/legacy/ui/public/timefilter/timefilter.test.mocks.ts
similarity index 93%
rename from src/legacy/core_plugins/data/public/timefilter/timefilter.test.mocks.ts
rename to src/legacy/ui/public/timefilter/timefilter.test.mocks.ts
index 7354916c3fc35..f6d50167e45db 100644
--- a/src/legacy/core_plugins/data/public/timefilter/timefilter.test.mocks.ts
+++ b/src/legacy/ui/public/timefilter/timefilter.test.mocks.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { chromeServiceMock } from '../../../../../core/public/mocks';
+import { chromeServiceMock } from '../../../../core/public/mocks';
jest.doMock('ui/new_platform', () => ({
npStart: {
diff --git a/src/legacy/core_plugins/data/public/timefilter/timefilter.test.ts b/src/legacy/ui/public/timefilter/timefilter.test.ts
similarity index 91%
rename from src/legacy/core_plugins/data/public/timefilter/timefilter.test.ts
rename to src/legacy/ui/public/timefilter/timefilter.test.ts
index 47896189aa080..f8885d842ef69 100644
--- a/src/legacy/core_plugins/data/public/timefilter/timefilter.test.ts
+++ b/src/legacy/ui/public/timefilter/timefilter.test.ts
@@ -19,38 +19,46 @@
import './timefilter.test.mocks';
-jest.mock('ui/chrome', () => ({
- getBasePath: () => `/some/base/path`,
- getUiSettingsClient: () => {
- return {
- get: (key: string) => {
- switch (key) {
- case 'timepicker:timeDefaults':
- return { from: 'now-15m', to: 'now' };
- case 'timepicker:refreshIntervalDefaults':
- return { pause: false, value: 0 };
- default:
- throw new Error(`Unexpected config key: ${key}`);
- }
- },
- };
- },
-}));
-
-jest.mock('./lib/parse_querystring', () => ({
- parseQueryString: () => {
- return {
- // Can not access local variable from within a mock
- // @ts-ignore
- forceNow: global.nowTime,
- };
- },
-}));
+jest.mock(
+ 'ui/chrome',
+ () => ({
+ getBasePath: () => `/some/base/path`,
+ getUiSettingsClient: () => {
+ return {
+ get: (key: string) => {
+ switch (key) {
+ case 'timepicker:timeDefaults':
+ return { from: 'now-15m', to: 'now' };
+ case 'timepicker:refreshIntervalDefaults':
+ return { pause: false, value: 0 };
+ default:
+ throw new Error(`Unexpected config key: ${key}`);
+ }
+ },
+ };
+ },
+ }),
+ { virtual: true }
+);
+
+jest.mock(
+ 'ui/timefilter/lib/parse_querystring',
+ () => ({
+ parseQueryString: () => {
+ return {
+ // Can not access local variable from within a mock
+ // @ts-ignore
+ forceNow: global.nowTime,
+ };
+ },
+ }),
+ { virtual: true }
+);
import sinon from 'sinon';
import expect from '@kbn/expect';
import moment from 'moment';
-import { timefilter } from 'ui/timefilter';
+import { timefilter } from './timefilter';
import { Subscription } from 'rxjs';
import { TimeRange, RefreshInterval } from 'src/plugins/data/public';
diff --git a/src/legacy/core_plugins/data/public/timefilter/timefilter.ts b/src/legacy/ui/public/timefilter/timefilter.ts
similarity index 69%
rename from src/legacy/core_plugins/data/public/timefilter/timefilter.ts
rename to src/legacy/ui/public/timefilter/timefilter.ts
index b07060018f9d7..729575a833e37 100644
--- a/src/legacy/core_plugins/data/public/timefilter/timefilter.ts
+++ b/src/legacy/ui/public/timefilter/timefilter.ts
@@ -20,18 +20,18 @@
import _ from 'lodash';
import { Subject, BehaviorSubject } from 'rxjs';
import moment, { Moment } from 'moment';
+import { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
+import chrome from 'ui/chrome';
+import { UiSettingsClientContract } from 'src/core/public';
import { RefreshInterval, TimeRange } from 'src/plugins/data/public';
import { IndexPattern } from 'src/legacy/core_plugins/data/public';
-import { TimeHistory } from './time_history';
+import { IScope } from 'angular';
+import { timeHistory } from './time_history';
import { areRefreshIntervalsDifferent, areTimeRangesDifferent } from './lib/diff_time_picker_vals';
+import uiRoutes from '../routes';
import { parseQueryString } from './lib/parse_querystring';
import { calculateBounds, getTime } from './get_time';
-export interface TimefilterConfig {
- timeDefaults: TimeRange;
- refreshIntervalDefaults: RefreshInterval;
-}
-
// Timefilter accepts moment input but always returns string output
export type InputTimeRange =
| TimeRange
@@ -53,15 +53,13 @@ export class Timefilter {
private _time: TimeRange;
private _refreshInterval!: RefreshInterval;
- private _history: TimeHistory;
public isTimeRangeSelectorEnabled: boolean = false;
public isAutoRefreshSelectorEnabled: boolean = false;
- constructor(config: TimefilterConfig, timeHistory: TimeHistory) {
- this._history = timeHistory;
- this._time = config.timeDefaults;
- this.setRefreshInterval(config.refreshIntervalDefaults);
+ constructor(uiSettings: UiSettingsClientContract) {
+ this._time = uiSettings.get('timepicker:timeDefaults');
+ this.setRefreshInterval(uiSettings.get('timepicker:refreshIntervalDefaults'));
}
getEnabledUpdated$ = () => {
@@ -108,7 +106,7 @@ export class Timefilter {
from: newTime.from,
to: newTime.to,
};
- this._history.add(this._time);
+ timeHistory.add(this._time);
this.timeUpdate$.next();
this.fetch$.next();
}
@@ -223,3 +221,64 @@ export class Timefilter {
this.autoRefreshFetch$.next();
};
}
+
+export const timefilter = new Timefilter(chrome.getUiSettingsClient());
+
+// TODO
+// remove everything underneath once globalState is no longer an angular service
+// and listener can be registered without angular.
+function convertISO8601(stringTime: string): string {
+ const obj = moment(stringTime, 'YYYY-MM-DDTHH:mm:ss.SSSZ', true);
+ return obj.isValid() ? obj.toString() : stringTime;
+}
+
+// Currently some parts of Kibana (index patterns, timefilter) rely on addSetupWork in the uiRouter
+// and require it to be executed to properly function.
+// This function is exposed for applications that do not use uiRoutes like APM
+// Kibana issue https://github.com/elastic/kibana/issues/19110 tracks the removal of this dependency on uiRouter
+export const registerTimefilterWithGlobalState = _.once((globalState: any, $rootScope: IScope) => {
+ const uiSettings = chrome.getUiSettingsClient();
+ const timeDefaults = uiSettings.get('timepicker:timeDefaults');
+ const refreshIntervalDefaults = uiSettings.get('timepicker:refreshIntervalDefaults');
+
+ timefilter.setTime(_.defaults(globalState.time || {}, timeDefaults));
+ timefilter.setRefreshInterval(
+ _.defaults(globalState.refreshInterval || {}, refreshIntervalDefaults)
+ );
+
+ globalState.on('fetch_with_changes', () => {
+ // clone and default to {} in one
+ const newTime: TimeRange = _.defaults({}, globalState.time, timeDefaults);
+ const newRefreshInterval: RefreshInterval = _.defaults(
+ {},
+ globalState.refreshInterval,
+ refreshIntervalDefaults
+ );
+
+ if (newTime) {
+ if (newTime.to) newTime.to = convertISO8601(newTime.to);
+ if (newTime.from) newTime.from = convertISO8601(newTime.from);
+ }
+
+ timefilter.setTime(newTime);
+ timefilter.setRefreshInterval(newRefreshInterval);
+ });
+
+ const updateGlobalStateWithTime = () => {
+ globalState.time = timefilter.getTime();
+ globalState.refreshInterval = timefilter.getRefreshInterval();
+ globalState.save();
+ };
+
+ subscribeWithScope($rootScope, timefilter.getRefreshIntervalUpdate$(), {
+ next: updateGlobalStateWithTime,
+ });
+
+ subscribeWithScope($rootScope, timefilter.getTimeUpdate$(), {
+ next: updateGlobalStateWithTime,
+ });
+});
+
+uiRoutes.addSetupWork((globalState, $rootScope) => {
+ return registerTimefilterWithGlobalState(globalState, $rootScope);
+});
diff --git a/src/legacy/ui/public/vis/agg_configs.ts b/src/legacy/ui/public/vis/agg_configs.ts
index e16784bb6e2f2..e3edbef40c654 100644
--- a/src/legacy/ui/public/vis/agg_configs.ts
+++ b/src/legacy/ui/public/vis/agg_configs.ts
@@ -27,8 +27,8 @@
*/
import _ from 'lodash';
-import { TimeRange } from 'src/plugins/data/public';
import { Schemas } from '../visualize/loader/pipeline_helpers/build_pipeline';
+import { TimeRange } from '../timefilter';
import { Schema } from '../vis/editors/default/schemas';
import { AggConfig, AggConfigOptions } from './agg_config';
import { AggGroupNames } from './editors/default/agg_groups';
diff --git a/src/legacy/ui/public/vis/request_handlers/courier.js b/src/legacy/ui/public/vis/request_handlers/courier.js
index b6f05f6228ea3..cdd5158c5701d 100644
--- a/src/legacy/ui/public/vis/request_handlers/courier.js
+++ b/src/legacy/ui/public/vis/request_handlers/courier.js
@@ -24,7 +24,7 @@ import { calculateObjectHash } from '../lib/calculate_object_hash';
import { getRequestInspectorStats, getResponseInspectorStats } from '../../courier/utils/courier_inspector_utils';
import { tabifyAggResponse } from '../../agg_response/tabify/tabify';
import { buildTabularInspectorData } from '../../inspector/build_tabular_inspector_data';
-import { getTime } from '../../timefilter';
+import { getTime } from '../../timefilter/get_time';
const CourierRequestHandlerProvider = function () {
diff --git a/src/legacy/ui/public/vis/request_handlers/request_handlers.d.ts b/src/legacy/ui/public/vis/request_handlers/request_handlers.d.ts
index 03751e189210a..213f1e6252a6d 100644
--- a/src/legacy/ui/public/vis/request_handlers/request_handlers.d.ts
+++ b/src/legacy/ui/public/vis/request_handlers/request_handlers.d.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { TimeRange } from 'src/plugins/data/public';
+import { TimeRange } from 'ui/timefilter';
import { Query } from 'src/legacy/core_plugins/data/public';
import { Filter } from '@kbn/es-query';
import { AggConfigs } from 'ui/vis/agg_configs';
diff --git a/src/legacy/ui/public/visualize/loader/types.ts b/src/legacy/ui/public/visualize/loader/types.ts
index bb1113d212261..595a0649ec5ef 100644
--- a/src/legacy/ui/public/visualize/loader/types.ts
+++ b/src/legacy/ui/public/visualize/loader/types.ts
@@ -18,7 +18,7 @@
*/
import { Filter } from '@kbn/es-query';
-import { TimeRange } from 'src/plugins/data/public';
+import { TimeRange } from 'ui/timefilter';
import { Query } from 'src/legacy/core_plugins/data/public';
import { SavedObject } from 'ui/saved_objects/saved_object';
diff --git a/src/legacy/ui/ui_bundles/ui_bundles_controller.js b/src/legacy/ui/ui_bundles/ui_bundles_controller.js
index 5e9ae0abbb183..a4521268ea121 100644
--- a/src/legacy/ui/ui_bundles/ui_bundles_controller.js
+++ b/src/legacy/ui/ui_bundles/ui_bundles_controller.js
@@ -25,7 +25,6 @@ import { existsSync } from 'fs';
import del from 'del';
import { makeRe } from 'minimatch';
import mkdirp from 'mkdirp';
-import jsonStableStringify from 'json-stable-stringify';
import { IS_KIBANA_DISTRIBUTABLE } from '../../utils';
@@ -49,21 +48,6 @@ function getWebpackAliases(pluginSpecs) {
}, {});
}
-function sortAllArrays(input) {
- if (Array.isArray(input)) {
- return input
- .map(i => sortAllArrays(i))
- .sort((a, b) => typeof a === 'string' && typeof b === 'string' ? a.localeCompare(b) : 0);
- }
-
- if (typeof input === 'object') {
- return Object.entries(input)
- .map(([key, value]) => [key, sortAllArrays(value)]);
- }
-
- return input;
-}
-
export class UiBundlesController {
constructor(kbnServer) {
const { config, uiApps, uiExports, pluginSpecs } = kbnServer;
@@ -75,7 +59,9 @@ export class UiBundlesController {
sourceMaps: config.get('optimize.sourceMaps'),
kbnVersion: config.get('pkg.version'),
buildNum: config.get('pkg.buildNum'),
- appExtensions: sortAllArrays(uiExports.appExtensions),
+ plugins: pluginSpecs
+ .map(spec => spec.getId())
+ .sort((a, b) => a.localeCompare(b))
};
this._filter = makeRe(config.get('optimize.bundleFilter') || '*', {
@@ -95,13 +81,6 @@ export class UiBundlesController {
this._postLoaders = [];
this._bundles = [];
- // create a bundle for core-only with no modules
- this.add({
- id: 'core',
- modules: [],
- template: appEntryTemplate
- });
-
// create a bundle for each uiApp
for (const uiApp of uiApps) {
this.add({
@@ -164,9 +143,7 @@ export class UiBundlesController {
}
getContext() {
- return jsonStableStringify(this._context, {
- space: ' '
- });
+ return JSON.stringify(this._context, null, ' ');
}
resolvePath(...args) {
diff --git a/src/legacy/ui/ui_render/ui_render_mixin.js b/src/legacy/ui/ui_render/ui_render_mixin.js
index 7e6609c4b5487..47d13184bfd0a 100644
--- a/src/legacy/ui/ui_render/ui_render_mixin.js
+++ b/src/legacy/ui/ui_render/ui_render_mixin.js
@@ -102,7 +102,9 @@ export function uiRenderMixin(kbnServer, server, config) {
async handler(request, h) {
const { id } = request.params;
const app = server.getUiAppById(id) || server.getHiddenUiAppById(id);
- const isCore = !app;
+ if (!app) {
+ throw Boom.notFound(`Unknown app: ${id}`);
+ }
const uiSettings = request.getUiSettingsService();
const darkMode = !authEnabled || request.auth.isAuthenticated
@@ -128,9 +130,7 @@ export function uiRenderMixin(kbnServer, server, config) {
),
`${regularBundlePath}/${darkMode ? 'dark' : 'light'}_theme.style.css`,
`${regularBundlePath}/commons.style.css`,
- ...(
- !isCore ? [`${regularBundlePath}/${app.getId()}.style.css`] : []
- ),
+ `${regularBundlePath}/${app.getId()}.style.css`,
...kbnServer.uiExports.styleSheetPaths
.filter(path => (
path.theme === '*' || path.theme === (darkMode ? 'dark' : 'light')
@@ -145,7 +145,7 @@ export function uiRenderMixin(kbnServer, server, config) {
const bootstrap = new AppBootstrap({
templateData: {
- appId: isCore ? 'core' : app.getId(),
+ appId: app.getId(),
regularBundlePath,
dllBundlePath,
styleSheetPaths,
@@ -164,11 +164,12 @@ export function uiRenderMixin(kbnServer, server, config) {
});
server.route({
- path: '/app/{id}/{any*}',
+ path: '/app/{id}',
method: 'GET',
async handler(req, h) {
const id = req.params.id;
const app = server.getUiAppById(id);
+ if (!app) throw Boom.notFound('Unknown app ' + id);
try {
if (kbnServer.status.isGreen()) {
@@ -182,15 +183,9 @@ export function uiRenderMixin(kbnServer, server, config) {
}
});
- async function getUiSettings({ request, includeUserProvidedConfig }) {
+ async function getLegacyKibanaPayload({ app, translations, request, includeUserProvidedConfig }) {
const uiSettings = request.getUiSettingsService();
- return props({
- defaults: uiSettings.getDefaults(),
- user: includeUserProvidedConfig && uiSettings.getUserProvided()
- });
- }
- async function getLegacyKibanaPayload({ app, translations, request, includeUserProvidedConfig }) {
return {
app,
translations,
@@ -203,15 +198,16 @@ export function uiRenderMixin(kbnServer, server, config) {
basePath: request.getBasePath(),
serverName: config.get('server.name'),
devMode: config.get('env.dev'),
- uiSettings: await getUiSettings({ request, includeUserProvidedConfig }),
+ uiSettings: await props({
+ defaults: uiSettings.getDefaults(),
+ user: includeUserProvidedConfig && uiSettings.getUserProvided()
+ })
};
}
async function renderApp({ app, h, includeUserProvidedConfig = true, injectedVarsOverrides = {} }) {
const request = h.request;
const basePath = request.getBasePath();
- const uiSettings = await getUiSettings({ request, includeUserProvidedConfig });
- app = app || { getId: () => 'core' };
const legacyMetadata = await getLegacyKibanaPayload({
app,
@@ -232,14 +228,13 @@ export function uiRenderMixin(kbnServer, server, config) {
bootstrapScriptUrl: `${basePath}/bundles/app/${app.getId()}/bootstrap.js`,
i18n: (id, options) => i18n.translate(id, options),
locale: i18n.getLocale(),
- darkMode: get(uiSettings.user, ['theme:darkMode', 'userValue'], false),
+ darkMode: get(legacyMetadata.uiSettings.user, ['theme:darkMode', 'userValue'], false),
injectedMetadata: {
version: kbnServer.version,
buildNumber: config.get('pkg.buildNum'),
branch: config.get('pkg.branch'),
basePath,
- legacyMode: app.getId() !== 'core',
i18n: {
translationsUrl: `${basePath}/translations/${i18n.getLocale()}.json`,
},
@@ -250,7 +245,7 @@ export function uiRenderMixin(kbnServer, server, config) {
request,
mergeVariables(
injectedVarsOverrides,
- app ? await server.getInjectedUiAppVars(app.getId()) : {},
+ await server.getInjectedUiAppVars(app.getId()),
defaultInjectedVars,
),
),
diff --git a/src/legacy/ui/ui_render/views/ui_app.pug b/src/legacy/ui/ui_render/views/ui_app.pug
index 95b321e09b500..5bbcc51e7745c 100644
--- a/src/legacy/ui/ui_render/views/ui_app.pug
+++ b/src/legacy/ui/ui_render/views/ui_app.pug
@@ -114,7 +114,7 @@ block content
}
}
- .kibanaWelcomeView(id="kbn_loading_message", style="display: none;", data-test-subj="kbnLoadingMessage")
+ .kibanaWelcomeView(id="kbn_loading_message", style="display: none;")
.kibanaLoaderWrap
.kibanaLoader
.kibanaWelcomeLogoCircle
diff --git a/src/plugins/data/common/expressions/expression_types/kibana_context.ts b/src/plugins/data/common/expressions/expression_types/kibana_context.ts
index 0a3e8a4db87f6..5ee3f7abbbdb0 100644
--- a/src/plugins/data/common/expressions/expression_types/kibana_context.ts
+++ b/src/plugins/data/common/expressions/expression_types/kibana_context.ts
@@ -18,8 +18,8 @@
*/
import { Filter } from '@kbn/es-query';
-import { TimeRange } from 'src/plugins/data/public';
import { Query } from '../../query/types';
+import { TimeRange } from '../../timefilter/types';
const name = 'kibana_context';
diff --git a/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap b/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap
index 5bf5c8be05ed8..47b4a5219068f 100644
--- a/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap
+++ b/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap
@@ -6,7 +6,7 @@ exports[`SavedObjectSaveModal should render matching snapshot 1`] = `
onSubmit={[Function]}
>
- Save
+
diff --git a/src/plugins/kibana_react/public/saved_objects/_index.scss b/src/plugins/kibana_react/public/saved_objects/_index.scss
deleted file mode 100644
index 6c773c7f777be..0000000000000
--- a/src/plugins/kibana_react/public/saved_objects/_index.scss
+++ /dev/null
@@ -1 +0,0 @@
-@import './saved_object_save_modal';
diff --git a/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.scss b/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.scss
deleted file mode 100644
index b8758f692b7f7..0000000000000
--- a/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.kbnSavedObjectSaveModal {
- width: $euiSizeXXL * 10;
-}
\ No newline at end of file
diff --git a/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx b/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx
index 4d4e429417085..27da5d90646b3 100644
--- a/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx
+++ b/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx
@@ -35,9 +35,8 @@ import {
import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
import { EuiText } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
-export interface OnSaveProps {
+interface OnSaveProps {
newTitle: string;
newCopyOnSave: boolean;
isTitleDuplicateConfirmed: boolean;
@@ -73,14 +72,14 @@ export class SavedObjectSaveModal extends React.Component {
};
public render() {
- const { isTitleDuplicateConfirmed, hasTitleDuplicate, title } = this.state;
+ const { isTitleDuplicateConfirmed, hasTitleDuplicate, title, isLoading } = this.state;
return (
@@ -190,34 +204,6 @@ export class SavedObjectSaveModal extends React.Component {
this.saveSavedObject();
};
- private renderConfirmButton = () => {
- const { isLoading, title, hasTitleDuplicate } = this.state;
-
- let confirmLabel: string | React.ReactNode = hasTitleDuplicate
- ? i18n.translate('kibana-react.savedObjects.saveModal.confirmSaveButtonLabel', {
- defaultMessage: 'Confirm save',
- })
- : i18n.translate('kibana-react.savedObjects.saveModal.saveButtonLabel', {
- defaultMessage: 'Save',
- });
-
- if (this.props.confirmButtonLabel) {
- confirmLabel = this.props.confirmButtonLabel;
- }
-
- return (
-
- {confirmLabel}
-
- );
- };
-
private renderDuplicateTitleCallout = () => {
if (!this.state.hasTitleDuplicate) {
return;
@@ -244,14 +230,10 @@ export class SavedObjectSaveModal extends React.Component {
objectType: this.props.objectType,
confirmSaveLabel: (
- {this.props.confirmButtonLabel
- ? this.props.confirmButtonLabel
- : i18n.translate(
- 'kibana-react.savedObjects.saveModal.duplicateTitleDescription.confirmSaveText',
- {
- defaultMessage: 'Confirm save',
- }
- )}
+
),
}}
diff --git a/src/test_utils/public/enzyme_helpers.tsx b/src/test_utils/public/enzyme_helpers.tsx
index 43ec49c5c1404..17027bd8dce48 100644
--- a/src/test_utils/public/enzyme_helpers.tsx
+++ b/src/test_utils/public/enzyme_helpers.tsx
@@ -128,15 +128,3 @@ export function renderWithIntl(
}
export const nextTick = () => new Promise(res => process.nextTick(res));
-
-export function shallowWithI18nProvider(child: ReactElement) {
- const wrapped = shallow({child});
- const name = typeof child.type === 'string' ? child.type : child.type.name;
- return wrapped.find(name).dive();
-}
-
-export function mountWithI18nProvider(child: ReactElement) {
- const wrapped = mount({child});
- const name = typeof child.type === 'string' ? child.type : child.type.name;
- return wrapped.find(name);
-}
diff --git a/test/functional/apps/dashboard/dashboard_filter_bar.js b/test/functional/apps/dashboard/dashboard_filter_bar.js
index a48393e11b19c..312066000c63c 100644
--- a/test/functional/apps/dashboard/dashboard_filter_bar.js
+++ b/test/functional/apps/dashboard/dashboard_filter_bar.js
@@ -133,10 +133,10 @@ export default function ({ getService, getPageObjects }) {
await PageObjects.dashboard.setTimepickerInDataRange();
});
- it('are added when a cell magnifying glass is clicked', async function () {
- await dashboardAddPanel.addSavedSearch('Rendering-Test:-saved-search');
+ it('are added when pie chart legend item is clicked', async function () {
+ await dashboardAddPanel.addVisualization('Rendering Test: pie');
await PageObjects.dashboard.waitForRenderComplete();
- await testSubjects.click('docTableCellFilter');
+ await pieChart.filterByLegendItem('4,886');
const filterCount = await filterBar.getFilterCount();
expect(filterCount).to.equal(1);
diff --git a/test/functional/apps/dashboard/dashboard_filtering.js b/test/functional/apps/dashboard/dashboard_filtering.js
index 862ed8c87d347..15b444cb74151 100644
--- a/test/functional/apps/dashboard/dashboard_filtering.js
+++ b/test/functional/apps/dashboard/dashboard_filtering.js
@@ -74,6 +74,7 @@ export default function ({ getService, getPageObjects }) {
it('tsvb time series shows no data message', async () => {
expect(await testSubjects.exists('noTSVBDataMessage')).to.be(true);
+ await dashboardExpect.tsvbTimeSeriesLegendCount(0);
});
it('metric value shows no data', async () => {
@@ -133,6 +134,11 @@ export default function ({ getService, getPageObjects }) {
await dashboardExpect.goalAndGuageLabelsExist(['0', '0%']);
});
+ it('tsvb time series shows no data message', async () => {
+ expect(await testSubjects.exists('noTSVBDataMessage')).to.be(true);
+ await dashboardExpect.tsvbTimeSeriesLegendCount(0);
+ });
+
it('metric value shows no data', async () => {
await dashboardExpect.metricValuesExist(['-']);
});
@@ -189,6 +195,11 @@ export default function ({ getService, getPageObjects }) {
await dashboardExpect.goalAndGuageLabelsExist(['39.958%', '7,544']);
});
+ it('tsvb time series', async () => {
+ expect(await testSubjects.exists('noTSVBDataMessage')).to.be(false);
+ await dashboardExpect.tsvbTimeSeriesLegendCount(10);
+ });
+
it('metric value', async () => {
await dashboardExpect.metricValuesExist(['101']);
});
diff --git a/test/functional/apps/dashboard/dashboard_grid.js b/test/functional/apps/dashboard/dashboard_grid.js
index a0c22ca85b91b..958d61176ded2 100644
--- a/test/functional/apps/dashboard/dashboard_grid.js
+++ b/test/functional/apps/dashboard/dashboard_grid.js
@@ -25,6 +25,7 @@ export default function ({ getService, getPageObjects }) {
const PageObjects = getPageObjects(['dashboard']);
describe('dashboard grid', function () {
+ this.tags(['skipFirefox']);
before(async () => {
await PageObjects.dashboard.gotoDashboardLandingPage();
diff --git a/test/functional/apps/dashboard/embeddable_rendering.js b/test/functional/apps/dashboard/embeddable_rendering.js
index e21964495e46e..831622716f381 100644
--- a/test/functional/apps/dashboard/embeddable_rendering.js
+++ b/test/functional/apps/dashboard/embeddable_rendering.js
@@ -50,6 +50,7 @@ export default function ({ getService, getPageObjects }) {
await dashboardExpect.tagCloudWithValuesFound(['CN', 'IN', 'US', 'BR', 'ID']);
// TODO add test for 'region map viz'
// TODO add test for 'tsvb gauge' viz
+ await dashboardExpect.tsvbTimeSeriesLegendCount(1);
// TODO add test for 'geo map' viz
// This tests the presence of the two input control embeddables
await dashboardExpect.inputControlItemCount(5);
@@ -85,6 +86,7 @@ export default function ({ getService, getPageObjects }) {
await dashboardExpect.tsvbMetricValuesExist(['0']);
await dashboardExpect.tsvbMarkdownWithValuesExists(['Hi Avg last bytes: 0']);
await dashboardExpect.tsvbTableCellCount(0);
+ await dashboardExpect.tsvbTimeSeriesLegendCount(1);
await dashboardExpect.tsvbTopNValuesExist(['0']);
await dashboardExpect.vegaTextsDoNotExist(['5,000']);
};
diff --git a/test/functional/apps/dashboard/full_screen_mode.js b/test/functional/apps/dashboard/full_screen_mode.js
index 2a534a66d43e4..1f935e9b9aa1b 100644
--- a/test/functional/apps/dashboard/full_screen_mode.js
+++ b/test/functional/apps/dashboard/full_screen_mode.js
@@ -21,6 +21,7 @@ import expect from '@kbn/expect';
export default function ({ getService, getPageObjects }) {
const retry = getService('retry');
+ const browser = getService('browser');
const dashboardPanelActions = getService('dashboardPanelActions');
const PageObjects = getPageObjects(['dashboard', 'common']);
@@ -68,7 +69,7 @@ export default function ({ getService, getPageObjects }) {
it('exits when the text button is clicked on', async () => {
const logoButton = await PageObjects.dashboard.getExitFullScreenLogoButton();
- await logoButton.moveMouseTo();
+ await browser.moveMouseTo(logoButton);
await PageObjects.dashboard.clickExitFullScreenTextButton();
await retry.try(async () => {
diff --git a/test/functional/apps/discover/_discover.js b/test/functional/apps/discover/_discover.js
index c29542e6a4035..3cb5d0a71cce5 100644
--- a/test/functional/apps/discover/_discover.js
+++ b/test/functional/apps/discover/_discover.js
@@ -160,7 +160,7 @@ export default function ({ getService, getPageObjects }) {
const newDurationHours = await PageObjects.timePicker.getTimeDurationInHours();
expect(Math.round(newDurationHours)).to.be(3);
- const rowData = await PageObjects.discover.getDocTableField(1);
+ const rowData = await PageObjects.discover.getDocTableIndex(1);
expect(rowData).to.have.string('Sep 20, 2015 @ 02:56:02.323');
});
diff --git a/test/functional/apps/management/index.js b/test/functional/apps/management/index.js
index 4d4031b4e489b..c9b444e501789 100644
--- a/test/functional/apps/management/index.js
+++ b/test/functional/apps/management/index.js
@@ -33,7 +33,7 @@ export default function ({ getService, loadTestFile }) {
});
describe('', function () {
- this.tags('ciGroup7');
+ this.tags('ciGroup1');
loadTestFile(require.resolve('./_create_index_pattern_wizard'));
loadTestFile(require.resolve('./_index_pattern_create_delete'));
@@ -45,7 +45,7 @@ export default function ({ getService, loadTestFile }) {
});
describe('', function () {
- this.tags('ciGroup8');
+ this.tags('ciGroup2');
loadTestFile(require.resolve('./_index_pattern_filter'));
loadTestFile(require.resolve('./_scripted_fields_filter'));
diff --git a/test/functional/apps/visualize/_tsvb_time_series.ts b/test/functional/apps/visualize/_tsvb_time_series.ts
index fa79190a5bf94..0a2400a367a76 100644
--- a/test/functional/apps/visualize/_tsvb_time_series.ts
+++ b/test/functional/apps/visualize/_tsvb_time_series.ts
@@ -75,7 +75,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await visualBuilder.changePanelPreview();
await visualBuilder.cloneSeries();
- const legend = await visualBuilder.getLegendItems();
+ const legend = await visualBuilder.getLegentItems();
const series = await visualBuilder.getSeries();
expect(legend.length).to.be(2);
expect(series.length).to.be(2);
@@ -108,7 +108,8 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
expect(actualCount).to.be(expectedLegendValue);
});
- it.skip('should show the correct count in the legend with "Human readable" duration formatter', async () => {
+ // FLAKY: https://github.com/elastic/kibana/issues/40458
+ it('should show the correct count in the legend with "Human readable" duration formatter', async () => {
await visualBuilder.clickSeriesOption();
await visualBuilder.changeDataFormatter('Duration');
await visualBuilder.setDurationFormatterSettings({ to: 'Human readable' });
@@ -126,8 +127,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
expect(actualCountMin).to.be('3 hours');
});
- // --reversed class is not implemented in @elastic\chart
- describe.skip('Dark mode', () => {
+ describe('Dark mode', () => {
before(async () => {
await kibanaServer.uiSettings.update({
'theme:darkMode': true,
diff --git a/test/functional/apps/visualize/index.ts b/test/functional/apps/visualize/index.ts
index 2a13b6fea9158..68a00b29d107e 100644
--- a/test/functional/apps/visualize/index.ts
+++ b/test/functional/apps/visualize/index.ts
@@ -40,7 +40,7 @@ export default function({ getService, loadTestFile }: FtrProviderContext) {
});
describe('', function() {
- this.tags('ciGroup9');
+ this.tags('ciGroup3');
loadTestFile(require.resolve('./_embedding_chart'));
loadTestFile(require.resolve('./_chart_types'));
@@ -50,7 +50,7 @@ export default function({ getService, loadTestFile }: FtrProviderContext) {
});
describe('', function() {
- this.tags('ciGroup10');
+ this.tags('ciGroup4');
loadTestFile(require.resolve('./_inspector'));
loadTestFile(require.resolve('./_experimental_vis'));
@@ -62,7 +62,7 @@ export default function({ getService, loadTestFile }: FtrProviderContext) {
});
describe('', function() {
- this.tags('ciGroup11');
+ this.tags('ciGroup5');
loadTestFile(require.resolve('./_line_chart'));
loadTestFile(require.resolve('./_pie_chart'));
@@ -76,7 +76,7 @@ export default function({ getService, loadTestFile }: FtrProviderContext) {
});
describe('', function() {
- this.tags('ciGroup12');
+ this.tags('ciGroup6');
loadTestFile(require.resolve('./_tag_cloud'));
loadTestFile(require.resolve('./_tile_map'));
diff --git a/test/functional/page_objects/common_page.js b/test/functional/page_objects/common_page.js
index fc47a53a092e8..651d82608961a 100644
--- a/test/functional/page_objects/common_page.js
+++ b/test/functional/page_objects/common_page.js
@@ -151,22 +151,11 @@ export function CommonPageProvider({ getService, getPageObjects }) {
navigateToApp(appName, { basePath = '', shouldLoginIfPrompted = true, shouldAcceptAlert = true, hash = '' } = {}) {
const self = this;
-
- let appUrl;
- if (config.has(['apps', appName])) {
- // Legacy applications
- const appConfig = config.get(['apps', appName]);
- appUrl = getUrl.noAuth(config.get('servers.kibana'), {
- pathname: `${basePath}${appConfig.pathname}`,
- hash: hash || appConfig.hash,
- });
- } else {
- appUrl = getUrl.noAuth(config.get('servers.kibana'), {
- pathname: `${basePath}/app/${appName}`,
- hash
- });
- }
-
+ const appConfig = config.get(['apps', appName]);
+ const appUrl = getUrl.noAuth(config.get('servers.kibana'), {
+ pathname: `${basePath}${appConfig.pathname}`,
+ hash: hash || appConfig.hash,
+ });
log.debug('navigating to ' + appName + ' url: ' + appUrl);
function navigateTo(url) {
@@ -370,7 +359,7 @@ export function CommonPageProvider({ getService, getPageObjects }) {
throw new Error('Toast is not visible yet');
}
});
- await toast.moveMouseTo();
+ await browser.moveMouseTo(toast);
const title = await (await find.byCssSelector('.euiToastHeader__title')).getVisibleText();
log.debug(title);
await find.clickByCssSelector('.euiToast__closeButton');
@@ -381,7 +370,7 @@ export function CommonPageProvider({ getService, getPageObjects }) {
const toasts = await find.allByCssSelector('.euiToast');
for (const toastElement of toasts) {
try {
- await toastElement.moveMouseTo();
+ await browser.moveMouseTo(toastElement);
const closeBtn = await toastElement.findByCssSelector('.euiToast__closeButton');
await closeBtn.click();
} catch (err) {
diff --git a/test/functional/page_objects/discover_page.js b/test/functional/page_objects/discover_page.js
index dfe8dc1071d46..6954bed438478 100644
--- a/test/functional/page_objects/discover_page.js
+++ b/test/functional/page_objects/discover_page.js
@@ -193,13 +193,6 @@ export function DiscoverPageProvider({ getService, getPageObjects }) {
return await row.getVisibleText();
}
- async getDocTableField(index) {
- const field = await find.byCssSelector(
- `tr.kbnDocTable__row:nth-child(${index}) > [data-test-subj='docTableField']`
- );
- return await field.getVisibleText();
- }
-
async clickDocSortDown() {
await find.clickByCssSelector('.fa-sort-down');
}
diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts
index 5f34e5c4f8637..c64d623979313 100644
--- a/test/functional/page_objects/visual_builder_page.ts
+++ b/test/functional/page_objects/visual_builder_page.ts
@@ -67,14 +67,11 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro
}
public async checkTimeSeriesChartIsPresent() {
- const isPresent = await find.existsByCssSelector('.tvbVisTimeSeries');
- if (!isPresent) {
- throw new Error(`TimeSeries chart is not loaded`);
- }
+ await testSubjects.existOrFail('timeseriesChart');
}
public async checkTimeSeriesLegendIsPresent() {
- const isPresent = await find.existsByCssSelector('.echLegend');
+ const isPresent = await find.existsByCssSelector('.tvbLegend');
if (!isPresent) {
throw new Error(`TimeSeries legend is not loaded`);
}
@@ -242,7 +239,7 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro
formatter: 'Bytes' | 'Number' | 'Percent' | 'Duration' | 'Custom'
) {
const formatterEl = await find.byCssSelector('[id$="row"] .euiComboBox');
- await comboBox.setElement(formatterEl, formatter, { clickWithMouse: true });
+ await comboBox.setElement(formatterEl, formatter);
}
/**
@@ -263,11 +260,11 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro
}) {
if (from) {
const fromCombobox = await find.byCssSelector('[id$="from-row"] .euiComboBox');
- await comboBox.setElement(fromCombobox, from, { clickWithMouse: true });
+ await comboBox.setElement(fromCombobox, from);
}
if (to) {
const toCombobox = await find.byCssSelector('[id$="to-row"] .euiComboBox');
- await comboBox.setElement(toCombobox, to, { clickWithMouse: true });
+ await comboBox.setElement(toCombobox, to);
}
if (decimalPlaces) {
const decimalPlacesInput = await find.byCssSelector('[id$="decimal"]');
@@ -294,11 +291,9 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro
await el.type(value);
}
- public async getRhythmChartLegendValue(nth = 0) {
+ public async getRhythmChartLegendValue() {
await PageObjects.visualize.waitForVisualizationRenderingStabilized();
- const metricValue = (await find.allByCssSelector(
- `.echLegendItem .echLegendItem__displayValue`
- ))[nth];
+ const metricValue = await find.byCssSelector('.tvbLegend__itemValue');
await metricValue.moveMouseTo();
return await metricValue.getVisibleText();
}
@@ -452,7 +447,7 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro
public async clickColorPicker(): Promise {
const picker = await find.byCssSelector('.tvbColorPicker button');
- await picker.clickMouseButton();
+ await browser.clickMouseButton(picker);
}
public async setBackgroundColor(colorHex: string): Promise {
@@ -507,8 +502,8 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro
await PageObjects.visualize.waitForRenderingCount(prevRenderingCount + 1);
}
- public async getLegendItems(): Promise {
- return await find.allByCssSelector('.echLegendItem');
+ public async getLegentItems(): Promise {
+ return await testSubjects.findAll('tsvbLegendItem');
}
public async getSeries(): Promise {
diff --git a/test/functional/page_objects/visualize_page.js b/test/functional/page_objects/visualize_page.js
index d02638d37aa49..db6656deed7cb 100644
--- a/test/functional/page_objects/visualize_page.js
+++ b/test/functional/page_objects/visualize_page.js
@@ -1187,7 +1187,7 @@ export function VisualizePageProvider({ getService, getPageObjects, updateBaseli
await retry.try(async () => {
const table = await testSubjects.find('tableVis');
const cell = await table.findByCssSelector(`tbody tr:nth-child(${row}) td:nth-child(${column})`);
- await cell.moveMouseTo();
+ await browser.moveMouseTo(cell);
const filterBtn = await testSubjects.findDescendant('filterForCellValue', cell);
await filterBtn.click();
});
diff --git a/test/functional/services/browser.ts b/test/functional/services/browser.ts
index ccd32590e941c..d52be4b90c043 100644
--- a/test/functional/services/browser.ts
+++ b/test/functional/services/browser.ts
@@ -155,26 +155,49 @@ export async function BrowserProvider({ getService }: FtrProviderContext) {
}
/**
- * Moves the remote environment’s mouse cursor to the specified point {x, y} which is
- * offset to browser page top left corner.
+ * Moves the remote environment’s mouse cursor to the specified element or relative
+ * position.
* https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/input_exports_Actions.html#move
*
- * @param {x: number, y: number} point on browser page
+ * @param {WebElementWrapper} element Optional
+ * @param {number} xOffset Optional
+ * @param {number} yOffset Optional
* @return {Promise}
*/
- public async moveMouseTo(point: { x: number; y: number }): Promise {
+ public async moveMouseTo(element: any, xOffset: number, yOffset: number): Promise;
+ public async moveMouseTo(element: WebElementWrapper): Promise;
+ public async moveMouseTo(
+ element: WebElementWrapper,
+ xOffset?: number,
+ yOffset?: number
+ ): Promise {
if (this.isW3CEnabled) {
+ // Workaround for scrolling bug in W3C mode: move pointer to { x: 0, y: 0 }
+ // https://github.com/mozilla/geckodriver/issues/776
await this.getActions()
.move({ x: 0, y: 0 })
.perform();
- await this.getActions()
- .move({ x: point.x, y: point.y, origin: 'pointer' })
- .perform();
+ if (element instanceof WebElementWrapper) {
+ await this.getActions()
+ .move({ x: xOffset || 10, y: yOffset || 10, origin: element._webElement })
+ .perform();
+ } else {
+ await this.getActions()
+ .move({ origin: { x: xOffset, y: yOffset } })
+ .perform();
+ }
} else {
- await this.getActions()
- .pause(this.getActions().mouse)
- .move({ x: point.x, y: point.y, origin: 'pointer' })
- .perform();
+ if (element instanceof WebElementWrapper) {
+ await this.getActions()
+ .pause(this.getActions().mouse)
+ .move({ origin: element._webElement })
+ .perform();
+ } else {
+ await this.getActions()
+ .pause(this.getActions().mouse)
+ .move({ origin: { x: xOffset, y: yOffset } })
+ .perform();
+ }
}
}
@@ -190,47 +213,70 @@ export async function BrowserProvider({ getService }: FtrProviderContext) {
from: { offset: { x: any; y: any }; location: any },
to: { offset: { x: any; y: any }; location: any }
) {
+ // tslint:disable-next-line:variable-name
+ let _from;
+ // tslint:disable-next-line:variable-name
+ let _to;
+ // tslint:disable-next-line:variable-name
+ const _fromOffset = from.offset
+ ? { x: from.offset.x || 0, y: from.offset.y || 0 }
+ : { x: 0, y: 0 };
+ // tslint:disable-next-line:variable-name
+ const _toOffset = to.offset ? { x: to.offset.x || 0, y: to.offset.y || 0 } : { x: 0, y: 0 };
+ // tslint:disable-next-line:variable-name
+ const _convertPointW3C = async (point: any, offset: { x: any; y: any }) => {
+ if (point.location instanceof WebElementWrapper) {
+ const position = await point.location.getPosition();
+ return {
+ x: Math.round(position.x + offset.x),
+ y: Math.round(position.y + offset.y),
+ };
+ } else {
+ return {
+ x: Math.round(point.location.x + offset.x),
+ y: Math.round(point.location.y + offset.y),
+ };
+ }
+ };
+ // tslint:disable-next-line:variable-name
+ const _convertPoint = (point: any) => {
+ return point.location instanceof WebElementWrapper
+ ? point.location._webElement
+ : point.location;
+ };
+
if (this.isW3CEnabled) {
- // The offset should be specified in pixels relative to the center of the element's bounding box
- const getW3CPoint = (data: any) => {
- if (!data.offset) {
- data.offset = {};
- }
- return data.location instanceof WebElementWrapper
- ? { x: data.offset.x || 0, y: data.offset.y || 0, origin: data.location._webElement }
- : { x: data.location.x, y: data.location.y, origin: 'pointer' };
- };
+ // tslint:disable-next-line:variable-name
+ _from = await _convertPointW3C(from, _fromOffset);
+ // tslint:disable-next-line:variable-name
+ _to = await _convertPointW3C(to, _toOffset);
+ // tslint:disable-next-line:variable-name
+ const _offset = { x: _to.x - _from.x, y: _to.y - _from.y };
- const startPoint = getW3CPoint(from);
- const endPoint = getW3CPoint(to);
- await this.getActions()
- .move({ x: 0, y: 0 })
- .perform();
return await this.getActions()
- .move(startPoint)
+ .move({ x: _from.x, y: _from.y, origin: 'pointer' })
.press()
- .move(endPoint)
+ .move({ x: _offset.x, y: _offset.y, origin: 'pointer' })
.release()
.perform();
} else {
- // The offset should be specified in pixels relative to the top-left corner of the element's bounding box
- const getOffset: any = (offset: { x: number; y: number }) =>
- offset ? { x: offset.x || 0, y: offset.y || 0 } : { x: 0, y: 0 };
-
- if (from.location instanceof WebElementWrapper === false) {
- throw new Error('Dragging point should be WebElementWrapper instance');
- } else if (typeof to.location.x === 'number') {
+ // until Chromedriver is not supporting W3C Webdriver Actions API
+ // tslint:disable-next-line:variable-name
+ _from = _convertPoint(from);
+ // tslint:disable-next-line:variable-name
+ _to = _convertPoint(to);
+ if (from.location instanceof WebElementWrapper && typeof to.location.x === 'number') {
return await this.getActions()
- .move({ origin: from.location._webElement })
+ .move({ origin: _from })
.press()
- .move({ x: to.location.x, y: to.location.y, origin: 'pointer' })
+ .move({ x: _to.x, y: _to.y, origin: 'pointer' })
.release()
.perform();
} else {
return await new LegacyActionSequence(driver)
- .mouseMove(from.location._webElement, getOffset(from.offset))
+ .mouseMove(_from, _fromOffset)
.mouseDown()
- .mouseMove(to.location._webElement, getOffset(to.offset))
+ .mouseMove(_to, _toOffset)
.mouseUp()
.perform();
}
@@ -274,29 +320,34 @@ export async function BrowserProvider({ getService }: FtrProviderContext) {
}
/**
- * Moves the remote environment’s mouse cursor to the specified point {x, y} which is
- * offset to browser page top left corner.
- * Then adds an action for left-click (down/up) with the mouse.
+ * Inserts an action for moving the mouse x and y pixels relative to the specified origin.
+ * The origin may be defined as the mouse's current position, the viewport, or the center
+ * of a specific WebElement. Then adds an action for left-click (down/up) with the mouse.
* https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/input_exports_Actions.html#click
*
- * @param {x: number, y: number} point on browser page
+ * @param {WebElementWrapper} element Optional
+ * @param {number} xOffset Optional
+ * @param {number} yOffset Optional
* @return {Promise}
*/
- public async clickMouseButton(point: { x: number; y: number }): Promise {
- if (this.isW3CEnabled) {
+ public async clickMouseButton(element: any, xOffset: number, yOffset: number): Promise;
+ public async clickMouseButton(element: WebElementWrapper): Promise;
+ public async clickMouseButton(...args: unknown[]): Promise {
+ const arg0 = args[0];
+ if (arg0 instanceof WebElementWrapper) {
await this.getActions()
- .move({ x: 0, y: 0 })
- .perform();
- await this.getActions()
- .move({ x: point.x, y: point.y, origin: 'pointer' })
+ .pause(this.getActions().mouse)
+ .move({ origin: arg0._webElement })
.click()
.perform();
- } else {
+ } else if (isNaN(args[1] as number) || isNaN(args[2] as number) === false) {
await this.getActions()
.pause(this.getActions().mouse)
- .move({ x: point.x, y: point.y, origin: 'pointer' })
+ .move({ origin: { x: args[1], y: args[2] } })
.click()
.perform();
+ } else {
+ throw new Error('Element or coordinates should be provided');
}
}
@@ -327,10 +378,16 @@ export async function BrowserProvider({ getService }: FtrProviderContext) {
* @param {WebElementWrapper} element
* @return {Promise}
*/
- public async doubleClick(): Promise {
- await this.getActions()
- .doubleClick()
- .perform();
+ public async doubleClick(element?: WebElementWrapper): Promise {
+ if (element instanceof WebElementWrapper) {
+ await this.getActions()
+ .doubleClick(element._webElement)
+ .perform();
+ } else {
+ await this.getActions()
+ .doubleClick()
+ .perform();
+ }
}
/**
diff --git a/test/functional/services/combo_box.ts b/test/functional/services/combo_box.ts
index 5ecd8cd883c8a..b8267f0b4cbe3 100644
--- a/test/functional/services/combo_box.ts
+++ b/test/functional/services/combo_box.ts
@@ -46,21 +46,13 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont
await this.setElement(comboBox, value);
}
- private async clickOption(isMouseClick: boolean, element: WebElementWrapper) {
- return isMouseClick ? await element.clickMouseButton() : await element.click();
- }
-
/**
* set value inside combobox element
*
* @param comboBoxElement
* @param value
*/
- public async setElement(
- comboBoxElement: WebElementWrapper,
- value: string,
- options = { clickWithMouse: false }
- ): Promise {
+ public async setElement(comboBoxElement: WebElementWrapper, value: string): Promise {
log.debug(`comboBox.setElement, value: ${value}`);
const isOptionSelected = await this.isOptionSelected(comboBoxElement, value);
@@ -73,22 +65,21 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont
await this.openOptionsList(comboBoxElement);
if (value !== undefined) {
- const selectOptions = await find.allByCssSelector(
+ const options = await find.allByCssSelector(
`.euiFilterSelectItem[title^="${value.toString().trim()}"]`,
WAIT_FOR_EXISTS_TIME
);
- if (selectOptions.length > 0) {
- await this.clickOption(options.clickWithMouse, selectOptions[0]);
+ if (options.length > 0) {
+ await options[0].click();
} else {
// if it doesn't find the item which text starts with value, it will choose the first option
- const firstOption = await find.byCssSelector('.euiFilterSelectItem');
- await this.clickOption(options.clickWithMouse, firstOption);
+ await find.clickByCssSelector('.euiFilterSelectItem');
}
} else {
- const firstOption = await find.byCssSelector('.euiFilterSelectItem');
- await this.clickOption(options.clickWithMouse, firstOption);
+ await find.clickByCssSelector('.euiFilterSelectItem');
}
+
await this.closeOptionsList(comboBoxElement);
}
@@ -250,11 +241,11 @@ export function ComboBoxProvider({ getService, getPageObjects }: FtrProviderCont
value: string
): Promise {
log.debug(`comboBox.isOptionSelected, value: ${value}`);
- const $ = await comboBoxElement.parseDomContent();
- const selectedOptions = $('.euiComboBoxPill')
- .toArray()
- .map(option => $(option).text());
- return selectedOptions.length === 1 && selectedOptions[0] === value;
+ const selectedOptions = await comboBoxElement.findAllByClassName(
+ 'euiComboBoxPill',
+ WAIT_FOR_EXISTS_TIME
+ );
+ return selectedOptions.length === 1 && (await selectedOptions[0].getVisibleText()) === value;
}
}
diff --git a/test/functional/services/dashboard/expectations.js b/test/functional/services/dashboard/expectations.js
index abafe89c40941..b6bede32b769c 100644
--- a/test/functional/services/dashboard/expectations.js
+++ b/test/functional/services/dashboard/expectations.js
@@ -62,6 +62,14 @@ export function DashboardExpectProvider({ getService, getPageObjects }) {
});
}
+ async tsvbTimeSeriesLegendCount(expectedCount) {
+ log.debug(`DashboardExpect.tsvbTimeSeriesLegendCount(${expectedCount})`);
+ await retry.try(async () => {
+ const tsvbLegendItems = await testSubjects.findAll('tsvbLegendItem', findTimeout);
+ expect(tsvbLegendItems.length).to.be(expectedCount);
+ });
+ }
+
async fieldSuggestions(expectedFields) {
log.debug(`DashboardExpect.fieldSuggestions(${expectedFields})`);
const fields = await filterBar.getFilterEditorFields();
diff --git a/test/functional/services/dashboard/panel_actions.js b/test/functional/services/dashboard/panel_actions.js
index b7327f4af6d17..051074eb9b3d0 100644
--- a/test/functional/services/dashboard/panel_actions.js
+++ b/test/functional/services/dashboard/panel_actions.js
@@ -26,6 +26,7 @@ const OPEN_INSPECTOR_TEST_SUBJ = 'embeddablePanelAction-openInspector';
export function DashboardPanelActionsProvider({ getService, getPageObjects }) {
const log = getService('log');
+ const browser = getService('browser');
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['header', 'common']);
@@ -44,7 +45,7 @@ export function DashboardPanelActionsProvider({ getService, getPageObjects }) {
async toggleContextMenu(parent) {
log.debug('toggleContextMenu');
- await (parent ? parent.moveMouseTo() : testSubjects.moveMouseTo('dashboardPanelTitle'));
+ await (parent ? browser.moveMouseTo(parent) : testSubjects.moveMouseTo('dashboardPanelTitle'));
const toggleMenuItem = await this.findContextMenu(parent);
await toggleMenuItem.click();
}
diff --git a/test/functional/services/inspector.js b/test/functional/services/inspector.js
index d7c3109251aaf..9c25ebea48b4f 100644
--- a/test/functional/services/inspector.js
+++ b/test/functional/services/inspector.js
@@ -22,6 +22,7 @@ import expect from '@kbn/expect';
export function InspectorProvider({ getService }) {
const log = getService('log');
const retry = getService('retry');
+ const browser = getService('browser');
const renderable = getService('renderable');
const flyout = getService('flyout');
const testSubjects = getService('testSubjects');
@@ -131,7 +132,7 @@ export function InspectorProvider({ getService }) {
await retry.try(async () => {
const table = await testSubjects.find('inspectorTable');
const cell = await table.findByCssSelector(`tbody tr:nth-child(${row}) td:nth-child(${column})`);
- await cell.moveMouseTo();
+ await browser.moveMouseTo(cell);
const filterBtn = await testSubjects.findDescendant('filterForInspectorCellValue', cell);
await filterBtn.click();
});
@@ -142,7 +143,7 @@ export function InspectorProvider({ getService }) {
await retry.try(async () => {
const table = await testSubjects.find('inspectorTable');
const cell = await table.findByCssSelector(`tbody tr:nth-child(${row}) td:nth-child(${column})`);
- await cell.moveMouseTo();
+ await browser.moveMouseTo(cell);
const filterBtn = await testSubjects.findDescendant('filterOutInspectorCellValue', cell);
await filterBtn.click();
});
diff --git a/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts b/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts
index 65478c4e5ccd2..b05485618da01 100644
--- a/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts
+++ b/test/functional/services/lib/web_element_wrapper/web_element_wrapper.ts
@@ -58,7 +58,6 @@ export class WebElementWrapper {
private Keys: IKey = this.webDriver.Key;
private driver: WebDriver = this.webDriver.driver;
public LegacyAction: any = this.webDriver.LegacyActionSequence;
- public isW3CEnabled: boolean = (this.webDriver.driver as any).executor_.w3c === true;
public static create(
webElement: WebElement | WebElementWrapper,
@@ -150,12 +149,6 @@ export class WebElementWrapper {
}
}
- private getActions(): any {
- return this.isW3CEnabled
- ? (this.driver as any).actions()
- : (this.driver as any).actions({ bridge: true });
- }
-
/**
* Returns whether or not the element would be visible to an actual user. This means
* that the following types of elements are considered to be not displayed:
@@ -409,81 +402,29 @@ export class WebElementWrapper {
}
/**
- * Moves the remote environment’s mouse cursor to the current element with optional offset
+ * Moves the remote environment’s mouse cursor to the current element
* https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/input_exports_Actions.html#move
- * @param { xOffset: 0, yOffset: 0 } options
- * @return {Promise}
- */
- public async moveMouseTo(options = { xOffset: 0, yOffset: 0 }) {
- await this.retryCall(async function moveMouseTo(wrapper) {
- await wrapper.scrollIntoViewIfNecessary();
- if (wrapper.isW3CEnabled) {
- await wrapper
- .getActions()
- .move({ x: 0, y: 0 })
- .perform();
- await wrapper
- .getActions()
- .move({ x: options.xOffset, y: options.yOffset, origin: wrapper._webElement })
- .perform();
- } else {
- await wrapper
- .getActions()
- .pause(wrapper.getActions().mouse)
- .move({ x: options.xOffset, y: options.yOffset, origin: wrapper._webElement })
- .perform();
- }
- });
- }
-
- /**
- * Inserts an action for moving the mouse to element center, unless optional offset is provided.
- * Then adds an action for left-click (down/up) with the mouse.
- * https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/input_exports_Actions.html#click
*
- * @param { xOffset: 0, yOffset: 0 } options Optional
* @return {Promise