From f79531ff8b84184520e558a7be2d4ae8ebf69c9b Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Thu, 14 Nov 2019 17:50:44 +0300 Subject: [PATCH 01/26] TableVis uses local angular --- .../public/get_inner_angular.ts | 140 ++++++++ .../public/shim/legacy_dependencies_plugin.ts | 2 +- .../public/shim/table_vis_legacy_module.ts | 5 +- .../vis_type_table/public/table_vis_type.ts | 5 +- .../vis_type_table/public/vis_controller.ts | 109 ++++++ src/legacy/ui/public/directives/paginate.js | 338 +++++++++--------- .../directives/watch_multi/watch_multi.js | 148 ++++---- 7 files changed, 500 insertions(+), 247 deletions(-) create mode 100644 src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts create mode 100644 src/legacy/core_plugins/vis_type_table/public/vis_controller.ts diff --git a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts new file mode 100644 index 0000000000000..5a1cbfa420e72 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts @@ -0,0 +1,140 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// inner angular imports +// these are necessary to bootstrap the local angular. +// They can stay even after NP cutover +import angular from 'angular'; +import 'ui/angular-bootstrap'; +import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular'; +// @ts-ignore +import { PrivateProvider } from 'ui/private/private'; +import { CoreStart, LegacyCoreStart, UiSettingsClientContract } from 'kibana/public'; +// @ts-ignore +import { watchMultiDecorator } from 'ui/directives/watch_multi/watch_multi'; +// @ts-ignore +import { GlobalStateProvider } from 'ui/state_management/global_state'; +// @ts-ignore +import { StateManagementConfigProvider } from 'ui/state_management/config_provider'; +// @ts-ignore +import { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; +import { configureAppAngularModule } from 'ui/legacy_compat'; + +import { + PaginateDirectiveProvider, + PaginateControlsDirectiveProvider, + // @ts-ignore +} from 'ui/directives/paginate'; + +import { NavigationStart } from '../../navigation/public'; + +const thirdPartyAngularDependencies = [ + 'ngSanitize', + 'ngRoute', + 'react', + 'ui.bootstrap', + 'RecursionHelper', +]; + +export function getAngularModule(name: string, core: CoreStart, deps: any) { + const discoverUiModule = getInnerAngular(name, core, deps.navigation); + configureAppAngularModule(discoverUiModule, core as LegacyCoreStart, true); + return discoverUiModule; +} + +let initialized = false; + +export function getInnerAngular( + name = 'kibana/table_vis', + core: CoreStart, + navigation: NavigationStart +) { + if (!initialized) { + createLocalPrivateModule(); + createLocalI18nModule(); + createLocalTopNavModule(navigation); + createLocalConfigModule(core.uiSettings); + createLocalPaginateModule(); + initialized = true; + } + return angular + .module(name, [ + ...thirdPartyAngularDependencies, + 'tableVisPaginate', + 'tableVisConfig', + 'tableVisPrivate', + 'tableVisTopNav', + 'tableVisI18n', + ]) + .config(watchMultiDecorator); +} + +function createLocalPrivateModule() { + angular.module('tableVisPrivate', []).provider('Private', PrivateProvider); +} + +function createLocalConfigModule(uiSettings: UiSettingsClientContract) { + angular + .module('tableVisConfig', ['tableVisPrivate']) + .provider('stateManagementConfig', StateManagementConfigProvider) + .provider('config', () => { + return { + $get: () => ({ + get: (value: string) => { + return uiSettings ? uiSettings.get(value) : undefined; + }, + }), + }; + }); +} + +export function createLocalGlobalStateModule() { + angular + .module('tableVisGlobalState', [ + 'tableVisPrivate', + 'tableVisConfig', + 'tableVisKbnUrl', + 'tableVisPromise', + ]) + .service('globalState', function(Private: any) { + return Private(GlobalStateProvider); + }); +} + +function createLocalTopNavModule(navigation: NavigationStart) { + angular + .module('tableVisTopNav', ['react']) + .directive('kbnTopNav', createTopNavDirective) + .directive('kbnTopNavHelper', createTopNavHelper(navigation.ui)); +} + +function createLocalI18nModule() { + angular + .module('tableVisI18n', []) + .provider('i18n', I18nProvider) + .filter('i18n', i18nFilter) + .directive('i18nId', i18nDirective); +} + +function createLocalPaginateModule() { + angular + .module('tableVisPaginate', []) + .directive('paginate', PaginateDirectiveProvider) + .directive('paginateControls', PaginateControlsDirectiveProvider); +} diff --git a/src/legacy/core_plugins/vis_type_table/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/vis_type_table/public/shim/legacy_dependencies_plugin.ts index ba30664951f47..72d7f5bcb0023 100644 --- a/src/legacy/core_plugins/vis_type_table/public/shim/legacy_dependencies_plugin.ts +++ b/src/legacy/core_plugins/vis_type_table/public/shim/legacy_dependencies_plugin.ts @@ -23,7 +23,7 @@ import { initTableVisLegacyModule } from './table_vis_legacy_module'; /** @internal */ export class LegacyDependenciesPlugin implements Plugin { public setup() { - initTableVisLegacyModule(); + // initTableVisLegacyModule(); } public start(core: CoreStart) { diff --git a/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts b/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts index e148fd98490df..94412f8d02191 100644 --- a/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts +++ b/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts @@ -37,9 +37,8 @@ import { KbnRows } from '../paginated_table/rows'; import { PaginatedTable } from '../paginated_table/paginated_table'; /** @internal */ -export const initTableVisLegacyModule = once((): void => { - uiModules - .get('kibana/table_vis', ['kibana', 'RecursionHelper']) +export const initTableVisLegacyModule = once((angularIns: any): void => { + angularIns .controller('KbnTableVisController', TableVisController) .directive('kbnAggTable', KbnAggTable) .directive('kbnAggTableGroup', KbnAggTableGroup) diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts index 1de72c0b33a4c..e48ca0f578179 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts @@ -24,13 +24,12 @@ import { visFactory } from 'ui/vis/vis_factory'; // @ts-ignore import { Schemas } from 'ui/vis/editors/default/schemas'; -// @ts-ignore -import { AngularVisController } from 'ui/vis/vis_types/angular_vis_type'; import { AggGroupNames } from 'ui/vis/editors/default'; import { tableVisResponseHandler } from './table_vis_request_handler'; // @ts-ignore import tableVisTemplate from './table_vis.html'; import { TableOptions } from './components/table_vis_options'; +import { TableVisController } from './vis_controller'; export const createTableVisTypeDefinition = () => { return visFactory.createBaseVisualization({ @@ -43,7 +42,7 @@ export const createTableVisTypeDefinition = () => { description: i18n.translate('visTypeTable.tableVisDescription', { defaultMessage: 'Display values in a table', }), - visualization: AngularVisController, + visualization: TableVisController, visConfig: { defaults: { perPage: 10, diff --git a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts new file mode 100644 index 0000000000000..ed25218476aac --- /dev/null +++ b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts @@ -0,0 +1,109 @@ +/* + * 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 angular from 'angular'; +import $ from 'jquery'; +import { npStart } from 'ui/new_platform'; +import { getAngularModule } from './get_inner_angular'; +import { Vis } from '../../visualizations/public'; + +import { start as navigation } from '../../navigation/public/legacy'; +import { initTableVisLegacyModule } from './shim/table_vis_legacy_module'; + +const innerAngularName = 'kibana/table_vis'; + +interface ITableVisController { + el: JQuery; + vis: Vis; +} +export class TableVisController implements ITableVisController { + private innerAngularBootstrapped: boolean = false; + private injector: any; + el: JQuery; + vis: Vis; + $rootScope: any; + $scope: any; + $compile: any; + + constructor(domeElement: Element, vis: Vis) { + this.el = $(domeElement); + this.vis = vis; + } + + async getInjector() { + if (!this.injector) { + const mountpoint = document.createElement('div'); + mountpoint.setAttribute('style', 'height: 100%; width: 100%;'); + this.injector = angular.bootstrap(mountpoint, [innerAngularName]); + this.el.append(mountpoint); + } + + return this.injector; + } + + async render(esResponse: any, visParams: any, status: any) { + if (!this.innerAngularBootstrapped) { + this.bootstrapInnerAngular(); + } + + return new Promise(async (resolve, reject) => { + if (!this.$rootScope) { + const $injector = await this.getInjector(); + this.$rootScope = $injector.get('$rootScope'); + this.$compile = $injector.get('$compile'); + } + const updateScope = () => { + this.$scope.vis = this.vis; + this.$scope.visState = this.vis.getState(); + this.$scope.esResponse = esResponse; + this.$scope.visParams = visParams; + this.$scope.renderComplete = resolve; + this.$scope.renderFailed = reject; + this.$scope.resize = Date.now(); + this.$scope.updateStatus = status; + this.$scope.$apply(); + }; + + if (!this.$scope) { + this.$scope = this.$rootScope.$new(); + this.$scope.uiState = this.vis.getUiState(); + updateScope(); + this.el.find('div').html(this.$compile(this.vis.type.visConfig.template)(this.$scope)); + this.$scope.$apply(); + } else { + updateScope(); + } + }); + } + + bootstrapInnerAngular = async () => { + if (!this.innerAngularBootstrapped) { + const tableVisModule = getAngularModule(innerAngularName, npStart.core, { navigation }); + initTableVisLegacyModule(tableVisModule); + this.innerAngularBootstrapped = true; + } + }; + + destroy() { + if (this.$rootScope) { + this.$rootScope.$destroy(); + this.$rootScope = null; + } + } +} diff --git a/src/legacy/ui/public/directives/paginate.js b/src/legacy/ui/public/directives/paginate.js index 7ecd5fefe6710..6663e1fb8b6e4 100644 --- a/src/legacy/ui/public/directives/paginate.js +++ b/src/legacy/ui/public/directives/paginate.js @@ -22,209 +22,215 @@ import { i18n } from '@kbn/i18n'; import { uiModules } from '../modules'; import paginateControlsTemplate from './partials/paginate_controls.html'; -uiModules.get('kibana') - .directive('paginate', function ($parse, $compile) { - return { - restrict: 'E', - scope: true, - link: { - pre: function ($scope, $el, attrs) { - if (_.isUndefined(attrs.bottomControls)) attrs.bottomControls = true; - if ($el.find('paginate-controls.paginate-bottom').length === 0 && attrs.bottomControls) { - $el.append($compile('')($scope)); - } - }, - post: function ($scope, $el, attrs) { - if (_.isUndefined(attrs.topControls)) attrs.topControls = false; - if ($el.find('paginate-controls.paginate-top').length === 0 && attrs.topControls) { - $el.prepend($compile('')($scope)); - } - - const paginate = $scope.paginate; - - // add some getters to the controller powered by attributes - paginate.getList = $parse(attrs.list); - paginate.perPageProp = attrs.perPageProp; - - if (attrs.perPage) { - paginate.perPage = attrs.perPage; - $scope.showSelector = false; - } else { - $scope.showSelector = true; - } - - paginate.otherWidthGetter = $parse(attrs.otherWidth); - - paginate.init(); +export function PaginateDirectiveProvider($parse, $compile) { + return { + restrict: 'E', + scope: true, + link: { + pre: function ($scope, $el, attrs) { + if (_.isUndefined(attrs.bottomControls)) attrs.bottomControls = true; + if ($el.find('paginate-controls.paginate-bottom').length === 0 && attrs.bottomControls) { + $el.append($compile('')($scope)); } }, - controllerAs: 'paginate', - controller: function ($scope, $document) { - const self = this; - const ALL = 0; - const allSizeTitle = i18n.translate('common.ui.directives.paginate.size.allDropDownOptionLabel', { - defaultMessage: 'All', - }); + post: function ($scope, $el, attrs) { + if (_.isUndefined(attrs.topControls)) attrs.topControls = false; + if ($el.find('paginate-controls.paginate-top').length === 0 && attrs.topControls) { + $el.prepend($compile('')($scope)); + } - self.sizeOptions = [ - { title: '10', value: 10 }, - { title: '25', value: 25 }, - { title: '100', value: 100 }, - { title: allSizeTitle, value: ALL } - ]; + const paginate = $scope.paginate; - // setup the watchers, called in the post-link function - self.init = function () { + // add some getters to the controller powered by attributes + paginate.getList = $parse(attrs.list); + paginate.perPageProp = attrs.perPageProp; - self.perPage = _.parseInt(self.perPage) || $scope[self.perPageProp]; + if (attrs.perPage) { + paginate.perPage = attrs.perPage; + $scope.showSelector = false; + } else { + $scope.showSelector = true; + } - $scope.$watchMulti([ - 'paginate.perPage', - self.perPageProp, - self.otherWidthGetter - ], function (vals, oldVals) { - const intChanges = vals[0] !== oldVals[0]; + paginate.otherWidthGetter = $parse(attrs.otherWidth); - if (intChanges) { - if (!setPerPage(self.perPage)) { + paginate.init(); + }, + }, + controllerAs: 'paginate', + controller: function ($scope, $document) { + const self = this; + const ALL = 0; + const allSizeTitle = i18n.translate( + 'common.ui.directives.paginate.size.allDropDownOptionLabel', + { + defaultMessage: 'All', + } + ); + + self.sizeOptions = [ + { title: '10', value: 10 }, + { title: '25', value: 25 }, + { title: '100', value: 100 }, + { title: allSizeTitle, value: ALL }, + ]; + + // setup the watchers, called in the post-link function + self.init = function () { + self.perPage = _.parseInt(self.perPage) || $scope[self.perPageProp]; + + $scope.$watchMulti(['paginate.perPage', self.perPageProp, self.otherWidthGetter], function ( + vals, + oldVals + ) { + const intChanges = vals[0] !== oldVals[0]; + + if (intChanges) { + if (!setPerPage(self.perPage)) { // if we are not able to set the external value, // render now, otherwise wait for the external value // to trigger the watcher again - self.renderList(); - } - return; + self.renderList(); } + return; + } - self.perPage = _.parseInt(self.perPage) || $scope[self.perPageProp]; - if (self.perPage == null) { - self.perPage = ALL; - return; - } + self.perPage = _.parseInt(self.perPage) || $scope[self.perPageProp]; + if (self.perPage == null) { + self.perPage = ALL; + return; + } - self.renderList(); - }); + self.renderList(); + }); - $scope.$watch('page', self.changePage); - $scope.$watchCollection(self.getList, function (list) { - $scope.list = list; - self.renderList(); - }); - }; + $scope.$watch('page', self.changePage); + $scope.$watchCollection(self.getList, function (list) { + $scope.list = list; + self.renderList(); + }); + }; - self.goToPage = function (number) { - if (number) { - if (number.hasOwnProperty('number')) number = number.number; - $scope.page = $scope.pages[number - 1] || $scope.pages[0]; - } - }; + self.goToPage = function (number) { + if (number) { + if (number.hasOwnProperty('number')) number = number.number; + $scope.page = $scope.pages[number - 1] || $scope.pages[0]; + } + }; - self.goToTop = function goToTop() { - $document.scrollTop(0); - }; + self.goToTop = function goToTop() { + $document.scrollTop(0); + }; - self.renderList = function () { - $scope.pages = []; - if (!$scope.list) return; + self.renderList = function () { + $scope.pages = []; + if (!$scope.list) return; - const perPage = _.parseInt(self.perPage); - const count = perPage ? Math.ceil($scope.list.length / perPage) : 1; + const perPage = _.parseInt(self.perPage); + const count = perPage ? Math.ceil($scope.list.length / perPage) : 1; - _.times(count, function (i) { - let page; + _.times(count, function (i) { + let page; - if (perPage) { - const start = perPage * i; - page = $scope.list.slice(start, start + perPage); - } else { - page = $scope.list.slice(0); - } + if (perPage) { + const start = perPage * i; + page = $scope.list.slice(start, start + perPage); + } else { + page = $scope.list.slice(0); + } - page.number = i + 1; - page.i = i; + page.number = i + 1; + page.i = i; - page.count = count; - page.first = page.number === 1; - page.last = page.number === count; - page.firstItem = (page.number - 1) * perPage + 1; - page.lastItem = Math.min(page.number * perPage, $scope.list.length); + page.count = count; + page.first = page.number === 1; + page.last = page.number === count; + page.firstItem = (page.number - 1) * perPage + 1; + page.lastItem = Math.min(page.number * perPage, $scope.list.length); - page.prev = $scope.pages[i - 1]; - if (page.prev) page.prev.next = page; + page.prev = $scope.pages[i - 1]; + if (page.prev) page.prev.next = page; - $scope.pages.push(page); - }); + $scope.pages.push(page); + }); - // set the new page, or restore the previous page number - if ($scope.page && $scope.page.i < $scope.pages.length) { - $scope.page = $scope.pages[$scope.page.i]; - } else { - $scope.page = $scope.pages[0]; - } + // set the new page, or restore the previous page number + if ($scope.page && $scope.page.i < $scope.pages.length) { + $scope.page = $scope.pages[$scope.page.i]; + } else { + $scope.page = $scope.pages[0]; + } - if ($scope.page && $scope.onPageChanged) { - $scope.onPageChanged($scope.page); - } - }; + if ($scope.page && $scope.onPageChanged) { + $scope.onPageChanged($scope.page); + } + }; - self.changePage = function (page) { - if (!page) { - $scope.otherPages = null; - return; - } + self.changePage = function (page) { + if (!page) { + $scope.otherPages = null; + return; + } - // setup the list of the other pages to link to - $scope.otherPages = []; - const width = +self.otherWidthGetter($scope) || 5; - let left = page.i - Math.round((width - 1) / 2); - let right = left + width - 1; + // setup the list of the other pages to link to + $scope.otherPages = []; + const width = +self.otherWidthGetter($scope) || 5; + let left = page.i - Math.round((width - 1) / 2); + let right = left + width - 1; - // shift neg count from left to right - if (left < 0) { - right += 0 - left; - left = 0; - } + // shift neg count from left to right + if (left < 0) { + right += 0 - left; + left = 0; + } - // shift extra right nums to left - const lastI = page.count - 1; - if (right > lastI) { - right = lastI; - left = right - width + 1; - } + // shift extra right nums to left + const lastI = page.count - 1; + if (right > lastI) { + right = lastI; + left = right - width + 1; + } - for (let i = left; i <= right; i++) { - const other = $scope.pages[i]; + for (let i = left; i <= right; i++) { + const other = $scope.pages[i]; - if (!other) continue; + if (!other) continue; - $scope.otherPages.push(other); - if (other.last) $scope.otherPages.containsLast = true; - if (other.first) $scope.otherPages.containsFirst = true; - } + $scope.otherPages.push(other); + if (other.last) $scope.otherPages.containsLast = true; + if (other.first) $scope.otherPages.containsFirst = true; + } - if ($scope.onPageChanged) { - $scope.onPageChanged($scope.page); - } - }; + if ($scope.onPageChanged) { + $scope.onPageChanged($scope.page); + } + }; - function setPerPage(val) { - let $ppParent = $scope; + function setPerPage(val) { + let $ppParent = $scope; - while ($ppParent && !_.has($ppParent, self.perPageProp)) { - $ppParent = $ppParent.$parent; - } + while ($ppParent && !_.has($ppParent, self.perPageProp)) { + $ppParent = $ppParent.$parent; + } - if ($ppParent) { - $ppParent[self.perPageProp] = val; - return true; - } + if ($ppParent) { + $ppParent[self.perPageProp] = val; + return true; } } - }; - }) - .directive('paginateControls', function () { + }, + }; +} + +export function PaginateControlsDirectiveProvider() { // this directive is automatically added by paginate if not found within it's $el - return { - restrict: 'E', - template: paginateControlsTemplate - }; - }); + return { + restrict: 'E', + template: paginateControlsTemplate, + }; +} + +uiModules + .get('kibana') + .directive('paginate', PaginateDirectiveProvider) + .directive('paginateControls', PaginateControlsDirectiveProvider); diff --git a/src/legacy/ui/public/directives/watch_multi/watch_multi.js b/src/legacy/ui/public/directives/watch_multi/watch_multi.js index add95e8146f26..03bccd598f351 100644 --- a/src/legacy/ui/public/directives/watch_multi/watch_multi.js +++ b/src/legacy/ui/public/directives/watch_multi/watch_multi.js @@ -21,10 +21,8 @@ import _ from 'lodash'; import { uiModules } from '../../modules'; import { callEach } from '../../utils/function'; -uiModules.get('kibana') - .config(function ($provide) { - - $provide.decorator('$rootScope', function ($delegate) { +export function watchMultiDecorator($provide) { + $provide.decorator('$rootScope', function ($delegate) { /** * Watch multiple expressions with a single callback. Along * with making code simpler it also merges all of the watcher @@ -53,84 +51,86 @@ uiModules.get('kibana') * @param {Function} fn - the callback function * @return {Function} - an unwatch function, just like the return value of $watch */ - $delegate.constructor.prototype.$watchMulti = function (expressions, fn) { - if (!Array.isArray(expressions)) throw new TypeError('expected an array of expressions to watch'); - if (!_.isFunction(fn)) throw new TypeError('expected a function that is triggered on each watch'); - - const $scope = this; - const vals = new Array(expressions.length); - const prev = new Array(expressions.length); - let fire = false; - let init = 0; - const neededInits = expressions.length; - - // first, register all of the multi-watchers - const unwatchers = expressions.map(function (expr, i) { - expr = normalizeExpression($scope, expr); - if (!expr) return; - - return expr.fn.call($scope, expr.get, function (newVal, oldVal) { - if (newVal === oldVal) { - init += 1; - } - - vals[i] = newVal; - prev[i] = oldVal; - fire = true; - }, expr.deep); - }); - - // then, the watcher that checks to see if any of - // the other watchers triggered this cycle - let flip = false; - unwatchers.push($scope.$watch(function () { - if (init < neededInits) return init; + $delegate.constructor.prototype.$watchMulti = function (expressions, fn) { + if (!Array.isArray(expressions)) throw new TypeError('expected an array of expressions to watch'); + if (!_.isFunction(fn)) throw new TypeError('expected a function that is triggered on each watch'); + + const $scope = this; + const vals = new Array(expressions.length); + const prev = new Array(expressions.length); + let fire = false; + let init = 0; + const neededInits = expressions.length; + + // first, register all of the multi-watchers + const unwatchers = expressions.map(function (expr, i) { + expr = normalizeExpression($scope, expr); + if (!expr) return; - if (fire) { - fire = false; - flip = !flip; + return expr.fn.call($scope, expr.get, function (newVal, oldVal) { + if (newVal === oldVal) { + init += 1; } - return flip; - }, function () { - if (init < neededInits) return false; - fn(vals.slice(0), prev.slice(0)); - vals.forEach(function (v, i) { - prev[i] = v; - }); - })); + vals[i] = newVal; + prev[i] = oldVal; + fire = true; + }, expr.deep); + }); + + // then, the watcher that checks to see if any of + // the other watchers triggered this cycle + let flip = false; + unwatchers.push($scope.$watch(function () { + if (init < neededInits) return init; + + if (fire) { + fire = false; + flip = !flip; + } + return flip; + }, function () { + if (init < neededInits) return false; + + fn(vals.slice(0), prev.slice(0)); + vals.forEach(function (v, i) { + prev[i] = v; + }); + })); + + return _.partial(callEach, unwatchers); + }; - return _.partial(callEach, unwatchers); + function normalizeExpression($scope, expr) { + if (!expr) return; + const norm = { + fn: $scope.$watch, + deep: false }; - function normalizeExpression($scope, expr) { - if (!expr) return; - const norm = { - fn: $scope.$watch, - deep: false - }; - - if (_.isFunction(expr)) return _.assign(norm, { get: expr }); - if (_.isObject(expr)) return _.assign(norm, expr); - if (!_.isString(expr)) return; - - if (expr.substr(0, 2) === '[]') { - return _.assign(norm, { - fn: $scope.$watchCollection, - get: expr.substr(2) - }); - } + if (_.isFunction(expr)) return _.assign(norm, { get: expr }); + if (_.isObject(expr)) return _.assign(norm, expr); + if (!_.isString(expr)) return; - if (expr.charAt(0) === '=') { - return _.assign(norm, { - deep: true, - get: expr.substr(1) - }); - } + if (expr.substr(0, 2) === '[]') { + return _.assign(norm, { + fn: $scope.$watchCollection, + get: expr.substr(2) + }); + } - return _.assign(norm, { get: expr }); + if (expr.charAt(0) === '=') { + return _.assign(norm, { + deep: true, + get: expr.substr(1) + }); } - return $delegate; - }); + return _.assign(norm, { get: expr }); + } + + return $delegate; }); +} + +uiModules.get('kibana').config(watchMultiDecorator); From 8e5f09b4de9aca51cdabf31e9f56ceb963691ddb Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Fri, 15 Nov 2019 12:29:20 +0300 Subject: [PATCH 02/26] Clean up --- .../public/get_inner_angular.ts | 49 ++--------- .../public/shim/legacy_dependencies_plugin.ts | 3 +- .../vis_type_table/public/table_vis_type.ts | 4 +- .../vis_type_table/public/vis_controller.ts | 47 +++++----- .../accessibility/kbn_accessible_click.js | 86 ++++++++++--------- 5 files changed, 75 insertions(+), 114 deletions(-) diff --git a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts index 5a1cbfa420e72..c761c60525c26 100644 --- a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts +++ b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts @@ -29,11 +29,9 @@ import { CoreStart, LegacyCoreStart, UiSettingsClientContract } from 'kibana/pub // @ts-ignore import { watchMultiDecorator } from 'ui/directives/watch_multi/watch_multi'; // @ts-ignore -import { GlobalStateProvider } from 'ui/state_management/global_state'; +import { KbnAccessibleClickProvider } from 'ui/accessibility/kbn_accessible_click'; // @ts-ignore import { StateManagementConfigProvider } from 'ui/state_management/config_provider'; -// @ts-ignore -import { createTopNavDirective, createTopNavHelper } from 'ui/kbn_top_nav/kbn_top_nav'; import { configureAppAngularModule } from 'ui/legacy_compat'; import { @@ -42,33 +40,20 @@ import { // @ts-ignore } from 'ui/directives/paginate'; -import { NavigationStart } from '../../navigation/public'; - -const thirdPartyAngularDependencies = [ - 'ngSanitize', - 'ngRoute', - 'react', - 'ui.bootstrap', - 'RecursionHelper', -]; +const thirdPartyAngularDependencies = ['ngSanitize', 'ui.bootstrap', 'RecursionHelper']; -export function getAngularModule(name: string, core: CoreStart, deps: any) { - const discoverUiModule = getInnerAngular(name, core, deps.navigation); +export function getAngularModule(name: string, core: CoreStart) { + const discoverUiModule = getInnerAngular(name, core); configureAppAngularModule(discoverUiModule, core as LegacyCoreStart, true); return discoverUiModule; } let initialized = false; -export function getInnerAngular( - name = 'kibana/table_vis', - core: CoreStart, - navigation: NavigationStart -) { +export function getInnerAngular(name = 'kibana/table_vis', core: CoreStart) { if (!initialized) { createLocalPrivateModule(); createLocalI18nModule(); - createLocalTopNavModule(navigation); createLocalConfigModule(core.uiSettings); createLocalPaginateModule(); initialized = true; @@ -79,10 +64,10 @@ export function getInnerAngular( 'tableVisPaginate', 'tableVisConfig', 'tableVisPrivate', - 'tableVisTopNav', 'tableVisI18n', ]) - .config(watchMultiDecorator); + .config(watchMultiDecorator) + .directive('kbnAccessibleClick', KbnAccessibleClickProvider); } function createLocalPrivateModule() { @@ -104,26 +89,6 @@ function createLocalConfigModule(uiSettings: UiSettingsClientContract) { }); } -export function createLocalGlobalStateModule() { - angular - .module('tableVisGlobalState', [ - 'tableVisPrivate', - 'tableVisConfig', - 'tableVisKbnUrl', - 'tableVisPromise', - ]) - .service('globalState', function(Private: any) { - return Private(GlobalStateProvider); - }); -} - -function createLocalTopNavModule(navigation: NavigationStart) { - angular - .module('tableVisTopNav', ['react']) - .directive('kbnTopNav', createTopNavDirective) - .directive('kbnTopNavHelper', createTopNavHelper(navigation.ui)); -} - function createLocalI18nModule() { angular .module('tableVisI18n', []) diff --git a/src/legacy/core_plugins/vis_type_table/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/vis_type_table/public/shim/legacy_dependencies_plugin.ts index 72d7f5bcb0023..18b15b88eabce 100644 --- a/src/legacy/core_plugins/vis_type_table/public/shim/legacy_dependencies_plugin.ts +++ b/src/legacy/core_plugins/vis_type_table/public/shim/legacy_dependencies_plugin.ts @@ -18,12 +18,11 @@ */ import { CoreStart, Plugin } from '../../../../../core/public'; -import { initTableVisLegacyModule } from './table_vis_legacy_module'; /** @internal */ export class LegacyDependenciesPlugin implements Plugin { public setup() { - // initTableVisLegacyModule(); + // nothing to do here yet } public start(core: CoreStart) { diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts index e48ca0f578179..89a0c152251b1 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts @@ -29,7 +29,7 @@ import { tableVisResponseHandler } from './table_vis_request_handler'; // @ts-ignore import tableVisTemplate from './table_vis.html'; import { TableOptions } from './components/table_vis_options'; -import { TableVisController } from './vis_controller'; +import { TableVisualizationController } from './vis_controller'; export const createTableVisTypeDefinition = () => { return visFactory.createBaseVisualization({ @@ -42,7 +42,7 @@ export const createTableVisTypeDefinition = () => { description: i18n.translate('visTypeTable.tableVisDescription', { defaultMessage: 'Display values in a table', }), - visualization: TableVisController, + visualization: TableVisualizationController, visConfig: { defaults: { perPage: 10, diff --git a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts index ed25218476aac..9351a592342b8 100644 --- a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts +++ b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts @@ -17,36 +17,31 @@ * under the License. */ -import angular from 'angular'; +import angular, { IModule, auto, IRootScopeService, IScope, ICompileService } from 'angular'; import $ from 'jquery'; import { npStart } from 'ui/new_platform'; import { getAngularModule } from './get_inner_angular'; -import { Vis } from '../../visualizations/public'; +import { Vis, VisParams } from '../../visualizations/public'; -import { start as navigation } from '../../navigation/public/legacy'; import { initTableVisLegacyModule } from './shim/table_vis_legacy_module'; const innerAngularName = 'kibana/table_vis'; -interface ITableVisController { +export class TableVisualizationController { + private tableVisModule: IModule | undefined; + private injector: auto.IInjectorService | undefined; el: JQuery; vis: Vis; -} -export class TableVisController implements ITableVisController { - private innerAngularBootstrapped: boolean = false; - private injector: any; - el: JQuery; - vis: Vis; - $rootScope: any; - $scope: any; - $compile: any; + $rootScope: IRootScopeService | null = null; + $scope: IScope & { [key: string]: any } | undefined; + $compile: ICompileService | undefined; constructor(domeElement: Element, vis: Vis) { this.el = $(domeElement); this.vis = vis; } - async getInjector() { + getInjector() { if (!this.injector) { const mountpoint = document.createElement('div'); mountpoint.setAttribute('style', 'height: 100%; width: 100%;'); @@ -57,18 +52,19 @@ export class TableVisController implements ITableVisController { return this.injector; } - async render(esResponse: any, visParams: any, status: any) { - if (!this.innerAngularBootstrapped) { - this.bootstrapInnerAngular(); - } + async render(esResponse: object, visParams: VisParams, status: { [key: string]: boolean }) { + this.initLocalAngular(); return new Promise(async (resolve, reject) => { if (!this.$rootScope) { - const $injector = await this.getInjector(); + const $injector = this.getInjector(); this.$rootScope = $injector.get('$rootScope'); this.$compile = $injector.get('$compile'); } const updateScope = () => { + if (!this.$scope) { + return; + } this.$scope.vis = this.vis; this.$scope.visState = this.vis.getState(); this.$scope.esResponse = esResponse; @@ -80,11 +76,11 @@ export class TableVisController implements ITableVisController { this.$scope.$apply(); }; - if (!this.$scope) { + if (!this.$scope && this.$compile) { this.$scope = this.$rootScope.$new(); this.$scope.uiState = this.vis.getUiState(); updateScope(); - this.el.find('div').html(this.$compile(this.vis.type.visConfig.template)(this.$scope)); + this.el.find('div').append(this.$compile(this.vis.type.visConfig.template)(this.$scope)); this.$scope.$apply(); } else { updateScope(); @@ -92,11 +88,10 @@ export class TableVisController implements ITableVisController { }); } - bootstrapInnerAngular = async () => { - if (!this.innerAngularBootstrapped) { - const tableVisModule = getAngularModule(innerAngularName, npStart.core, { navigation }); - initTableVisLegacyModule(tableVisModule); - this.innerAngularBootstrapped = true; + initLocalAngular = async () => { + if (!this.tableVisModule) { + this.tableVisModule = getAngularModule(innerAngularName, npStart.core); + initTableVisLegacyModule(this.tableVisModule); } }; diff --git a/src/legacy/ui/public/accessibility/kbn_accessible_click.js b/src/legacy/ui/public/accessibility/kbn_accessible_click.js index 1abf322daa9a8..12cd79e206b28 100644 --- a/src/legacy/ui/public/accessibility/kbn_accessible_click.js +++ b/src/legacy/ui/public/accessibility/kbn_accessible_click.js @@ -43,52 +43,54 @@ import { } from '@elastic/eui'; import { uiModules } from '../modules'; -uiModules.get('kibana') - .directive('kbnAccessibleClick', function () { - return { - restrict: 'A', - controller: $element => { - $element.on('keydown', e => { - // Prevent a scroll from occurring if the user has hit space. - if (e.keyCode === keyCodes.SPACE) { - e.preventDefault(); - } - }); - }, - link: (scope, element, attrs) => { - // The whole point of this directive is to hack in functionality that native buttons provide - // by default. - const elementType = element.prop('tagName'); - - if (elementType === 'BUTTON') { - throw new Error(`kbnAccessibleClick doesn't need to be used on a button.`); +export function KbnAccessibleClickProvider() { + return { + restrict: 'A', + controller: $element => { + $element.on('keydown', e => { + // Prevent a scroll from occurring if the user has hit space. + if (e.keyCode === keyCodes.SPACE) { + e.preventDefault(); } + }); + }, + link: (scope, element, attrs) => { + // The whole point of this directive is to hack in functionality that native buttons provide + // by default. + const elementType = element.prop('tagName'); - if (elementType === 'A' && attrs.href !== undefined) { - throw new Error(`kbnAccessibleClick doesn't need to be used on a link if it has a href attribute.`); - } + if (elementType === 'BUTTON') { + throw new Error(`kbnAccessibleClick doesn't need to be used on a button.`); + } - // We're emulating a click action, so we should already have a regular click handler defined. - if (!attrs.ngClick) { - throw new Error('kbnAccessibleClick requires ng-click to be defined on its element.'); - } + if (elementType === 'A' && attrs.href !== undefined) { + throw new Error(`kbnAccessibleClick doesn't need to be used on a link if it has a href attribute.`); + } - // If the developer hasn't already specified attributes required for accessibility, add them. - if (attrs.tabindex === undefined) { - element.attr('tabindex', '0'); - } + // We're emulating a click action, so we should already have a regular click handler defined. + if (!attrs.ngClick) { + throw new Error('kbnAccessibleClick requires ng-click to be defined on its element.'); + } + + // If the developer hasn't already specified attributes required for accessibility, add them. + if (attrs.tabindex === undefined) { + element.attr('tabindex', '0'); + } - if (attrs.role === undefined) { - element.attr('role', 'button'); + if (attrs.role === undefined) { + element.attr('role', 'button'); + } + + element.on('keyup', e => { + // Support keyboard accessibility by emulating mouse click on ENTER or SPACE keypress. + if (accessibleClickKeys[e.keyCode]) { + // Delegate to the click handler on the element (assumed to be ng-click). + element.click(); } + }); + }, + }; +} - element.on('keyup', e => { - // Support keyboard accessibility by emulating mouse click on ENTER or SPACE keypress. - if (accessibleClickKeys[e.keyCode]) { - // Delegate to the click handler on the element (assumed to be ng-click). - element.click(); - } - }); - }, - }; - }); +uiModules.get('kibana') + .directive('kbnAccessibleClick', KbnAccessibleClickProvider); From 652bc543b03084d97dfc9b9e44628ab97ecabee9 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Fri, 15 Nov 2019 13:58:08 +0300 Subject: [PATCH 03/26] Fix TS --- src/legacy/core_plugins/vis_type_table/public/vis_controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts index 9351a592342b8..62264c9866999 100644 --- a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts +++ b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts @@ -33,7 +33,7 @@ export class TableVisualizationController { el: JQuery; vis: Vis; $rootScope: IRootScopeService | null = null; - $scope: IScope & { [key: string]: any } | undefined; + $scope: (IScope & { [key: string]: any }) | undefined; $compile: ICompileService | undefined; constructor(domeElement: Element, vis: Vis) { From 3dcf983f286ffe154b168847729f1dcb1b74de5d Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Fri, 15 Nov 2019 17:04:20 +0300 Subject: [PATCH 04/26] Update angular_config --- src/legacy/ui/public/chrome/api/angular.js | 4 +- .../public/legacy_compat/angular_config.tsx | 93 ++++++++++++++----- 2 files changed, 73 insertions(+), 24 deletions(-) diff --git a/src/legacy/ui/public/chrome/api/angular.js b/src/legacy/ui/public/chrome/api/angular.js index e6457fec93633..73d50a83e11a5 100644 --- a/src/legacy/ui/public/chrome/api/angular.js +++ b/src/legacy/ui/public/chrome/api/angular.js @@ -21,13 +21,15 @@ import { uiModules } from '../../modules'; import { directivesProvider } from '../directives'; import { registerSubUrlHooks } from './sub_url_hooks'; +import { start as data } from '../../../../core_plugins/data/public/legacy'; import { configureAppAngularModule } from 'ui/legacy_compat'; +import { npStart } from '../../new_platform/new_platform'; export function initAngularApi(chrome, internals) { chrome.setupAngular = function () { const kibana = uiModules.get('kibana'); - configureAppAngularModule(kibana); + configureAppAngularModule(kibana, npStart.core, data, false); kibana.value('chrome', chrome); diff --git a/src/legacy/ui/public/legacy_compat/angular_config.tsx b/src/legacy/ui/public/legacy_compat/angular_config.tsx index 788718e848430..6e9f5c85aa1b2 100644 --- a/src/legacy/ui/public/legacy_compat/angular_config.tsx +++ b/src/legacy/ui/public/legacy_compat/angular_config.tsx @@ -28,7 +28,7 @@ import { IRootScopeService, } from 'angular'; import $ from 'jquery'; -import { cloneDeep, forOwn, set } from 'lodash'; +import _, { cloneDeep, forOwn, get, set } from 'lodash'; import React, { Fragment } from 'react'; import * as Rx from 'rxjs'; @@ -37,27 +37,43 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { CoreStart, LegacyCoreStart } from 'kibana/public'; import { fatalError } from 'ui/notify'; -import { capabilities } from 'ui/capabilities'; +import { RouteConfiguration } from 'ui/routes/route_manager'; // @ts-ignore import { modifyUrl } from 'ui/url'; import { toMountPoint } from '../../../../plugins/kibana_react/public'; // @ts-ignore import { UrlOverflowService } from '../error_url_overflow'; -import { npStart } from '../new_platform'; -import { toastNotifications } from '../notify'; // @ts-ignore import { isSystemApiRequest } from '../system_api'; const URL_LIMIT_WARN_WITHIN = 1000; -function isDummyWrapperRoute($route: any) { +/** + * Detects whether a given angular route is a dummy route that doesn't + * require any action. There are two ways this can happen: + * If `outerAngularWrapperRoute` is set on the route config object, + * it means the local application service set up this route on the outer angular + * and the internal routes will handle the hooks. + * + * If angular did not detect a route and it is the local angular, we are currently + * navigating away from a URL controlled by a local angular router and the + * application will get unmounted. In this case the outer router will handle + * the hooks. + * @param $route Injected $route dependency + * @param isLocalAngular Flag whether this is the local angular router + */ +function isDummyRoute($route: any, isLocalAngular: boolean) { return ( - $route.current && $route.current.$$route && $route.current.$$route.outerAngularWrapperRoute + ($route.current && $route.current.$$route && $route.current.$$route.outerAngularWrapperRoute) || + (!$route.current && isLocalAngular) ); } -export const configureAppAngularModule = (angularModule: IModule) => { - const newPlatform = npStart.core; +export const configureAppAngularModule = ( + angularModule: IModule, + newPlatform: LegacyCoreStart, + isLocalAngular: boolean +) => { const legacyMetadata = newPlatform.injectedMetadata.getLegacyMetadata(); forOwn(newPlatform.injectedMetadata.getInjectedVars(), (val, name) => { @@ -73,15 +89,16 @@ export const configureAppAngularModule = (angularModule: IModule) => { .value('buildSha', legacyMetadata.buildSha) .value('serverName', legacyMetadata.serverName) .value('esUrl', getEsUrl(newPlatform)) - .value('uiCapabilities', capabilities.get()) + .value('uiCapabilities', newPlatform.application.capabilities) .config(setupCompileProvider(newPlatform)) .config(setupLocationProvider(newPlatform)) .config($setupXsrfRequestInterceptor(newPlatform)) .run(capture$httpLoadingCount(newPlatform)) - .run($setupBreadcrumbsAutoClear(newPlatform)) - .run($setupBadgeAutoClear(newPlatform)) - .run($setupHelpExtensionAutoClear(newPlatform)) - .run($setupUrlOverflowHandling(newPlatform)); + .run($setupBreadcrumbsAutoClear(newPlatform, isLocalAngular)) + .run($setupBadgeAutoClear(newPlatform, isLocalAngular)) + .run($setupHelpExtensionAutoClear(newPlatform, isLocalAngular)) + .run($setupUrlOverflowHandling(newPlatform, isLocalAngular)) + .run($setupUICapabilityRedirect(newPlatform)); }; const getEsUrl = (newPlatform: CoreStart) => { @@ -168,12 +185,42 @@ const capture$httpLoadingCount = (newPlatform: CoreStart) => ( ); }; +/** + * integrates with angular to automatically redirect to home if required + * capability is not met + */ +const $setupUICapabilityRedirect = (newPlatform: CoreStart) => ( + $rootScope: IRootScopeService, + $injector: any +) => { + const isKibanaAppRoute = window.location.pathname.endsWith('/app/kibana'); + // this feature only works within kibana app for now after everything is + // switched to the application service, this can be changed to handle all + // apps. + if (!isKibanaAppRoute) { + return; + } + $rootScope.$on( + '$routeChangeStart', + (event, { $$route: route }: { $$route?: RouteConfiguration } = {}) => { + if (!route || !route.requireUICapability) { + return; + } + + if (!get(newPlatform.application.capabilities, route.requireUICapability)) { + $injector.get('kbnUrl').change('/home'); + event.preventDefault(); + } + } + ); +}; + /** * internal angular run function that will be called when angular bootstraps and * 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: CoreStart, isLocalAngular: boolean) => ( $rootScope: IRootScopeService, $injector: any ) => { @@ -195,7 +242,7 @@ const $setupBreadcrumbsAutoClear = (newPlatform: CoreStart) => ( }); $rootScope.$on('$routeChangeSuccess', () => { - if (isDummyWrapperRoute($route)) { + if (isDummyRoute($route, isLocalAngular)) { return; } const current = $route.current || {}; @@ -223,7 +270,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: CoreStart, isLocalAngular: boolean) => ( $rootScope: IRootScopeService, $injector: any ) => { @@ -237,7 +284,7 @@ const $setupBadgeAutoClear = (newPlatform: CoreStart) => ( }); $rootScope.$on('$routeChangeSuccess', () => { - if (isDummyWrapperRoute($route)) { + if (isDummyRoute($route, isLocalAngular)) { return; } const current = $route.current || {}; @@ -266,7 +313,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: CoreStart, isLocalAngular: boolean) => ( $rootScope: IRootScopeService, $injector: any ) => { @@ -284,14 +331,14 @@ const $setupHelpExtensionAutoClear = (newPlatform: CoreStart) => ( const $route = $injector.has('$route') ? $injector.get('$route') : {}; $rootScope.$on('$routeChangeStart', () => { - if (isDummyWrapperRoute($route)) { + if (isDummyRoute($route, isLocalAngular)) { return; } helpExtensionSetSinceRouteChange = false; }); $rootScope.$on('$routeChangeSuccess', () => { - if (isDummyWrapperRoute($route)) { + if (isDummyRoute($route, isLocalAngular)) { return; } const current = $route.current || {}; @@ -304,7 +351,7 @@ const $setupHelpExtensionAutoClear = (newPlatform: CoreStart) => ( }); }; -const $setupUrlOverflowHandling = (newPlatform: CoreStart) => ( +const $setupUrlOverflowHandling = (newPlatform: CoreStart, isLocalAngular: boolean) => ( $location: ILocationService, $rootScope: IRootScopeService, $injector: auto.IInjectorService @@ -312,7 +359,7 @@ const $setupUrlOverflowHandling = (newPlatform: CoreStart) => ( const $route = $injector.has('$route') ? $injector.get('$route') : {}; const urlOverflow = new UrlOverflowService(); const check = () => { - if (isDummyWrapperRoute($route)) { + if (isDummyRoute($route, isLocalAngular)) { return; } // disable long url checks when storing state in session storage @@ -326,7 +373,7 @@ const $setupUrlOverflowHandling = (newPlatform: CoreStart) => ( try { if (urlOverflow.check($location.absUrl()) <= URL_LIMIT_WARN_WITHIN) { - toastNotifications.addWarning({ + newPlatform.notifications.toasts.addWarning({ title: i18n.translate('common.ui.chrome.bigUrlWarningNotificationTitle', { defaultMessage: 'The URL is big and Kibana might stop working', }), From ca87855acd4b4f20a314610df08c4773c7bcea8c Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Fri, 15 Nov 2019 17:06:19 +0300 Subject: [PATCH 05/26] Fix export --- src/legacy/ui/public/routes/route_manager.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/legacy/ui/public/routes/route_manager.d.ts b/src/legacy/ui/public/routes/route_manager.d.ts index 56203354f3c20..a5261a7c8ee3a 100644 --- a/src/legacy/ui/public/routes/route_manager.d.ts +++ b/src/legacy/ui/public/routes/route_manager.d.ts @@ -23,7 +23,7 @@ import { ChromeBreadcrumb } from '../../../../core/public'; -interface RouteConfiguration { +export interface RouteConfiguration { controller?: string | ((...args: any[]) => void); redirectTo?: string; resolveRedirectTo?: (...args: any[]) => void; From 197b5833b2131d9044c849f7f30e936cb4922b59 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Mon, 18 Nov 2019 11:45:07 +0300 Subject: [PATCH 06/26] Update render_app.ts --- x-pack/legacy/plugins/graph/public/render_app.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/graph/public/render_app.ts b/x-pack/legacy/plugins/graph/public/render_app.ts index a8a86f4d1f850..6c317b09fd035 100644 --- a/x-pack/legacy/plugins/graph/public/render_app.ts +++ b/x-pack/legacy/plugins/graph/public/render_app.ts @@ -25,6 +25,7 @@ import { DataStart } from 'src/legacy/core_plugins/data/public'; import { AppMountContext, ChromeStart, + LegacyCoreStart, SavedObjectsClientContract, ToastsStart, UiSettingsClientContract, @@ -32,6 +33,7 @@ import { // @ts-ignore import { initGraphApp } from './app'; import { Plugin as DataPlugin } from '../../../../../src/plugins/data/public'; +import { NavigationStart } from '../../../../../src/legacy/core_plugins/navigation/public'; /** * These are dependencies of the Graph app besides the base dependencies @@ -44,6 +46,7 @@ export interface GraphDependencies extends LegacyAngularInjectedDependencies { appBasePath: string; capabilities: Record>; coreStart: AppMountContext['core']; + navigation: NavigationStart; chrome: ChromeStart; config: UiSettingsClientContract; toastNotifications: ToastsStart; @@ -75,8 +78,8 @@ export interface LegacyAngularInjectedDependencies { } export const renderApp = ({ appBasePath, element, ...deps }: GraphDependencies) => { - const graphAngularModule = createLocalAngularModule(deps.coreStart); - configureAppAngularModule(graphAngularModule); + const graphAngularModule = createLocalAngularModule(deps.navigation); + configureAppAngularModule(graphAngularModule, deps.coreStart as LegacyCoreStart, true); initGraphApp(graphAngularModule, deps); const $injector = mountGraphApp(appBasePath, element); return () => $injector.get('$rootScope').$destroy(); From ffc151c50238cd684269ff241e2a2b025bf060d0 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Mon, 18 Nov 2019 12:00:44 +0300 Subject: [PATCH 07/26] Cetralize ui deps --- .../public/__tests__/table_vis_controller.js | 12 +++-- .../public/agg_table/__tests__/agg_table.js | 5 +- .../agg_table/__tests__/agg_table_group.js | 4 +- .../public/agg_table/agg_table.js | 2 +- .../public/components/table_vis_options.tsx | 3 +- .../public/get_inner_angular.ts | 19 +++---- .../vis_type_table/public/legacy.ts | 2 +- .../vis_type_table/public/legacy_imports.ts | 54 +++++++++++++++++++ .../public/shim/table_vis_legacy_module.ts | 6 --- .../public/table_vis_fn.test.ts | 6 +-- .../public/table_vis_request_handler.ts | 3 +- .../vis_type_table/public/table_vis_type.ts | 8 +-- .../vis_type_table/public/types.ts | 2 +- .../vis_type_table/public/vis_controller.ts | 2 +- 14 files changed, 79 insertions(+), 49 deletions(-) create mode 100644 src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts diff --git a/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js b/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js index 4153ce2da36a7..56e827c8106ea 100644 --- a/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js +++ b/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js @@ -20,12 +20,14 @@ import $ from 'jquery'; import expect from '@kbn/expect'; import ngMock from 'ng_mock'; -import { legacyResponseHandlerProvider } from 'ui/vis/response_handlers/legacy'; -import { Vis } from 'ui/vis'; -import { VisFactoryProvider } from 'ui/vis/vis_factory'; +import { + AppStateProvider, + legacyResponseHandlerProvider, + Vis, + VisFactoryProvider, + tabifyAggResponse, +} from '../legacy_imports'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { AppStateProvider } from 'ui/state_management/app_state'; -import { tabifyAggResponse } from 'ui/agg_response/tabify'; import { createTableVisTypeDefinition } from '../table_vis_type'; import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; 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 13e8a4fd9535a..446f0ac0acd2b 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 @@ -23,13 +23,10 @@ import ngMock from 'ng_mock'; import expect from '@kbn/expect'; import fixtures from 'fixtures/fake_hierarchical_data'; import sinon from 'sinon'; -import { legacyResponseHandlerProvider } from 'ui/vis/response_handlers/legacy'; +import { legacyResponseHandlerProvider, Vis, tabifyAggResponse, VisFactoryProvider } from '../../legacy_imports'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { Vis } from 'ui/vis'; -import { tabifyAggResponse } from 'ui/agg_response/tabify'; import { round } from 'lodash'; -import { VisFactoryProvider } from 'ui/vis/vis_factory'; import { createTableVisTypeDefinition } from '../../table_vis_type'; import { setup as visualizationsSetup } from '../../../../visualizations/public/np_ready/public/legacy'; 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 f4e3a8e36605c..9db2b8042cd70 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 @@ -21,10 +21,8 @@ import $ from 'jquery'; import ngMock from 'ng_mock'; import expect from '@kbn/expect'; import fixtures from 'fixtures/fake_hierarchical_data'; -import { legacyResponseHandlerProvider } from 'ui/vis/response_handlers/legacy'; +import { legacyResponseHandlerProvider, Vis, tabifyAggResponse } from '../../legacy_imports'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -import { Vis } from 'ui/vis'; -import { tabifyAggResponse } from 'ui/agg_response/tabify'; describe('Table Vis - AggTableGroup Directive', function () { let $rootScope; diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.js b/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.js index 06cca15f88556..8bc275f5255bb 100644 --- a/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.js +++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.js @@ -18,7 +18,7 @@ */ import _ from 'lodash'; import aggTableTemplate from './agg_table.html'; -import { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; +import { getFormat } from '../legacy_imports'; import { i18n } from '@kbn/i18n'; export function KbnAggTable(config, RecursionHelper) { diff --git a/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx b/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx index fdcd531ad6930..4d69af59b0c99 100644 --- a/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx +++ b/src/legacy/core_plugins/vis_type_table/public/components/table_vis_options.tsx @@ -23,8 +23,7 @@ import { EuiIconTip, EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { tabifyGetColumns } from 'ui/agg_response/tabify/_get_columns'; -import { VisOptionsProps } from 'ui/vis/editors/default'; +import { tabifyGetColumns, VisOptionsProps } from '../legacy_imports'; import { NumberInputOption, SwitchOption, diff --git a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts index c761c60525c26..bb0e9a40ee1c8 100644 --- a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts +++ b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts @@ -22,23 +22,18 @@ // They can stay even after NP cutover import angular from 'angular'; import 'ui/angular-bootstrap'; +import 'angular-recursion'; import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular'; -// @ts-ignore -import { PrivateProvider } from 'ui/private/private'; import { CoreStart, LegacyCoreStart, UiSettingsClientContract } from 'kibana/public'; -// @ts-ignore -import { watchMultiDecorator } from 'ui/directives/watch_multi/watch_multi'; -// @ts-ignore -import { KbnAccessibleClickProvider } from 'ui/accessibility/kbn_accessible_click'; -// @ts-ignore -import { StateManagementConfigProvider } from 'ui/state_management/config_provider'; -import { configureAppAngularModule } from 'ui/legacy_compat'; - import { + PrivateProvider, PaginateDirectiveProvider, PaginateControlsDirectiveProvider, - // @ts-ignore -} from 'ui/directives/paginate'; + watchMultiDecorator, + KbnAccessibleClickProvider, + StateManagementConfigProvider, + configureAppAngularModule, +} from './legacy_imports'; const thirdPartyAngularDependencies = ['ngSanitize', 'ui.bootstrap', 'RecursionHelper']; 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 8513622dec9aa..0b7827400e194 100644 --- a/src/legacy/core_plugins/vis_type_table/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_table/public/legacy.ts @@ -18,7 +18,7 @@ */ import { PluginInitializerContext } from 'kibana/public'; -import { npSetup, npStart } from 'ui/new_platform'; +import { npSetup, npStart } from './legacy_imports'; import { plugin } from '.'; import { TablePluginSetupDependencies } from './plugin'; diff --git a/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts new file mode 100644 index 0000000000000..2eb3284ed0ca2 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts @@ -0,0 +1,54 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export { npSetup, npStart } from 'ui/new_platform'; +export { SchemaConfig } from 'ui/visualize/loader/pipeline_helpers/build_pipeline'; +// @ts-ignore +export { visFactory, VisFactoryProvider } from 'ui/vis/vis_factory'; + +export { Vis } from 'ui/vis'; + +// @ts-ignore +export { Schemas } from 'ui/vis/editors/default/schemas'; +export { AggGroupNames, VisOptionsProps } from 'ui/vis/editors/default'; + +// @ts-ignore +export { legacyResponseHandlerProvider } from 'ui/vis/response_handlers/legacy'; +// @ts-ignore +export { PrivateProvider } from 'ui/private/private'; +// @ts-ignore +export { watchMultiDecorator } from 'ui/directives/watch_multi/watch_multi'; +// @ts-ignore +export { KbnAccessibleClickProvider } from 'ui/accessibility/kbn_accessible_click'; +// @ts-ignore +export { StateManagementConfigProvider } from 'ui/state_management/config_provider'; +export { configureAppAngularModule } from 'ui/legacy_compat'; + +// @ts-ignore +export { PaginateDirectiveProvider } from 'ui/directives/paginate'; +// @ts-ignore +export { PaginateControlsDirectiveProvider } from 'ui/directives/paginate'; + +export { tabifyGetColumns } from 'ui/agg_response/tabify/_get_columns'; + +export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; +// @ts-ignore +export { AppStateProvider } from 'ui/state_management/app_state'; +// @ts-ignore +export { tabifyAggResponse } from 'ui/agg_response/tabify'; diff --git a/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts b/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts index 94412f8d02191..3d11014a738be 100644 --- a/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts +++ b/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts @@ -19,12 +19,6 @@ import { once } from 'lodash'; -// @ts-ignore -import { uiModules } from 'ui/modules'; - -import 'angular-recursion'; -import 'ui/directives/paginate'; - // @ts-ignore import { TableVisController } from '../table_vis_controller.js'; // @ts-ignore diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.test.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.test.ts index 1c1b808ffb014..8ee55e5bff75f 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_fn.test.ts @@ -22,9 +22,7 @@ import { createTableVisFn } from './table_vis_fn'; // @ts-ignore import { functionWrapper } from '../../interpreter/test_helpers'; -jest.mock('ui/new_platform'); - -jest.mock('ui/vis/response_handlers/legacy', () => { +jest.mock('./legacy_imports', () => { const mockResponseHandler = jest.fn().mockReturnValue( Promise.resolve({ tables: [{ columns: [], rows: [] }], @@ -37,7 +35,7 @@ jest.mock('ui/vis/response_handlers/legacy', () => { }; }); -const { mockResponseHandler } = jest.requireMock('ui/vis/response_handlers/legacy'); +const { mockResponseHandler } = jest.requireMock('./legacy_imports'); describe('interpreter/functions#table', () => { const fn = functionWrapper(createTableVisFn); diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_request_handler.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_request_handler.ts index c432dfd84cbb8..1a6d4600025f1 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_request_handler.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_request_handler.ts @@ -17,7 +17,6 @@ * under the License. */ -// @ts-ignore -import { legacyResponseHandlerProvider } from 'ui/vis/response_handlers/legacy'; +import { legacyResponseHandlerProvider } from './legacy_imports'; export const tableVisResponseHandler = legacyResponseHandlerProvider().handler; diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts index 89a0c152251b1..d36abbfc9eab1 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_type.ts @@ -18,13 +18,7 @@ */ import { i18n } from '@kbn/i18n'; -import { Vis } from 'ui/vis'; -// @ts-ignore -import { visFactory } from 'ui/vis/vis_factory'; - -// @ts-ignore -import { Schemas } from 'ui/vis/editors/default/schemas'; -import { AggGroupNames } from 'ui/vis/editors/default'; +import { AggGroupNames, Schemas, Vis, visFactory } from './legacy_imports'; import { tableVisResponseHandler } from './table_vis_request_handler'; // @ts-ignore import tableVisTemplate from './table_vis.html'; diff --git a/src/legacy/core_plugins/vis_type_table/public/types.ts b/src/legacy/core_plugins/vis_type_table/public/types.ts index 4a16bb72bd2e3..963298ea89a43 100644 --- a/src/legacy/core_plugins/vis_type_table/public/types.ts +++ b/src/legacy/core_plugins/vis_type_table/public/types.ts @@ -17,7 +17,7 @@ * under the License. */ -import { SchemaConfig } from 'ui/visualize/loader/pipeline_helpers/build_pipeline'; +import { SchemaConfig } from './legacy_imports'; export enum AggTypes { SUM = 'sum', diff --git a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts index 62264c9866999..c61c8c6d0d3cf 100644 --- a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts +++ b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts @@ -19,7 +19,7 @@ import angular, { IModule, auto, IRootScopeService, IScope, ICompileService } from 'angular'; import $ from 'jquery'; -import { npStart } from 'ui/new_platform'; +import { npStart } from './legacy_imports'; import { getAngularModule } from './get_inner_angular'; import { Vis, VisParams } from '../../visualizations/public'; From bbbc3f6e2200eae3c7a58ba96eb248158cf9b103 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Mon, 18 Nov 2019 12:25:30 +0300 Subject: [PATCH 08/26] Fix loading KbnTableVisController in Dashboard --- .../vis_type_table/public/shim/table_vis_legacy_module.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts b/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts index 3d11014a738be..fe1b1ceeb14b9 100644 --- a/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts +++ b/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts @@ -17,8 +17,6 @@ * under the License. */ -import { once } from 'lodash'; - // @ts-ignore import { TableVisController } from '../table_vis_controller.js'; // @ts-ignore @@ -31,11 +29,11 @@ import { KbnRows } from '../paginated_table/rows'; import { PaginatedTable } from '../paginated_table/paginated_table'; /** @internal */ -export const initTableVisLegacyModule = once((angularIns: any): void => { +export const initTableVisLegacyModule = (angularIns: any): void => { angularIns .controller('KbnTableVisController', TableVisController) .directive('kbnAggTable', KbnAggTable) .directive('kbnAggTableGroup', KbnAggTableGroup) .directive('kbnRows', KbnRows) .directive('paginatedTable', PaginatedTable); -}); +}; From f17f3b712a8e17205852b5f4aea814d484d515fc Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Mon, 18 Nov 2019 14:01:28 +0300 Subject: [PATCH 09/26] Fix graph --- .../core_plugins/vis_type_table/public/vis_controller.ts | 2 +- x-pack/legacy/plugins/graph/public/index.ts | 2 ++ x-pack/legacy/plugins/graph/public/plugin.ts | 8 ++++++-- x-pack/legacy/plugins/graph/public/render_app.ts | 8 ++++---- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts index c61c8c6d0d3cf..99cd6b900ec98 100644 --- a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts +++ b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts @@ -88,7 +88,7 @@ export class TableVisualizationController { }); } - initLocalAngular = async () => { + initLocalAngular = () => { if (!this.tableVisModule) { this.tableVisModule = getAngularModule(innerAngularName, npStart.core); initTableVisLegacyModule(this.tableVisModule); diff --git a/x-pack/legacy/plugins/graph/public/index.ts b/x-pack/legacy/plugins/graph/public/index.ts index 48420d403653f..833134abff0b6 100644 --- a/x-pack/legacy/plugins/graph/public/index.ts +++ b/x-pack/legacy/plugins/graph/public/index.ts @@ -20,6 +20,7 @@ import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_regis import { npSetup, npStart } from 'ui/new_platform'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { start as data } from '../../../../../src/legacy/core_plugins/data/public/legacy'; +import { start as navigation } from '../../../../../src/legacy/core_plugins/navigation/public/legacy'; import { GraphPlugin } from './plugin'; // @ts-ignore @@ -53,6 +54,7 @@ async function getAngularInjectedDependencies(): Promise; + navigation: NavigationStart; } export interface GraphPluginSetupDependencies { @@ -30,6 +32,7 @@ export interface GraphPluginStartDependencies { export class GraphPlugin implements Plugin { private dataStart: DataStart | null = null; + private navigationStart: NavigationStart | null = null; private npDataStart: ReturnType | null = null; private savedObjectsClient: SavedObjectsClientContract | null = null; private angularDependencies: LegacyAngularInjectedDependencies | null = null; @@ -42,6 +45,7 @@ export class GraphPlugin implements Plugin { const { renderApp } = await import('./render_app'); return renderApp({ ...params, + navigation: this.navigationStart!, npData: this.npDataStart!, savedObjectsClient: this.savedObjectsClient!, xpackInfo, @@ -66,9 +70,9 @@ export class GraphPlugin implements Plugin { start( core: CoreStart, - { data, npData, __LEGACY: { angularDependencies } }: GraphPluginStartDependencies + { data, npData, navigation, __LEGACY: { angularDependencies } }: GraphPluginStartDependencies ) { - // TODO is this really the right way? I though the app context would give us those + this.navigationStart = navigation; this.dataStart = data; this.npDataStart = npData; this.angularDependencies = angularDependencies; diff --git a/x-pack/legacy/plugins/graph/public/render_app.ts b/x-pack/legacy/plugins/graph/public/render_app.ts index 6c317b09fd035..18cdf0ddd81b2 100644 --- a/x-pack/legacy/plugins/graph/public/render_app.ts +++ b/x-pack/legacy/plugins/graph/public/render_app.ts @@ -107,9 +107,9 @@ function mountGraphApp(appBasePath: string, element: HTMLElement) { return $injector; } -function createLocalAngularModule(core: AppMountContext['core']) { +function createLocalAngularModule(navigation: NavigationStart) { createLocalI18nModule(); - createLocalTopNavModule(); + createLocalTopNavModule(navigation); createLocalConfirmModalModule(); const graphAngularModule = angular.module(moduleName, [ @@ -128,11 +128,11 @@ function createLocalConfirmModalModule() { .directive('confirmModal', reactDirective => reactDirective(EuiConfirmModal)); } -function createLocalTopNavModule() { +function createLocalTopNavModule(navigation: NavigationStart) { angular .module('graphTopNav', ['react']) .directive('kbnTopNav', createTopNavDirective) - .directive('kbnTopNavHelper', createTopNavHelper); + .directive('kbnTopNavHelper', createTopNavHelper(navigation.ui)); } function createLocalI18nModule() { From 9186322be9bac480cb147797d768793d522c45fd Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Mon, 18 Nov 2019 14:05:56 +0300 Subject: [PATCH 10/26] Rename const --- .../core_plugins/vis_type_table/public/get_inner_angular.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts index bb0e9a40ee1c8..a8008203af26a 100644 --- a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts +++ b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts @@ -38,9 +38,9 @@ import { const thirdPartyAngularDependencies = ['ngSanitize', 'ui.bootstrap', 'RecursionHelper']; export function getAngularModule(name: string, core: CoreStart) { - const discoverUiModule = getInnerAngular(name, core); - configureAppAngularModule(discoverUiModule, core as LegacyCoreStart, true); - return discoverUiModule; + const uiModule = getInnerAngular(name, core); + configureAppAngularModule(uiModule, core as LegacyCoreStart, true); + return uiModule; } let initialized = false; From 916bf18fe5461c0e24d2fd56fc2997d91f5ac61e Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Mon, 18 Nov 2019 23:32:53 +0300 Subject: [PATCH 11/26] Add table vis mocks --- .../public/get_inner_angular.ts | 2 +- .../paginated_table/paginated_table.test.ts | 132 ++++++++++++++++++ .../vis_type_table/public/table_vis.mock.ts | 71 ++++++++++ 3 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts create mode 100644 src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts diff --git a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts index a8008203af26a..fdbfc66af84a4 100644 --- a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts +++ b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts @@ -72,7 +72,7 @@ function createLocalPrivateModule() { function createLocalConfigModule(uiSettings: UiSettingsClientContract) { angular .module('tableVisConfig', ['tableVisPrivate']) - .provider('stateManagementConfig', StateManagementConfigProvider) + // .provider('stateManagementConfig', StateManagementConfigProvider) .provider('config', () => { return { $get: () => ({ diff --git a/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts b/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts new file mode 100644 index 0000000000000..43a1784758e47 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts @@ -0,0 +1,132 @@ +/* + * 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 angular from 'angular'; +import 'angular-sanitize'; +import 'angular-mocks'; +import '../table_vis.mock'; + +import { getAngularModule } from '../get_inner_angular'; +import { initTableVisLegacyModule } from '../shim/table_vis_legacy_module'; +import { npStart } from '../legacy_imports'; + +describe('Table Vis - Paginated table', () => { + let $el: any; + let $rootScope; + let $compile: any; + let $scope: any; + const defaultPerPage = 10; + + const initLocalAngular = () => { + const tableVisModule = getAngularModule('kibana/table_vis', npStart.core); + initTableVisLegacyModule(tableVisModule); + }; + + beforeEach(initLocalAngular); + beforeEach(angular.mock.module('kibana/table_vis')); + + beforeEach(inject((_$rootScope_: any, _$compile_: any) => { + $rootScope = _$rootScope_; + $compile = _$compile_; + $scope = $rootScope.$new(); + })); + + // @ts-ignore + const makeData = function(colCount: any, rowCount: any) { + let columns = []; + let rows = []; + + if (_.isNumber(colCount)) { + _.times(colCount, function(i) { + columns.push({ id: i, title: 'column' + i, formatter: { convert: _.identity } }); + }); + } else { + columns = colCount.map((col, i) => ({ + id: i, + title: col.title, + formatter: col.formatter || { convert: _.identity }, + })); + } + + if (_.isNumber(rowCount)) { + _.times(rowCount, function(row) { + const rowItems = {}; + + _.times(columns.length, function(col) { + rowItems[col] = 'item' + col + row; + }); + + rows.push(rowItems); + }); + } else { + rows = rowCount.map(row => { + const newRow = {}; + row.forEach((v, i) => (newRow[i] = v)); + return newRow; + }); + } + + return { + columns: columns, + rows: rows, + }; + }; + + const renderTable = function( + table: any, + cols: any, + rows: any, + perPage: any, + sort: any, + linkToTop: any + ) { + $scope.table = table || { columns: [], rows: [] }; + $scope.cols = cols || []; + $scope.rows = rows || []; + $scope.perPage = perPage || defaultPerPage; + $scope.sort = sort || {}; + $scope.linkToTop = linkToTop; + + const template = ` + `; + $el = $compile(template)($scope); + + $scope.$digest(); + }; + + describe('rendering', () => { + it('should not display without rows', () => { + const cols = [ + { + title: 'test1', + }, + ]; + const rows: any = []; + + renderTable(null, cols, rows, undefined, undefined, undefined); + expect($el.children().length).toBe(0); + }); + }); +}); diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts new file mode 100644 index 0000000000000..2fe91e9e2ba4c --- /dev/null +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts @@ -0,0 +1,71 @@ +/* + * 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 { + chromeServiceMock, + notificationServiceMock, + overlayServiceMock, + uiSettingsServiceMock, + i18nServiceMock, + httpServiceMock, + injectedMetadataServiceMock, +} from '../../../../core/public/mocks'; +import { StubBrowserStorage } from 'test_utils/stub_browser_storage'; + +import { applicationServiceMock } from '../../../../core/public/application/application_service.mock'; +import { createUiNewPlatformMock } from 'ui/new_platform/__mocks__/helpers'; + +// jest.mock('ui/new_platform'); +// jest.doMock('ui/new_platform', () => ({ +// ...createUiNewPlatformMock() +// })); +jest.doMock('ui/new_platform', () => ({ + npSetup: { + core: { + notifications: notificationServiceMock.createSetupContract(), + injectedMetadata: injectedMetadataServiceMock.createSetupContract(), + }, + }, + npStart: { + core: { + i18n: i18nServiceMock.createStartContract(), + chrome: chromeServiceMock.createStartContract(), + http: httpServiceMock.createStartContract({ basePath: 'path' }), + overlays: overlayServiceMock.createStartContract(), + notifications: notificationServiceMock.createStartContract(), + uiSettings: uiSettingsServiceMock.createStartContract(), + injectedMetadata: injectedMetadataServiceMock.createStartContract(), + application: applicationServiceMock.createInternalStartContract(), + }, + plugins: { + data: { + query: { + timefilter: { + history: {}, + timefilter: {}, + }, + }, + }, + }, + }, +})); + +Object.assign(window, { + sessionStorage: new StubBrowserStorage(), +}); From 656637d1832e866a1d9ac1b7b0e53db23e994db5 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Tue, 19 Nov 2019 09:05:39 +0300 Subject: [PATCH 12/26] Fix kbn_top_nav --- src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js b/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js index 9c4cee6b05db0..a1d48caf3f489 100644 --- a/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js +++ b/src/legacy/ui/public/kbn_top_nav/kbn_top_nav.js @@ -75,8 +75,7 @@ export function createTopNavDirective() { module.directive('kbnTopNav', createTopNavDirective); -export function createTopNavHelper(reactDirective) { - const { TopNavMenu } = navigation.ui; +export const createTopNavHelper = ({ TopNavMenu }) => (reactDirective) => { return reactDirective( wrapInI18nContext(TopNavMenu), [ @@ -116,6 +115,6 @@ export function createTopNavHelper(reactDirective) { 'showAutoRefreshOnly', ], ); -} +}; -module.directive('kbnTopNavHelper', createTopNavHelper); +module.directive('kbnTopNavHelper', createTopNavHelper(navigation.ui)); From d38db791c98eb9c5d1fffab04f72372daeb285b1 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Thu, 21 Nov 2019 20:25:46 +0300 Subject: [PATCH 13/26] Add TS for test --- .../public/get_inner_angular.ts | 4 +- .../paginated_table/paginated_table.test.ts | 631 +++++++++++++++++- 2 files changed, 600 insertions(+), 35 deletions(-) diff --git a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts index fdbfc66af84a4..ec95c4aeec9f2 100644 --- a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts +++ b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts @@ -72,8 +72,8 @@ function createLocalPrivateModule() { function createLocalConfigModule(uiSettings: UiSettingsClientContract) { angular .module('tableVisConfig', ['tableVisPrivate']) - // .provider('stateManagementConfig', StateManagementConfigProvider) - .provider('config', () => { + .provider('stateManagementConfig', StateManagementConfigProvider) + .provider('config', function() { return { $get: () => ({ get: (value: string) => { diff --git a/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts b/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts index 43a1784758e47..f0e41c1b84846 100644 --- a/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts @@ -17,7 +17,9 @@ * under the License. */ +import { isNumber, times, identity, random } from 'lodash'; import angular from 'angular'; +import $ from 'jquery'; import 'angular-sanitize'; import 'angular-mocks'; import '../table_vis.mock'; @@ -26,6 +28,21 @@ import { getAngularModule } from '../get_inner_angular'; import { initTableVisLegacyModule } from '../shim/table_vis_legacy_module'; import { npStart } from '../legacy_imports'; +interface Sort { + columnIndex: number; + direction: string; +} + +interface Row { + [key: string]: number; +} + +interface Column { + id: string; + title: string; + formatter?: object; +} + describe('Table Vis - Paginated table', () => { let $el: any; let $rootScope; @@ -47,54 +64,56 @@ describe('Table Vis - Paginated table', () => { $scope = $rootScope.$new(); })); - // @ts-ignore - const makeData = function(colCount: any, rowCount: any) { - let columns = []; - let rows = []; + const makeData = function(colCount: number | Column[], rowCount: number | string[][]) { + let columns: Column[] = []; + let rows: Row[] = []; - if (_.isNumber(colCount)) { - _.times(colCount, function(i) { - columns.push({ id: i, title: 'column' + i, formatter: { convert: _.identity } }); + if (isNumber(colCount)) { + times(colCount, i => { + columns.push({ id: `${i}`, title: `column${i}`, formatter: { convert: identity } }); }); } else { - columns = colCount.map((col, i) => ({ - id: i, - title: col.title, - formatter: col.formatter || { convert: _.identity }, - })); + columns = colCount.map( + (col, i) => + ({ + id: `${i}`, + title: col.title, + formatter: col.formatter || { convert: identity }, + } as Column) + ); } - if (_.isNumber(rowCount)) { - _.times(rowCount, function(row) { - const rowItems = {}; + if (isNumber(rowCount)) { + times(rowCount, row => { + const rowItems: Row = {}; - _.times(columns.length, function(col) { - rowItems[col] = 'item' + col + row; + times(columns.length, col => { + rowItems[`${col}`] = `item-${col}-${row}`; }); rows.push(rowItems); }); } else { - rows = rowCount.map(row => { - const newRow = {}; + rows = rowCount.map((row: string[]) => { + const newRow: Row = {}; row.forEach((v, i) => (newRow[i] = v)); return newRow; }); } return { - columns: columns, - rows: rows, + columns, + rows, }; }; const renderTable = function( - table: any, - cols: any, - rows: any, - perPage: any, - sort: any, - linkToTop: any + table: { columns: Column[]; rows: Row[] } | null, + cols: Column[], + rows: Row[], + perPage?: number, + sort?: Sort, + linkToTop?: boolean ) { $scope.table = table || { columns: [], rows: [] }; $scope.cols = cols || []; @@ -103,30 +122,576 @@ describe('Table Vis - Paginated table', () => { $scope.sort = sort || {}; $scope.linkToTop = linkToTop; - const template = ` + const template = angular.element(` `; - $el = $compile(template)($scope); + link-to-top="linkToTop">`); + $el = $($compile(template)($scope)); $scope.$digest(); }; describe('rendering', () => { it('should not display without rows', () => { - const cols = [ + const cols: Column[] = [ { + id: 'col-1-1', title: 'test1', }, ]; - const rows: any = []; + const rows: Row[] = []; - renderTable(null, cols, rows, undefined, undefined, undefined); + renderTable(null, cols, rows); expect($el.children().length).toBe(0); }); + + it('should render columns and rows', function() { + const data = makeData(2, 2); + const cols = data.columns; + const rows = data.rows; + + renderTable(data, cols, rows); + expect($el.children().length).toBe(1); + const tableRows = $el.find('tbody tr'); + + // should contain the row data + expect( + tableRows + .eq(0) + .find('td') + .eq(0) + .text() + ).toBe(rows[0][0]); + expect( + tableRows + .eq(0) + .find('td') + .eq(1) + .text() + ).toBe(rows[0][1]); + expect( + tableRows + .eq(1) + .find('td') + .eq(0) + .text() + ).toBe(rows[1][0]); + expect( + tableRows + .eq(1) + .find('td') + .eq(1) + .text() + ).toBe(rows[1][1]); + }); + + it('should paginate rows', function() { + // note: paginate truncates pages, so don't make too many + const rowCount = random(16, 24); + const perPageCount = random(5, 8); + const data = makeData(3, rowCount); + const pageCount = Math.ceil(rowCount / perPageCount); + + renderTable(data, data.columns, data.rows, perPageCount); + const tableRows = $el.find('tbody tr'); + expect(tableRows.length).toBe(perPageCount); + // add 2 for the first and last page links + expect($el.find('paginate-controls button').length).toBe(pageCount + 2); + }); + + it('should not show blank rows on last page', function() { + const rowCount = 7; + const perPageCount = 10; + const data = makeData(3, rowCount); + + renderTable(data, data.columns, data.rows, perPageCount); + const tableRows = $el.find('tbody tr'); + expect(tableRows.length).toBe(rowCount); + }); + + it('should not show link to top when not set', function() { + const data = makeData(5, 5); + renderTable(data, data.columns, data.rows, 10); + + const linkToTop = $el.find('[data-test-subj="paginateControlsLinkToTop"]'); + expect(linkToTop.length).toBe(0); + }); + + it('should show link to top when set', function() { + const data = makeData(5, 5); + renderTable(data, data.columns, data.rows, 10, undefined, true); + + const linkToTop = $el.find('[data-test-subj="paginateControlsLinkToTop"]'); + expect(linkToTop.length).toBe(1); + }); + }); + + describe('sorting', function() { + let data; + let lastRowIndex; + let paginatedTable; + + beforeEach(function() { + data = makeData(3, [ + ['bbbb', 'aaaa', 'zzzz'], + ['cccc', 'cccc', 'aaaa'], + ['zzzz', 'bbbb', 'bbbb'], + ['aaaa', 'zzzz', 'cccc'], + ]); + + lastRowIndex = data.rows.length - 1; + renderTable(data, data.columns, data.rows); + paginatedTable = $el.isolateScope().paginatedTable; + }); + + // afterEach(function () { + // $scope.$destroy(); + // }); + + it('should not sort by default', function() { + const tableRows = $el.find('tbody tr'); + expect( + tableRows + .eq(0) + .find('td') + .eq(0) + .text() + ).toBe(data.rows[0][0]); + expect( + tableRows + .eq(lastRowIndex) + .find('td') + .eq(0) + .text() + ).toBe(data.rows[lastRowIndex][0]); + }); + + it('should do nothing when sorting by invalid column id', function() { + // sortColumn + paginatedTable.sortColumn(999); + $scope.$digest(); + + const tableRows = $el.find('tbody tr'); + expect( + tableRows + .eq(0) + .find('td') + .eq(0) + .text() + ).toBe('bbbb'); + expect( + tableRows + .eq(0) + .find('td') + .eq(1) + .text() + ).toBe('aaaa'); + expect( + tableRows + .eq(0) + .find('td') + .eq(2) + .text() + ).toBe('zzzz'); + }); + + it('should do nothing when sorting by non sortable column', function() { + data.columns[0].sortable = false; + + // sortColumn + paginatedTable.sortColumn(0); + $scope.$digest(); + + const tableRows = $el.find('tbody tr'); + expect( + tableRows + .eq(0) + .find('td') + .eq(0) + .text() + ).toBe('bbbb'); + expect( + tableRows + .eq(0) + .find('td') + .eq(1) + .text() + ).toBe('aaaa'); + expect( + tableRows + .eq(0) + .find('td') + .eq(2) + .text() + ).toBe('zzzz'); + }); + + it("should set the sort direction to asc when it's not explicitly set", function() { + paginatedTable.sortColumn(1); + $scope.$digest(); + + const tableRows = $el.find('tbody tr'); + expect( + tableRows + .eq(2) + .find('td') + .eq(1) + .text() + ).toBe('cccc'); + expect( + tableRows + .eq(1) + .find('td') + .eq(1) + .text() + ).toBe('bbbb'); + expect( + tableRows + .eq(0) + .find('td') + .eq(1) + .text() + ).toBe('aaaa'); + }); + + it('should allow you to explicitly set the sort direction', function() { + paginatedTable.sortColumn(1, 'desc'); + $scope.$digest(); + + const tableRows = $el.find('tbody tr'); + expect( + tableRows + .eq(0) + .find('td') + .eq(1) + .text() + ).toBe('zzzz'); + expect( + tableRows + .eq(1) + .find('td') + .eq(1) + .text() + ).toBe('cccc'); + expect( + tableRows + .eq(2) + .find('td') + .eq(1) + .text() + ).toBe('bbbb'); + }); + + it('should sort ascending on first invocation', function() { + // sortColumn + paginatedTable.sortColumn(0); + $scope.$digest(); + + const tableRows = $el.find('tbody tr'); + expect( + tableRows + .eq(0) + .find('td') + .eq(0) + .text() + ).toBe('aaaa'); + expect( + tableRows + .eq(lastRowIndex) + .find('td') + .eq(0) + .text() + ).toBe('zzzz'); + }); + + it('should sort descending on second invocation', function() { + // sortColumn + paginatedTable.sortColumn(0); + paginatedTable.sortColumn(0); + $scope.$digest(); + + const tableRows = $el.find('tbody tr'); + expect( + tableRows + .eq(0) + .find('td') + .eq(0) + .text() + ).toBe('zzzz'); + expect( + tableRows + .eq(lastRowIndex) + .find('td') + .eq(0) + .text() + ).toBe('aaaa'); + }); + + it('should clear sorting on third invocation', function() { + // sortColumn + paginatedTable.sortColumn(0); + paginatedTable.sortColumn(0); + paginatedTable.sortColumn(0); + $scope.$digest(); + + const tableRows = $el.find('tbody tr'); + expect( + tableRows + .eq(0) + .find('td') + .eq(0) + .text() + ).toBe(data.rows[0][0]); + expect( + tableRows + .eq(lastRowIndex) + .find('td') + .eq(0) + .text() + ).toBe('aaaa'); + }); + + it('should sort new column ascending', function() { + // sort by first column + paginatedTable.sortColumn(0); + $scope.$digest(); + + // sort by second column + paginatedTable.sortColumn(1); + $scope.$digest(); + + const tableRows = $el.find('tbody tr'); + expect( + tableRows + .eq(0) + .find('td') + .eq(1) + .text() + ).toBe('aaaa'); + expect( + tableRows + .eq(lastRowIndex) + .find('td') + .eq(1) + .text() + ).toBe('zzzz'); + }); + }); + + describe('sorting duplicate columns', function() { + let data; + let paginatedTable; + const colText = 'test row'; + + beforeEach(function() { + const cols = [{ title: colText }, { title: colText }, { title: colText }]; + const rows = [ + ['bbbb', 'aaaa', 'zzzz'], + ['cccc', 'cccc', 'aaaa'], + ['zzzz', 'bbbb', 'bbbb'], + ['aaaa', 'zzzz', 'cccc'], + ]; + data = makeData(cols, rows); + + renderTable(data, data.columns, data.rows); + paginatedTable = $el.isolateScope().paginatedTable; + }); + + it('should have duplicate column titles', function() { + const columns = $el.find('thead th span'); + columns.each(function() { + expect($(this).text()).toBe(colText); + }); + }); + + it('should handle sorting on columns with the same name', function() { + // sort by the last column + paginatedTable.sortColumn(2); + $scope.$digest(); + + const tableRows = $el.find('tbody tr'); + expect( + tableRows + .eq(0) + .find('td') + .eq(0) + .text() + ).toBe('cccc'); + expect( + tableRows + .eq(0) + .find('td') + .eq(1) + .text() + ).toBe('cccc'); + expect( + tableRows + .eq(0) + .find('td') + .eq(2) + .text() + ).toBe('aaaa'); + expect( + tableRows + .eq(1) + .find('td') + .eq(2) + .text() + ).toBe('bbbb'); + expect( + tableRows + .eq(2) + .find('td') + .eq(2) + .text() + ).toBe('cccc'); + expect( + tableRows + .eq(3) + .find('td') + .eq(2) + .text() + ).toBe('zzzz'); + }); + + it('should sort correctly between columns', function() { + // sort by the last column + paginatedTable.sortColumn(2); + $scope.$digest(); + + let tableRows = $el.find('tbody tr'); + expect( + tableRows + .eq(0) + .find('td') + .eq(0) + .text() + ).toBe('cccc'); + expect( + tableRows + .eq(0) + .find('td') + .eq(1) + .text() + ).toBe('cccc'); + expect( + tableRows + .eq(0) + .find('td') + .eq(2) + .text() + ).toBe('aaaa'); + + // sort by the first column + paginatedTable.sortColumn(0); + $scope.$digest(); + + tableRows = $el.find('tbody tr'); + expect( + tableRows + .eq(0) + .find('td') + .eq(0) + .text() + ).toBe('aaaa'); + expect( + tableRows + .eq(0) + .find('td') + .eq(1) + .text() + ).toBe('zzzz'); + expect( + tableRows + .eq(0) + .find('td') + .eq(2) + .text() + ).toBe('cccc'); + + expect( + tableRows + .eq(1) + .find('td') + .eq(0) + .text() + ).toBe('bbbb'); + expect( + tableRows + .eq(2) + .find('td') + .eq(0) + .text() + ).toBe('cccc'); + expect( + tableRows + .eq(3) + .find('td') + .eq(0) + .text() + ).toBe('zzzz'); + }); + + it('should not sort duplicate columns', function() { + paginatedTable.sortColumn(1); + $scope.$digest(); + + const sorters = $el.find('thead th i'); + expect(sorters.eq(0).hasClass('fa-sort')).toBe(true); + expect(sorters.eq(1).hasClass('fa-sort')).toBe(false); + expect(sorters.eq(2).hasClass('fa-sort')).toBe(true); + }); + }); + + describe('object rows', function() { + let cols; + let rows; + let paginatedTable; + + beforeEach(function() { + cols = [ + { + title: 'object test', + id: 0, + formatter: { + convert: val => { + return val === 'zzz' ? '

hello

' : val; + }, + }, + }, + ]; + rows = [['aaaa'], ['zzz'], ['bbbb']]; + renderTable({ columns: cols, rows }, cols, rows); + paginatedTable = $el.isolateScope().paginatedTable; + }); + + it('should append object markup', function() { + const tableRows = $el.find('tbody tr'); + expect(tableRows.eq(0).find('h1').length).toBe(0); + expect(tableRows.eq(1).find('h1').length).toBe(1); + expect(tableRows.eq(2).find('h1').length).toBe(0); + }); + + it('should sort using object value', function() { + paginatedTable.sortColumn(0); + $scope.$digest(); + let tableRows = $el.find('tbody tr'); + expect(tableRows.eq(0).find('h1').length).toBe(0); + expect(tableRows.eq(1).find('h1').length).toBe(0); + // html row should be the last row + expect(tableRows.eq(2).find('h1').length).toBe(1); + + paginatedTable.sortColumn(0); + $scope.$digest(); + tableRows = $el.find('tbody tr'); + // html row should be the first row + expect(tableRows.eq(0).find('h1').length).toBe(1); + expect(tableRows.eq(1).find('h1').length).toBe(0); + expect(tableRows.eq(2).find('h1').length).toBe(0); + }); }); }); From edb1638928bf320895f44e6bf0b7b3510679e89b Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Fri, 22 Nov 2019 15:29:31 +0300 Subject: [PATCH 14/26] Complete conversion paginated_table test to Jest --- .../__tests__/paginated_table.js | 419 ------------------ .../paginated_table/paginated_table.test.ts | 146 +++--- .../vis_type_table/public/table_vis.mock.ts | 60 +-- 3 files changed, 98 insertions(+), 527 deletions(-) delete mode 100644 src/legacy/core_plugins/vis_type_table/public/paginated_table/__tests__/paginated_table.js diff --git a/src/legacy/core_plugins/vis_type_table/public/paginated_table/__tests__/paginated_table.js b/src/legacy/core_plugins/vis_type_table/public/paginated_table/__tests__/paginated_table.js deleted file mode 100644 index d146a1bddf260..0000000000000 --- a/src/legacy/core_plugins/vis_type_table/public/paginated_table/__tests__/paginated_table.js +++ /dev/null @@ -1,419 +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 expect from '@kbn/expect'; -import ngMock from 'ng_mock'; - -import $ from 'jquery'; - -describe('Table Vis - Paginated table', function () { - let $el; - let $rootScope; - let $compile; - let $scope; - const defaultPerPage = 10; - - const makeData = function (colCount, rowCount) { - let columns = []; - let rows = []; - - if (_.isNumber(colCount)) { - _.times(colCount, function (i) { - columns.push({ id: i, title: 'column' + i, formatter: { convert: _.identity } }); - }); - } else { - columns = colCount.map((col, i) => ({ - id: i, - title: col.title, - formatter: col.formatter || { convert: _.identity } - })); - } - - if (_.isNumber(rowCount)) { - _.times(rowCount, function (row) { - const rowItems = {}; - - _.times(columns.length, function (col) { - rowItems[col] = 'item' + col + row; - }); - - rows.push(rowItems); - }); - } else { - rows = rowCount.map(row => { - const newRow = {}; - row.forEach((v, i) => newRow[i] = v); - return newRow; - }); - } - - return { - columns: columns, - rows: rows - }; - }; - - const renderTable = function (table, cols, rows, perPage, sort, linkToTop) { - $scope.table = table || { columns: [], rows: [] }; - $scope.cols = cols || []; - $scope.rows = rows || []; - $scope.perPage = perPage || defaultPerPage; - $scope.sort = sort || {}; - $scope.linkToTop = linkToTop; - - const template = ` - `; - $el = $compile(template)($scope); - - $scope.$digest(); - }; - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function (_$rootScope_, _$compile_) { - $rootScope = _$rootScope_; - $compile = _$compile_; - $scope = $rootScope.$new(); - })); - - describe('rendering', function () { - it('should not display without rows', function () { - const cols = [{ - title: 'test1' - }]; - const rows = []; - - renderTable(null, cols, rows); - expect($el.children().length).to.be(0); - }); - - it('should render columns and rows', function () { - const data = makeData(2, 2); - const cols = data.columns; - const rows = data.rows; - - renderTable(data, cols, rows); - expect($el.children().length).to.be(1); - const tableRows = $el.find('tbody tr'); - // should contain the row data - expect(tableRows.eq(0).find('td').eq(0).text()).to.be(rows[0][0]); - expect(tableRows.eq(0).find('td').eq(1).text()).to.be(rows[0][1]); - expect(tableRows.eq(1).find('td').eq(0).text()).to.be(rows[1][0]); - expect(tableRows.eq(1).find('td').eq(1).text()).to.be(rows[1][1]); - }); - - it('should paginate rows', function () { - // note: paginate truncates pages, so don't make too many - const rowCount = _.random(16, 24); - const perPageCount = _.random(5, 8); - const data = makeData(3, rowCount); - const pageCount = Math.ceil(rowCount / perPageCount); - - renderTable(data, data.columns, data.rows, perPageCount); - const tableRows = $el.find('tbody tr'); - expect(tableRows.length).to.be(perPageCount); - // add 2 for the first and last page links - expect($el.find('paginate-controls button').length).to.be(pageCount + 2); - }); - - it('should not show blank rows on last page', function () { - const rowCount = 7; - const perPageCount = 10; - const data = makeData(3, rowCount); - - renderTable(data, data.columns, data.rows, perPageCount, null); - const tableRows = $el.find('tbody tr'); - expect(tableRows.length).to.be(rowCount); - }); - - it('should not show link to top when not set', function () { - const data = makeData(5, 5); - renderTable(data, data.columns, data.rows, 10, null); - - const linkToTop = $el.find('[data-test-subj="paginateControlsLinkToTop"]'); - expect(linkToTop.length).to.be(0); - }); - - it('should show link to top when set', function () { - const data = makeData(5, 5); - renderTable(data, data.columns, data.rows, 10, null, true); - - const linkToTop = $el.find('[data-test-subj="paginateControlsLinkToTop"]'); - expect(linkToTop.length).to.be(1); - }); - - }); - - describe('sorting', function () { - let data; - let lastRowIndex; - let paginatedTable; - - beforeEach(function () { - data = makeData(3, [ - ['bbbb', 'aaaa', 'zzzz'], - ['cccc', 'cccc', 'aaaa'], - ['zzzz', 'bbbb', 'bbbb'], - ['aaaa', 'zzzz', 'cccc'], - ]); - - lastRowIndex = data.rows.length - 1; - renderTable(data, data.columns, data.rows); - paginatedTable = $el.isolateScope().paginatedTable; - }); - - // afterEach(function () { - // $scope.$destroy(); - // }); - - it('should not sort by default', function () { - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).to.be(data.rows[0][0]); - expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).to.be(data.rows[lastRowIndex][0]); - }); - - it('should do nothing when sorting by invalid column id', function () { - // sortColumn - paginatedTable.sortColumn(999); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).to.be('bbbb'); - expect(tableRows.eq(0).find('td').eq(1).text()).to.be('aaaa'); - expect(tableRows.eq(0).find('td').eq(2).text()).to.be('zzzz'); - }); - - it('should do nothing when sorting by non sortable column', function () { - data.columns[0].sortable = false; - - // sortColumn - paginatedTable.sortColumn(0); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).to.be('bbbb'); - expect(tableRows.eq(0).find('td').eq(1).text()).to.be('aaaa'); - expect(tableRows.eq(0).find('td').eq(2).text()).to.be('zzzz'); - }); - - it('should set the sort direction to asc when it\'s not explicitly set', function () { - paginatedTable.sortColumn(1); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(2).find('td').eq(1).text()).to.be('cccc'); - expect(tableRows.eq(1).find('td').eq(1).text()).to.be('bbbb'); - expect(tableRows.eq(0).find('td').eq(1).text()).to.be('aaaa'); - }); - - it('should allow you to explicitly set the sort direction', function () { - paginatedTable.sortColumn(1, 'desc'); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(1).text()).to.be('zzzz'); - expect(tableRows.eq(1).find('td').eq(1).text()).to.be('cccc'); - expect(tableRows.eq(2).find('td').eq(1).text()).to.be('bbbb'); - }); - - it('should sort ascending on first invocation', function () { - // sortColumn - paginatedTable.sortColumn(0); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).to.be('aaaa'); - expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).to.be('zzzz'); - }); - - it('should sort descending on second invocation', function () { - // sortColumn - paginatedTable.sortColumn(0); - paginatedTable.sortColumn(0); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).to.be('zzzz'); - expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).to.be('aaaa'); - }); - - it('should clear sorting on third invocation', function () { - // sortColumn - paginatedTable.sortColumn(0); - paginatedTable.sortColumn(0); - paginatedTable.sortColumn(0); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).to.be(data.rows[0][0]); - expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).to.be('aaaa'); - }); - - it('should sort new column ascending', function () { - // sort by first column - paginatedTable.sortColumn(0); - $scope.$digest(); - - // sort by second column - paginatedTable.sortColumn(1); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(1).text()).to.be('aaaa'); - expect(tableRows.eq(lastRowIndex).find('td').eq(1).text()).to.be('zzzz'); - }); - - }); - - describe('sorting duplicate columns', function () { - let data; - let paginatedTable; - const colText = 'test row'; - - beforeEach(function () { - const cols = [ - { title: colText }, - { title: colText }, - { title: colText } - ]; - const rows = [ - ['bbbb', 'aaaa', 'zzzz'], - ['cccc', 'cccc', 'aaaa'], - ['zzzz', 'bbbb', 'bbbb'], - ['aaaa', 'zzzz', 'cccc'], - ]; - data = makeData(cols, rows); - - renderTable(data, data.columns, data.rows); - paginatedTable = $el.isolateScope().paginatedTable; - }); - - it('should have duplicate column titles', function () { - const columns = $el.find('thead th span'); - columns.each(function () { - expect($(this).text()).to.be(colText); - }); - }); - - it('should handle sorting on columns with the same name', function () { - // sort by the last column - paginatedTable.sortColumn(2); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).to.be('cccc'); - expect(tableRows.eq(0).find('td').eq(1).text()).to.be('cccc'); - expect(tableRows.eq(0).find('td').eq(2).text()).to.be('aaaa'); - expect(tableRows.eq(1).find('td').eq(2).text()).to.be('bbbb'); - expect(tableRows.eq(2).find('td').eq(2).text()).to.be('cccc'); - expect(tableRows.eq(3).find('td').eq(2).text()).to.be('zzzz'); - }); - - it('should sort correctly between columns', function () { - // sort by the last column - paginatedTable.sortColumn(2); - $scope.$digest(); - - let tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).to.be('cccc'); - expect(tableRows.eq(0).find('td').eq(1).text()).to.be('cccc'); - expect(tableRows.eq(0).find('td').eq(2).text()).to.be('aaaa'); - - // sort by the first column - paginatedTable.sortColumn(0); - $scope.$digest(); - - tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).to.be('aaaa'); - expect(tableRows.eq(0).find('td').eq(1).text()).to.be('zzzz'); - expect(tableRows.eq(0).find('td').eq(2).text()).to.be('cccc'); - - expect(tableRows.eq(1).find('td').eq(0).text()).to.be('bbbb'); - expect(tableRows.eq(2).find('td').eq(0).text()).to.be('cccc'); - expect(tableRows.eq(3).find('td').eq(0).text()).to.be('zzzz'); - }); - - it('should not sort duplicate columns', function () { - paginatedTable.sortColumn(1); - $scope.$digest(); - - const sorters = $el.find('thead th i'); - expect(sorters.eq(0).hasClass('fa-sort')).to.be(true); - expect(sorters.eq(1).hasClass('fa-sort')).to.be(false); - expect(sorters.eq(2).hasClass('fa-sort')).to.be(true); - }); - - }); - - - describe('object rows', function () { - let cols; - let rows; - let paginatedTable; - - beforeEach(function () { - cols = [{ - title: 'object test', - id: 0, - formatter: { convert: val => { - return val === 'zzz' ? '

hello

' : val; - } } - }]; - rows = [ - ['aaaa'], - ['zzz'], - ['bbbb'] - ]; - renderTable({ columns: cols, rows }, cols, rows); - paginatedTable = $el.isolateScope().paginatedTable; - }); - - it('should append object markup', function () { - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('h1').length).to.be(0); - expect(tableRows.eq(1).find('h1').length).to.be(1); - expect(tableRows.eq(2).find('h1').length).to.be(0); - }); - - it('should sort using object value', function () { - paginatedTable.sortColumn(0); - $scope.$digest(); - let tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('h1').length).to.be(0); - expect(tableRows.eq(1).find('h1').length).to.be(0); - // html row should be the last row - expect(tableRows.eq(2).find('h1').length).to.be(1); - - paginatedTable.sortColumn(0); - $scope.$digest(); - tableRows = $el.find('tbody tr'); - // html row should be the first row - expect(tableRows.eq(0).find('h1').length).to.be(1); - expect(tableRows.eq(1).find('h1').length).to.be(0); - expect(tableRows.eq(2).find('h1').length).to.be(0); - }); - }); -}); diff --git a/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts b/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts index f0e41c1b84846..42f379e705b83 100644 --- a/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts @@ -18,7 +18,7 @@ */ import { isNumber, times, identity, random } from 'lodash'; -import angular from 'angular'; +import angular, { IRootScopeService, IScope, ICompileService } from 'angular'; import $ from 'jquery'; import 'angular-sanitize'; import 'angular-mocks'; @@ -34,21 +34,39 @@ interface Sort { } interface Row { - [key: string]: number; + [key: string]: number | string; } interface Column { - id: string; + id?: string; title: string; - formatter?: object; + formatter?: { + convert?: (val: string) => string; + }; + sortable?: boolean; +} + +interface Table { + columns: Column[]; + rows: Row[]; +} + +interface PaginatedTableScope extends IScope { + table?: Table; + cols?: Column[]; + rows?: Row[]; + perPage?: number; + sort?: Sort; + linkToTop?: boolean; } describe('Table Vis - Paginated table', () => { - let $el: any; - let $rootScope; - let $compile: any; - let $scope: any; + let $el: JQuery; + let $rootScope: IRootScopeService; + let $compile: ICompileService; + let $scope: PaginatedTableScope; const defaultPerPage = 10; + let paginatedTable: any; const initLocalAngular = () => { const tableVisModule = getAngularModule('kibana/table_vis', npStart.core); @@ -58,13 +76,19 @@ describe('Table Vis - Paginated table', () => { beforeEach(initLocalAngular); beforeEach(angular.mock.module('kibana/table_vis')); - beforeEach(inject((_$rootScope_: any, _$compile_: any) => { - $rootScope = _$rootScope_; - $compile = _$compile_; - $scope = $rootScope.$new(); - })); + beforeEach( + angular.mock.inject((_$rootScope_: IRootScopeService, _$compile_: ICompileService) => { + $rootScope = _$rootScope_; + $compile = _$compile_; + $scope = $rootScope.$new(); + }) + ); - const makeData = function(colCount: number | Column[], rowCount: number | string[][]) { + afterEach(() => { + $scope.$destroy(); + }); + + const makeData = (colCount: number | Column[], rowCount: number | string[][]) => { let columns: Column[] = []; let rows: Row[] = []; @@ -107,36 +131,38 @@ describe('Table Vis - Paginated table', () => { }; }; - const renderTable = function( + const renderTable = ( table: { columns: Column[]; rows: Row[] } | null, cols: Column[], rows: Row[], perPage?: number, sort?: Sort, linkToTop?: boolean - ) { + ) => { $scope.table = table || { columns: [], rows: [] }; $scope.cols = cols || []; $scope.rows = rows || []; $scope.perPage = perPage || defaultPerPage; - $scope.sort = sort || {}; + $scope.sort = sort; $scope.linkToTop = linkToTop; - const template = angular.element(` + const template = ` `); - $el = $($compile(template)($scope)); + link-to-top="linkToTop">`; + const element = $compile(template)($scope); + $el = $(element); $scope.$digest(); + paginatedTable = element.controller('paginatedTable'); }; describe('rendering', () => { - it('should not display without rows', () => { + test('should not display without rows', () => { const cols: Column[] = [ { id: 'col-1-1', @@ -149,7 +175,7 @@ describe('Table Vis - Paginated table', () => { expect($el.children().length).toBe(0); }); - it('should render columns and rows', function() { + test('should render columns and rows', () => { const data = makeData(2, 2); const cols = data.columns; const rows = data.rows; @@ -189,7 +215,7 @@ describe('Table Vis - Paginated table', () => { ).toBe(rows[1][1]); }); - it('should paginate rows', function() { + test('should paginate rows', () => { // note: paginate truncates pages, so don't make too many const rowCount = random(16, 24); const perPageCount = random(5, 8); @@ -203,7 +229,7 @@ describe('Table Vis - Paginated table', () => { expect($el.find('paginate-controls button').length).toBe(pageCount + 2); }); - it('should not show blank rows on last page', function() { + test('should not show blank rows on last page', () => { const rowCount = 7; const perPageCount = 10; const data = makeData(3, rowCount); @@ -213,7 +239,7 @@ describe('Table Vis - Paginated table', () => { expect(tableRows.length).toBe(rowCount); }); - it('should not show link to top when not set', function() { + test('should not show link to top when not set', () => { const data = makeData(5, 5); renderTable(data, data.columns, data.rows, 10); @@ -221,7 +247,7 @@ describe('Table Vis - Paginated table', () => { expect(linkToTop.length).toBe(0); }); - it('should show link to top when set', function() { + test('should show link to top when set', () => { const data = makeData(5, 5); renderTable(data, data.columns, data.rows, 10, undefined, true); @@ -230,12 +256,11 @@ describe('Table Vis - Paginated table', () => { }); }); - describe('sorting', function() { - let data; - let lastRowIndex; - let paginatedTable; + describe('sorting', () => { + let data: Table; + let lastRowIndex: number; - beforeEach(function() { + beforeEach(() => { data = makeData(3, [ ['bbbb', 'aaaa', 'zzzz'], ['cccc', 'cccc', 'aaaa'], @@ -245,14 +270,9 @@ describe('Table Vis - Paginated table', () => { lastRowIndex = data.rows.length - 1; renderTable(data, data.columns, data.rows); - paginatedTable = $el.isolateScope().paginatedTable; }); - // afterEach(function () { - // $scope.$destroy(); - // }); - - it('should not sort by default', function() { + test('should not sort by default', () => { const tableRows = $el.find('tbody tr'); expect( tableRows @@ -270,7 +290,7 @@ describe('Table Vis - Paginated table', () => { ).toBe(data.rows[lastRowIndex][0]); }); - it('should do nothing when sorting by invalid column id', function() { + test('should do nothing when sorting by invalid column id', () => { // sortColumn paginatedTable.sortColumn(999); $scope.$digest(); @@ -299,7 +319,7 @@ describe('Table Vis - Paginated table', () => { ).toBe('zzzz'); }); - it('should do nothing when sorting by non sortable column', function() { + test('should do nothing when sorting by non sortable column', () => { data.columns[0].sortable = false; // sortColumn @@ -330,7 +350,7 @@ describe('Table Vis - Paginated table', () => { ).toBe('zzzz'); }); - it("should set the sort direction to asc when it's not explicitly set", function() { + test("should set the sort direction to asc when it's not explicitly set", () => { paginatedTable.sortColumn(1); $scope.$digest(); @@ -358,7 +378,7 @@ describe('Table Vis - Paginated table', () => { ).toBe('aaaa'); }); - it('should allow you to explicitly set the sort direction', function() { + test('should allow you to explicitly set the sort direction', () => { paginatedTable.sortColumn(1, 'desc'); $scope.$digest(); @@ -386,7 +406,7 @@ describe('Table Vis - Paginated table', () => { ).toBe('bbbb'); }); - it('should sort ascending on first invocation', function() { + test('should sort ascending on first invocation', () => { // sortColumn paginatedTable.sortColumn(0); $scope.$digest(); @@ -408,7 +428,7 @@ describe('Table Vis - Paginated table', () => { ).toBe('zzzz'); }); - it('should sort descending on second invocation', function() { + test('should sort descending on second invocation', () => { // sortColumn paginatedTable.sortColumn(0); paginatedTable.sortColumn(0); @@ -431,7 +451,7 @@ describe('Table Vis - Paginated table', () => { ).toBe('aaaa'); }); - it('should clear sorting on third invocation', function() { + test('should clear sorting on third invocation', () => { // sortColumn paginatedTable.sortColumn(0); paginatedTable.sortColumn(0); @@ -455,7 +475,7 @@ describe('Table Vis - Paginated table', () => { ).toBe('aaaa'); }); - it('should sort new column ascending', function() { + test('should sort new column ascending', () => { // sort by first column paginatedTable.sortColumn(0); $scope.$digest(); @@ -482,13 +502,12 @@ describe('Table Vis - Paginated table', () => { }); }); - describe('sorting duplicate columns', function() { + describe('sorting duplicate columns', () => { let data; - let paginatedTable; const colText = 'test row'; - beforeEach(function() { - const cols = [{ title: colText }, { title: colText }, { title: colText }]; + beforeEach(() => { + const cols: Column[] = [{ title: colText }, { title: colText }, { title: colText }]; const rows = [ ['bbbb', 'aaaa', 'zzzz'], ['cccc', 'cccc', 'aaaa'], @@ -498,17 +517,16 @@ describe('Table Vis - Paginated table', () => { data = makeData(cols, rows); renderTable(data, data.columns, data.rows); - paginatedTable = $el.isolateScope().paginatedTable; }); - it('should have duplicate column titles', function() { + test('should have duplicate column titles', () => { const columns = $el.find('thead th span'); - columns.each(function() { - expect($(this).text()).toBe(colText); + columns.each((i, col) => { + expect($(col).text()).toBe(colText); }); }); - it('should handle sorting on columns with the same name', function() { + test('should handle sorting on columns with the same name', () => { // sort by the last column paginatedTable.sortColumn(2); $scope.$digest(); @@ -558,7 +576,7 @@ describe('Table Vis - Paginated table', () => { ).toBe('zzzz'); }); - it('should sort correctly between columns', function() { + test('should sort correctly between columns', () => { // sort by the last column paginatedTable.sortColumn(2); $scope.$digest(); @@ -636,7 +654,7 @@ describe('Table Vis - Paginated table', () => { ).toBe('zzzz'); }); - it('should not sort duplicate columns', function() { + test('should not sort duplicate columns', () => { paginatedTable.sortColumn(1); $scope.$digest(); @@ -647,16 +665,15 @@ describe('Table Vis - Paginated table', () => { }); }); - describe('object rows', function() { - let cols; - let rows; - let paginatedTable; + describe('object rows', () => { + let cols: Column[]; + let rows: any; - beforeEach(function() { + beforeEach(() => { cols = [ { title: 'object test', - id: 0, + id: '0', formatter: { convert: val => { return val === 'zzz' ? '

hello

' : val; @@ -666,17 +683,16 @@ describe('Table Vis - Paginated table', () => { ]; rows = [['aaaa'], ['zzz'], ['bbbb']]; renderTable({ columns: cols, rows }, cols, rows); - paginatedTable = $el.isolateScope().paginatedTable; }); - it('should append object markup', function() { + test('should append object markup', () => { const tableRows = $el.find('tbody tr'); expect(tableRows.eq(0).find('h1').length).toBe(0); expect(tableRows.eq(1).find('h1').length).toBe(1); expect(tableRows.eq(2).find('h1').length).toBe(0); }); - it('should sort using object value', function() { + test('should sort using object value', () => { paginatedTable.sortColumn(0); $scope.$digest(); let tableRows = $el.find('tbody tr'); diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts index 2fe91e9e2ba4c..98ea84fd3c5c7 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts @@ -17,54 +17,28 @@ * under the License. */ -import { - chromeServiceMock, - notificationServiceMock, - overlayServiceMock, - uiSettingsServiceMock, - i18nServiceMock, - httpServiceMock, - injectedMetadataServiceMock, -} from '../../../../core/public/mocks'; -import { StubBrowserStorage } from 'test_utils/stub_browser_storage'; - -import { applicationServiceMock } from '../../../../core/public/application/application_service.mock'; import { createUiNewPlatformMock } from 'ui/new_platform/__mocks__/helpers'; +import { StubBrowserStorage } from 'test_utils/stub_browser_storage'; +import { injectedMetadataServiceMock } from '../../../../core/public/mocks'; -// jest.mock('ui/new_platform'); -// jest.doMock('ui/new_platform', () => ({ -// ...createUiNewPlatformMock() -// })); -jest.doMock('ui/new_platform', () => ({ - npSetup: { - core: { - notifications: notificationServiceMock.createSetupContract(), - injectedMetadata: injectedMetadataServiceMock.createSetupContract(), - }, - }, - npStart: { - core: { - i18n: i18nServiceMock.createStartContract(), - chrome: chromeServiceMock.createStartContract(), - http: httpServiceMock.createStartContract({ basePath: 'path' }), - overlays: overlayServiceMock.createStartContract(), - notifications: notificationServiceMock.createStartContract(), - uiSettings: uiSettingsServiceMock.createStartContract(), - injectedMetadata: injectedMetadataServiceMock.createStartContract(), - application: applicationServiceMock.createInternalStartContract(), +jest.doMock('ui/new_platform', () => { + const npMock = createUiNewPlatformMock(); + return { + npSetup: { + core: { + ...npMock.npSetup.core, + injectedMetadata: injectedMetadataServiceMock.createSetupContract(), + }, }, - plugins: { - data: { - query: { - timefilter: { - history: {}, - timefilter: {}, - }, - }, + npStart: { + ...npMock.npStart, + core: { + ...npMock.npStart.core, + injectedMetadata: injectedMetadataServiceMock.createStartContract(), }, }, - }, -})); + }; +}); Object.assign(window, { sessionStorage: new StubBrowserStorage(), From 270978ee8dddc772180e8dfc7193c16ef3fedfe9 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Fri, 22 Nov 2019 18:34:39 +0300 Subject: [PATCH 15/26] Convert table_vis_controller test to Jest --- .../public/__tests__/table_vis_controller.js | 204 --------------- .../vis_type_table/public/legacy_imports.ts | 2 +- .../vis_type_table/public/table_vis.mock.ts | 1 + .../public/table_vis_controller.test.ts | 245 ++++++++++++++++++ 4 files changed, 247 insertions(+), 205 deletions(-) delete mode 100644 src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js create mode 100644 src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts diff --git a/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js b/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js deleted file mode 100644 index 56e827c8106ea..0000000000000 --- a/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js +++ /dev/null @@ -1,204 +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 'jquery'; -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { - AppStateProvider, - legacyResponseHandlerProvider, - Vis, - VisFactoryProvider, - tabifyAggResponse, -} from '../legacy_imports'; -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; - -import { createTableVisTypeDefinition } from '../table_vis_type'; -import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; - -describe('Table Vis - Controller', async function () { - let $rootScope; - let $compile; - let Private; - let $scope; - let $el; - let fixtures; - let AppState; - let tableAggResponse; - let tabifiedResponse; - let legacyDependencies; - - ngMock.inject(function ($injector) { - Private = $injector.get('Private'); - legacyDependencies = { - // eslint-disable-next-line new-cap - createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization, - }; - - visualizationsSetup.types.registerVisualization(() => - createTableVisTypeDefinition(legacyDependencies) - ); - }); - - beforeEach(ngMock.module('kibana', 'kibana/table_vis')); - beforeEach( - ngMock.inject(function ($injector) { - Private = $injector.get('Private'); - $rootScope = $injector.get('$rootScope'); - $compile = $injector.get('$compile'); - fixtures = require('fixtures/fake_hierarchical_data'); - AppState = Private(AppStateProvider); - tableAggResponse = legacyResponseHandlerProvider().handler; - }) - ); - - function OneRangeVis(params) { - return new Vis(Private(FixturesStubbedLogstashIndexPatternProvider), { - type: 'table', - params: params || {}, - aggs: [ - { type: 'count', schema: 'metric' }, - { - type: 'range', - schema: 'bucket', - params: { - field: 'bytes', - ranges: [{ from: 0, to: 1000 }, { from: 1000, to: 2000 }], - }, - }, - ], - }); - } - - const dimensions = { - buckets: [ - { - accessor: 0, - }, - ], - metrics: [ - { - accessor: 1, - format: { id: 'range' }, - }, - ], - }; - - // basically a parameterized beforeEach - function initController(vis) { - vis.aggs.aggs.forEach(function (agg, i) { - agg.id = 'agg_' + (i + 1); - }); - - tabifiedResponse = tabifyAggResponse(vis.aggs, fixtures.oneRangeBucket); - $rootScope.vis = vis; - $rootScope.visParams = vis.params; - $rootScope.uiState = new AppState({ uiState: {} }).makeStateful('uiState'); - $rootScope.renderComplete = () => {}; - $rootScope.newScope = function (scope) { - $scope = scope; - }; - - $el = $('
') - .attr('ng-controller', 'KbnTableVisController') - .attr('ng-init', 'newScope(this)'); - - $compile($el)($rootScope); - } - - // put a response into the controller - function attachEsResponseToScope(resp) { - $rootScope.esResponse = resp; - $rootScope.$apply(); - } - - // remove the response from the controller - function removeEsResponseFromScope() { - delete $rootScope.esResponse; - $rootScope.renderComplete = () => {}; - $rootScope.$apply(); - } - - it('exposes #tableGroups and #hasSomeRows when a response is attached to scope', async function () { - const vis = new OneRangeVis(); - initController(vis); - - expect(!$scope.tableGroups).to.be.ok(); - expect(!$scope.hasSomeRows).to.be.ok(); - - attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); - - expect($scope.hasSomeRows).to.be(true); - expect($scope.tableGroups).to.have.property('tables'); - expect($scope.tableGroups.tables).to.have.length(1); - expect($scope.tableGroups.tables[0].columns).to.have.length(2); - expect($scope.tableGroups.tables[0].rows).to.have.length(2); - }); - - it('clears #tableGroups and #hasSomeRows when the response is removed', async function () { - const vis = new OneRangeVis(); - initController(vis); - - attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); - removeEsResponseFromScope(); - - expect(!$scope.hasSomeRows).to.be.ok(); - expect(!$scope.tableGroups).to.be.ok(); - }); - - it('sets the sort on the scope when it is passed as a vis param', async function () { - const sortObj = { - columnIndex: 1, - direction: 'asc', - }; - const vis = new OneRangeVis({ sort: sortObj }); - initController(vis); - - attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); - - expect($scope.sort.columnIndex).to.equal(sortObj.columnIndex); - expect($scope.sort.direction).to.equal(sortObj.direction); - }); - - it('sets #hasSomeRows properly if the table group is empty', async function () { - const vis = new OneRangeVis(); - initController(vis); - - tabifiedResponse.rows = []; - - attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); - - expect($scope.hasSomeRows).to.be(false); - expect(!$scope.tableGroups).to.be.ok(); - }); - - it('passes partialRows:true to tabify based on the vis params', function () { - const vis = new OneRangeVis({ showPartialRows: true }); - initController(vis); - - expect(vis.isHierarchical()).to.equal(true); - }); - - it('passes partialRows:false to tabify based on the vis params', function () { - const vis = new OneRangeVis({ showPartialRows: false }); - initController(vis); - - expect(vis.isHierarchical()).to.equal(false); - }); -}); diff --git a/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts index 2eb3284ed0ca2..575df68a051a9 100644 --- a/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts @@ -22,7 +22,7 @@ export { SchemaConfig } from 'ui/visualize/loader/pipeline_helpers/build_pipelin // @ts-ignore export { visFactory, VisFactoryProvider } from 'ui/vis/vis_factory'; -export { Vis } from 'ui/vis'; +export { Vis, AggConfig } from 'ui/vis'; // @ts-ignore export { Schemas } from 'ui/vis/editors/default/schemas'; diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts index 98ea84fd3c5c7..d04964cb7af03 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts @@ -25,6 +25,7 @@ jest.doMock('ui/new_platform', () => { const npMock = createUiNewPlatformMock(); return { npSetup: { + ...npMock.npSetup, core: { ...npMock.npSetup.core, injectedMetadata: injectedMetadataServiceMock.createSetupContract(), diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts new file mode 100644 index 0000000000000..f192fd86af63f --- /dev/null +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts @@ -0,0 +1,245 @@ +/* + * 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 angular, { IRootScopeService, IScope, ICompileService } from 'angular'; +import 'angular-mocks'; +import 'angular-sanitize'; +import $ from 'jquery'; +import './table_vis.mock'; + +// @ts-ignore +import StubIndexPattern from 'test_utils/stub_index_pattern'; +import { getAngularModule } from './get_inner_angular'; +import { initTableVisLegacyModule } from './shim/table_vis_legacy_module'; +import { + npStart, + legacyResponseHandlerProvider, + Vis, + AggConfig, + tabifyAggResponse, +} from './legacy_imports'; +import { createTableVisTypeDefinition } from './table_vis_type'; +import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; +// eslint-disable-next-line +import { stubFields } from '../../../../plugins/data/public/stubs'; + +interface TableVisScope extends IScope { + [key: string]: any; +} + +const oneRangeBucket = { + hits: { + total: 6039, + max_score: 0, + hits: [], + }, + aggregations: { + agg_2: { + buckets: { + '0.0-1000.0': { + from: 0, + from_as_string: '0.0', + to: 1000, + to_as_string: '1000.0', + doc_count: 606, + }, + '1000.0-2000.0': { + from: 1000, + from_as_string: '1000.0', + to: 2000, + to_as_string: '2000.0', + doc_count: 298, + }, + }, + }, + }, +}; + +describe('Table Vis - Controller', () => { + let $rootScope: IRootScopeService & { [key: string]: any }; + let $compile: ICompileService; + let $scope: TableVisScope; + let $el: JQuery; + let tableAggResponse: any; + let tabifiedResponse: any; + const stubIndexPattern = new StubIndexPattern( + 'logstash-*', + (cfg: any) => cfg, + 'time', + stubFields, + npStart.core.uiSettings + ); + + const initLocalAngular = () => { + const tableVisModule = getAngularModule('kibana/table_vis', npStart.core); + initTableVisLegacyModule(tableVisModule); + }; + + beforeEach(initLocalAngular); + beforeAll(() => { + visualizationsSetup.types.registerVisualization(() => createTableVisTypeDefinition()); + }); + beforeEach(angular.mock.module('kibana/table_vis')); + + beforeEach( + angular.mock.inject((_$rootScope_: IRootScopeService, _$compile_: ICompileService) => { + $rootScope = _$rootScope_; + $compile = _$compile_; + tableAggResponse = legacyResponseHandlerProvider().handler; + }) + ); + + function getRangeVis(params?: any) { + // @ts-ignore + return new Vis(stubIndexPattern, { + type: 'table', + params: params || {}, + aggs: [ + { type: 'count', schema: 'metric' }, + { + type: 'range', + schema: 'bucket', + params: { + field: 'bytes', + ranges: [{ from: 0, to: 1000 }, { from: 1000, to: 2000 }], + }, + }, + ], + }); + } + + const dimensions = { + buckets: [ + { + accessor: 0, + }, + ], + metrics: [ + { + accessor: 1, + format: { id: 'range' }, + }, + ], + }; + + // basically a parameterized beforeEach + function initController(vis: Vis) { + vis.aggs.aggs.forEach((agg: AggConfig, i: number) => { + agg.id = 'agg_' + (i + 1); + }); + + tabifiedResponse = tabifyAggResponse(vis.aggs, oneRangeBucket); + $rootScope.vis = vis; + $rootScope.visParams = vis.params; + $rootScope.uiState = { + get: jest.fn(), + set: jest.fn(), + }; + $rootScope.renderComplete = () => {}; + $rootScope.newScope = (scope: TableVisScope) => { + $scope = scope; + }; + + $el = $('
') + .attr('ng-controller', 'KbnTableVisController') + .attr('ng-init', 'newScope(this)'); + + $compile($el)($rootScope); + } + + // put a response into the controller + function attachEsResponseToScope(resp: any) { + $rootScope.esResponse = resp; + $rootScope.$apply(); + } + + // remove the response from the controller + function removeEsResponseFromScope() { + delete $rootScope.esResponse; + $rootScope.renderComplete = () => {}; + $rootScope.$apply(); + } + + test('exposes #tableGroups and #hasSomeRows when a response is attached to scope', async () => { + const vis: Vis = getRangeVis(); + initController(vis); + + expect(!$scope.tableGroups).toBeTruthy(); + expect(!$scope.hasSomeRows).toBeTruthy(); + + attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); + + expect($scope.hasSomeRows).toBeTruthy(); + expect($scope.tableGroups.tables).toBeDefined(); + expect($scope.tableGroups.tables.length).toBe(1); + expect($scope.tableGroups.tables[0].columns.length).toBe(2); + expect($scope.tableGroups.tables[0].rows.length).toBe(2); + }); + + test('clears #tableGroups and #hasSomeRows when the response is removed', async () => { + const vis = getRangeVis(); + initController(vis); + + attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); + removeEsResponseFromScope(); + + expect(!$scope.hasSomeRows).toBeTruthy(); + expect(!$scope.tableGroups).toBeTruthy(); + }); + + test('sets the sort on the scope when it is passed as a vis param', async () => { + const sortObj = { + columnIndex: 1, + direction: 'asc', + }; + const vis = getRangeVis({ sort: sortObj }); + initController(vis); + + attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); + + expect($scope.sort.columnIndex).toEqual(sortObj.columnIndex); + expect($scope.sort.direction).toEqual(sortObj.direction); + }); + + test('sets #hasSomeRows properly if the table group is empty', async () => { + const vis = getRangeVis(); + initController(vis); + + tabifiedResponse.rows = []; + + attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); + + expect($scope.hasSomeRows).toBeFalsy(); + expect(!$scope.tableGroups).toBeTruthy(); + }); + + test('passes partialRows:true to tabify based on the vis params', () => { + const vis = getRangeVis({ showPartialRows: true }); + initController(vis); + + expect(vis.isHierarchical()).toEqual(true); + }); + + test('passes partialRows:false to tabify based on the vis params', () => { + const vis = getRangeVis({ showPartialRows: false }); + initController(vis); + + expect(vis.isHierarchical()).toEqual(false); + }); +}); From e208fb860b0d2d9104d08446ce5d33b0badff4e9 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Fri, 22 Nov 2019 18:34:39 +0300 Subject: [PATCH 16/26] Convert table_vis_controller test to Jest --- .../public/__tests__/table_vis_controller.js | 204 -------------- .../vis_type_table/public/legacy_imports.ts | 2 +- .../vis_type_table/public/table_vis.mock.ts | 1 + .../public/table_vis_controller.test.ts | 248 ++++++++++++++++++ 4 files changed, 250 insertions(+), 205 deletions(-) delete mode 100644 src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js create mode 100644 src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts diff --git a/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js b/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js deleted file mode 100644 index 56e827c8106ea..0000000000000 --- a/src/legacy/core_plugins/vis_type_table/public/__tests__/table_vis_controller.js +++ /dev/null @@ -1,204 +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 'jquery'; -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; -import { - AppStateProvider, - legacyResponseHandlerProvider, - Vis, - VisFactoryProvider, - tabifyAggResponse, -} from '../legacy_imports'; -import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; - -import { createTableVisTypeDefinition } from '../table_vis_type'; -import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; - -describe('Table Vis - Controller', async function () { - let $rootScope; - let $compile; - let Private; - let $scope; - let $el; - let fixtures; - let AppState; - let tableAggResponse; - let tabifiedResponse; - let legacyDependencies; - - ngMock.inject(function ($injector) { - Private = $injector.get('Private'); - legacyDependencies = { - // eslint-disable-next-line new-cap - createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization, - }; - - visualizationsSetup.types.registerVisualization(() => - createTableVisTypeDefinition(legacyDependencies) - ); - }); - - beforeEach(ngMock.module('kibana', 'kibana/table_vis')); - beforeEach( - ngMock.inject(function ($injector) { - Private = $injector.get('Private'); - $rootScope = $injector.get('$rootScope'); - $compile = $injector.get('$compile'); - fixtures = require('fixtures/fake_hierarchical_data'); - AppState = Private(AppStateProvider); - tableAggResponse = legacyResponseHandlerProvider().handler; - }) - ); - - function OneRangeVis(params) { - return new Vis(Private(FixturesStubbedLogstashIndexPatternProvider), { - type: 'table', - params: params || {}, - aggs: [ - { type: 'count', schema: 'metric' }, - { - type: 'range', - schema: 'bucket', - params: { - field: 'bytes', - ranges: [{ from: 0, to: 1000 }, { from: 1000, to: 2000 }], - }, - }, - ], - }); - } - - const dimensions = { - buckets: [ - { - accessor: 0, - }, - ], - metrics: [ - { - accessor: 1, - format: { id: 'range' }, - }, - ], - }; - - // basically a parameterized beforeEach - function initController(vis) { - vis.aggs.aggs.forEach(function (agg, i) { - agg.id = 'agg_' + (i + 1); - }); - - tabifiedResponse = tabifyAggResponse(vis.aggs, fixtures.oneRangeBucket); - $rootScope.vis = vis; - $rootScope.visParams = vis.params; - $rootScope.uiState = new AppState({ uiState: {} }).makeStateful('uiState'); - $rootScope.renderComplete = () => {}; - $rootScope.newScope = function (scope) { - $scope = scope; - }; - - $el = $('
') - .attr('ng-controller', 'KbnTableVisController') - .attr('ng-init', 'newScope(this)'); - - $compile($el)($rootScope); - } - - // put a response into the controller - function attachEsResponseToScope(resp) { - $rootScope.esResponse = resp; - $rootScope.$apply(); - } - - // remove the response from the controller - function removeEsResponseFromScope() { - delete $rootScope.esResponse; - $rootScope.renderComplete = () => {}; - $rootScope.$apply(); - } - - it('exposes #tableGroups and #hasSomeRows when a response is attached to scope', async function () { - const vis = new OneRangeVis(); - initController(vis); - - expect(!$scope.tableGroups).to.be.ok(); - expect(!$scope.hasSomeRows).to.be.ok(); - - attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); - - expect($scope.hasSomeRows).to.be(true); - expect($scope.tableGroups).to.have.property('tables'); - expect($scope.tableGroups.tables).to.have.length(1); - expect($scope.tableGroups.tables[0].columns).to.have.length(2); - expect($scope.tableGroups.tables[0].rows).to.have.length(2); - }); - - it('clears #tableGroups and #hasSomeRows when the response is removed', async function () { - const vis = new OneRangeVis(); - initController(vis); - - attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); - removeEsResponseFromScope(); - - expect(!$scope.hasSomeRows).to.be.ok(); - expect(!$scope.tableGroups).to.be.ok(); - }); - - it('sets the sort on the scope when it is passed as a vis param', async function () { - const sortObj = { - columnIndex: 1, - direction: 'asc', - }; - const vis = new OneRangeVis({ sort: sortObj }); - initController(vis); - - attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); - - expect($scope.sort.columnIndex).to.equal(sortObj.columnIndex); - expect($scope.sort.direction).to.equal(sortObj.direction); - }); - - it('sets #hasSomeRows properly if the table group is empty', async function () { - const vis = new OneRangeVis(); - initController(vis); - - tabifiedResponse.rows = []; - - attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); - - expect($scope.hasSomeRows).to.be(false); - expect(!$scope.tableGroups).to.be.ok(); - }); - - it('passes partialRows:true to tabify based on the vis params', function () { - const vis = new OneRangeVis({ showPartialRows: true }); - initController(vis); - - expect(vis.isHierarchical()).to.equal(true); - }); - - it('passes partialRows:false to tabify based on the vis params', function () { - const vis = new OneRangeVis({ showPartialRows: false }); - initController(vis); - - expect(vis.isHierarchical()).to.equal(false); - }); -}); diff --git a/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts index 2eb3284ed0ca2..575df68a051a9 100644 --- a/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts @@ -22,7 +22,7 @@ export { SchemaConfig } from 'ui/visualize/loader/pipeline_helpers/build_pipelin // @ts-ignore export { visFactory, VisFactoryProvider } from 'ui/vis/vis_factory'; -export { Vis } from 'ui/vis'; +export { Vis, AggConfig } from 'ui/vis'; // @ts-ignore export { Schemas } from 'ui/vis/editors/default/schemas'; diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts index 98ea84fd3c5c7..d04964cb7af03 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis.mock.ts @@ -25,6 +25,7 @@ jest.doMock('ui/new_platform', () => { const npMock = createUiNewPlatformMock(); return { npSetup: { + ...npMock.npSetup, core: { ...npMock.npSetup.core, injectedMetadata: injectedMetadataServiceMock.createSetupContract(), diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts new file mode 100644 index 0000000000000..b25db1d6c5fe3 --- /dev/null +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts @@ -0,0 +1,248 @@ +/* + * 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 angular, { IRootScopeService, IScope, ICompileService } from 'angular'; +import 'angular-mocks'; +import 'angular-sanitize'; +import $ from 'jquery'; +import './table_vis.mock'; + +// @ts-ignore +import StubIndexPattern from 'test_utils/stub_index_pattern'; +import { getAngularModule } from './get_inner_angular'; +import { initTableVisLegacyModule } from './shim/table_vis_legacy_module'; +import { + npStart, + legacyResponseHandlerProvider, + Vis, + AggConfig, + tabifyAggResponse, +} from './legacy_imports'; +import { createTableVisTypeDefinition } from './table_vis_type'; +import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; +// eslint-disable-next-line +import { stubFields } from '../../../../plugins/data/public/stubs'; + +interface TableVisScope extends IScope { + [key: string]: any; +} + +const oneRangeBucket = { + hits: { + total: 6039, + max_score: 0, + hits: [], + }, + aggregations: { + agg_2: { + buckets: { + '0.0-1000.0': { + from: 0, + from_as_string: '0.0', + to: 1000, + to_as_string: '1000.0', + doc_count: 606, + }, + '1000.0-2000.0': { + from: 1000, + from_as_string: '1000.0', + to: 2000, + to_as_string: '2000.0', + doc_count: 298, + }, + }, + }, + }, +}; + +describe('Table Vis - Controller', () => { + let $rootScope: IRootScopeService & { [key: string]: any }; + let $compile: ICompileService; + let $scope: TableVisScope; + let $el: JQuery; + let tableAggResponse: any; + let tabifiedResponse: any; + const stubIndexPattern = new StubIndexPattern( + 'logstash-*', + (cfg: any) => cfg, + 'time', + stubFields, + npStart.core.uiSettings + ); + + const initLocalAngular = () => { + const tableVisModule = getAngularModule('kibana/table_vis', npStart.core); + initTableVisLegacyModule(tableVisModule); + }; + + beforeEach(initLocalAngular); + beforeAll(() => { + visualizationsSetup.types.registerVisualization(() => createTableVisTypeDefinition()); + }); + beforeEach(angular.mock.module('kibana/table_vis')); + + beforeEach( + angular.mock.inject((_$rootScope_: IRootScopeService, _$compile_: ICompileService) => { + $rootScope = _$rootScope_; + $compile = _$compile_; + tableAggResponse = legacyResponseHandlerProvider().handler; + }) + ); + + function getRangeVis(params?: any) { + // @ts-ignore + return new Vis(stubIndexPattern, { + type: 'table', + params: params || {}, + aggs: [ + { type: 'count', schema: 'metric' }, + { + type: 'range', + schema: 'bucket', + params: { + field: 'bytes', + ranges: [ + { from: 0, to: 1000 }, + { from: 1000, to: 2000 }, + ], + }, + }, + ], + }); + } + + const dimensions = { + buckets: [ + { + accessor: 0, + }, + ], + metrics: [ + { + accessor: 1, + format: { id: 'range' }, + }, + ], + }; + + // basically a parameterized beforeEach + function initController(vis: Vis) { + vis.aggs.aggs.forEach((agg: AggConfig, i: number) => { + agg.id = 'agg_' + (i + 1); + }); + + tabifiedResponse = tabifyAggResponse(vis.aggs, oneRangeBucket); + $rootScope.vis = vis; + $rootScope.visParams = vis.params; + $rootScope.uiState = { + get: jest.fn(), + set: jest.fn(), + }; + $rootScope.renderComplete = () => {}; + $rootScope.newScope = (scope: TableVisScope) => { + $scope = scope; + }; + + $el = $('
') + .attr('ng-controller', 'KbnTableVisController') + .attr('ng-init', 'newScope(this)'); + + $compile($el)($rootScope); + } + + // put a response into the controller + function attachEsResponseToScope(resp: any) { + $rootScope.esResponse = resp; + $rootScope.$apply(); + } + + // remove the response from the controller + function removeEsResponseFromScope() { + delete $rootScope.esResponse; + $rootScope.renderComplete = () => {}; + $rootScope.$apply(); + } + + test('exposes #tableGroups and #hasSomeRows when a response is attached to scope', async () => { + const vis: Vis = getRangeVis(); + initController(vis); + + expect(!$scope.tableGroups).toBeTruthy(); + expect(!$scope.hasSomeRows).toBeTruthy(); + + attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); + + expect($scope.hasSomeRows).toBeTruthy(); + expect($scope.tableGroups.tables).toBeDefined(); + expect($scope.tableGroups.tables.length).toBe(1); + expect($scope.tableGroups.tables[0].columns.length).toBe(2); + expect($scope.tableGroups.tables[0].rows.length).toBe(2); + }); + + test('clears #tableGroups and #hasSomeRows when the response is removed', async () => { + const vis = getRangeVis(); + initController(vis); + + attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); + removeEsResponseFromScope(); + + expect(!$scope.hasSomeRows).toBeTruthy(); + expect(!$scope.tableGroups).toBeTruthy(); + }); + + test('sets the sort on the scope when it is passed as a vis param', async () => { + const sortObj = { + columnIndex: 1, + direction: 'asc', + }; + const vis = getRangeVis({ sort: sortObj }); + initController(vis); + + attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); + + expect($scope.sort.columnIndex).toEqual(sortObj.columnIndex); + expect($scope.sort.direction).toEqual(sortObj.direction); + }); + + test('sets #hasSomeRows properly if the table group is empty', async () => { + const vis = getRangeVis(); + initController(vis); + + tabifiedResponse.rows = []; + + attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); + + expect($scope.hasSomeRows).toBeFalsy(); + expect(!$scope.tableGroups).toBeTruthy(); + }); + + test('passes partialRows:true to tabify based on the vis params', () => { + const vis = getRangeVis({ showPartialRows: true }); + initController(vis); + + expect(vis.isHierarchical()).toEqual(true); + }); + + test('passes partialRows:false to tabify based on the vis params', () => { + const vis = getRangeVis({ showPartialRows: false }); + initController(vis); + + expect(vis.isHierarchical()).toEqual(false); + }); +}); From 351abe469c34651d819add7dd239bdf8800bb8a9 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Mon, 25 Nov 2019 08:46:43 +0300 Subject: [PATCH 17/26] Create agg_table.test.ts --- .../public/agg_table/__tests__/agg_table.js | 2 +- .../agg_table/__tests__/agg_table_group.js | 2 +- .../public/agg_table/agg_table.test.ts | 1125 +++++++++++++++++ 3 files changed, 1127 insertions(+), 2 deletions(-) create mode 100644 src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.test.ts 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 446f0ac0acd2b..b724373fc171c 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 @@ -30,7 +30,7 @@ import { round } from 'lodash'; import { createTableVisTypeDefinition } from '../../table_vis_type'; import { setup as visualizationsSetup } from '../../../../visualizations/public/np_ready/public/legacy'; -describe('Table Vis - AggTable Directive', function () { +describe.skip('Table Vis - AggTable Directive', function () { let $rootScope; let $compile; let indexPattern; 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 9db2b8042cd70..2f194a49894f7 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 @@ -24,7 +24,7 @@ import fixtures from 'fixtures/fake_hierarchical_data'; import { legacyResponseHandlerProvider, Vis, tabifyAggResponse } from '../../legacy_imports'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -describe('Table Vis - AggTableGroup Directive', function () { +describe.skip('Table Vis - AggTableGroup Directive', function () { let $rootScope; let $compile; let indexPattern; diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.test.ts b/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.test.ts new file mode 100644 index 0000000000000..95ef9cbc52e0a --- /dev/null +++ b/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.test.ts @@ -0,0 +1,1125 @@ +/* + * 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 angular, { IRootScopeService, IScope, ICompileService } from 'angular'; +import 'angular-mocks'; +import 'angular-sanitize'; +import '../table_vis.mock'; +import $ from 'jquery'; + +// @ts-ignore +import StubIndexPattern from 'test_utils/stub_index_pattern'; +import { getAngularModule } from '../get_inner_angular'; +import { initTableVisLegacyModule } from '../shim/table_vis_legacy_module'; +import { + npStart, + legacyResponseHandlerProvider, + Vis, + AggConfig, + tabifyAggResponse, +} from '../legacy_imports'; +import { createTableVisTypeDefinition } from '../table_vis_type'; +import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; + +interface TableVisScope extends IScope { + [key: string]: any; +} + +const metricOnly = { + hits: { total: 1000, hits: [], max_score: 0 }, + aggregations: { + agg_1: { value: 412032 }, + }, +}; +const threeTermBuckets = { + hits: { total: 1000, hits: [], max_score: 0 }, + aggregations: { + agg_2: { + buckets: [ + { + key: 'png', + doc_count: 50, + agg_1: { value: 412032 }, + agg_3: { + buckets: [ + { + key: 'IT', + doc_count: 10, + agg_1: { value: 9299 }, + agg_4: { + buckets: [ + { key: 'win', doc_count: 4, agg_1: { value: 0 } }, + { key: 'mac', doc_count: 6, agg_1: { value: 9299 } }, + ], + }, + }, + { + key: 'US', + doc_count: 20, + agg_1: { value: 8293 }, + agg_4: { + buckets: [ + { key: 'linux', doc_count: 12, agg_1: { value: 3992 } }, + { key: 'mac', doc_count: 8, agg_1: { value: 3029 } }, + ], + }, + }, + ], + }, + }, + { + key: 'css', + doc_count: 20, + agg_1: { value: 412032 }, + agg_3: { + buckets: [ + { + key: 'MX', + doc_count: 7, + agg_1: { value: 9299 }, + agg_4: { + buckets: [ + { key: 'win', doc_count: 3, agg_1: { value: 4992 } }, + { key: 'mac', doc_count: 4, agg_1: { value: 5892 } }, + ], + }, + }, + { + key: 'US', + doc_count: 13, + agg_1: { value: 8293 }, + agg_4: { + buckets: [ + { key: 'linux', doc_count: 12, agg_1: { value: 3992 } }, + { key: 'mac', doc_count: 1, agg_1: { value: 3029 } }, + ], + }, + }, + ], + }, + }, + { + key: 'html', + doc_count: 90, + agg_1: { value: 412032 }, + agg_3: { + buckets: [ + { + key: 'CN', + doc_count: 85, + agg_1: { value: 9299 }, + agg_4: { + buckets: [ + { key: 'win', doc_count: 46, agg_1: { value: 4992 } }, + { key: 'mac', doc_count: 39, agg_1: { value: 5892 } }, + ], + }, + }, + { + key: 'FR', + doc_count: 15, + agg_1: { value: 8293 }, + agg_4: { + buckets: [ + { key: 'win', doc_count: 3, agg_1: { value: 3992 } }, + { key: 'mac', doc_count: 12, agg_1: { value: 3029 } }, + ], + }, + }, + ], + }, + }, + ], + }, + }, +}; +const oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative = { + hits: { total: 1000, hits: [], max_score: 0 }, + aggregations: { + agg_3: { + buckets: [ + { + key: 'png', + doc_count: 50, + agg_4: { + buckets: [ + { + key_as_string: '2014-09-28T00:00:00.000Z', + key: 1411862400000, + doc_count: 1, + agg_1: { value: 9283 }, + agg_2: { value: 1411862400000 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 23, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-09-29T00:00:00.000Z', + key: 1411948800000, + doc_count: 2, + agg_1: { value: 28349 }, + agg_2: { value: 1411948800000 }, + agg_5: { value: 203 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 39, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-09-30T00:00:00.000Z', + key: 1412035200000, + doc_count: 3, + agg_1: { value: 84330 }, + agg_2: { value: 1412035200000 }, + agg_5: { value: 200 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 329, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-10-01T00:00:00.000Z', + key: 1412121600000, + doc_count: 4, + agg_1: { value: 34992 }, + agg_2: { value: 1412121600000 }, + agg_5: { value: 103 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 22, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-10-02T00:00:00.000Z', + key: 1412208000000, + doc_count: 5, + agg_1: { value: 145432 }, + agg_2: { value: 1412208000000 }, + agg_5: { value: 153 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 93, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-10-03T00:00:00.000Z', + key: 1412294400000, + doc_count: 35, + agg_1: { value: 220943 }, + agg_2: { value: 1412294400000 }, + agg_5: { value: 239 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 72, + }, + }, + ], + }, + }, + }, + ], + }, + }, + { + key: 'css', + doc_count: 20, + agg_4: { + buckets: [ + { + key_as_string: '2014-09-28T00:00:00.000Z', + key: 1411862400000, + doc_count: 1, + agg_1: { value: 9283 }, + agg_2: { value: 1411862400000 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 75, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-09-29T00:00:00.000Z', + key: 1411948800000, + doc_count: 2, + agg_1: { value: 28349 }, + agg_2: { value: 1411948800000 }, + agg_5: { value: 10 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 11, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-09-30T00:00:00.000Z', + key: 1412035200000, + doc_count: 3, + agg_1: { value: 84330 }, + agg_2: { value: 1412035200000 }, + agg_5: { value: 24 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 238, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-10-01T00:00:00.000Z', + key: 1412121600000, + doc_count: 4, + agg_1: { value: 34992 }, + agg_2: { value: 1412121600000 }, + agg_5: { value: 49 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 343, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-10-02T00:00:00.000Z', + key: 1412208000000, + doc_count: 5, + agg_1: { value: 145432 }, + agg_2: { value: 1412208000000 }, + agg_5: { value: 100 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 837, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-10-03T00:00:00.000Z', + key: 1412294400000, + doc_count: 5, + agg_1: { value: 220943 }, + agg_2: { value: 1412294400000 }, + agg_5: { value: 23 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 302, + }, + }, + ], + }, + }, + }, + ], + }, + }, + { + key: 'html', + doc_count: 90, + agg_4: { + buckets: [ + { + key_as_string: '2014-09-28T00:00:00.000Z', + key: 1411862400000, + doc_count: 10, + agg_1: { value: 9283 }, + agg_2: { value: 1411862400000 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 30, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-09-29T00:00:00.000Z', + key: 1411948800000, + doc_count: 20, + agg_1: { value: 28349 }, + agg_2: { value: 1411948800000 }, + agg_5: { value: 1 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 43, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-09-30T00:00:00.000Z', + key: 1412035200000, + doc_count: 30, + agg_1: { value: 84330 }, + agg_2: { value: 1412035200000 }, + agg_5: { value: 5 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 88, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-10-01T00:00:00.000Z', + key: 1412121600000, + doc_count: 11, + agg_1: { value: 34992 }, + agg_2: { value: 1412121600000 }, + agg_5: { value: 10 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 91, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-10-02T00:00:00.000Z', + key: 1412208000000, + doc_count: 12, + agg_1: { value: 145432 }, + agg_2: { value: 1412208000000 }, + agg_5: { value: 43 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 534, + }, + }, + ], + }, + }, + }, + { + key_as_string: '2014-10-03T00:00:00.000Z', + key: 1412294400000, + doc_count: 7, + agg_1: { value: 220943 }, + agg_2: { value: 1412294400000 }, + agg_5: { value: 1 }, + agg_6: { + hits: { + total: 2, + hits: [ + { + fields: { + bytes: 553, + }, + }, + ], + }, + }, + }, + ], + }, + }, + ], + }, + }, +}; + +describe.skip('Table Vis - AggTable Directive', () => { + let $rootScope: IRootScopeService & { [key: string]: any }; + let $compile: ICompileService; + let $scope: TableVisScope; + let tableAggResponse: any; + const tabifiedData: { + [key: string]: any; + } = {}; + const mockUiSettings: any = { + get: (item: string): any => { + return mockUiSettings[item]; + }, + getUpdate$: () => ({ + subscribe: jest.fn(), + }), + 'query:allowLeadingWildcards': true, + 'query:queryString:options': {}, + 'courier:ignoreFilterIfFieldNotInIndex': true, + 'dateFormat:tz': 'Browser', + 'format:defaultTypeMap': {}, + }; + const indexPattern = new StubIndexPattern( + 'logstash-*', + (cfg: any) => cfg, + 'time', + // [...stubFields, + // { name: 'extension', esType: 'text', aggregatable: true, searchable: true }, + // { name: 'geo.src', esType: 'keyword', aggregatable: true, searchable: true }, + // ], + [ + { + name: 'bytes', + type: 'number', + esTypes: ['long'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 10, + scripted: false, + sortable: true, + filterable: true, + displayName: 'bytes', + }, + { + name: 'ssl', + type: 'boolean', + esTypes: ['boolean'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 20, + scripted: false, + sortable: true, + filterable: true, + displayName: 'ssl', + }, + { + name: '@timestamp', + type: 'date', + esTypes: ['date'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 30, + scripted: false, + sortable: true, + filterable: true, + displayName: '@timestamp', + }, + { + name: 'time', + type: 'date', + esTypes: ['date'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 30, + scripted: false, + sortable: true, + filterable: true, + displayName: 'time', + }, + { + name: '@tags', + type: 'string', + esTypes: ['keyword'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: true, + filterable: true, + displayName: '@tags', + }, + { + name: 'utc_time', + type: 'date', + esTypes: ['date'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: true, + filterable: true, + displayName: 'utc_time', + }, + { + name: 'phpmemory', + type: 'number', + esTypes: ['integer'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: true, + filterable: true, + displayName: 'phpmemory', + }, + { + name: 'ip', + type: 'ip', + esTypes: ['ip'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: true, + filterable: true, + displayName: 'ip', + }, + { + name: 'request_body', + type: 'attachment', + esTypes: ['attachment'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: false, + filterable: false, + displayName: 'request_body', + }, + { + name: 'point', + type: 'geo_point', + esTypes: ['geo_point'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: false, + filterable: false, + displayName: 'point', + }, + { + name: 'area', + type: 'geo_shape', + esTypes: ['geo_shape'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: false, + filterable: false, + displayName: 'area', + }, + { + name: 'hashed', + type: 'murmur3', + esTypes: ['murmur3'], + readFromDocValues: false, + aggregatable: false, + searchable: true, + count: 0, + scripted: false, + sortable: false, + filterable: false, + displayName: 'hashed', + }, + { + name: 'geo.coordinates', + type: 'geo_point', + esTypes: ['geo_point'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: false, + filterable: false, + displayName: 'geo.coordinates', + }, + { + name: 'extension', + type: 'string', + esTypes: ['text'], + readFromDocValues: false, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: true, + filterable: true, + displayName: 'extension', + }, + { + name: 'extension.keyword', + type: 'string', + esTypes: ['keyword'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + subType: { multi: { parent: 'extension' } }, + sortable: true, + filterable: true, + displayName: 'extension.keyword', + }, + { + name: 'machine.os', + type: 'string', + esTypes: ['text'], + readFromDocValues: false, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: true, + filterable: true, + displayName: 'machine.os', + }, + { + name: 'machine.os.raw', + type: 'string', + esTypes: ['keyword'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + subType: { multi: { parent: 'machine.os' } }, + sortable: true, + filterable: true, + displayName: 'machine.os.raw', + }, + { + name: 'geo.src', + type: 'string', + esTypes: ['keyword'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: true, + filterable: true, + displayName: 'geo.src', + }, + { + name: '_id', + type: 'string', + esTypes: ['_id'], + readFromDocValues: false, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: true, + filterable: true, + displayName: '_id', + }, + { + name: '_type', + type: 'string', + esTypes: ['_type'], + readFromDocValues: false, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: true, + filterable: true, + displayName: '_type', + }, + { + name: '_source', + type: '_source', + esTypes: ['_source'], + readFromDocValues: false, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: false, + filterable: false, + displayName: '_source', + }, + { + name: 'non-filterable', + type: 'string', + esTypes: ['text'], + readFromDocValues: false, + aggregatable: true, + searchable: false, + count: 0, + scripted: false, + sortable: true, + filterable: true, + displayName: 'non-filterable', + }, + { + name: 'non-sortable', + type: 'string', + esTypes: ['text'], + readFromDocValues: false, + aggregatable: false, + searchable: false, + count: 0, + scripted: false, + sortable: true, + filterable: true, + displayName: 'non-sortable', + }, + { + name: 'custom_user_field', + type: 'conflict', + esTypes: ['conflict'], + readFromDocValues: true, + aggregatable: true, + searchable: true, + count: 0, + scripted: false, + sortable: false, + filterable: false, + displayName: 'custom_user_field', + }, + { + name: 'script string', + type: 'string', + esTypes: ['text'], + readFromDocValues: false, + aggregatable: true, + searchable: false, + count: 0, + script: "'i am a string'", + lang: 'expression', + scripted: true, + sortable: true, + filterable: true, + displayName: 'script string', + }, + { + name: 'script number', + type: 'number', + esTypes: ['long'], + readFromDocValues: true, + aggregatable: true, + searchable: false, + count: 0, + script: '1234', + lang: 'expression', + scripted: true, + sortable: true, + filterable: true, + displayName: 'script number', + }, + { + name: 'script date', + type: 'date', + esTypes: ['date'], + readFromDocValues: true, + aggregatable: true, + searchable: false, + count: 0, + script: '1234', + lang: 'painless', + scripted: true, + sortable: true, + filterable: true, + displayName: 'script date', + }, + { + name: 'script murmur3', + type: 'murmur3', + esTypes: ['murmur3'], + readFromDocValues: true, + aggregatable: true, + searchable: false, + count: 0, + script: '1234', + lang: 'expression', + scripted: true, + sortable: false, + filterable: false, + displayName: 'script murmur3', + }, + ], + // npStart.core.uiSettings + mockUiSettings + ); + indexPattern.id = 'logstash-*'; + indexPattern.isTimeNanosBased = () => false; + + const init = () => { + const vis1 = new Vis(indexPattern, 'table'); + tabifiedData.metricOnly = tabifyAggResponse(vis1.aggs, metricOnly); + // console.log(JSON.stringify(tabifiedData.metricOnly)); + const vis2 = new Vis(indexPattern, { + type: 'table', + params: { + 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' } }, + ], + }); + vis2.aggs.aggs.forEach((agg: AggConfig, i: number) => { + agg.id = 'agg_' + (i + 1); + }); + tabifiedData.threeTermBuckets = tabifyAggResponse(vis2.aggs, threeTermBuckets, { + metricsAtAllLevels: true, + }); + + const vis3 = new Vis(indexPattern, { + type: 'table', + aggs: [ + { 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 }, + }, + ], + }); + vis3.aggs.aggs.forEach((agg: AggConfig, i: number) => { + agg.id = 'agg_' + (i + 1); + }); + + tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative = tabifyAggResponse( + vis3.aggs, + oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative + ); + }; + + const initLocalAngular = () => { + const tableVisModule = getAngularModule('kibana/table_vis', npStart.core); + initTableVisLegacyModule(tableVisModule); + }; + + beforeEach(initLocalAngular); + beforeAll(() => { + visualizationsSetup.types.registerVisualization(() => createTableVisTypeDefinition()); + }); + beforeEach(angular.mock.module('kibana/table_vis')); + + beforeEach( + angular.mock.inject( + (_$rootScope_: IRootScopeService, _$compile_: ICompileService, config: any) => { + $rootScope = _$rootScope_; + $compile = _$compile_; + tableAggResponse = legacyResponseHandlerProvider().handler; + // settings = config; + + init(); + } + ) + ); + + beforeEach(function() { + $scope = $rootScope.$new(); + }); + afterEach(function() { + $scope.$destroy(); + }); + + it('renders a simple response properly', async function() { + $scope.dimensions = { + metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], + buckets: [], + }; + $scope.table = (await tableAggResponse(tabifiedData.metricOnly, $scope.dimensions)).tables[0]; + + const $el = $compile('')( + $scope + ); + $scope.$digest(); + + expect($el.find('tbody').length).toBe(1); + expect($el.find('td').length).toBe(1); + expect($el.find('td').text()).toEqual('1,000'); + }); + + it('renders nothing if the table is empty', function() { + $scope.dimensions = {}; + $scope.table = null; + const $el = $compile('')( + $scope + ); + $scope.$digest(); + + expect($el.find('tbody').length).toBe(0); + }); + + 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: {} }, + ], + }; + $scope.table = ( + await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions) + ).tables[0]; + + const $el = $(''); + $compile($el)($scope); + $scope.$digest(); + + expect($el.find('tbody').length).toBe(1); + + const $rows = $el.find('tbody tr'); + expect($rows.length).toBeGreaterThan(0); + + function validBytes(str: string) { + const num = str.replace(/,/g, ''); + if (num !== '-') { + expect(num).toMatch(/^\d+$/); + } + } + + $rows.each(function() { + // 6 cells in every row + const $cells = $(this).find('td'); + expect($cells.length).toBe(6); + + const txts = $cells.map(function() { + return $(this) + .text() + .trim(); + }); + // two character country code + expect(txts[0]).toMatch(/^(png|jpg|gif|html|css)$/); + validBytes(txts[1]); + + // country + expect(txts[2]).toMatch(/^\w\w$/); + validBytes(txts[3]); + + // os + expect(txts[4]).toMatch(/^(win|mac|linux)$/); + validBytes(txts[5]); + }); + }); +}); From 5446c8e97ee4809b9383e12e92a3fdeba47b80c8 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Tue, 26 Nov 2019 10:56:22 +0300 Subject: [PATCH 18/26] Fix mocha tests --- .../public/agg_table/__tests__/agg_table.js | 23 +- .../agg_table/__tests__/agg_table_group.js | 15 +- .../public/agg_table/agg_table.test.ts | 1125 ----------------- .../public/get_inner_angular.ts | 4 + .../new_platform/new_platform.karma_mock.js | 12 +- 5 files changed, 37 insertions(+), 1142 deletions(-) delete mode 100644 src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.test.ts 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 b724373fc171c..4d21f271c5a4c 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 @@ -23,20 +23,21 @@ import ngMock from 'ng_mock'; import expect from '@kbn/expect'; import fixtures from 'fixtures/fake_hierarchical_data'; import sinon from 'sinon'; -import { legacyResponseHandlerProvider, Vis, tabifyAggResponse, VisFactoryProvider } from '../../legacy_imports'; +import { legacyResponseHandlerProvider, Vis, tabifyAggResponse, npStart } from '../../legacy_imports'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { round } from 'lodash'; import { createTableVisTypeDefinition } from '../../table_vis_type'; import { setup as visualizationsSetup } from '../../../../visualizations/public/np_ready/public/legacy'; +import { getAngularModule } from '../../get_inner_angular'; +import { initTableVisLegacyModule } from '../../shim/table_vis_legacy_module'; -describe.skip('Table Vis - AggTable Directive', function () { +describe('Table Vis - AggTable Directive', function () { let $rootScope; let $compile; let indexPattern; let settings; let tableAggResponse; - let legacyDependencies; const tabifiedData = {}; const init = () => { @@ -95,16 +96,18 @@ describe.skip('Table Vis - AggTable Directive', function () { ); }; - ngMock.inject(function (Private) { - legacyDependencies = { - // eslint-disable-next-line new-cap - createAngularVisualization: VisFactoryProvider(Private).createAngularVisualization, - }; + const initLocalAngular = () => { + const tableVisModule = getAngularModule('kibana/table_vis', npStart.core); + initTableVisLegacyModule(tableVisModule); + }; + + beforeEach(initLocalAngular); - visualizationsSetup.types.registerVisualization(() => createTableVisTypeDefinition(legacyDependencies)); + ngMock.inject(function () { + visualizationsSetup.types.registerVisualization(() => createTableVisTypeDefinition()); }); - beforeEach(ngMock.module('kibana')); + beforeEach(ngMock.module('kibana/table_vis')); beforeEach( ngMock.inject(function ($injector, Private, config) { tableAggResponse = legacyResponseHandlerProvider().handler; 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 2f194a49894f7..1c569ed9b3fe0 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 @@ -21,10 +21,12 @@ import $ from 'jquery'; import ngMock from 'ng_mock'; import expect from '@kbn/expect'; import fixtures from 'fixtures/fake_hierarchical_data'; -import { legacyResponseHandlerProvider, Vis, tabifyAggResponse } from '../../legacy_imports'; +import { legacyResponseHandlerProvider, Vis, tabifyAggResponse, npStart } from '../../legacy_imports'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; +import { getAngularModule } from '../../get_inner_angular'; +import { initTableVisLegacyModule } from '../../shim/table_vis_legacy_module'; -describe.skip('Table Vis - AggTableGroup Directive', function () { +describe('Table Vis - AggTableGroup Directive', function () { let $rootScope; let $compile; let indexPattern; @@ -50,7 +52,14 @@ describe.skip('Table Vis - AggTableGroup Directive', function () { tabifiedData.threeTermBuckets = tabifyAggResponse(vis2.aggs, fixtures.threeTermBuckets); }; - beforeEach(ngMock.module('kibana')); + const initLocalAngular = () => { + const tableVisModule = getAngularModule('kibana/table_vis', npStart.core); + initTableVisLegacyModule(tableVisModule); + }; + + beforeEach(initLocalAngular); + + beforeEach(ngMock.module('kibana/table_vis')); beforeEach( ngMock.inject(function ($injector, Private) { // this is provided in table_vis_controller.js diff --git a/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.test.ts b/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.test.ts deleted file mode 100644 index 95ef9cbc52e0a..0000000000000 --- a/src/legacy/core_plugins/vis_type_table/public/agg_table/agg_table.test.ts +++ /dev/null @@ -1,1125 +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 angular, { IRootScopeService, IScope, ICompileService } from 'angular'; -import 'angular-mocks'; -import 'angular-sanitize'; -import '../table_vis.mock'; -import $ from 'jquery'; - -// @ts-ignore -import StubIndexPattern from 'test_utils/stub_index_pattern'; -import { getAngularModule } from '../get_inner_angular'; -import { initTableVisLegacyModule } from '../shim/table_vis_legacy_module'; -import { - npStart, - legacyResponseHandlerProvider, - Vis, - AggConfig, - tabifyAggResponse, -} from '../legacy_imports'; -import { createTableVisTypeDefinition } from '../table_vis_type'; -import { setup as visualizationsSetup } from '../../../visualizations/public/np_ready/public/legacy'; - -interface TableVisScope extends IScope { - [key: string]: any; -} - -const metricOnly = { - hits: { total: 1000, hits: [], max_score: 0 }, - aggregations: { - agg_1: { value: 412032 }, - }, -}; -const threeTermBuckets = { - hits: { total: 1000, hits: [], max_score: 0 }, - aggregations: { - agg_2: { - buckets: [ - { - key: 'png', - doc_count: 50, - agg_1: { value: 412032 }, - agg_3: { - buckets: [ - { - key: 'IT', - doc_count: 10, - agg_1: { value: 9299 }, - agg_4: { - buckets: [ - { key: 'win', doc_count: 4, agg_1: { value: 0 } }, - { key: 'mac', doc_count: 6, agg_1: { value: 9299 } }, - ], - }, - }, - { - key: 'US', - doc_count: 20, - agg_1: { value: 8293 }, - agg_4: { - buckets: [ - { key: 'linux', doc_count: 12, agg_1: { value: 3992 } }, - { key: 'mac', doc_count: 8, agg_1: { value: 3029 } }, - ], - }, - }, - ], - }, - }, - { - key: 'css', - doc_count: 20, - agg_1: { value: 412032 }, - agg_3: { - buckets: [ - { - key: 'MX', - doc_count: 7, - agg_1: { value: 9299 }, - agg_4: { - buckets: [ - { key: 'win', doc_count: 3, agg_1: { value: 4992 } }, - { key: 'mac', doc_count: 4, agg_1: { value: 5892 } }, - ], - }, - }, - { - key: 'US', - doc_count: 13, - agg_1: { value: 8293 }, - agg_4: { - buckets: [ - { key: 'linux', doc_count: 12, agg_1: { value: 3992 } }, - { key: 'mac', doc_count: 1, agg_1: { value: 3029 } }, - ], - }, - }, - ], - }, - }, - { - key: 'html', - doc_count: 90, - agg_1: { value: 412032 }, - agg_3: { - buckets: [ - { - key: 'CN', - doc_count: 85, - agg_1: { value: 9299 }, - agg_4: { - buckets: [ - { key: 'win', doc_count: 46, agg_1: { value: 4992 } }, - { key: 'mac', doc_count: 39, agg_1: { value: 5892 } }, - ], - }, - }, - { - key: 'FR', - doc_count: 15, - agg_1: { value: 8293 }, - agg_4: { - buckets: [ - { key: 'win', doc_count: 3, agg_1: { value: 3992 } }, - { key: 'mac', doc_count: 12, agg_1: { value: 3029 } }, - ], - }, - }, - ], - }, - }, - ], - }, - }, -}; -const oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative = { - hits: { total: 1000, hits: [], max_score: 0 }, - aggregations: { - agg_3: { - buckets: [ - { - key: 'png', - doc_count: 50, - agg_4: { - buckets: [ - { - key_as_string: '2014-09-28T00:00:00.000Z', - key: 1411862400000, - doc_count: 1, - agg_1: { value: 9283 }, - agg_2: { value: 1411862400000 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 23, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-09-29T00:00:00.000Z', - key: 1411948800000, - doc_count: 2, - agg_1: { value: 28349 }, - agg_2: { value: 1411948800000 }, - agg_5: { value: 203 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 39, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-09-30T00:00:00.000Z', - key: 1412035200000, - doc_count: 3, - agg_1: { value: 84330 }, - agg_2: { value: 1412035200000 }, - agg_5: { value: 200 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 329, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-10-01T00:00:00.000Z', - key: 1412121600000, - doc_count: 4, - agg_1: { value: 34992 }, - agg_2: { value: 1412121600000 }, - agg_5: { value: 103 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 22, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-10-02T00:00:00.000Z', - key: 1412208000000, - doc_count: 5, - agg_1: { value: 145432 }, - agg_2: { value: 1412208000000 }, - agg_5: { value: 153 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 93, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-10-03T00:00:00.000Z', - key: 1412294400000, - doc_count: 35, - agg_1: { value: 220943 }, - agg_2: { value: 1412294400000 }, - agg_5: { value: 239 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 72, - }, - }, - ], - }, - }, - }, - ], - }, - }, - { - key: 'css', - doc_count: 20, - agg_4: { - buckets: [ - { - key_as_string: '2014-09-28T00:00:00.000Z', - key: 1411862400000, - doc_count: 1, - agg_1: { value: 9283 }, - agg_2: { value: 1411862400000 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 75, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-09-29T00:00:00.000Z', - key: 1411948800000, - doc_count: 2, - agg_1: { value: 28349 }, - agg_2: { value: 1411948800000 }, - agg_5: { value: 10 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 11, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-09-30T00:00:00.000Z', - key: 1412035200000, - doc_count: 3, - agg_1: { value: 84330 }, - agg_2: { value: 1412035200000 }, - agg_5: { value: 24 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 238, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-10-01T00:00:00.000Z', - key: 1412121600000, - doc_count: 4, - agg_1: { value: 34992 }, - agg_2: { value: 1412121600000 }, - agg_5: { value: 49 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 343, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-10-02T00:00:00.000Z', - key: 1412208000000, - doc_count: 5, - agg_1: { value: 145432 }, - agg_2: { value: 1412208000000 }, - agg_5: { value: 100 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 837, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-10-03T00:00:00.000Z', - key: 1412294400000, - doc_count: 5, - agg_1: { value: 220943 }, - agg_2: { value: 1412294400000 }, - agg_5: { value: 23 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 302, - }, - }, - ], - }, - }, - }, - ], - }, - }, - { - key: 'html', - doc_count: 90, - agg_4: { - buckets: [ - { - key_as_string: '2014-09-28T00:00:00.000Z', - key: 1411862400000, - doc_count: 10, - agg_1: { value: 9283 }, - agg_2: { value: 1411862400000 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 30, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-09-29T00:00:00.000Z', - key: 1411948800000, - doc_count: 20, - agg_1: { value: 28349 }, - agg_2: { value: 1411948800000 }, - agg_5: { value: 1 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 43, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-09-30T00:00:00.000Z', - key: 1412035200000, - doc_count: 30, - agg_1: { value: 84330 }, - agg_2: { value: 1412035200000 }, - agg_5: { value: 5 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 88, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-10-01T00:00:00.000Z', - key: 1412121600000, - doc_count: 11, - agg_1: { value: 34992 }, - agg_2: { value: 1412121600000 }, - agg_5: { value: 10 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 91, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-10-02T00:00:00.000Z', - key: 1412208000000, - doc_count: 12, - agg_1: { value: 145432 }, - agg_2: { value: 1412208000000 }, - agg_5: { value: 43 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 534, - }, - }, - ], - }, - }, - }, - { - key_as_string: '2014-10-03T00:00:00.000Z', - key: 1412294400000, - doc_count: 7, - agg_1: { value: 220943 }, - agg_2: { value: 1412294400000 }, - agg_5: { value: 1 }, - agg_6: { - hits: { - total: 2, - hits: [ - { - fields: { - bytes: 553, - }, - }, - ], - }, - }, - }, - ], - }, - }, - ], - }, - }, -}; - -describe.skip('Table Vis - AggTable Directive', () => { - let $rootScope: IRootScopeService & { [key: string]: any }; - let $compile: ICompileService; - let $scope: TableVisScope; - let tableAggResponse: any; - const tabifiedData: { - [key: string]: any; - } = {}; - const mockUiSettings: any = { - get: (item: string): any => { - return mockUiSettings[item]; - }, - getUpdate$: () => ({ - subscribe: jest.fn(), - }), - 'query:allowLeadingWildcards': true, - 'query:queryString:options': {}, - 'courier:ignoreFilterIfFieldNotInIndex': true, - 'dateFormat:tz': 'Browser', - 'format:defaultTypeMap': {}, - }; - const indexPattern = new StubIndexPattern( - 'logstash-*', - (cfg: any) => cfg, - 'time', - // [...stubFields, - // { name: 'extension', esType: 'text', aggregatable: true, searchable: true }, - // { name: 'geo.src', esType: 'keyword', aggregatable: true, searchable: true }, - // ], - [ - { - name: 'bytes', - type: 'number', - esTypes: ['long'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 10, - scripted: false, - sortable: true, - filterable: true, - displayName: 'bytes', - }, - { - name: 'ssl', - type: 'boolean', - esTypes: ['boolean'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 20, - scripted: false, - sortable: true, - filterable: true, - displayName: 'ssl', - }, - { - name: '@timestamp', - type: 'date', - esTypes: ['date'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 30, - scripted: false, - sortable: true, - filterable: true, - displayName: '@timestamp', - }, - { - name: 'time', - type: 'date', - esTypes: ['date'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 30, - scripted: false, - sortable: true, - filterable: true, - displayName: 'time', - }, - { - name: '@tags', - type: 'string', - esTypes: ['keyword'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: true, - filterable: true, - displayName: '@tags', - }, - { - name: 'utc_time', - type: 'date', - esTypes: ['date'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: true, - filterable: true, - displayName: 'utc_time', - }, - { - name: 'phpmemory', - type: 'number', - esTypes: ['integer'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: true, - filterable: true, - displayName: 'phpmemory', - }, - { - name: 'ip', - type: 'ip', - esTypes: ['ip'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: true, - filterable: true, - displayName: 'ip', - }, - { - name: 'request_body', - type: 'attachment', - esTypes: ['attachment'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: false, - filterable: false, - displayName: 'request_body', - }, - { - name: 'point', - type: 'geo_point', - esTypes: ['geo_point'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: false, - filterable: false, - displayName: 'point', - }, - { - name: 'area', - type: 'geo_shape', - esTypes: ['geo_shape'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: false, - filterable: false, - displayName: 'area', - }, - { - name: 'hashed', - type: 'murmur3', - esTypes: ['murmur3'], - readFromDocValues: false, - aggregatable: false, - searchable: true, - count: 0, - scripted: false, - sortable: false, - filterable: false, - displayName: 'hashed', - }, - { - name: 'geo.coordinates', - type: 'geo_point', - esTypes: ['geo_point'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: false, - filterable: false, - displayName: 'geo.coordinates', - }, - { - name: 'extension', - type: 'string', - esTypes: ['text'], - readFromDocValues: false, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: true, - filterable: true, - displayName: 'extension', - }, - { - name: 'extension.keyword', - type: 'string', - esTypes: ['keyword'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - subType: { multi: { parent: 'extension' } }, - sortable: true, - filterable: true, - displayName: 'extension.keyword', - }, - { - name: 'machine.os', - type: 'string', - esTypes: ['text'], - readFromDocValues: false, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: true, - filterable: true, - displayName: 'machine.os', - }, - { - name: 'machine.os.raw', - type: 'string', - esTypes: ['keyword'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - subType: { multi: { parent: 'machine.os' } }, - sortable: true, - filterable: true, - displayName: 'machine.os.raw', - }, - { - name: 'geo.src', - type: 'string', - esTypes: ['keyword'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: true, - filterable: true, - displayName: 'geo.src', - }, - { - name: '_id', - type: 'string', - esTypes: ['_id'], - readFromDocValues: false, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: true, - filterable: true, - displayName: '_id', - }, - { - name: '_type', - type: 'string', - esTypes: ['_type'], - readFromDocValues: false, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: true, - filterable: true, - displayName: '_type', - }, - { - name: '_source', - type: '_source', - esTypes: ['_source'], - readFromDocValues: false, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: false, - filterable: false, - displayName: '_source', - }, - { - name: 'non-filterable', - type: 'string', - esTypes: ['text'], - readFromDocValues: false, - aggregatable: true, - searchable: false, - count: 0, - scripted: false, - sortable: true, - filterable: true, - displayName: 'non-filterable', - }, - { - name: 'non-sortable', - type: 'string', - esTypes: ['text'], - readFromDocValues: false, - aggregatable: false, - searchable: false, - count: 0, - scripted: false, - sortable: true, - filterable: true, - displayName: 'non-sortable', - }, - { - name: 'custom_user_field', - type: 'conflict', - esTypes: ['conflict'], - readFromDocValues: true, - aggregatable: true, - searchable: true, - count: 0, - scripted: false, - sortable: false, - filterable: false, - displayName: 'custom_user_field', - }, - { - name: 'script string', - type: 'string', - esTypes: ['text'], - readFromDocValues: false, - aggregatable: true, - searchable: false, - count: 0, - script: "'i am a string'", - lang: 'expression', - scripted: true, - sortable: true, - filterable: true, - displayName: 'script string', - }, - { - name: 'script number', - type: 'number', - esTypes: ['long'], - readFromDocValues: true, - aggregatable: true, - searchable: false, - count: 0, - script: '1234', - lang: 'expression', - scripted: true, - sortable: true, - filterable: true, - displayName: 'script number', - }, - { - name: 'script date', - type: 'date', - esTypes: ['date'], - readFromDocValues: true, - aggregatable: true, - searchable: false, - count: 0, - script: '1234', - lang: 'painless', - scripted: true, - sortable: true, - filterable: true, - displayName: 'script date', - }, - { - name: 'script murmur3', - type: 'murmur3', - esTypes: ['murmur3'], - readFromDocValues: true, - aggregatable: true, - searchable: false, - count: 0, - script: '1234', - lang: 'expression', - scripted: true, - sortable: false, - filterable: false, - displayName: 'script murmur3', - }, - ], - // npStart.core.uiSettings - mockUiSettings - ); - indexPattern.id = 'logstash-*'; - indexPattern.isTimeNanosBased = () => false; - - const init = () => { - const vis1 = new Vis(indexPattern, 'table'); - tabifiedData.metricOnly = tabifyAggResponse(vis1.aggs, metricOnly); - // console.log(JSON.stringify(tabifiedData.metricOnly)); - const vis2 = new Vis(indexPattern, { - type: 'table', - params: { - 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' } }, - ], - }); - vis2.aggs.aggs.forEach((agg: AggConfig, i: number) => { - agg.id = 'agg_' + (i + 1); - }); - tabifiedData.threeTermBuckets = tabifyAggResponse(vis2.aggs, threeTermBuckets, { - metricsAtAllLevels: true, - }); - - const vis3 = new Vis(indexPattern, { - type: 'table', - aggs: [ - { 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 }, - }, - ], - }); - vis3.aggs.aggs.forEach((agg: AggConfig, i: number) => { - agg.id = 'agg_' + (i + 1); - }); - - tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative = tabifyAggResponse( - vis3.aggs, - oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative - ); - }; - - const initLocalAngular = () => { - const tableVisModule = getAngularModule('kibana/table_vis', npStart.core); - initTableVisLegacyModule(tableVisModule); - }; - - beforeEach(initLocalAngular); - beforeAll(() => { - visualizationsSetup.types.registerVisualization(() => createTableVisTypeDefinition()); - }); - beforeEach(angular.mock.module('kibana/table_vis')); - - beforeEach( - angular.mock.inject( - (_$rootScope_: IRootScopeService, _$compile_: ICompileService, config: any) => { - $rootScope = _$rootScope_; - $compile = _$compile_; - tableAggResponse = legacyResponseHandlerProvider().handler; - // settings = config; - - init(); - } - ) - ); - - beforeEach(function() { - $scope = $rootScope.$new(); - }); - afterEach(function() { - $scope.$destroy(); - }); - - it('renders a simple response properly', async function() { - $scope.dimensions = { - metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], - buckets: [], - }; - $scope.table = (await tableAggResponse(tabifiedData.metricOnly, $scope.dimensions)).tables[0]; - - const $el = $compile('')( - $scope - ); - $scope.$digest(); - - expect($el.find('tbody').length).toBe(1); - expect($el.find('td').length).toBe(1); - expect($el.find('td').text()).toEqual('1,000'); - }); - - it('renders nothing if the table is empty', function() { - $scope.dimensions = {}; - $scope.table = null; - const $el = $compile('')( - $scope - ); - $scope.$digest(); - - expect($el.find('tbody').length).toBe(0); - }); - - 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: {} }, - ], - }; - $scope.table = ( - await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions) - ).tables[0]; - - const $el = $(''); - $compile($el)($scope); - $scope.$digest(); - - expect($el.find('tbody').length).toBe(1); - - const $rows = $el.find('tbody tr'); - expect($rows.length).toBeGreaterThan(0); - - function validBytes(str: string) { - const num = str.replace(/,/g, ''); - if (num !== '-') { - expect(num).toMatch(/^\d+$/); - } - } - - $rows.each(function() { - // 6 cells in every row - const $cells = $(this).find('td'); - expect($cells.length).toBe(6); - - const txts = $cells.map(function() { - return $(this) - .text() - .trim(); - }); - // two character country code - expect(txts[0]).toMatch(/^(png|jpg|gif|html|css)$/); - validBytes(txts[1]); - - // country - expect(txts[2]).toMatch(/^\w\w$/); - validBytes(txts[3]); - - // os - expect(txts[4]).toMatch(/^(win|mac|linux)$/); - validBytes(txts[5]); - }); - }); -}); diff --git a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts index ec95c4aeec9f2..c80d82793c42a 100644 --- a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts +++ b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts @@ -79,6 +79,10 @@ function createLocalConfigModule(uiSettings: UiSettingsClientContract) { get: (value: string) => { return uiSettings ? uiSettings.get(value) : undefined; }, + // set method is used in agg_table mocha test + set: (key: string, value: string) => { + return uiSettings ? uiSettings.set(key, value) : undefined; + }, }), }; }); diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index 773d4283cad88..4f4803b910779 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -102,8 +102,10 @@ export const npSetup = { registerAction: sinon.fake(), registerTrigger: sinon.fake(), }, - feature_catalogue: { - register: sinon.fake(), + home: { + featureCatalogue: { + register: sinon.fake(), + }, }, }, }; @@ -213,8 +215,10 @@ export const npStart = { getTriggerActions: sinon.fake(), getTriggerCompatibleActions: sinon.fake(), }, - feature_catalogue: { - register: sinon.fake(), + home: { + featureCatalogue: { + register: sinon.fake(), + }, }, }, }; From a04d80c8ceeb088c8045cebb29613732bd24be63 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Tue, 26 Nov 2019 12:08:34 +0300 Subject: [PATCH 19/26] Refactoring --- .../vis_type_table/public/legacy_imports.ts | 23 ++++++++----------- .../public/shim/table_vis_legacy_module.ts | 4 +++- .../public/table_vis_controller.test.ts | 4 ++-- .../vis_type_table/public/vis_controller.ts | 18 +++++++-------- 4 files changed, 23 insertions(+), 26 deletions(-) diff --git a/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts index 575df68a051a9..0db72a3937552 100644 --- a/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts +++ b/src/legacy/core_plugins/vis_type_table/public/legacy_imports.ts @@ -19,36 +19,31 @@ export { npSetup, npStart } from 'ui/new_platform'; export { SchemaConfig } from 'ui/visualize/loader/pipeline_helpers/build_pipeline'; +export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; +export { Vis, AggConfig } from 'ui/vis'; // @ts-ignore export { visFactory, VisFactoryProvider } from 'ui/vis/vis_factory'; - -export { Vis, AggConfig } from 'ui/vis'; - +export { AggGroupNames, VisOptionsProps } from 'ui/vis/editors/default'; // @ts-ignore export { Schemas } from 'ui/vis/editors/default/schemas'; -export { AggGroupNames, VisOptionsProps } from 'ui/vis/editors/default'; - // @ts-ignore export { legacyResponseHandlerProvider } from 'ui/vis/response_handlers/legacy'; + // @ts-ignore export { PrivateProvider } from 'ui/private/private'; // @ts-ignore +export { PaginateDirectiveProvider } from 'ui/directives/paginate'; +// @ts-ignore +export { PaginateControlsDirectiveProvider } from 'ui/directives/paginate'; +// @ts-ignore export { watchMultiDecorator } from 'ui/directives/watch_multi/watch_multi'; + // @ts-ignore export { KbnAccessibleClickProvider } from 'ui/accessibility/kbn_accessible_click'; // @ts-ignore export { StateManagementConfigProvider } from 'ui/state_management/config_provider'; export { configureAppAngularModule } from 'ui/legacy_compat'; -// @ts-ignore -export { PaginateDirectiveProvider } from 'ui/directives/paginate'; -// @ts-ignore -export { PaginateControlsDirectiveProvider } from 'ui/directives/paginate'; - export { tabifyGetColumns } from 'ui/agg_response/tabify/_get_columns'; - -export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities'; -// @ts-ignore -export { AppStateProvider } from 'ui/state_management/app_state'; // @ts-ignore export { tabifyAggResponse } from 'ui/agg_response/tabify'; diff --git a/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts b/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts index fe1b1ceeb14b9..7ac3620b7d0e4 100644 --- a/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts +++ b/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts @@ -17,6 +17,8 @@ * under the License. */ +import { IModule } from 'angular'; + // @ts-ignore import { TableVisController } from '../table_vis_controller.js'; // @ts-ignore @@ -29,7 +31,7 @@ import { KbnRows } from '../paginated_table/rows'; import { PaginatedTable } from '../paginated_table/paginated_table'; /** @internal */ -export const initTableVisLegacyModule = (angularIns: any): void => { +export const initTableVisLegacyModule = (angularIns: IModule): void => { angularIns .controller('KbnTableVisController', TableVisController) .directive('kbnAggTable', KbnAggTable) diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts index b25db1d6c5fe3..e481968df46c5 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts @@ -105,7 +105,7 @@ describe('Table Vis - Controller', () => { }) ); - function getRangeVis(params?: any) { + function getRangeVis(params?: object) { // @ts-ignore return new Vis(stubIndexPattern, { type: 'table', @@ -167,7 +167,7 @@ describe('Table Vis - Controller', () => { } // put a response into the controller - function attachEsResponseToScope(resp: any) { + function attachEsResponseToScope(resp: object) { $rootScope.esResponse = resp; $rootScope.$apply(); } diff --git a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts index 99cd6b900ec98..e82773907911d 100644 --- a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts +++ b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts @@ -19,10 +19,10 @@ import angular, { IModule, auto, IRootScopeService, IScope, ICompileService } from 'angular'; import $ from 'jquery'; + +import { Vis, VisParams } from '../../visualizations/public'; import { npStart } from './legacy_imports'; import { getAngularModule } from './get_inner_angular'; -import { Vis, VisParams } from '../../visualizations/public'; - import { initTableVisLegacyModule } from './shim/table_vis_legacy_module'; const innerAngularName = 'kibana/table_vis'; @@ -52,6 +52,13 @@ export class TableVisualizationController { return this.injector; } + initLocalAngular() { + if (!this.tableVisModule) { + this.tableVisModule = getAngularModule(innerAngularName, npStart.core); + initTableVisLegacyModule(this.tableVisModule); + } + } + async render(esResponse: object, visParams: VisParams, status: { [key: string]: boolean }) { this.initLocalAngular(); @@ -88,13 +95,6 @@ export class TableVisualizationController { }); } - initLocalAngular = () => { - if (!this.tableVisModule) { - this.tableVisModule = getAngularModule(innerAngularName, npStart.core); - initTableVisLegacyModule(this.tableVisModule); - } - }; - destroy() { if (this.$rootScope) { this.$rootScope.$destroy(); From d6891359a4c11eaf440936998616e0936561edc1 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Tue, 26 Nov 2019 12:09:30 +0300 Subject: [PATCH 20/26] Remove module dep --- .../ui/public/vis/vis_types/__tests__/vislib_vis_legend.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/legacy/ui/public/vis/vis_types/__tests__/vislib_vis_legend.js b/src/legacy/ui/public/vis/vis_types/__tests__/vislib_vis_legend.js index afb3fea15a430..68dd573045877 100644 --- a/src/legacy/ui/public/vis/vis_types/__tests__/vislib_vis_legend.js +++ b/src/legacy/ui/public/vis/vis_types/__tests__/vislib_vis_legend.js @@ -32,7 +32,7 @@ describe('visualize_legend directive', function () { let indexPattern; let fixtures; - beforeEach(ngMock.module('kibana', 'kibana/table_vis')); + beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(function (Private, $injector) { $rootScope = $injector.get('$rootScope'); $compile = $injector.get('$compile'); From c3e049991881a1b6750078ce25532bd9f8aa0fc4 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Wed, 27 Nov 2019 15:40:14 +0300 Subject: [PATCH 21/26] Remove LegacyDependenciesPlugin --- .../public/agg_table/__tests__/agg_table.js | 2 +- .../agg_table/__tests__/agg_table_group.js | 2 +- .../table_vis_legacy_module.ts | 0 .../vis_type_table/public/legacy.ts | 5 --- .../paginated_table/paginated_table.test.ts | 2 +- .../vis_type_table/public/plugin.ts | 6 +--- .../vis_type_table/public/shim/index.ts | 20 ------------ .../public/shim/legacy_dependencies_plugin.ts | 31 ------------------- .../public/table_vis_controller.test.ts | 2 +- .../vis_type_table/public/vis_controller.ts | 2 +- 10 files changed, 6 insertions(+), 66 deletions(-) rename src/legacy/core_plugins/vis_type_table/public/{shim => angular}/table_vis_legacy_module.ts (100%) delete mode 100644 src/legacy/core_plugins/vis_type_table/public/shim/index.ts delete mode 100644 src/legacy/core_plugins/vis_type_table/public/shim/legacy_dependencies_plugin.ts 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 6cf5790ed387b..9ca4a05cf1f9c 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,7 +31,7 @@ import { Vis } from '../../../../visualizations/public'; import { tableVisTypeDefinition } from '../../table_vis_type'; import { setup as visualizationsSetup } from '../../../../visualizations/public/np_ready/public/legacy'; import { getAngularModule } from '../../get_inner_angular'; -import { initTableVisLegacyModule } from '../../shim/table_vis_legacy_module'; +import { initTableVisLegacyModule } from '../../angular/table_vis_legacy_module'; describe('Table Vis - AggTable Directive', function () { let $rootScope; 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 6724aa43fcdb1..efb0855101c49 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 @@ -25,7 +25,7 @@ import { legacyResponseHandlerProvider, tabifyAggResponse, npStart } from '../.. import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { Vis } from '../../../../visualizations/public'; import { getAngularModule } from '../../get_inner_angular'; -import { initTableVisLegacyModule } from '../../shim/table_vis_legacy_module'; +import { initTableVisLegacyModule } from '../../angular/table_vis_legacy_module'; describe('Table Vis - AggTableGroup Directive', function () { let $rootScope; diff --git a/src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts b/src/legacy/core_plugins/vis_type_table/public/angular/table_vis_legacy_module.ts similarity index 100% rename from src/legacy/core_plugins/vis_type_table/public/shim/table_vis_legacy_module.ts rename to src/legacy/core_plugins/vis_type_table/public/angular/table_vis_legacy_module.ts 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 0b7827400e194..e5b2619ef2970 100644 --- a/src/legacy/core_plugins/vis_type_table/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_table/public/legacy.ts @@ -23,15 +23,10 @@ import { plugin } from '.'; import { TablePluginSetupDependencies } from './plugin'; import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; -import { LegacyDependenciesPlugin } from './shim'; const plugins: Readonly = { expressions: npSetup.plugins.expressions, visualizations: visualizationsSetup, - - // Temporary solution - // It will be removed when all dependent services are migrated to the new platform. - __LEGACY: new LegacyDependenciesPlugin(), }; const pluginInstance = plugin({} as PluginInitializerContext); diff --git a/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts b/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts index 42f379e705b83..de477cb84dc27 100644 --- a/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts @@ -25,7 +25,7 @@ import 'angular-mocks'; import '../table_vis.mock'; import { getAngularModule } from '../get_inner_angular'; -import { initTableVisLegacyModule } from '../shim/table_vis_legacy_module'; +import { initTableVisLegacyModule } from '../angular/table_vis_legacy_module'; import { npStart } from '../legacy_imports'; interface Sort { 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 ce8d349d8dd7a..17c50b0567b67 100644 --- a/src/legacy/core_plugins/vis_type_table/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_table/public/plugin.ts @@ -21,8 +21,6 @@ import { VisualizationsSetup } from '../../visualizations/public'; import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../../core/public'; -import { LegacyDependenciesPlugin } from './shim'; - import { createTableVisFn } from './table_vis_fn'; import { tableVisTypeDefinition } from './table_vis_type'; @@ -30,7 +28,6 @@ import { tableVisTypeDefinition } from './table_vis_type'; export interface TablePluginSetupDependencies { expressions: ReturnType; visualizations: VisualizationsSetup; - __LEGACY: LegacyDependenciesPlugin; } /** @internal */ @@ -43,9 +40,8 @@ export class TableVisPlugin implements Plugin, void> { public async setup( core: CoreSetup, - { expressions, visualizations, __LEGACY }: TablePluginSetupDependencies + { expressions, visualizations }: TablePluginSetupDependencies ) { - __LEGACY.setup(); expressions.registerFunction(createTableVisFn); visualizations.types.createBaseVisualization(tableVisTypeDefinition); diff --git a/src/legacy/core_plugins/vis_type_table/public/shim/index.ts b/src/legacy/core_plugins/vis_type_table/public/shim/index.ts deleted file mode 100644 index cfc7b62ff4f86..0000000000000 --- a/src/legacy/core_plugins/vis_type_table/public/shim/index.ts +++ /dev/null @@ -1,20 +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 * from './legacy_dependencies_plugin'; diff --git a/src/legacy/core_plugins/vis_type_table/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/vis_type_table/public/shim/legacy_dependencies_plugin.ts deleted file mode 100644 index 18b15b88eabce..0000000000000 --- a/src/legacy/core_plugins/vis_type_table/public/shim/legacy_dependencies_plugin.ts +++ /dev/null @@ -1,31 +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 { CoreStart, Plugin } from '../../../../../core/public'; - -/** @internal */ -export class LegacyDependenciesPlugin implements Plugin { - public setup() { - // nothing to do here yet - } - - public start(core: CoreStart) { - // nothing to do here yet - } -} diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts index 161dca21fb8b5..6d515e239f102 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts @@ -26,7 +26,7 @@ import './table_vis.mock'; // @ts-ignore import StubIndexPattern from 'test_utils/stub_index_pattern'; import { getAngularModule } from './get_inner_angular'; -import { initTableVisLegacyModule } from './shim/table_vis_legacy_module'; +import { initTableVisLegacyModule } from './angular/table_vis_legacy_module'; import { npStart, legacyResponseHandlerProvider, diff --git a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts index e82773907911d..65d48581e50c0 100644 --- a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts +++ b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts @@ -23,7 +23,7 @@ import $ from 'jquery'; import { Vis, VisParams } from '../../visualizations/public'; import { npStart } from './legacy_imports'; import { getAngularModule } from './get_inner_angular'; -import { initTableVisLegacyModule } from './shim/table_vis_legacy_module'; +import { initTableVisLegacyModule } from './angular/table_vis_legacy_module'; const innerAngularName = 'kibana/table_vis'; From e12997a0b48a7cf6647e56b1c91c5b036b62bec0 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Wed, 27 Nov 2019 16:45:52 +0300 Subject: [PATCH 22/26] Move file --- .../public/paginated_table/paginated_table.test.ts | 2 +- .../vis_type_table/public/table_vis_controller.test.ts | 2 +- .../public/{angular => }/table_vis_legacy_module.ts | 0 src/legacy/core_plugins/vis_type_table/public/vis_controller.ts | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename src/legacy/core_plugins/vis_type_table/public/{angular => }/table_vis_legacy_module.ts (100%) diff --git a/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts b/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts index de477cb84dc27..781782e42fbaf 100644 --- a/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/paginated_table/paginated_table.test.ts @@ -25,7 +25,7 @@ import 'angular-mocks'; import '../table_vis.mock'; import { getAngularModule } from '../get_inner_angular'; -import { initTableVisLegacyModule } from '../angular/table_vis_legacy_module'; +import { initTableVisLegacyModule } from '../table_vis_legacy_module'; import { npStart } from '../legacy_imports'; interface Sort { diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts index 6d515e239f102..d8621f7fb4823 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts @@ -26,7 +26,7 @@ import './table_vis.mock'; // @ts-ignore import StubIndexPattern from 'test_utils/stub_index_pattern'; import { getAngularModule } from './get_inner_angular'; -import { initTableVisLegacyModule } from './angular/table_vis_legacy_module'; +import { initTableVisLegacyModule } from './table_vis_legacy_module'; import { npStart, legacyResponseHandlerProvider, diff --git a/src/legacy/core_plugins/vis_type_table/public/angular/table_vis_legacy_module.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_legacy_module.ts similarity index 100% rename from src/legacy/core_plugins/vis_type_table/public/angular/table_vis_legacy_module.ts rename to src/legacy/core_plugins/vis_type_table/public/table_vis_legacy_module.ts diff --git a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts index 65d48581e50c0..7adaa21cac593 100644 --- a/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts +++ b/src/legacy/core_plugins/vis_type_table/public/vis_controller.ts @@ -23,7 +23,7 @@ import $ from 'jquery'; import { Vis, VisParams } from '../../visualizations/public'; import { npStart } from './legacy_imports'; import { getAngularModule } from './get_inner_angular'; -import { initTableVisLegacyModule } from './angular/table_vis_legacy_module'; +import { initTableVisLegacyModule } from './table_vis_legacy_module'; const innerAngularName = 'kibana/table_vis'; From c4448f70dc2add2fd5353f95905e2ea377dd5df5 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Wed, 27 Nov 2019 16:46:52 +0300 Subject: [PATCH 23/26] Fix path --- .../vis_type_table/public/table_vis_legacy_module.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_legacy_module.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_legacy_module.ts index 7ac3620b7d0e4..57d8b7c448b4c 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_legacy_module.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_legacy_module.ts @@ -20,15 +20,15 @@ import { IModule } from 'angular'; // @ts-ignore -import { TableVisController } from '../table_vis_controller.js'; +import { TableVisController } from './table_vis_controller.js'; // @ts-ignore -import { KbnAggTable } from '../agg_table/agg_table'; +import { KbnAggTable } from './agg_table/agg_table'; // @ts-ignore -import { KbnAggTableGroup } from '../agg_table/agg_table_group'; +import { KbnAggTableGroup } from './agg_table/agg_table_group'; // @ts-ignore -import { KbnRows } from '../paginated_table/rows'; +import { KbnRows } from './paginated_table/rows'; // @ts-ignore -import { PaginatedTable } from '../paginated_table/paginated_table'; +import { PaginatedTable } from './paginated_table/paginated_table'; /** @internal */ export const initTableVisLegacyModule = (angularIns: IModule): void => { From 1ae50ed00053d64e52d828fc0137e4068a236e15 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Wed, 27 Nov 2019 17:57:04 +0300 Subject: [PATCH 24/26] Fix path --- .../vis_type_table/public/agg_table/__tests__/agg_table.js | 2 +- .../public/agg_table/__tests__/agg_table_group.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 9ca4a05cf1f9c..25a28333b07ff 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,7 +31,7 @@ import { Vis } from '../../../../visualizations/public'; import { tableVisTypeDefinition } from '../../table_vis_type'; import { setup as visualizationsSetup } from '../../../../visualizations/public/np_ready/public/legacy'; import { getAngularModule } from '../../get_inner_angular'; -import { initTableVisLegacyModule } from '../../angular/table_vis_legacy_module'; +import { initTableVisLegacyModule } from '../../table_vis_legacy_module'; describe('Table Vis - AggTable Directive', function () { let $rootScope; 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 efb0855101c49..be981829ae909 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 @@ -25,7 +25,7 @@ import { legacyResponseHandlerProvider, tabifyAggResponse, npStart } from '../.. import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; import { Vis } from '../../../../visualizations/public'; import { getAngularModule } from '../../get_inner_angular'; -import { initTableVisLegacyModule } from '../../angular/table_vis_legacy_module'; +import { initTableVisLegacyModule } from '../../table_vis_legacy_module'; describe('Table Vis - AggTableGroup Directive', function () { let $rootScope; From e0f3fb2bb7d269fe6fef2c8295f1926688f88c99 Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Mon, 2 Dec 2019 10:09:14 +0300 Subject: [PATCH 25/26] Fix TS --- .../core_plugins/vis_type_table/public/get_inner_angular.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts index c80d82793c42a..9f3a8327c9ad9 100644 --- a/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts +++ b/src/legacy/core_plugins/vis_type_table/public/get_inner_angular.ts @@ -24,7 +24,7 @@ import angular from 'angular'; import 'ui/angular-bootstrap'; import 'angular-recursion'; import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular'; -import { CoreStart, LegacyCoreStart, UiSettingsClientContract } from 'kibana/public'; +import { CoreStart, LegacyCoreStart, IUiSettingsClient } from 'kibana/public'; import { PrivateProvider, PaginateDirectiveProvider, @@ -69,7 +69,7 @@ function createLocalPrivateModule() { angular.module('tableVisPrivate', []).provider('Private', PrivateProvider); } -function createLocalConfigModule(uiSettings: UiSettingsClientContract) { +function createLocalConfigModule(uiSettings: IUiSettingsClient) { angular .module('tableVisConfig', ['tableVisPrivate']) .provider('stateManagementConfig', StateManagementConfigProvider) From c07fad35f72304cfeaab6bee174c43280a4fbf3e Mon Sep 17 00:00:00 2001 From: maryia-lapata Date: Mon, 2 Dec 2019 12:49:47 +0300 Subject: [PATCH 26/26] Fix Jest test --- .../public/table_vis_controller.test.ts | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts index d8621f7fb4823..5ae58204a8cf3 100644 --- a/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts +++ b/src/legacy/core_plugins/vis_type_table/public/table_vis_controller.test.ts @@ -38,6 +38,8 @@ import { Vis } from '../../visualizations/public'; import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; // eslint-disable-next-line import { stubFields } from '../../../../plugins/data/public/stubs'; +// eslint-disable-next-line +import { setFieldFormats } from '../../../../plugins/data/public/index_patterns/services'; interface TableVisScope extends IScope { [key: string]: any; @@ -78,13 +80,7 @@ describe('Table Vis - Controller', () => { let $el: JQuery; let tableAggResponse: any; let tabifiedResponse: any; - const stubIndexPattern = new StubIndexPattern( - 'logstash-*', - (cfg: any) => cfg, - 'time', - stubFields, - npStart.core.uiSettings - ); + let stubIndexPattern: any; const initLocalAngular = () => { const tableVisModule = getAngularModule('kibana/table_vis', npStart.core); @@ -105,6 +101,19 @@ describe('Table Vis - Controller', () => { }) ); + beforeEach(() => { + setFieldFormats(({ + getDefaultInstance: jest.fn(), + } as unknown) as any); + stubIndexPattern = new StubIndexPattern( + 'logstash-*', + (cfg: any) => cfg, + 'time', + stubFields, + npStart.core.uiSettings + ); + }); + function getRangeVis(params?: object) { // @ts-ignore return new Vis(stubIndexPattern, {