;
@@ -59,6 +60,7 @@ function createKibanaRequestMock({
method = 'get',
socket = new Socket(),
routeTags,
+ routeAuthRequired,
validation = {},
}: RequestFixtureOptions
= {}) {
const queryString = stringify(query, { sort: false });
@@ -77,7 +79,9 @@ function createKibanaRequestMock
({
query: queryString,
search: queryString ? `?${queryString}` : queryString,
},
- route: { settings: { tags: routeTags } },
+ route: {
+ settings: { tags: routeTags, auth: routeAuthRequired },
+ },
raw: {
req: { socket },
},
diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts
index b8380a3045962..96b28ab5827e1 100644
--- a/src/core/server/mocks.ts
+++ b/src/core/server/mocks.ts
@@ -44,7 +44,11 @@ import { uuidServiceMock } from './uuid/uuid_service.mock';
export function pluginInitializerContextConfigMock(config: T) {
const globalConfig: SharedGlobalConfig = {
- kibana: { index: '.kibana-tests' },
+ kibana: {
+ index: '.kibana-tests',
+ autocompleteTerminateAfter: duration(100000),
+ autocompleteTimeout: duration(1000),
+ },
elasticsearch: {
shardTimeout: duration('30s'),
requestTimeout: duration('30s'),
diff --git a/src/core/server/plugins/plugin_context.test.ts b/src/core/server/plugins/plugin_context.test.ts
index 823299771544c..54350d96984b4 100644
--- a/src/core/server/plugins/plugin_context.test.ts
+++ b/src/core/server/plugins/plugin_context.test.ts
@@ -75,7 +75,11 @@ describe('Plugin Context', () => {
.pipe(first())
.toPromise();
expect(configObject).toStrictEqual({
- kibana: { index: '.kibana' },
+ kibana: {
+ index: '.kibana',
+ autocompleteTerminateAfter: duration(100000),
+ autocompleteTimeout: duration(1000),
+ },
elasticsearch: {
shardTimeout: duration(30, 's'),
requestTimeout: duration(30, 's'),
diff --git a/src/core/server/plugins/types.ts b/src/core/server/plugins/types.ts
index e6a04c1223e6c..100e3c2288dbf 100644
--- a/src/core/server/plugins/types.ts
+++ b/src/core/server/plugins/types.ts
@@ -214,7 +214,7 @@ export interface Plugin<
export const SharedGlobalConfigKeys = {
// We can add more if really needed
- kibana: ['index'] as const,
+ kibana: ['index', 'autocompleteTerminateAfter', 'autocompleteTimeout'] as const,
elasticsearch: ['shardTimeout', 'requestTimeout', 'pingTimeout', 'startupTimeout'] as const,
path: ['data'] as const,
};
diff --git a/src/core/server/saved_objects/mappings/types.ts b/src/core/server/saved_objects/mappings/types.ts
index 578fdcea3718e..bc556c0429981 100644
--- a/src/core/server/saved_objects/mappings/types.ts
+++ b/src/core/server/saved_objects/mappings/types.ts
@@ -45,6 +45,9 @@
* @public
*/
export interface SavedObjectsTypeMappingDefinition {
+ /** The dynamic property of the mapping. either `false` or 'strict'. Defaults to strict */
+ dynamic?: false | 'strict';
+ /** The underlying properties of the type mapping */
properties: SavedObjectsMappingProperties;
}
diff --git a/src/core/server/saved_objects/migrations/core/__snapshots__/build_active_mappings.test.ts.snap b/src/core/server/saved_objects/migrations/core/__snapshots__/build_active_mappings.test.ts.snap
index e82fbfc85dfa0..68f90ea70a0c6 100644
--- a/src/core/server/saved_objects/migrations/core/__snapshots__/build_active_mappings.test.ts.snap
+++ b/src/core/server/saved_objects/migrations/core/__snapshots__/build_active_mappings.test.ts.snap
@@ -60,3 +60,82 @@ Object {
},
}
`;
+
+exports[`buildActiveMappings handles the \`dynamic\` property of types 1`] = `
+Object {
+ "_meta": Object {
+ "migrationMappingPropertyHashes": Object {
+ "config": "87aca8fdb053154f11383fce3dbf3edf",
+ "firstType": "635418ab953d81d93f1190b70a8d3f57",
+ "migrationVersion": "4a1746014a75ade3a714e1db5763276f",
+ "namespace": "2f4316de49999235636386fe51dc06c1",
+ "references": "7997cf5a56cc02bdc9c93361bde732b0",
+ "secondType": "72d57924f415fbadb3ee293b67d233ab",
+ "thirdType": "510f1f0adb69830cf8a1c5ce2923ed82",
+ "type": "2f4316de49999235636386fe51dc06c1",
+ "updated_at": "00da57df13e94e9d98437d13ace4bfe0",
+ },
+ },
+ "dynamic": "strict",
+ "properties": Object {
+ "config": Object {
+ "dynamic": "true",
+ "properties": Object {
+ "buildNum": Object {
+ "type": "keyword",
+ },
+ },
+ },
+ "firstType": Object {
+ "dynamic": "strict",
+ "properties": Object {
+ "field": Object {
+ "type": "keyword",
+ },
+ },
+ },
+ "migrationVersion": Object {
+ "dynamic": "true",
+ "type": "object",
+ },
+ "namespace": Object {
+ "type": "keyword",
+ },
+ "references": Object {
+ "properties": Object {
+ "id": Object {
+ "type": "keyword",
+ },
+ "name": Object {
+ "type": "keyword",
+ },
+ "type": Object {
+ "type": "keyword",
+ },
+ },
+ "type": "nested",
+ },
+ "secondType": Object {
+ "dynamic": false,
+ "properties": Object {
+ "field": Object {
+ "type": "long",
+ },
+ },
+ },
+ "thirdType": Object {
+ "properties": Object {
+ "field": Object {
+ "type": "text",
+ },
+ },
+ },
+ "type": Object {
+ "type": "keyword",
+ },
+ "updated_at": Object {
+ "type": "date",
+ },
+ },
+}
+`;
diff --git a/src/core/server/saved_objects/migrations/core/build_active_mappings.test.ts b/src/core/server/saved_objects/migrations/core/build_active_mappings.test.ts
index 9d220cfdf94b7..33e1a395e64a2 100644
--- a/src/core/server/saved_objects/migrations/core/build_active_mappings.test.ts
+++ b/src/core/server/saved_objects/migrations/core/build_active_mappings.test.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { IndexMapping } from './../../mappings';
+import { IndexMapping, SavedObjectsTypeMappingDefinitions } from './../../mappings';
import { buildActiveMappings, diffMappings } from './build_active_mappings';
describe('buildActiveMappings', () => {
@@ -49,6 +49,23 @@ describe('buildActiveMappings', () => {
);
});
+ test('handles the `dynamic` property of types', () => {
+ const typeMappings: SavedObjectsTypeMappingDefinitions = {
+ firstType: {
+ dynamic: 'strict',
+ properties: { field: { type: 'keyword' } },
+ },
+ secondType: {
+ dynamic: false,
+ properties: { field: { type: 'long' } },
+ },
+ thirdType: {
+ properties: { field: { type: 'text' } },
+ },
+ };
+ expect(buildActiveMappings(typeMappings)).toMatchSnapshot();
+ });
+
test('generated hashes are stable', () => {
const properties = {
aaa: { type: 'keyword', fields: { a: { type: 'keyword' }, b: { type: 'text' } } },
diff --git a/src/core/server/saved_objects/saved_objects_service.ts b/src/core/server/saved_objects/saved_objects_service.ts
index d5a9f47420971..62e25ad5fb458 100644
--- a/src/core/server/saved_objects/saved_objects_service.ts
+++ b/src/core/server/saved_objects/saved_objects_service.ts
@@ -387,6 +387,14 @@ export class SavedObjectsService
this.logger.info(
'Waiting until all Elasticsearch nodes are compatible with Kibana before starting saved objects migrations...'
);
+
+ // TODO: Move to Status Service https://github.com/elastic/kibana/issues/41983
+ this.setupDeps!.elasticsearch.esNodesCompatibility$.subscribe(({ isCompatible, message }) => {
+ if (!isCompatible && message) {
+ this.logger.error(message);
+ }
+ });
+
await this.setupDeps!.elasticsearch.esNodesCompatibility$.pipe(
filter(nodes => nodes.isCompatible),
take(1)
diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md
index 8f4feb7169651..42bc1ce214b19 100644
--- a/src/core/server/server.api.md
+++ b/src/core/server/server.api.md
@@ -2058,7 +2058,7 @@ export interface SavedObjectsType {
// @public
export interface SavedObjectsTypeMappingDefinition {
- // (undocumented)
+ dynamic?: false | 'strict';
properties: SavedObjectsMappingProperties;
}
diff --git a/src/core/server/uuid/resolve_uuid.test.ts b/src/core/server/uuid/resolve_uuid.test.ts
index d1332daa02057..efc90c07c1fa6 100644
--- a/src/core/server/uuid/resolve_uuid.test.ts
+++ b/src/core/server/uuid/resolve_uuid.test.ts
@@ -19,7 +19,7 @@
import { join } from 'path';
import { readFile, writeFile } from './fs';
-import { resolveInstanceUuid } from './resolve_uuid';
+import { resolveInstanceUuid, UUID_7_6_0_BUG } from './resolve_uuid';
import { configServiceMock } from '../config/config_service.mock';
import { loggingServiceMock } from '../logging/logging_service.mock';
import { BehaviorSubject } from 'rxjs';
@@ -97,58 +97,96 @@ describe('resolveInstanceUuid', () => {
});
describe('when file is present and config property is set', () => {
- it('writes to file and returns the config uuid if they mismatch', async () => {
- const uuid = await resolveInstanceUuid(configService, logger);
- expect(uuid).toEqual(DEFAULT_CONFIG_UUID);
- expect(writeFile).toHaveBeenCalledWith(
- join('data-folder', 'uuid'),
- DEFAULT_CONFIG_UUID,
- expect.any(Object)
- );
- expect(logger.debug).toHaveBeenCalledTimes(1);
- expect(logger.debug.mock.calls[0]).toMatchInlineSnapshot(`
- Array [
- "Updating Kibana instance UUID to: CONFIG_UUID (was: FILE_UUID)",
- ]
- `);
+ describe('when they mismatch', () => {
+ describe('when syncToFile is true', () => {
+ it('writes to file and returns the config uuid', async () => {
+ const uuid = await resolveInstanceUuid({ configService, logger, syncToFile: true });
+ expect(uuid).toEqual(DEFAULT_CONFIG_UUID);
+ expect(writeFile).toHaveBeenCalledWith(
+ join('data-folder', 'uuid'),
+ DEFAULT_CONFIG_UUID,
+ expect.any(Object)
+ );
+ expect(logger.debug).toHaveBeenCalledTimes(1);
+ expect(logger.debug.mock.calls[0]).toMatchInlineSnapshot(`
+ Array [
+ "Updating Kibana instance UUID to: CONFIG_UUID (was: FILE_UUID)",
+ ]
+ `);
+ });
+ });
+
+ describe('when syncTofile is false', () => {
+ it('does not write to file and returns the config uuid', async () => {
+ const uuid = await resolveInstanceUuid({ configService, logger, syncToFile: false });
+ expect(uuid).toEqual(DEFAULT_CONFIG_UUID);
+ expect(writeFile).not.toHaveBeenCalled();
+ expect(logger.debug).toHaveBeenCalledTimes(1);
+ expect(logger.debug.mock.calls[0]).toMatchInlineSnapshot(`
+ Array [
+ "Updating Kibana instance UUID to: CONFIG_UUID (was: FILE_UUID)",
+ ]
+ `);
+ });
+ });
});
- it('does not write to file if they match', async () => {
- mockReadFile({ uuid: DEFAULT_CONFIG_UUID });
- const uuid = await resolveInstanceUuid(configService, logger);
- expect(uuid).toEqual(DEFAULT_CONFIG_UUID);
- expect(writeFile).not.toHaveBeenCalled();
- expect(logger.debug).toHaveBeenCalledTimes(1);
- expect(logger.debug.mock.calls[0]).toMatchInlineSnapshot(`
- Array [
- "Kibana instance UUID: CONFIG_UUID",
- ]
- `);
+
+ describe('when they match', () => {
+ it('does not write to file', async () => {
+ mockReadFile({ uuid: DEFAULT_CONFIG_UUID });
+ const uuid = await resolveInstanceUuid({ configService, logger, syncToFile: true });
+ expect(uuid).toEqual(DEFAULT_CONFIG_UUID);
+ expect(writeFile).not.toHaveBeenCalled();
+ expect(logger.debug).toHaveBeenCalledTimes(1);
+ expect(logger.debug.mock.calls[0]).toMatchInlineSnapshot(`
+ Array [
+ "Kibana instance UUID: CONFIG_UUID",
+ ]
+ `);
+ });
});
});
describe('when file is not present and config property is set', () => {
- it('writes the uuid to file and returns the config uuid', async () => {
- mockReadFile({ error: fileNotFoundError });
- const uuid = await resolveInstanceUuid(configService, logger);
- expect(uuid).toEqual(DEFAULT_CONFIG_UUID);
- expect(writeFile).toHaveBeenCalledWith(
- join('data-folder', 'uuid'),
- DEFAULT_CONFIG_UUID,
- expect.any(Object)
- );
- expect(logger.debug).toHaveBeenCalledTimes(1);
- expect(logger.debug.mock.calls[0]).toMatchInlineSnapshot(`
- Array [
- "Setting new Kibana instance UUID: CONFIG_UUID",
- ]
- `);
+ describe('when syncToFile is true', () => {
+ it('writes the uuid to file and returns the config uuid', async () => {
+ mockReadFile({ error: fileNotFoundError });
+ const uuid = await resolveInstanceUuid({ configService, logger, syncToFile: true });
+ expect(uuid).toEqual(DEFAULT_CONFIG_UUID);
+ expect(writeFile).toHaveBeenCalledWith(
+ join('data-folder', 'uuid'),
+ DEFAULT_CONFIG_UUID,
+ expect.any(Object)
+ );
+ expect(logger.debug).toHaveBeenCalledTimes(1);
+ expect(logger.debug.mock.calls[0]).toMatchInlineSnapshot(`
+ Array [
+ "Setting new Kibana instance UUID: CONFIG_UUID",
+ ]
+ `);
+ });
+ });
+
+ describe('when syncToFile is false', () => {
+ it('does not write the uuid to file and returns the config uuid', async () => {
+ mockReadFile({ error: fileNotFoundError });
+ const uuid = await resolveInstanceUuid({ configService, logger, syncToFile: false });
+ expect(uuid).toEqual(DEFAULT_CONFIG_UUID);
+ expect(writeFile).not.toHaveBeenCalled();
+ expect(logger.debug).toHaveBeenCalledTimes(1);
+ expect(logger.debug.mock.calls[0]).toMatchInlineSnapshot(`
+ Array [
+ "Setting new Kibana instance UUID: CONFIG_UUID",
+ ]
+ `);
+ });
});
});
describe('when file is present and config property is not set', () => {
it('does not write to file and returns the file uuid', async () => {
configService = getConfigService(undefined);
- const uuid = await resolveInstanceUuid(configService, logger);
+ const uuid = await resolveInstanceUuid({ configService, logger, syncToFile: true });
expect(uuid).toEqual(DEFAULT_FILE_UUID);
expect(writeFile).not.toHaveBeenCalled();
expect(logger.debug).toHaveBeenCalledTimes(1);
@@ -160,23 +198,95 @@ describe('resolveInstanceUuid', () => {
});
});
+ describe('when file is present with 7.6.0 UUID', () => {
+ describe('when config property is not set', () => {
+ it('writes new uuid to file and returns new uuid', async () => {
+ mockReadFile({ uuid: UUID_7_6_0_BUG });
+ configService = getConfigService(undefined);
+ const uuid = await resolveInstanceUuid({ configService, logger, syncToFile: true });
+ expect(uuid).not.toEqual(UUID_7_6_0_BUG);
+ expect(uuid).toEqual('NEW_UUID');
+ expect(writeFile).toHaveBeenCalledWith(
+ join('data-folder', 'uuid'),
+ 'NEW_UUID',
+ expect.any(Object)
+ );
+ expect(logger.debug).toHaveBeenCalledTimes(2);
+ expect(logger.debug.mock.calls).toMatchInlineSnapshot(`
+ Array [
+ Array [
+ "UUID from 7.6.0 bug detected, ignoring file UUID",
+ ],
+ Array [
+ "Setting new Kibana instance UUID: NEW_UUID",
+ ],
+ ]
+ `);
+ });
+ });
+
+ describe('when config property is set', () => {
+ it('writes config uuid to file and returns config uuid', async () => {
+ mockReadFile({ uuid: UUID_7_6_0_BUG });
+ configService = getConfigService(DEFAULT_CONFIG_UUID);
+ const uuid = await resolveInstanceUuid({ configService, logger, syncToFile: true });
+ expect(uuid).not.toEqual(UUID_7_6_0_BUG);
+ expect(uuid).toEqual(DEFAULT_CONFIG_UUID);
+ expect(writeFile).toHaveBeenCalledWith(
+ join('data-folder', 'uuid'),
+ DEFAULT_CONFIG_UUID,
+ expect.any(Object)
+ );
+ expect(logger.debug).toHaveBeenCalledTimes(2);
+ expect(logger.debug.mock.calls).toMatchInlineSnapshot(`
+ Array [
+ Array [
+ "UUID from 7.6.0 bug detected, ignoring file UUID",
+ ],
+ Array [
+ "Setting new Kibana instance UUID: CONFIG_UUID",
+ ],
+ ]
+ `);
+ });
+ });
+ });
+
describe('when file is not present and config property is not set', () => {
- it('generates a new uuid and write it to file', async () => {
- configService = getConfigService(undefined);
- mockReadFile({ error: fileNotFoundError });
- const uuid = await resolveInstanceUuid(configService, logger);
- expect(uuid).toEqual('NEW_UUID');
- expect(writeFile).toHaveBeenCalledWith(
- join('data-folder', 'uuid'),
- 'NEW_UUID',
- expect.any(Object)
- );
- expect(logger.debug).toHaveBeenCalledTimes(1);
- expect(logger.debug.mock.calls[0]).toMatchInlineSnapshot(`
- Array [
- "Setting new Kibana instance UUID: NEW_UUID",
- ]
- `);
+ describe('when syncToFile is true', () => {
+ it('generates a new uuid and write it to file', async () => {
+ configService = getConfigService(undefined);
+ mockReadFile({ error: fileNotFoundError });
+ const uuid = await resolveInstanceUuid({ configService, logger, syncToFile: true });
+ expect(uuid).toEqual('NEW_UUID');
+ expect(writeFile).toHaveBeenCalledWith(
+ join('data-folder', 'uuid'),
+ 'NEW_UUID',
+ expect.any(Object)
+ );
+ expect(logger.debug).toHaveBeenCalledTimes(1);
+ expect(logger.debug.mock.calls[0]).toMatchInlineSnapshot(`
+ Array [
+ "Setting new Kibana instance UUID: NEW_UUID",
+ ]
+ `);
+ });
+ });
+
+ describe('when syncToFile is false', () => {
+ it('generates a new uuid and does not write it to file', async () => {
+ configService = getConfigService(undefined);
+ mockReadFile({ error: fileNotFoundError });
+ const uuid = await resolveInstanceUuid({ configService, logger, syncToFile: false });
+ expect(uuid).toEqual('NEW_UUID');
+ expect(writeFile).not.toHaveBeenCalled();
+ expect(logger.debug).toHaveBeenCalledTimes(1);
+ expect(logger.debug.mock.calls[0]).toMatchInlineSnapshot(`
+ Array [
+ "Setting new Kibana instance UUID: NEW_UUID",
+ ]
+ `);
+ });
});
});
@@ -184,7 +294,7 @@ describe('resolveInstanceUuid', () => {
it('throws an explicit error for file read errors', async () => {
mockReadFile({ error: permissionError });
await expect(
- resolveInstanceUuid(configService, logger)
+ resolveInstanceUuid({ configService, logger, syncToFile: true })
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Unable to read Kibana UUID file, please check the uuid.server configuration value in kibana.yml and ensure Kibana has sufficient permissions to read / write to this file. Error was: EACCES"`
);
@@ -192,7 +302,7 @@ describe('resolveInstanceUuid', () => {
it('throws an explicit error for file write errors', async () => {
mockWriteFile(isDirectoryError);
await expect(
- resolveInstanceUuid(configService, logger)
+ resolveInstanceUuid({ configService, logger, syncToFile: true })
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Unable to write Kibana UUID file, please check the uuid.server configuration value in kibana.yml and ensure Kibana has sufficient permissions to read / write to this file. Error was: EISDIR"`
);
diff --git a/src/core/server/uuid/resolve_uuid.ts b/src/core/server/uuid/resolve_uuid.ts
index 3f5bdc7387392..516357e10d3f7 100644
--- a/src/core/server/uuid/resolve_uuid.ts
+++ b/src/core/server/uuid/resolve_uuid.ts
@@ -28,11 +28,21 @@ import { Logger } from '../logging';
const FILE_ENCODING = 'utf8';
const FILE_NAME = 'uuid';
+/**
+ * This UUID was inadvertantly shipped in the 7.6.0 distributable and should be deleted if found.
+ * See https://github.com/elastic/kibana/issues/57673 for more info.
+ */
+export const UUID_7_6_0_BUG = `ce42b997-a913-4d58-be46-bb1937feedd6`;
-export async function resolveInstanceUuid(
- configService: IConfigService,
- logger: Logger
-): Promise {
+export async function resolveInstanceUuid({
+ configService,
+ syncToFile,
+ logger,
+}: {
+ configService: IConfigService;
+ syncToFile: boolean;
+ logger: Logger;
+}): Promise {
const [pathConfig, serverConfig] = await Promise.all([
configService
.atPath(pathConfigDef.path)
@@ -46,7 +56,7 @@ export async function resolveInstanceUuid(
const uuidFilePath = join(pathConfig.data, FILE_NAME);
- const uuidFromFile = await readUuidFromFile(uuidFilePath);
+ const uuidFromFile = await readUuidFromFile(uuidFilePath, logger);
const uuidFromConfig = serverConfig.uuid;
if (uuidFromConfig) {
@@ -61,7 +71,7 @@ export async function resolveInstanceUuid(
} else {
logger.debug(`Updating Kibana instance UUID to: ${uuidFromConfig} (was: ${uuidFromFile})`);
}
- await writeUuidToFile(uuidFilePath, uuidFromConfig);
+ await writeUuidToFile(uuidFilePath, uuidFromConfig, syncToFile);
return uuidFromConfig;
}
}
@@ -69,7 +79,7 @@ export async function resolveInstanceUuid(
const newUuid = uuid.v4();
// no uuid either in config or file, we need to generate and write it.
logger.debug(`Setting new Kibana instance UUID: ${newUuid}`);
- await writeUuidToFile(uuidFilePath, newUuid);
+ await writeUuidToFile(uuidFilePath, newUuid, syncToFile);
return newUuid;
}
@@ -77,10 +87,17 @@ export async function resolveInstanceUuid(
return uuidFromFile;
}
-async function readUuidFromFile(filepath: string): Promise {
+async function readUuidFromFile(filepath: string, logger: Logger): Promise {
try {
const content = await readFile(filepath);
- return content.toString(FILE_ENCODING);
+ const decoded = content.toString(FILE_ENCODING);
+
+ if (decoded === UUID_7_6_0_BUG) {
+ logger.debug(`UUID from 7.6.0 bug detected, ignoring file UUID`);
+ return undefined;
+ } else {
+ return decoded;
+ }
} catch (e) {
if (e.code === 'ENOENT') {
// non-existent uuid file is ok, we will create it.
@@ -94,7 +111,11 @@ async function readUuidFromFile(filepath: string): Promise {
}
}
-async function writeUuidToFile(filepath: string, uuidValue: string) {
+async function writeUuidToFile(filepath: string, uuidValue: string, syncToFile: boolean) {
+ if (!syncToFile) {
+ return;
+ }
+
try {
return await writeFile(filepath, uuidValue, { encoding: FILE_ENCODING });
} catch (e) {
diff --git a/src/core/server/uuid/uuid_service.test.ts b/src/core/server/uuid/uuid_service.test.ts
index 315df7af8aa19..a61061ff84263 100644
--- a/src/core/server/uuid/uuid_service.test.ts
+++ b/src/core/server/uuid/uuid_service.test.ts
@@ -23,6 +23,8 @@ import { CoreContext } from '../core_context';
import { loggingServiceMock } from '../logging/logging_service.mock';
import { mockCoreContext } from '../core_context.mock';
+import { Env } from '../config';
+import { getEnvOptions } from '../config/__mocks__/env';
jest.mock('./resolve_uuid', () => ({
resolveInstanceUuid: jest.fn().mockResolvedValue('SOME_UUID'),
@@ -31,26 +33,44 @@ jest.mock('./resolve_uuid', () => ({
describe('UuidService', () => {
let logger: ReturnType;
let coreContext: CoreContext;
- let service: UuidService;
beforeEach(() => {
jest.clearAllMocks();
logger = loggingServiceMock.create();
coreContext = mockCoreContext.create({ logger });
- service = new UuidService(coreContext);
});
describe('#setup()', () => {
- it('calls manageInstanceUuid with core configuration service', async () => {
+ it('calls resolveInstanceUuid with core configuration service', async () => {
+ const service = new UuidService(coreContext);
await service.setup();
expect(resolveInstanceUuid).toHaveBeenCalledTimes(1);
- expect(resolveInstanceUuid).toHaveBeenCalledWith(
- coreContext.configService,
- logger.get('uuid')
- );
+ expect(resolveInstanceUuid).toHaveBeenCalledWith({
+ configService: coreContext.configService,
+ syncToFile: true,
+ logger: logger.get('uuid'),
+ });
});
- it('returns the uuid resolved from manageInstanceUuid', async () => {
+ describe('when cliArgs.optimize is true', () => {
+ it('calls resolveInstanceUuid with syncToFile: false', async () => {
+ coreContext = mockCoreContext.create({
+ logger,
+ env: Env.createDefault(getEnvOptions({ cliArgs: { optimize: true } })),
+ });
+ const service = new UuidService(coreContext);
+ await service.setup();
+ expect(resolveInstanceUuid).toHaveBeenCalledTimes(1);
+ expect(resolveInstanceUuid).toHaveBeenCalledWith({
+ configService: coreContext.configService,
+ syncToFile: false,
+ logger: logger.get('uuid'),
+ });
+ });
+ });
+
+ it('returns the uuid resolved from resolveInstanceUuid', async () => {
+ const service = new UuidService(coreContext);
const setup = await service.setup();
expect(setup.getInstanceUuid()).toEqual('SOME_UUID');
});
diff --git a/src/core/server/uuid/uuid_service.ts b/src/core/server/uuid/uuid_service.ts
index 10104fa704936..62ed4a19edf5a 100644
--- a/src/core/server/uuid/uuid_service.ts
+++ b/src/core/server/uuid/uuid_service.ts
@@ -20,7 +20,7 @@
import { resolveInstanceUuid } from './resolve_uuid';
import { CoreContext } from '../core_context';
import { Logger } from '../logging';
-import { IConfigService } from '../config';
+import { IConfigService, CliArgs } from '../config';
/**
* APIs to access the application's instance uuid.
@@ -38,15 +38,21 @@ export interface UuidServiceSetup {
export class UuidService {
private readonly log: Logger;
private readonly configService: IConfigService;
+ private readonly cliArgs: CliArgs;
private uuid: string = '';
constructor(core: CoreContext) {
this.log = core.logger.get('uuid');
this.configService = core.configService;
+ this.cliArgs = core.env.cliArgs;
}
public async setup() {
- this.uuid = await resolveInstanceUuid(this.configService, this.log);
+ this.uuid = await resolveInstanceUuid({
+ configService: this.configService,
+ syncToFile: !this.cliArgs.optimize,
+ logger: this.log,
+ });
return {
getInstanceUuid: () => this.uuid,
diff --git a/src/dev/build/build_distributables.js b/src/dev/build/build_distributables.js
index c4f9d7f56554c..6c2efeebc60c3 100644
--- a/src/dev/build/build_distributables.js
+++ b/src/dev/build/build_distributables.js
@@ -54,6 +54,7 @@ import {
VerifyExistingNodeBuildsTask,
PathLengthTask,
WriteShaSumsTask,
+ UuidVerificationTask,
} from './tasks';
export async function buildDistributables(options) {
@@ -136,6 +137,7 @@ export async function buildDistributables(options) {
await run(CleanNodeBuildsTask);
await run(PathLengthTask);
+ await run(UuidVerificationTask);
/**
* package platform-specific builds into archives
diff --git a/src/dev/build/tasks/index.js b/src/dev/build/tasks/index.js
index 56e813111279d..8105fa8a7d5d4 100644
--- a/src/dev/build/tasks/index.js
+++ b/src/dev/build/tasks/index.js
@@ -38,3 +38,4 @@ export * from './verify_env_task';
export * from './write_sha_sums_task';
export * from './path_length_task';
export * from './build_kibana_platform_plugins';
+export * from './uuid_verification_task';
diff --git a/src/dev/build/tasks/uuid_verification_task.js b/src/dev/build/tasks/uuid_verification_task.js
new file mode 100644
index 0000000000000..32c9e73dba988
--- /dev/null
+++ b/src/dev/build/tasks/uuid_verification_task.js
@@ -0,0 +1,38 @@
+/*
+ * 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 { read } from '../lib';
+
+export const UuidVerificationTask = {
+ description: 'Verify that no UUID file is baked into the build',
+
+ async run(config, log, build) {
+ const uuidFilePath = build.resolvePath('data', 'uuid');
+ await read(uuidFilePath).then(
+ function success() {
+ throw new Error(`UUID file should not exist at [${uuidFilePath}]`);
+ },
+ function error(err) {
+ if (err.code !== 'ENOENT') {
+ throw err;
+ }
+ }
+ );
+ },
+};
diff --git a/src/legacy/core_plugins/application_usage/index.ts b/src/legacy/core_plugins/application_usage/index.ts
new file mode 100644
index 0000000000000..752d6eaa19bb0
--- /dev/null
+++ b/src/legacy/core_plugins/application_usage/index.ts
@@ -0,0 +1,31 @@
+/*
+ * 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 { Legacy } from '../../../../kibana';
+import { mappings } from './mappings';
+
+// eslint-disable-next-line import/no-default-export
+export default function ApplicationUsagePlugin(kibana: any) {
+ const config: Legacy.PluginSpecOptions = {
+ id: 'application_usage',
+ uiExports: { mappings }, // Needed to define the mappings for the SavedObjects
+ };
+
+ return new kibana.Plugin(config);
+}
diff --git a/src/legacy/core_plugins/application_usage/mappings.ts b/src/legacy/core_plugins/application_usage/mappings.ts
new file mode 100644
index 0000000000000..39adc53f7e9ff
--- /dev/null
+++ b/src/legacy/core_plugins/application_usage/mappings.ts
@@ -0,0 +1,36 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+export const mappings = {
+ application_usage_totals: {
+ properties: {
+ appId: { type: 'keyword' },
+ numberOfClicks: { type: 'long' },
+ minutesOnScreen: { type: 'float' },
+ },
+ },
+ application_usage_transactional: {
+ properties: {
+ timestamp: { type: 'date' },
+ appId: { type: 'keyword' },
+ numberOfClicks: { type: 'long' },
+ minutesOnScreen: { type: 'float' },
+ },
+ },
+};
diff --git a/src/legacy/core_plugins/application_usage/package.json b/src/legacy/core_plugins/application_usage/package.json
new file mode 100644
index 0000000000000..5ab10a2f8d237
--- /dev/null
+++ b/src/legacy/core_plugins/application_usage/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "application_usage",
+ "version": "kibana"
+}
\ No newline at end of file
diff --git a/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.ts b/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.ts
index 0e18c7c707fa3..eb29530f92fee 100644
--- a/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.ts
+++ b/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.ts
@@ -19,34 +19,14 @@
import moment from 'moment';
-jest.mock('../../search/aggs', () => ({
- AggConfigs: function AggConfigs() {
- return {
- createAggConfig: ({ params }: Record) => ({
- params,
- getIndexPattern: () => ({
- timeFieldName: 'time',
- }),
- }),
- };
- },
-}));
-
-jest.mock('../../../../../../plugins/data/public/services', () => ({
- getIndexPatterns: () => {
- return {
- get: async () => {
- return {
- id: 'logstash-*',
- timeFieldName: 'time',
- };
- },
- };
- },
-}));
-
import { onBrushEvent, BrushEvent } from './brush_event';
+import { mockDataServices } from '../../search/aggs/test_helpers';
+import { IndexPatternsContract } from '../../../../../../plugins/data/public';
+import { dataPluginMock } from '../../../../../../plugins/data/public/mocks';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { setIndexPatterns } from '../../../../../../plugins/data/public/services';
+
describe('brushEvent', () => {
const DAY_IN_MS = 24 * 60 * 60 * 1000;
const JAN_01_2014 = 1388559600000;
@@ -59,11 +39,28 @@ describe('brushEvent', () => {
},
getIndexPattern: () => ({
timeFieldName: 'time',
+ fields: {
+ getByName: () => undefined,
+ filter: () => [],
+ },
}),
},
];
beforeEach(() => {
+ mockDataServices();
+ setIndexPatterns(({
+ ...dataPluginMock.createStartContract().indexPatterns,
+ get: async () => ({
+ id: 'indexPatternId',
+ timeFieldName: 'time',
+ fields: {
+ getByName: () => undefined,
+ filter: () => [],
+ },
+ }),
+ } as unknown) as IndexPatternsContract);
+
baseEvent = {
data: {
ordered: {
diff --git a/src/legacy/core_plugins/data/public/index.ts b/src/legacy/core_plugins/data/public/index.ts
index 8cde5d0a1fc11..8d730d18a1755 100644
--- a/src/legacy/core_plugins/data/public/index.ts
+++ b/src/legacy/core_plugins/data/public/index.ts
@@ -35,18 +35,18 @@ export {
} from '../../../../plugins/data/public';
export {
// agg_types
- AggParam,
- AggParamOption,
- DateRangeKey,
+ AggParam, // only the type is used externally, only in vis editor
+ AggParamOption, // only the type is used externally
+ DateRangeKey, // only used in field formatter deserialization, which will live in data
IAggConfig,
IAggConfigs,
IAggType,
IFieldParamType,
IMetricAggType,
- IpRangeKey,
+ IpRangeKey, // only used in field formatter deserialization, which will live in data
ISchemas,
- OptionedParamEditorProps,
- OptionedValueProp,
+ OptionedParamEditorProps, // only type is used externally
+ OptionedValueProp, // only type is used externally
} from './search/types';
/** @public static code */
diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts
index e13e8e34eaebe..e2b8ca5dda78c 100644
--- a/src/legacy/core_plugins/data/public/plugin.ts
+++ b/src/legacy/core_plugins/data/public/plugin.ts
@@ -36,6 +36,7 @@ import {
setOverlays,
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../../../plugins/data/public/services';
+import { setSearchServiceShim } from './services';
import { SELECT_RANGE_ACTION, selectRangeAction } from './actions/select_range_action';
import { VALUE_CLICK_ACTION, valueClickAction } from './actions/value_click_action';
import {
@@ -112,6 +113,9 @@ export class DataPlugin
}
public start(core: CoreStart, { data, uiActions }: DataPluginStartDependencies): DataStart {
+ const search = this.search.start(core);
+ setSearchServiceShim(search);
+
setUiSettings(core.uiSettings);
setQueryService(data.query);
setIndexPatterns(data.indexPatterns);
@@ -123,7 +127,7 @@ export class DataPlugin
uiActions.attachAction(VALUE_CLICK_TRIGGER, VALUE_CLICK_ACTION);
return {
- search: this.search.start(core),
+ search,
};
}
diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_config.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_config.test.ts
new file mode 100644
index 0000000000000..7769aa29184d3
--- /dev/null
+++ b/src/legacy/core_plugins/data/public/search/aggs/agg_config.test.ts
@@ -0,0 +1,497 @@
+/*
+ * 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 { identity } from 'lodash';
+
+import { AggConfig, IAggConfig } from './agg_config';
+import { AggConfigs, CreateAggConfigParams } from './agg_configs';
+import { AggType } from './agg_types';
+import { AggTypesRegistryStart } from './agg_types_registry';
+import { mockDataServices, mockAggTypesRegistry } from './test_helpers';
+import { IndexPatternField, IndexPattern } from '../../../../../../plugins/data/public';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { stubIndexPatternWithFields } from '../../../../../../plugins/data/public/stubs';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { dataPluginMock } from '../../../../../../plugins/data/public/mocks';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { setFieldFormats } from '../../../../../../plugins/data/public/services';
+
+describe('AggConfig', () => {
+ let indexPattern: IndexPattern;
+ let typesRegistry: AggTypesRegistryStart;
+
+ beforeEach(() => {
+ jest.restoreAllMocks();
+ mockDataServices();
+ indexPattern = stubIndexPatternWithFields as IndexPattern;
+ typesRegistry = mockAggTypesRegistry();
+ });
+
+ describe('#toDsl', () => {
+ it('calls #write()', () => {
+ const ac = new AggConfigs(indexPattern, [], { typesRegistry });
+ const configStates = {
+ enabled: true,
+ type: 'date_histogram',
+ schema: 'segment',
+ params: {},
+ };
+ const aggConfig = ac.createAggConfig(configStates);
+
+ const spy = jest.spyOn(aggConfig, 'write').mockImplementation(() => ({ params: {} }));
+ aggConfig.toDsl();
+ expect(spy).toHaveBeenCalledTimes(1);
+ });
+
+ it('uses the type name as the agg name', () => {
+ const ac = new AggConfigs(indexPattern, [], { typesRegistry });
+ const configStates = {
+ enabled: true,
+ type: 'date_histogram',
+ schema: 'segment',
+ params: {},
+ };
+ const aggConfig = ac.createAggConfig(configStates);
+
+ jest.spyOn(aggConfig, 'write').mockImplementation(() => ({ params: {} }));
+ const dsl = aggConfig.toDsl();
+ expect(dsl).toHaveProperty('date_histogram');
+ });
+
+ it('uses the params from #write() output as the agg params', () => {
+ const ac = new AggConfigs(indexPattern, [], { typesRegistry });
+ const configStates = {
+ enabled: true,
+ type: 'date_histogram',
+ schema: 'segment',
+ params: {},
+ };
+ const aggConfig = ac.createAggConfig(configStates);
+
+ const football = {};
+ jest.spyOn(aggConfig, 'write').mockImplementation(() => ({ params: football }));
+ const dsl = aggConfig.toDsl();
+ expect(dsl.date_histogram).toBe(football);
+ });
+
+ it('includes subAggs from #write() output', () => {
+ const configStates = [
+ {
+ enabled: true,
+ type: 'avg',
+ schema: 'metric',
+ params: {},
+ },
+ {
+ enabled: true,
+ type: 'date_histogram',
+ schema: 'segment',
+ params: {},
+ },
+ ];
+ const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
+
+ const histoConfig = ac.byName('date_histogram')[0];
+ const avgConfig = ac.byName('avg')[0];
+ const football = {};
+
+ jest
+ .spyOn(histoConfig, 'write')
+ .mockImplementation(() => ({ params: {}, subAggs: [avgConfig] }));
+ jest.spyOn(avgConfig, 'write').mockImplementation(() => ({ params: football }));
+
+ const dsl = histoConfig.toDsl();
+ expect(dsl).toHaveProperty('aggs');
+ expect(dsl.aggs).toHaveProperty(avgConfig.id);
+ expect(dsl.aggs[avgConfig.id]).toHaveProperty('avg');
+ expect(dsl.aggs[avgConfig.id].avg).toBe(football);
+ });
+ });
+
+ describe('::ensureIds', () => {
+ it('accepts an array of objects and assigns ids to them', () => {
+ const objs = [{}, {}, {}, {}];
+ AggConfig.ensureIds(objs);
+ expect(objs[0]).toHaveProperty('id', '1');
+ expect(objs[1]).toHaveProperty('id', '2');
+ expect(objs[2]).toHaveProperty('id', '3');
+ expect(objs[3]).toHaveProperty('id', '4');
+ });
+
+ it('assigns ids relative to the other only item in the list', () => {
+ const objs = [{ id: '100' }, {}];
+ AggConfig.ensureIds(objs);
+ expect(objs[0]).toHaveProperty('id', '100');
+ expect(objs[1]).toHaveProperty('id', '101');
+ });
+
+ it('assigns ids relative to the other items in the list', () => {
+ const objs = [{ id: '100' }, { id: '200' }, { id: '500' }, { id: '350' }, {}];
+ AggConfig.ensureIds(objs);
+ expect(objs[0]).toHaveProperty('id', '100');
+ expect(objs[1]).toHaveProperty('id', '200');
+ expect(objs[2]).toHaveProperty('id', '500');
+ expect(objs[3]).toHaveProperty('id', '350');
+ expect(objs[4]).toHaveProperty('id', '501');
+ });
+
+ it('uses ::nextId to get the starting value', () => {
+ jest.spyOn(AggConfig, 'nextId').mockImplementation(() => 534);
+ const objs = AggConfig.ensureIds([{}]);
+ expect(objs[0]).toHaveProperty('id', '534');
+ });
+
+ it('only calls ::nextId once', () => {
+ const start = 420;
+ const spy = jest.spyOn(AggConfig, 'nextId').mockImplementation(() => start);
+ const objs = AggConfig.ensureIds([{}, {}, {}, {}, {}, {}, {}]);
+
+ expect(spy).toHaveBeenCalledTimes(1);
+ objs.forEach((obj, i) => {
+ expect(obj).toHaveProperty('id', String(start + i));
+ });
+ });
+ });
+
+ describe('::nextId', () => {
+ it('accepts a list of objects and picks the next id', () => {
+ const next = AggConfig.nextId([{ id: '100' }, { id: '500' }] as IAggConfig[]);
+ expect(next).toBe(501);
+ });
+
+ it('handles an empty list', () => {
+ const next = AggConfig.nextId([]);
+ expect(next).toBe(1);
+ });
+
+ it('fails when the list is not defined', () => {
+ expect(() => {
+ AggConfig.nextId((undefined as unknown) as IAggConfig[]);
+ }).toThrowError();
+ });
+ });
+
+ describe('#toJsonDataEquals', () => {
+ const testsIdentical = [
+ [
+ {
+ enabled: true,
+ type: 'count',
+ schema: 'metric',
+ params: { field: '@timestamp' },
+ },
+ ],
+ [
+ {
+ enabled: true,
+ type: 'avg',
+ schema: 'metric',
+ params: {},
+ },
+ {
+ enabled: true,
+ type: 'date_histogram',
+ schema: 'segment',
+ params: {},
+ },
+ ],
+ ];
+
+ testsIdentical.forEach((configState, index) => {
+ it(`identical aggregations (${index})`, () => {
+ const ac1 = new AggConfigs(indexPattern, configState, { typesRegistry });
+ const ac2 = new AggConfigs(indexPattern, configState, { typesRegistry });
+ expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true);
+ });
+ });
+
+ const testsIdenticalDifferentOrder = [
+ {
+ config1: [
+ {
+ enabled: true,
+ type: 'avg',
+ schema: 'metric',
+ params: {},
+ },
+ {
+ enabled: true,
+ type: 'date_histogram',
+ schema: 'segment',
+ params: {},
+ },
+ ],
+ config2: [
+ {
+ enabled: true,
+ schema: 'metric',
+ type: 'avg',
+ params: {},
+ },
+ {
+ enabled: true,
+ schema: 'segment',
+ type: 'date_histogram',
+ params: {},
+ },
+ ],
+ },
+ ];
+
+ testsIdenticalDifferentOrder.forEach((test, index) => {
+ it(`identical aggregations (${index}) - init json is in different order`, () => {
+ const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry });
+ const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry });
+ expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true);
+ });
+ });
+
+ const testsDifferent = [
+ {
+ config1: [
+ {
+ enabled: true,
+ type: 'avg',
+ schema: 'metric',
+ params: {},
+ },
+ {
+ enabled: true,
+ type: 'date_histogram',
+ schema: 'segment',
+ params: {},
+ },
+ ],
+ config2: [
+ {
+ enabled: true,
+ type: 'max',
+ schema: 'metric',
+ params: {},
+ },
+ {
+ enabled: true,
+ type: 'date_histogram',
+ schema: 'segment',
+ params: {},
+ },
+ ],
+ },
+ {
+ config1: [
+ {
+ enabled: true,
+ type: 'count',
+ schema: 'metric',
+ params: { field: '@timestamp' },
+ },
+ ],
+ config2: [
+ {
+ enabled: true,
+ type: 'count',
+ schema: 'metric',
+ params: { field: '@timestamp' },
+ },
+ {
+ enabled: true,
+ type: 'date_histogram',
+ schema: 'segment',
+ params: {},
+ },
+ ],
+ },
+ ];
+
+ testsDifferent.forEach((test, index) => {
+ it(`different aggregations (${index})`, () => {
+ const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry });
+ const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry });
+ expect(ac1.jsonDataEquals(ac2.aggs)).toBe(false);
+ });
+ });
+ });
+
+ describe('#toJSON', () => {
+ it('includes the aggs id, params, type and schema', () => {
+ const ac = new AggConfigs(indexPattern, [], { typesRegistry });
+ const configStates = {
+ enabled: true,
+ type: 'date_histogram',
+ schema: 'segment',
+ params: {},
+ };
+ const aggConfig = ac.createAggConfig(configStates);
+
+ expect(aggConfig.id).toBe('1');
+ expect(typeof aggConfig.params).toBe('object');
+ expect(aggConfig.type).toBeInstanceOf(AggType);
+ expect(aggConfig.type).toHaveProperty('name', 'date_histogram');
+ expect(typeof aggConfig.schema).toBe('object');
+ expect(aggConfig.schema).toHaveProperty('name', 'segment');
+
+ const state = aggConfig.toJSON();
+ expect(state).toHaveProperty('id', '1');
+ expect(typeof state.params).toBe('object');
+ expect(state).toHaveProperty('type', 'date_histogram');
+ expect(state).toHaveProperty('schema', 'segment');
+ });
+
+ it('test serialization order is identical (for visual consistency)', () => {
+ const configStates = [
+ {
+ enabled: true,
+ type: 'date_histogram',
+ schema: 'segment',
+ params: {},
+ },
+ ];
+ const ac1 = new AggConfigs(indexPattern, configStates, { typesRegistry });
+ const ac2 = new AggConfigs(indexPattern, configStates, { typesRegistry });
+
+ // this relies on the assumption that js-engines consistently loop over properties in insertion order.
+ // most likely the case, but strictly speaking not guaranteed by the JS and JSON specifications.
+ expect(JSON.stringify(ac1.aggs) === JSON.stringify(ac2.aggs)).toBe(true);
+ });
+ });
+
+ describe('#makeLabel', () => {
+ let aggConfig: AggConfig;
+
+ beforeEach(() => {
+ const ac = new AggConfigs(indexPattern, [], { typesRegistry });
+ aggConfig = ac.createAggConfig({ type: 'count' } as CreateAggConfigParams);
+ });
+
+ it('uses the custom label if it is defined', () => {
+ aggConfig.params.customLabel = 'Custom label';
+ const label = aggConfig.makeLabel();
+ expect(label).toBe(aggConfig.params.customLabel);
+ });
+
+ it('default label should be "Count"', () => {
+ const label = aggConfig.makeLabel();
+ expect(label).toBe('Count');
+ });
+
+ it('default label should be "Percentage of Count" when percentageMode is set to true', () => {
+ const label = aggConfig.makeLabel(true);
+ expect(label).toBe('Percentage of Count');
+ });
+
+ it('empty label if the type is not defined', () => {
+ aggConfig.type = (undefined as unknown) as AggType;
+ const label = aggConfig.makeLabel();
+ expect(label).toBe('');
+ });
+ });
+
+ describe('#fieldFormatter - custom getFormat handler', () => {
+ it('returns formatter from getFormat handler', () => {
+ setFieldFormats({
+ ...dataPluginMock.createStartContract().fieldFormats,
+ getDefaultInstance: jest.fn().mockImplementation(() => ({
+ getConverterFor: jest.fn().mockImplementation(() => (t: string) => t),
+ })) as any,
+ });
+
+ const ac = new AggConfigs(indexPattern, [], { typesRegistry });
+ const configStates = {
+ enabled: true,
+ type: 'count',
+ schema: 'metric',
+ params: { field: '@timestamp' },
+ };
+ const aggConfig = ac.createAggConfig(configStates);
+
+ const fieldFormatter = aggConfig.fieldFormatter();
+ expect(fieldFormatter).toBeDefined();
+ expect(fieldFormatter('text')).toBe('text');
+ });
+ });
+
+ // TODO: Converting these field formatter tests from browser tests to unit
+ // tests makes them much less helpful due to the extensive use of mocking.
+ // We should revisit these and rewrite them into something more useful.
+ describe('#fieldFormatter - no custom getFormat handler', () => {
+ let aggConfig: AggConfig;
+
+ beforeEach(() => {
+ setFieldFormats({
+ ...dataPluginMock.createStartContract().fieldFormats,
+ getDefaultInstance: jest.fn().mockImplementation(() => ({
+ getConverterFor: (t?: string) => t || identity,
+ })) as any,
+ });
+ indexPattern.fields.getByName = name =>
+ ({
+ format: {
+ getConverterFor: (t?: string) => t || identity,
+ },
+ } as IndexPatternField);
+
+ const configStates = {
+ enabled: true,
+ type: 'histogram',
+ schema: 'bucket',
+ params: {
+ field: {
+ format: {
+ getConverterFor: (t?: string) => t || identity,
+ },
+ },
+ },
+ };
+ const ac = new AggConfigs(indexPattern, [configStates], { typesRegistry });
+ aggConfig = ac.createAggConfig(configStates);
+ });
+
+ it("returns the field's formatter", () => {
+ expect(aggConfig.fieldFormatter().toString()).toBe(
+ aggConfig
+ .getField()
+ .format.getConverterFor()
+ .toString()
+ );
+ });
+
+ it('returns the string format if the field does not have a format', () => {
+ const agg = aggConfig;
+ agg.params.field = { type: 'number', format: null };
+ const fieldFormatter = agg.fieldFormatter();
+ expect(fieldFormatter).toBeDefined();
+ expect(fieldFormatter('text')).toBe('text');
+ });
+
+ it('returns the string format if there is no field', () => {
+ const agg = aggConfig;
+ delete agg.params.field;
+ const fieldFormatter = agg.fieldFormatter();
+ expect(fieldFormatter).toBeDefined();
+ expect(fieldFormatter('text')).toBe('text');
+ });
+
+ it('returns the html converter if "html" is passed in', () => {
+ const field = indexPattern.fields.getByName('bytes');
+ expect(aggConfig.fieldFormatter('html').toString()).toBe(
+ field!.format.getConverterFor('html').toString()
+ );
+ });
+ });
+});
diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_config.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_config.ts
index 2b21c5c4868a5..659bec3f702e3 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/agg_config.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/agg_config.ts
@@ -17,16 +17,8 @@
* under the License.
*/
-/**
- * @name AggConfig
- *
- * @description This class represents an aggregation, which is displayed in the left-hand nav of
- * the Visualize app.
- */
-
import _ from 'lodash';
import { i18n } from '@kbn/i18n';
-import { npStart } from 'ui/new_platform';
import { IAggType } from './agg_type';
import { AggGroupNames } from './agg_groups';
import { writeParams } from './agg_params';
@@ -38,18 +30,20 @@ import {
FieldFormatsContentType,
KBN_FIELD_TYPES,
} from '../../../../../../plugins/data/public';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { getFieldFormats } from '../../../../../../plugins/data/public/services';
export interface AggConfigOptions {
- enabled: boolean;
- type: string;
- params: any;
+ type: IAggType;
+ enabled?: boolean;
id?: string;
- schema?: string;
+ params?: Record;
+ schema?: string | Schema;
}
const unknownSchema: Schema = {
name: 'unknown',
- title: 'Unknown',
+ title: 'Unknown', // only here for illustrative purposes
hideCustomLabel: true,
aggFilter: [],
min: 1,
@@ -65,21 +59,6 @@ const unknownSchema: Schema = {
},
};
-const getTypeFromRegistry = (type: string): IAggType => {
- // We need to inline require here, since we're having a cyclic dependency
- // from somewhere inside agg_types back to AggConfig.
- const aggTypes = require('../aggs').aggTypes;
- const registeredType =
- aggTypes.metrics.find((agg: IAggType) => agg.name === type) ||
- aggTypes.buckets.find((agg: IAggType) => agg.name === type);
-
- if (!registeredType) {
- throw new Error('unknown type');
- }
-
- return registeredType;
-};
-
const getSchemaFromRegistry = (schemas: any, schema: string): Schema => {
let registeredSchema = schemas ? schemas.byName[schema] : null;
if (!registeredSchema) {
@@ -90,6 +69,13 @@ const getSchemaFromRegistry = (schemas: any, schema: string): Schema => {
return registeredSchema;
};
+/**
+ * @name AggConfig
+ *
+ * @description This class represents an aggregation, which is displayed in the left-hand nav of
+ * the Visualize app.
+ */
+
// TODO need to make a more explicit interface for this
export type IAggConfig = AggConfig;
@@ -101,9 +87,9 @@ export class AggConfig {
* @param {array[object]} list - a list of objects, objects can be anything really
* @return {array} - the list that was passed in
*/
- static ensureIds(list: AggConfig[]) {
- const have: AggConfig[] = [];
- const haveNot: AggConfig[] = [];
+ static ensureIds(list: any[]) {
+ const have: IAggConfig[] = [];
+ const haveNot: AggConfigOptions[] = [];
list.forEach(function(obj) {
(obj.id ? have : haveNot).push(obj);
});
@@ -121,7 +107,7 @@ export class AggConfig {
*
* @return {array} list - a list of objects with id properties
*/
- static nextId(list: AggConfig[]) {
+ static nextId(list: IAggConfig[]) {
return (
1 +
list.reduce(function(max, obj) {
@@ -161,10 +147,10 @@ export class AggConfig {
// set the params to the values from opts, or just to the defaults
this.setParams(opts.params || {});
- // @ts-ignore
- this.__type = this.__type;
// @ts-ignore
this.__schema = this.__schema;
+ // @ts-ignore
+ this.__type = this.__type;
}
/**
@@ -394,7 +380,8 @@ export class AggConfig {
}
fieldOwnFormatter(contentType?: FieldFormatsContentType, defaultFormat?: any) {
- const fieldFormatsService = npStart.plugins.data.fieldFormats;
+ const fieldFormatsService = getFieldFormats();
+
const field = this.getField();
let format = field && field.format;
if (!format) format = defaultFormat;
@@ -456,8 +443,8 @@ export class AggConfig {
});
}
- public setType(type: string | IAggType) {
- this.type = typeof type === 'string' ? getTypeFromRegistry(type) : type;
+ public setType(type: IAggType) {
+ this.type = type;
}
public get schema() {
diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_configs.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_configs.test.ts
new file mode 100644
index 0000000000000..29f16b1e4f0bf
--- /dev/null
+++ b/src/legacy/core_plugins/data/public/search/aggs/agg_configs.test.ts
@@ -0,0 +1,503 @@
+/*
+ * 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 { indexBy } from 'lodash';
+import { AggConfig } from './agg_config';
+import { AggConfigs } from './agg_configs';
+import { AggTypesRegistryStart } from './agg_types_registry';
+import { Schemas } from './schemas';
+import { AggGroupNames } from './agg_groups';
+import { mockDataServices, mockAggTypesRegistry } from './test_helpers';
+import { IndexPatternField, IndexPattern } from '../../../../../../plugins/data/public';
+import {
+ stubIndexPattern,
+ stubIndexPatternWithFields,
+ // eslint-disable-next-line @kbn/eslint/no-restricted-paths
+} from '../../../../../../plugins/data/public/stubs';
+
+describe('AggConfigs', () => {
+ let indexPattern: IndexPattern;
+ let typesRegistry: AggTypesRegistryStart;
+
+ beforeEach(() => {
+ indexPattern = stubIndexPatternWithFields as IndexPattern;
+ typesRegistry = mockAggTypesRegistry();
+ });
+
+ describe('constructor', () => {
+ it('handles passing just a type', () => {
+ const configStates = [
+ {
+ enabled: true,
+ type: 'histogram',
+ params: {},
+ },
+ ];
+
+ const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
+ expect(ac.aggs).toHaveLength(1);
+ });
+
+ it('attempts to ensure that all states have an id', () => {
+ const configStates = [
+ {
+ enabled: true,
+ type: 'histogram',
+ params: {},
+ },
+ {
+ enabled: true,
+ type: 'date_histogram',
+ params: {},
+ },
+ {
+ enabled: true,
+ type: 'terms',
+ params: {},
+ schema: 'split',
+ },
+ ];
+
+ const spy = jest.spyOn(AggConfig, 'ensureIds');
+ new AggConfigs(indexPattern, configStates, { typesRegistry });
+ expect(spy).toHaveBeenCalledTimes(1);
+ expect(spy.mock.calls[0]).toEqual([configStates]);
+ spy.mockRestore();
+ });
+
+ describe('defaults', () => {
+ const schemas = new Schemas([
+ {
+ group: AggGroupNames.Metrics,
+ name: 'metric',
+ title: 'Simple',
+ min: 1,
+ max: 2,
+ defaults: [
+ { schema: 'metric', type: 'count' },
+ { schema: 'metric', type: 'avg' },
+ { schema: 'metric', type: 'sum' },
+ ],
+ },
+ {
+ group: AggGroupNames.Buckets,
+ name: 'segment',
+ title: 'Example',
+ min: 0,
+ max: 1,
+ defaults: [
+ { schema: 'segment', type: 'terms' },
+ { schema: 'segment', type: 'filters' },
+ ],
+ },
+ ]);
+
+ it('should only set the number of defaults defined by the max', () => {
+ const ac = new AggConfigs(indexPattern, [], {
+ schemas: schemas.all,
+ typesRegistry,
+ });
+ expect(ac.bySchemaName('metric')).toHaveLength(2);
+ });
+
+ it('should set the defaults defined in the schema when none exist', () => {
+ const ac = new AggConfigs(indexPattern, [], {
+ schemas: schemas.all,
+ typesRegistry,
+ });
+ expect(ac.aggs).toHaveLength(3);
+ });
+
+ it('should NOT set the defaults defined in the schema when some exist', () => {
+ const configStates = [
+ {
+ enabled: true,
+ type: 'date_histogram',
+ params: {},
+ schema: 'segment',
+ },
+ ];
+ const ac = new AggConfigs(indexPattern, configStates, {
+ schemas: schemas.all,
+ typesRegistry,
+ });
+ expect(ac.aggs).toHaveLength(3);
+ expect(ac.bySchemaName('segment')[0].type.name).toEqual('date_histogram');
+ });
+ });
+ });
+
+ describe('#createAggConfig', () => {
+ it('accepts a configState which is provided as an AggConfig object', () => {
+ const configStates = [
+ {
+ enabled: true,
+ type: 'histogram',
+ params: {},
+ },
+ {
+ enabled: true,
+ type: 'date_histogram',
+ params: {},
+ },
+ ];
+
+ const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
+ expect(ac.aggs).toHaveLength(2);
+
+ ac.createAggConfig(
+ new AggConfig(ac, {
+ enabled: true,
+ type: typesRegistry.get('terms'),
+ params: {},
+ schema: 'split',
+ })
+ );
+ expect(ac.aggs).toHaveLength(3);
+ });
+
+ it('adds new AggConfig entries to AggConfigs by default', () => {
+ const configStates = [
+ {
+ enabled: true,
+ type: 'histogram',
+ params: {},
+ },
+ ];
+
+ const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
+ expect(ac.aggs).toHaveLength(1);
+
+ ac.createAggConfig({
+ enabled: true,
+ type: 'terms',
+ params: {},
+ schema: 'split',
+ });
+ expect(ac.aggs).toHaveLength(2);
+ });
+
+ it('does not add an agg to AggConfigs if addToAggConfigs: false', () => {
+ const configStates = [
+ {
+ enabled: true,
+ type: 'histogram',
+ params: {},
+ },
+ ];
+
+ const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
+ expect(ac.aggs).toHaveLength(1);
+
+ ac.createAggConfig(
+ {
+ enabled: true,
+ type: 'terms',
+ params: {},
+ schema: 'split',
+ },
+ { addToAggConfigs: false }
+ );
+ expect(ac.aggs).toHaveLength(1);
+ });
+ });
+
+ describe('#getRequestAggs', () => {
+ it('performs a stable sort, but moves metrics to the bottom', () => {
+ const configStates = [
+ { type: 'avg', enabled: true, params: {}, schema: 'metric' },
+ { type: 'terms', enabled: true, params: {}, schema: 'split' },
+ { type: 'histogram', enabled: true, params: {}, schema: 'split' },
+ { type: 'sum', enabled: true, params: {}, schema: 'metric' },
+ { type: 'date_histogram', enabled: true, params: {}, schema: 'segment' },
+ { type: 'filters', enabled: true, params: {}, schema: 'split' },
+ { type: 'percentiles', enabled: true, params: {}, schema: 'metric' },
+ ];
+
+ const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
+ const sorted = ac.getRequestAggs();
+ const aggs = indexBy(ac.aggs, agg => agg.type.name);
+
+ expect(sorted.shift()).toBe(aggs.terms);
+ expect(sorted.shift()).toBe(aggs.histogram);
+ expect(sorted.shift()).toBe(aggs.date_histogram);
+ expect(sorted.shift()).toBe(aggs.filters);
+ expect(sorted.shift()).toBe(aggs.avg);
+ expect(sorted.shift()).toBe(aggs.sum);
+ expect(sorted.shift()).toBe(aggs.percentiles);
+ expect(sorted).toHaveLength(0);
+ });
+ });
+
+ describe('#getResponseAggs', () => {
+ it('returns all request aggs for basic aggs', () => {
+ const configStates = [
+ { type: 'terms', enabled: true, params: {}, schema: 'split' },
+ { type: 'date_histogram', enabled: true, params: {}, schema: 'segment' },
+ { type: 'count', enabled: true, params: {}, schema: 'metric' },
+ ];
+
+ const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
+ const sorted = ac.getResponseAggs();
+ const aggs = indexBy(ac.aggs, agg => agg.type.name);
+
+ expect(sorted.shift()).toBe(aggs.terms);
+ expect(sorted.shift()).toBe(aggs.date_histogram);
+ expect(sorted.shift()).toBe(aggs.count);
+ expect(sorted).toHaveLength(0);
+ });
+
+ it('expands aggs that have multiple responses', () => {
+ const configStates = [
+ { type: 'terms', enabled: true, params: {}, schema: 'split' },
+ { type: 'date_histogram', enabled: true, params: {}, schema: 'segment' },
+ { type: 'percentiles', enabled: true, params: { percents: [1, 2, 3] }, schema: 'metric' },
+ ];
+
+ const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
+ const sorted = ac.getResponseAggs();
+ const aggs = indexBy(ac.aggs, agg => agg.type.name);
+
+ expect(sorted.shift()).toBe(aggs.terms);
+ expect(sorted.shift()).toBe(aggs.date_histogram);
+ expect(sorted.shift()!.id!).toBe(aggs.percentiles.id + '.' + 1);
+ expect(sorted.shift()!.id!).toBe(aggs.percentiles.id + '.' + 2);
+ expect(sorted.shift()!.id!).toBe(aggs.percentiles.id + '.' + 3);
+ expect(sorted).toHaveLength(0);
+ });
+ });
+
+ describe('#toDsl', () => {
+ const schemas = new Schemas([
+ {
+ group: AggGroupNames.Buckets,
+ name: 'segment',
+ },
+ {
+ group: AggGroupNames.Buckets,
+ name: 'split',
+ },
+ ]);
+
+ beforeEach(() => {
+ mockDataServices();
+ indexPattern = stubIndexPattern as IndexPattern;
+ indexPattern.fields.getByName = name => (name as unknown) as IndexPatternField;
+ });
+
+ it('uses the sorted aggs', () => {
+ const configStates = [{ enabled: true, type: 'avg', params: { field: 'bytes' } }];
+ const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
+ const spy = jest.spyOn(AggConfigs.prototype, 'getRequestAggs');
+ ac.toDsl();
+ expect(spy).toHaveBeenCalledTimes(1);
+ spy.mockRestore();
+ });
+
+ it('calls aggConfig#toDsl() on each aggConfig and compiles the nested output', () => {
+ const configStates = [
+ { enabled: true, type: 'date_histogram', params: {}, schema: 'segment' },
+ { enabled: true, type: 'terms', params: {}, schema: 'split' },
+ { enabled: true, type: 'count', params: {} },
+ ];
+
+ const ac = new AggConfigs(indexPattern, configStates, {
+ typesRegistry,
+ schemas: schemas.all,
+ });
+
+ const aggInfos = ac.aggs.map(aggConfig => {
+ const football = {};
+ aggConfig.toDsl = jest.fn().mockImplementation(() => football);
+
+ return {
+ id: aggConfig.id,
+ football,
+ };
+ });
+
+ (function recurse(lvl: Record): void {
+ const info = aggInfos.shift();
+ if (!info) return;
+
+ expect(lvl).toHaveProperty(info.id);
+ expect(lvl[info.id]).toBe(info.football);
+
+ if (lvl[info.id].aggs) {
+ return recurse(lvl[info.id].aggs);
+ }
+ })(ac.toDsl());
+
+ expect(aggInfos).toHaveLength(1);
+ });
+
+ it("skips aggs that don't have a dsl representation", () => {
+ const configStates = [
+ {
+ enabled: true,
+ type: 'date_histogram',
+ params: { field: '@timestamp', interval: '10s' },
+ schema: 'segment',
+ },
+ {
+ enabled: true,
+ type: 'count',
+ params: {},
+ schema: 'metric',
+ },
+ ];
+
+ const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
+ const dsl = ac.toDsl();
+ const histo = ac.byName('date_histogram')[0];
+ const count = ac.byName('count')[0];
+
+ expect(dsl).toHaveProperty(histo.id);
+ expect(typeof dsl[histo.id]).toBe('object');
+ expect(dsl[histo.id]).not.toHaveProperty('aggs');
+ expect(dsl).not.toHaveProperty(count.id);
+ });
+
+ it('writes multiple metric aggregations at the same level', () => {
+ const configStates = [
+ {
+ enabled: true,
+ type: 'date_histogram',
+ schema: 'segment',
+ params: { field: '@timestamp', interval: '10s' },
+ },
+ { enabled: true, type: 'avg', schema: 'metric', params: { field: 'bytes' } },
+ { enabled: true, type: 'sum', schema: 'metric', params: { field: 'bytes' } },
+ { enabled: true, type: 'min', schema: 'metric', params: { field: 'bytes' } },
+ { enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } },
+ ];
+
+ const ac = new AggConfigs(indexPattern, configStates, {
+ typesRegistry,
+ schemas: schemas.all,
+ });
+ const dsl = ac.toDsl();
+ const histo = ac.byName('date_histogram')[0];
+ const metrics = ac.bySchemaGroup('metrics');
+
+ expect(dsl).toHaveProperty(histo.id);
+ expect(typeof dsl[histo.id]).toBe('object');
+ expect(dsl[histo.id]).toHaveProperty('aggs');
+
+ metrics.forEach(metric => {
+ expect(dsl[histo.id].aggs).toHaveProperty(metric.id);
+ expect(dsl[histo.id].aggs[metric.id]).not.toHaveProperty('aggs');
+ });
+ });
+
+ it('writes multiple metric aggregations at every level if the vis is hierarchical', () => {
+ const configStates = [
+ { enabled: true, type: 'terms', schema: 'segment', params: { field: 'bytes', orderBy: 1 } },
+ { enabled: true, type: 'terms', schema: 'segment', params: { field: 'bytes', orderBy: 1 } },
+ { enabled: true, id: '1', type: 'avg', schema: 'metric', params: { field: 'bytes' } },
+ { enabled: true, type: 'sum', schema: 'metric', params: { field: 'bytes' } },
+ { enabled: true, type: 'min', schema: 'metric', params: { field: 'bytes' } },
+ { enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } },
+ ];
+
+ const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
+ const topLevelDsl = ac.toDsl(true);
+ const buckets = ac.bySchemaGroup('buckets');
+ const metrics = ac.bySchemaGroup('metrics');
+
+ (function checkLevel(dsl) {
+ const bucket = buckets.shift();
+ if (!bucket) return;
+
+ expect(dsl).toHaveProperty(bucket.id);
+
+ expect(typeof dsl[bucket.id]).toBe('object');
+ expect(dsl[bucket.id]).toHaveProperty('aggs');
+
+ metrics.forEach((metric: AggConfig) => {
+ expect(dsl[bucket.id].aggs).toHaveProperty(metric.id);
+ expect(dsl[bucket.id].aggs[metric.id]).not.toHaveProperty('aggs');
+ });
+
+ if (buckets.length) {
+ checkLevel(dsl[bucket.id].aggs);
+ }
+ })(topLevelDsl);
+ });
+
+ it('adds the parent aggs of nested metrics at every level if the vis is hierarchical', () => {
+ const configStates = [
+ {
+ enabled: true,
+ id: '1',
+ type: 'avg_bucket',
+ schema: 'metric',
+ params: {
+ customBucket: {
+ id: '1-bucket',
+ type: 'date_histogram',
+ schema: 'bucketAgg',
+ params: {
+ field: '@timestamp',
+ interval: '10s',
+ },
+ },
+ customMetric: {
+ id: '1-metric',
+ type: 'count',
+ schema: 'metricAgg',
+ params: {},
+ },
+ },
+ },
+ {
+ enabled: true,
+ id: '2',
+ type: 'terms',
+ schema: 'bucket',
+ params: {
+ field: 'clientip',
+ },
+ },
+ {
+ enabled: true,
+ id: '3',
+ type: 'terms',
+ schema: 'bucket',
+ params: {
+ field: 'machine.os.raw',
+ },
+ },
+ ];
+
+ const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
+ const topLevelDsl = ac.toDsl(true)['2'];
+
+ expect(Object.keys(topLevelDsl.aggs)).toContain('1');
+ expect(Object.keys(topLevelDsl.aggs)).toContain('1-bucket');
+ expect(topLevelDsl.aggs['1'].avg_bucket).toHaveProperty('buckets_path', '1-bucket>_count');
+ expect(Object.keys(topLevelDsl.aggs['3'].aggs)).toContain('1');
+ expect(Object.keys(topLevelDsl.aggs['3'].aggs)).toContain('1-bucket');
+ expect(topLevelDsl.aggs['3'].aggs['1'].avg_bucket).toHaveProperty(
+ 'buckets_path',
+ '1-bucket>_count'
+ );
+ });
+ });
+});
diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_configs.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_configs.ts
index 8e091ed5f21ae..ab70e66b1e138 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/agg_configs.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/agg_configs.ts
@@ -17,17 +17,12 @@
* under the License.
*/
-/**
- * @name AggConfig
- *
- * @extends IndexedArray
- *
- * @description A "data structure"-like class with methods for indexing and
- * accessing instances of AggConfig.
- */
-
import _ from 'lodash';
+import { Assign } from '@kbn/utility-types';
+
import { AggConfig, AggConfigOptions, IAggConfig } from './agg_config';
+import { IAggType } from './agg_type';
+import { AggTypesRegistryStart } from './agg_types_registry';
import { Schema } from './schemas';
import { AggGroupNames } from './agg_groups';
import {
@@ -55,6 +50,24 @@ function parseParentAggs(dslLvlCursor: any, dsl: any) {
}
}
+export interface AggConfigsOptions {
+ schemas?: Schemas;
+ typesRegistry: AggTypesRegistryStart;
+}
+
+export type CreateAggConfigParams = Assign;
+
+/**
+ * @name AggConfigs
+ *
+ * @description A "data structure"-like class with methods for indexing and
+ * accessing instances of AggConfig. This should never be instantiated directly
+ * outside of this plugin. Rather, downstream plugins should do this via
+ * `createAggConfigs()`
+ *
+ * @internal
+ */
+
// TODO need to make a more explicit interface for this
export type IAggConfigs = AggConfigs;
@@ -62,23 +75,31 @@ export class AggConfigs {
public indexPattern: IndexPattern;
public schemas: any;
public timeRange?: TimeRange;
+ private readonly typesRegistry: AggTypesRegistryStart;
aggs: IAggConfig[];
- constructor(indexPattern: IndexPattern, configStates = [] as any, schemas?: any) {
+ constructor(
+ indexPattern: IndexPattern,
+ configStates: CreateAggConfigParams[] = [],
+ opts: AggConfigsOptions
+ ) {
+ this.typesRegistry = opts.typesRegistry;
+
configStates = AggConfig.ensureIds(configStates);
this.aggs = [];
this.indexPattern = indexPattern;
- this.schemas = schemas;
+ this.schemas = opts.schemas;
configStates.forEach((params: any) => this.createAggConfig(params));
- if (schemas) {
- this.initializeDefaultsFromSchemas(schemas);
+ if (this.schemas) {
+ this.initializeDefaultsFromSchemas(this.schemas);
}
}
+ // do this wherever the schemas were passed in, & pass in state defaults instead
initializeDefaultsFromSchemas(schemas: Schemas) {
// Set the defaults for any schema which has them. If the defaults
// for some reason has more then the max only set the max number
@@ -91,10 +112,11 @@ export class AggConfigs {
})
.each((schema: any) => {
if (!this.aggs.find((agg: AggConfig) => agg.schema && agg.schema.name === schema.name)) {
+ // the result here should be passable as a configState
const defaults = schema.defaults.slice(0, schema.max);
_.each(defaults, defaultState => {
const state = _.defaults({ id: AggConfig.nextId(this.aggs) }, defaultState);
- this.aggs.push(new AggConfig(this, state as AggConfigOptions));
+ this.createAggConfig(state as AggConfigOptions);
});
}
})
@@ -124,28 +146,36 @@ export class AggConfigs {
if (!enabledOnly) return true;
return agg.enabled;
};
- const aggConfigs = new AggConfigs(
- this.indexPattern,
- this.aggs.filter(filterAggs),
- this.schemas
- );
+
+ const aggConfigs = new AggConfigs(this.indexPattern, this.aggs.filter(filterAggs), {
+ schemas: this.schemas,
+ typesRegistry: this.typesRegistry,
+ });
+
return aggConfigs;
}
createAggConfig = (
- params: AggConfig | AggConfigOptions,
+ params: CreateAggConfigParams,
{ addToAggConfigs = true } = {}
) => {
+ const { type } = params;
let aggConfig;
+
if (params instanceof AggConfig) {
aggConfig = params;
params.parent = this;
} else {
- aggConfig = new AggConfig(this, params);
+ aggConfig = new AggConfig(this, {
+ ...params,
+ type: typeof type === 'string' ? this.typesRegistry.get(type) : type,
+ });
}
+
if (addToAggConfigs) {
this.aggs.push(aggConfig);
}
+
return aggConfig as T;
};
@@ -166,10 +196,10 @@ export class AggConfigs {
return true;
}
- toDsl(hierarchical: boolean = false) {
+ toDsl(hierarchical: boolean = false): Record {
const dslTopLvl = {};
let dslLvlCursor: Record;
- let nestedMetrics: Array<{ config: AggConfig; dsl: any }> | [];
+ let nestedMetrics: Array<{ config: AggConfig; dsl: Record }> | [];
if (hierarchical) {
// collect all metrics, and filter out the ones that we won't be copying
diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_params.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_params.test.ts
index 30ab272537dad..b08fcf309e9ed 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/agg_params.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/agg_params.test.ts
@@ -23,8 +23,6 @@ import { FieldParamType } from './param_types/field';
import { OptionedParamType } from './param_types/optioned';
import { AggParamType } from '../aggs/param_types/agg';
-jest.mock('ui/new_platform');
-
describe('AggParams class', () => {
describe('constructor args', () => {
it('accepts an array of param defs', () => {
diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_type.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_type.test.ts
index 6d4c2d1317f50..c78e56dd25887 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/agg_type.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/agg_type.test.ts
@@ -19,11 +19,16 @@
import { AggType, AggTypeConfig } from './agg_type';
import { IAggConfig } from './agg_config';
-import { npStart } from 'ui/new_platform';
-
-jest.mock('ui/new_platform');
+import { mockDataServices } from './test_helpers';
+import { dataPluginMock } from '../../../../../../plugins/data/public/mocks';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { setFieldFormats } from '../../../../../../plugins/data/public/services';
describe('AggType Class', () => {
+ beforeEach(() => {
+ mockDataServices();
+ });
+
describe('constructor', () => {
it("requires a valid config object as it's first param", () => {
expect(() => {
@@ -153,7 +158,10 @@ describe('AggType Class', () => {
});
it('returns default formatter', () => {
- npStart.plugins.data.fieldFormats.getDefaultInstance = jest.fn(() => 'default') as any;
+ setFieldFormats({
+ ...dataPluginMock.createStartContract().fieldFormats,
+ getDefaultInstance: jest.fn(() => 'default') as any,
+ });
const aggType = new AggType({
name: 'name',
diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_type.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_type.ts
index 5ccf0f65c0e92..3cd9496d3f23d 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/agg_type.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/agg_type.ts
@@ -19,7 +19,6 @@
import { constant, noop, identity } from 'lodash';
import { i18n } from '@kbn/i18n';
-import { npStart } from 'ui/new_platform';
import { initParams } from './agg_params';
import { AggConfig } from './agg_config';
@@ -32,6 +31,8 @@ import {
IFieldFormat,
ISearchSource,
} from '../../../../../../plugins/data/public';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { getFieldFormats } from '../../../../../../plugins/data/public/services';
export interface AggTypeConfig<
TAggConfig extends AggConfig = AggConfig,
@@ -65,7 +66,7 @@ export interface AggTypeConfig<
const getFormat = (agg: AggConfig) => {
const field = agg.getField();
- const fieldFormatsService = npStart.plugins.data.fieldFormats;
+ const fieldFormatsService = getFieldFormats();
return field ? field.format : fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.STRING);
};
diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.test.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.test.ts
new file mode 100644
index 0000000000000..405f83e237de8
--- /dev/null
+++ b/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.test.ts
@@ -0,0 +1,91 @@
+/*
+ * 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 {
+ AggTypesRegistry,
+ AggTypesRegistrySetup,
+ AggTypesRegistryStart,
+} from './agg_types_registry';
+import { BucketAggType } from './buckets/_bucket_agg_type';
+import { MetricAggType } from './metrics/metric_agg_type';
+
+const bucketType = { name: 'terms', type: 'bucket' } as BucketAggType;
+const metricType = { name: 'count', type: 'metric' } as MetricAggType;
+
+describe('AggTypesRegistry', () => {
+ let registry: AggTypesRegistry;
+ let setup: AggTypesRegistrySetup;
+ let start: AggTypesRegistryStart;
+
+ beforeEach(() => {
+ registry = new AggTypesRegistry();
+ setup = registry.setup();
+ start = registry.start();
+ });
+
+ it('registerBucket adds new buckets', () => {
+ setup.registerBucket(bucketType);
+ expect(start.getBuckets()).toEqual([bucketType]);
+ });
+
+ it('registerBucket throws error when registering duplicate bucket', () => {
+ expect(() => {
+ setup.registerBucket(bucketType);
+ setup.registerBucket(bucketType);
+ }).toThrow(/already been registered with name: terms/);
+ });
+
+ it('registerMetric adds new metrics', () => {
+ setup.registerMetric(metricType);
+ expect(start.getMetrics()).toEqual([metricType]);
+ });
+
+ it('registerMetric throws error when registering duplicate metric', () => {
+ expect(() => {
+ setup.registerMetric(metricType);
+ setup.registerMetric(metricType);
+ }).toThrow(/already been registered with name: count/);
+ });
+
+ it('gets either buckets or metrics by id', () => {
+ setup.registerBucket(bucketType);
+ setup.registerMetric(metricType);
+ expect(start.get('terms')).toEqual(bucketType);
+ expect(start.get('count')).toEqual(metricType);
+ });
+
+ it('getBuckets retrieves only buckets', () => {
+ setup.registerBucket(bucketType);
+ expect(start.getBuckets()).toEqual([bucketType]);
+ });
+
+ it('getMetrics retrieves only metrics', () => {
+ setup.registerMetric(metricType);
+ expect(start.getMetrics()).toEqual([metricType]);
+ });
+
+ it('getAll returns all buckets and metrics', () => {
+ setup.registerBucket(bucketType);
+ setup.registerMetric(metricType);
+ expect(start.getAll()).toEqual({
+ buckets: [bucketType],
+ metrics: [metricType],
+ });
+ });
+});
diff --git a/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.ts b/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.ts
new file mode 100644
index 0000000000000..8a8746106ae58
--- /dev/null
+++ b/src/legacy/core_plugins/data/public/search/aggs/agg_types_registry.ts
@@ -0,0 +1,68 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { BucketAggType } from './buckets/_bucket_agg_type';
+import { MetricAggType } from './metrics/metric_agg_type';
+
+export type AggTypesRegistrySetup = ReturnType;
+export type AggTypesRegistryStart = ReturnType;
+
+export class AggTypesRegistry {
+ private readonly bucketAggs = new Map();
+ private readonly metricAggs = new Map();
+
+ setup = () => {
+ return {
+ registerBucket: >(type: T): void => {
+ const { name } = type;
+ if (this.bucketAggs.get(name)) {
+ throw new Error(`Bucket agg has already been registered with name: ${name}`);
+ }
+ this.bucketAggs.set(name, type);
+ },
+ registerMetric: >(type: T): void => {
+ const { name } = type;
+ if (this.metricAggs.get(name)) {
+ throw new Error(`Metric agg has already been registered with name: ${name}`);
+ }
+ this.metricAggs.set(name, type);
+ },
+ };
+ };
+
+ start = () => {
+ return {
+ get: (name: string) => {
+ return this.bucketAggs.get(name) || this.metricAggs.get(name);
+ },
+ getBuckets: () => {
+ return Array.from(this.bucketAggs.values());
+ },
+ getMetrics: () => {
+ return Array.from(this.metricAggs.values());
+ },
+ getAll: () => {
+ return {
+ buckets: Array.from(this.bucketAggs.values()),
+ metrics: Array.from(this.metricAggs.values()),
+ };
+ },
+ };
+ };
+}
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/_bucket_agg_type.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/_bucket_agg_type.ts
index 546d054c5af97..d6ab58d5250a8 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/_bucket_agg_type.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/_bucket_agg_type.ts
@@ -17,16 +17,16 @@
* under the License.
*/
-import { AggConfig } from '../agg_config';
+import { IAggConfig } from '../agg_config';
import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public';
import { AggType, AggTypeConfig } from '../agg_type';
import { AggParamType } from '../param_types/agg';
-export interface IBucketAggConfig extends AggConfig {
+export interface IBucketAggConfig extends IAggConfig {
type: InstanceType;
}
-export interface BucketAggParam
+export interface BucketAggParam
extends AggParamType {
scriptable?: boolean;
filterFieldTypes?: KBN_FIELD_TYPES | KBN_FIELD_TYPES[] | '*';
@@ -34,12 +34,12 @@ export interface BucketAggParam
const bucketType = 'buckets';
-interface BucketAggTypeConfig
+interface BucketAggTypeConfig
extends AggTypeConfig> {
- getKey?: (bucket: any, key: any, agg: AggConfig) => any;
+ getKey?: (bucket: any, key: any, agg: IAggConfig) => any;
}
-export class BucketAggType extends AggType<
+export class BucketAggType extends AggType<
TBucketAggConfig,
BucketAggParam
> {
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/_interval_options.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/_interval_options.ts
index e196687607d19..393d3b745250f 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/_interval_options.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/_interval_options.ts
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
+
import { i18n } from '@kbn/i18n';
import { IBucketAggConfig } from './_bucket_agg_type';
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts
index 0d3f58c50a42e..2b47dc384bca2 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_histogram.test.ts
@@ -21,14 +21,22 @@ import moment from 'moment';
import { createFilterDateHistogram } from './date_histogram';
import { intervalOptions } from '../_interval_options';
import { AggConfigs } from '../../agg_configs';
-import { IBucketDateHistogramAggConfig } from '../date_histogram';
+import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers';
+import { dateHistogramBucketAgg, IBucketDateHistogramAggConfig } from '../date_histogram';
import { BUCKET_TYPES } from '../bucket_agg_types';
import { RangeFilter } from '../../../../../../../../plugins/data/public';
+// TODO: remove this once time buckets is migrated
jest.mock('ui/new_platform');
describe('AggConfig Filters', () => {
describe('date_histogram', () => {
+ beforeEach(() => {
+ mockDataServices();
+ });
+
+ const typesRegistry = mockAggTypesRegistry([dateHistogramBucketAgg]);
+
let agg: IBucketDateHistogramAggConfig;
let filter: RangeFilter;
let bucketStart: any;
@@ -56,7 +64,7 @@ describe('AggConfig Filters', () => {
params: { field: field.name, interval, customInterval: '5d' },
},
],
- null
+ { typesRegistry }
);
const bucketKey = 1422579600000;
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts
index 41e806668337e..c594c7718e58b 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/date_range.test.ts
@@ -18,16 +18,17 @@
*/
import moment from 'moment';
+import { dateRangeBucketAgg } from '../date_range';
import { createFilterDateRange } from './date_range';
import { fieldFormats, FieldFormatsGetConfigFn } from '../../../../../../../../plugins/data/public';
import { AggConfigs } from '../../agg_configs';
+import { mockAggTypesRegistry } from '../../test_helpers';
import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../_bucket_agg_type';
-jest.mock('ui/new_platform');
-
describe('AggConfig Filters', () => {
describe('Date range', () => {
+ const typesRegistry = mockAggTypesRegistry([dateRangeBucketAgg]);
const getConfig = (() => {}) as FieldFormatsGetConfigFn;
const getAggConfigs = () => {
const field = {
@@ -55,7 +56,7 @@ describe('AggConfig Filters', () => {
},
},
],
- null
+ { typesRegistry }
);
};
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts
index 34cf996826865..3b9c771e0f15f 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/filters.test.ts
@@ -16,14 +16,21 @@
* specific language governing permissions and limitations
* under the License.
*/
+
+import { filtersBucketAgg } from '../filters';
import { createFilterFilters } from './filters';
import { AggConfigs } from '../../agg_configs';
+import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers';
import { IBucketAggConfig } from '../_bucket_agg_type';
-jest.mock('ui/new_platform');
-
describe('AggConfig Filters', () => {
describe('filters', () => {
+ beforeEach(() => {
+ mockDataServices();
+ });
+
+ const typesRegistry = mockAggTypesRegistry([filtersBucketAgg]);
+
const getAggConfigs = () => {
const field = {
name: 'bytes',
@@ -52,7 +59,7 @@ describe('AggConfig Filters', () => {
},
},
],
- null
+ { typesRegistry }
);
};
it('should return a filters filter', () => {
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts
index 9f845847df5d9..b046c802c58c1 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/histogram.test.ts
@@ -16,16 +16,22 @@
* specific language governing permissions and limitations
* under the License.
*/
+
import { createFilterHistogram } from './histogram';
import { AggConfigs } from '../../agg_configs';
+import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers';
import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../_bucket_agg_type';
import { fieldFormats, FieldFormatsGetConfigFn } from '../../../../../../../../plugins/data/public';
-jest.mock('ui/new_platform');
-
describe('AggConfig Filters', () => {
describe('histogram', () => {
+ beforeEach(() => {
+ mockDataServices();
+ });
+
+ const typesRegistry = mockAggTypesRegistry();
+
const getConfig = (() => {}) as FieldFormatsGetConfigFn;
const getAggConfigs = () => {
const field = {
@@ -55,7 +61,7 @@ describe('AggConfig Filters', () => {
},
},
],
- null
+ { typesRegistry }
);
};
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts
index e92ba5cb2852a..7572c48390dc2 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/ip_range.test.ts
@@ -17,17 +17,18 @@
* under the License.
*/
+import { ipRangeBucketAgg } from '../ip_range';
import { createFilterIpRange } from './ip_range';
-import { AggConfigs } from '../../agg_configs';
+import { AggConfigs, CreateAggConfigParams } from '../../agg_configs';
+import { mockAggTypesRegistry } from '../../test_helpers';
import { fieldFormats } from '../../../../../../../../plugins/data/public';
import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../_bucket_agg_type';
-jest.mock('ui/new_platform');
-
describe('AggConfig Filters', () => {
describe('IP range', () => {
- const getAggConfigs = (aggs: Array>) => {
+ const typesRegistry = mockAggTypesRegistry([ipRangeBucketAgg]);
+ const getAggConfigs = (aggs: CreateAggConfigParams[]) => {
const field = {
name: 'ip',
format: fieldFormats.IpFormat,
@@ -42,7 +43,7 @@ describe('AggConfig Filters', () => {
},
} as any;
- return new AggConfigs(indexPattern, aggs, null);
+ return new AggConfigs(indexPattern, aggs, { typesRegistry });
};
it('should return a range filter for ip_range agg', () => {
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/range.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/range.test.ts
index 33344ca0a3484..324d425290832 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/range.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/range.test.ts
@@ -17,16 +17,22 @@
* under the License.
*/
+import { rangeBucketAgg } from '../range';
import { createFilterRange } from './range';
import { fieldFormats, FieldFormatsGetConfigFn } from '../../../../../../../../plugins/data/public';
import { AggConfigs } from '../../agg_configs';
+import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers';
import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../_bucket_agg_type';
-jest.mock('ui/new_platform');
-
describe('AggConfig Filters', () => {
describe('range', () => {
+ beforeEach(() => {
+ mockDataServices();
+ });
+
+ const typesRegistry = mockAggTypesRegistry([rangeBucketAgg]);
+
const getConfig = (() => {}) as FieldFormatsGetConfigFn;
const getAggConfigs = () => {
const field = {
@@ -56,7 +62,7 @@ describe('AggConfig Filters', () => {
},
},
],
- null
+ { typesRegistry }
);
};
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts
index 7c6e769437ca1..6db6eb11a5f52 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/create_filter/terms.test.ts
@@ -17,17 +17,18 @@
* under the License.
*/
+import { termsBucketAgg } from '../terms';
import { createFilterTerms } from './terms';
-import { AggConfigs } from '../../agg_configs';
+import { AggConfigs, CreateAggConfigParams } from '../../agg_configs';
+import { mockAggTypesRegistry } from '../../test_helpers';
import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../_bucket_agg_type';
import { Filter, ExistsFilter } from '../../../../../../../../plugins/data/public';
-jest.mock('ui/new_platform');
-
describe('AggConfig Filters', () => {
describe('terms', () => {
- const getAggConfigs = (aggs: Array>) => {
+ const typesRegistry = mockAggTypesRegistry([termsBucketAgg]);
+ const getAggConfigs = (aggs: CreateAggConfigParams[]) => {
const indexPattern = {
id: '1234',
title: 'logstash-*',
@@ -42,7 +43,7 @@ describe('AggConfig Filters', () => {
indexPattern,
};
- return new AggConfigs(indexPattern, aggs, null);
+ return new AggConfigs(indexPattern, aggs, { typesRegistry });
};
it('should return a match_phrase filter for terms', () => {
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_histogram.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_histogram.ts
index dc0f9baa6d0cc..a5368135728d4 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_histogram.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_histogram.ts
@@ -21,8 +21,7 @@ import _ from 'lodash';
import moment from 'moment-timezone';
import { i18n } from '@kbn/i18n';
-import { npStart } from 'ui/new_platform';
-import { timefilter } from 'ui/timefilter';
+// TODO need to move TimeBuckets
import { TimeBuckets } from 'ui/time_buckets';
import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type';
import { BUCKET_TYPES } from './bucket_agg_types';
@@ -33,6 +32,8 @@ import { writeParams } from '../agg_params';
import { isMetricAggType } from '../metrics/metric_agg_type';
import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { getQueryService, getUiSettings } from '../../../../../../../plugins/data/public/services';
const detectedTimezone = moment.tz.guess();
const tzOffset = moment().format('Z');
@@ -40,6 +41,7 @@ const tzOffset = moment().format('Z');
const getInterval = (agg: IBucketAggConfig): string => _.get(agg, ['params', 'interval']);
export const setBounds = (agg: IBucketDateHistogramAggConfig, force?: boolean) => {
+ const { timefilter } = getQueryService().timefilter;
if (agg.buckets._alreadySet && !force) return;
agg.buckets._alreadySet = true;
const bounds = agg.params.timeRange ? timefilter.calculateBounds(agg.params.timeRange) : null;
@@ -221,7 +223,7 @@ export const dateHistogramBucketAgg = new BucketAggType {
+ beforeEach(() => {
+ mockDataServices();
+ });
+
+ const typesRegistry = mockAggTypesRegistry([dateRangeBucketAgg]);
+
const getAggConfigs = (params: Record = {}, hasIncludeTypeMeta: boolean = true) => {
const field = {
name: 'bytes',
@@ -58,7 +67,7 @@ describe('date_range params', () => {
params,
},
],
- null
+ { typesRegistry }
);
};
@@ -95,7 +104,11 @@ describe('date_range params', () => {
});
it('should use the Kibana time_zone if no parameter specified', () => {
- npStart.core.uiSettings.get = jest.fn(() => 'kibanaTimeZone' as any);
+ const core = coreMock.createStart();
+ setUiSettings({
+ ...core.uiSettings,
+ get: () => 'kibanaTimeZone' as any,
+ });
const aggConfigs = getAggConfigs(
{
@@ -106,6 +119,8 @@ describe('date_range params', () => {
const dateRange = aggConfigs.aggs[0];
const params = dateRange.toDsl()[BUCKET_TYPES.DATE_RANGE];
+ setUiSettings(core.uiSettings); // clean up
+
expect(params.time_zone).toBe('kibanaTimeZone');
});
});
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts
index 1dc24ca80035c..933cdd0577f8d 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/date_range.ts
@@ -16,18 +16,20 @@
* specific language governing permissions and limitations
* under the License.
*/
+
import { get } from 'lodash';
import moment from 'moment-timezone';
import { i18n } from '@kbn/i18n';
-import { npStart } from 'ui/new_platform';
-import { convertDateRangeToString, DateRangeKey } from './lib/date_range';
import { BUCKET_TYPES } from './bucket_agg_types';
import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type';
import { createFilterDateRange } from './create_filter/date_range';
import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../../../plugins/data/public';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { getFieldFormats, getUiSettings } from '../../../../../../../plugins/data/public/services';
-export { convertDateRangeToString, DateRangeKey };
+import { convertDateRangeToString, DateRangeKey } from './lib/date_range';
+export { convertDateRangeToString, DateRangeKey }; // for BWC
const dateRangeTitle = i18n.translate('data.search.aggs.buckets.dateRangeTitle', {
defaultMessage: 'Date Range',
@@ -41,7 +43,7 @@ export const dateRangeBucketAgg = new BucketAggType({
return { from, to };
},
getFormat(agg) {
- const fieldFormatsService = npStart.plugins.data.fieldFormats;
+ const fieldFormatsService = getFieldFormats();
const formatter = agg.fieldOwnFormatter(
fieldFormats.TEXT_CONTEXT_TYPE,
@@ -92,7 +94,7 @@ export const dateRangeBucketAgg = new BucketAggType({
]);
}
if (!tz) {
- const config = npStart.core.uiSettings;
+ const config = getUiSettings();
const detectedTimezone = moment.tz.guess();
const tzOffset = moment().format('Z');
const isDefaultTimezone = config.isDefault('dateFormat:tz');
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/filter.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/filter.ts
index b52e2d6cfd4df..80efc0cf92071 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/filter.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/filter.ts
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
+
import { i18n } from '@kbn/i18n';
import { BucketAggType } from './_bucket_agg_type';
import { BUCKET_TYPES } from './bucket_agg_types';
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/filters.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/filters.ts
index 6eaf788b83c04..2852f3e4bdf46 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/filters.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/filters.ts
@@ -18,19 +18,21 @@
*/
import _ from 'lodash';
-import angular from 'angular';
-
import { i18n } from '@kbn/i18n';
import chrome from 'ui/chrome';
+
import { createFilterFilters } from './create_filter/filters';
+import { toAngularJSON } from '../utils';
import { BucketAggType } from './_bucket_agg_type';
+import { BUCKET_TYPES } from './bucket_agg_types';
import { Storage } from '../../../../../../../plugins/kibana_utils/public';
+
import { getQueryLog, esQuery, Query } from '../../../../../../../plugins/data/public';
-import { BUCKET_TYPES } from './bucket_agg_types';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { getUiSettings } from '../../../../../../../plugins/data/public/services';
const config = chrome.getUiSettingsClient();
-const storage = new Storage(window.localStorage);
const filtersTitle = i18n.translate('data.search.aggs.buckets.filtersTitle', {
defaultMessage: 'Filters',
@@ -52,15 +54,17 @@ export const filtersBucketAgg = new BucketAggType({
params: [
{
name: 'filters',
+ // TODO need to get rid of reference to `config` below
default: [{ input: { query: '', language: config.get('search:queryLanguage') }, label: '' }],
write(aggConfig, output) {
+ const uiSettings = getUiSettings();
const inFilters: FilterValue[] = aggConfig.params.filters;
if (!_.size(inFilters)) return;
inFilters.forEach(filter => {
const persistedLog = getQueryLog(
- config,
- storage,
+ uiSettings,
+ new Storage(window.localStorage),
'vis_default_editor',
filter.input.language
);
@@ -77,7 +81,13 @@ export const filtersBucketAgg = new BucketAggType({
return;
}
- const query = esQuery.buildEsQuery(aggConfig.getIndexPattern(), [input], [], config);
+ const esQueryConfigs = esQuery.getEsQueryConfig(uiSettings);
+ const query = esQuery.buildEsQuery(
+ aggConfig.getIndexPattern(),
+ [input],
+ [],
+ esQueryConfigs
+ );
if (!query) {
console.log('malformed filter agg params, missing "query" on input'); // eslint-disable-line no-console
@@ -90,7 +100,7 @@ export const filtersBucketAgg = new BucketAggType({
matchAllLabel ||
(typeof filter.input.query === 'string'
? filter.input.query
- : angular.toJson(filter.input.query));
+ : toAngularJSON(filter.input.query));
filters[label] = { query };
},
{}
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_hash.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_hash.test.ts
index f0ad595476486..09dd03c759155 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_hash.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_hash.test.ts
@@ -19,12 +19,13 @@
import { geoHashBucketAgg } from './geo_hash';
import { AggConfigs, IAggConfigs } from '../agg_configs';
+import { mockAggTypesRegistry } from '../test_helpers';
import { BUCKET_TYPES } from './bucket_agg_types';
import { IBucketAggConfig } from './_bucket_agg_type';
-jest.mock('ui/new_platform');
-
describe('Geohash Agg', () => {
+ // const typesRegistry = mockAggTypesRegistry([geoHashBucketAgg]);
+ const typesRegistry = mockAggTypesRegistry();
const getAggConfigs = (params?: Record) => {
const indexPattern = {
id: '1234',
@@ -62,7 +63,7 @@ describe('Geohash Agg', () => {
},
},
],
- null
+ { typesRegistry }
);
};
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_tile.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_tile.ts
index 57e8f6e8c5ded..9142a30338163 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_tile.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/geo_tile.ts
@@ -19,7 +19,6 @@
import { i18n } from '@kbn/i18n';
import { noop } from 'lodash';
-import { AggConfigOptions } from '../agg_config';
import { BucketAggType } from './_bucket_agg_type';
import { BUCKET_TYPES } from './bucket_agg_types';
@@ -57,7 +56,7 @@ export const geoTileBucketAgg = new BucketAggType({
aggs.push(agg);
if (useGeocentroid) {
- const aggConfig: AggConfigOptions = {
+ const aggConfig = {
type: METRIC_TYPES.GEO_CENTROID,
enabled: true,
params: {
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.test.ts
index 4e89d7db1ff64..11dc8e42fd653 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.test.ts
@@ -17,16 +17,23 @@
* under the License.
*/
-import { npStart } from 'ui/new_platform';
-import { AggConfigs } from '../index';
+import { AggConfigs } from '../agg_configs';
+import { mockDataServices, mockAggTypesRegistry } from '../test_helpers';
import { BUCKET_TYPES } from './bucket_agg_types';
import { IBucketHistogramAggConfig, histogramBucketAgg, AutoBounds } from './histogram';
import { BucketAggType } from './_bucket_agg_type';
-
-jest.mock('ui/new_platform');
+import { coreMock } from '../../../../../../../../src/core/public/mocks';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { setUiSettings } from '../../../../../../../plugins/data/public/services';
describe('Histogram Agg', () => {
- const getAggConfigs = (params: Record = {}) => {
+ beforeEach(() => {
+ mockDataServices();
+ });
+
+ const typesRegistry = mockAggTypesRegistry([histogramBucketAgg]);
+
+ const getAggConfigs = (params: Record) => {
const indexPattern = {
id: '1234',
title: 'logstash-*',
@@ -45,16 +52,13 @@ describe('Histogram Agg', () => {
indexPattern,
[
{
- field: {
- name: 'field',
- },
id: 'test',
type: BUCKET_TYPES.HISTOGRAM,
schema: 'segment',
params,
},
],
- null
+ { typesRegistry }
);
};
@@ -158,10 +162,15 @@ describe('Histogram Agg', () => {
aggConfig.setAutoBounds(autoBounds);
}
- // mock histogram:maxBars value;
- npStart.core.uiSettings.get = jest.fn(() => maxBars as any);
+ const core = coreMock.createStart();
+ setUiSettings({
+ ...core.uiSettings,
+ get: () => maxBars as any,
+ });
- return aggConfig.write(aggConfigs).params;
+ const interval = aggConfig.write(aggConfigs).params;
+ setUiSettings(core.uiSettings); // clean up
+ return interval;
};
it('will respect the histogram:maxBars setting', () => {
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.ts
index f7e9ef45961e0..70df2f230db09 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/histogram.ts
@@ -19,13 +19,13 @@
import _ from 'lodash';
import { i18n } from '@kbn/i18n';
-import { toastNotifications } from 'ui/notify';
-import { npStart } from 'ui/new_platform';
import { BucketAggType, IBucketAggConfig } from './_bucket_agg_type';
import { createFilterHistogram } from './create_filter/histogram';
-import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public';
import { BUCKET_TYPES } from './bucket_agg_types';
+import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { getNotifications, getUiSettings } from '../../../../../../../plugins/data/public/services';
export interface AutoBounds {
min: number;
@@ -37,8 +37,6 @@ export interface IBucketHistogramAggConfig extends IBucketAggConfig {
getAutoBounds: () => AutoBounds;
}
-const getUIConfig = () => npStart.core.uiSettings;
-
export const histogramBucketAgg = new BucketAggType({
name: BUCKET_TYPES.HISTOGRAM,
title: i18n.translate('data.search.aggs.buckets.histogramTitle', {
@@ -116,7 +114,7 @@ export const histogramBucketAgg = new BucketAggType({
})
.catch((e: Error) => {
if (e.name === 'AbortError') return;
- toastNotifications.addWarning(
+ getNotifications().toasts.addWarning(
i18n.translate('data.search.aggs.histogram.missingMaxMinValuesWarning', {
defaultMessage:
'Unable to retrieve max and min values to auto-scale histogram buckets. This may lead to poor visualization performance.',
@@ -136,7 +134,7 @@ export const histogramBucketAgg = new BucketAggType({
const range = autoBounds.max - autoBounds.min;
const bars = range / interval;
- const config = getUIConfig();
+ const config = getUiSettings();
if (bars > config.get('histogram:maxBars')) {
const minInterval = range / config.get('histogram:maxBars');
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts
index 91bdf53e7f809..3fb464d8fa7a8 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/ip_range.ts
@@ -19,15 +19,17 @@
import { noop, map, omit, isNull } from 'lodash';
import { i18n } from '@kbn/i18n';
-import { npStart } from 'ui/new_platform';
-import { IpRangeKey, convertIPRangeToString } from './lib/ip_range';
import { BucketAggType } from './_bucket_agg_type';
import { BUCKET_TYPES } from './bucket_agg_types';
-// @ts-ignore
import { createFilterIpRange } from './create_filter/ip_range';
import { KBN_FIELD_TYPES, fieldFormats } from '../../../../../../../plugins/data/public';
-export { IpRangeKey, convertIPRangeToString };
+
+import { IpRangeKey, convertIPRangeToString } from './lib/ip_range';
+export { IpRangeKey, convertIPRangeToString }; // for BWC
+
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { getFieldFormats } from '../../../../../../../plugins/data/public/services';
const ipRangeTitle = i18n.translate('data.search.aggs.buckets.ipRangeTitle', {
defaultMessage: 'IPv4 Range',
@@ -44,7 +46,7 @@ export const ipRangeBucketAgg = new BucketAggType({
return { type: 'range', from: bucket.from, to: bucket.to };
},
getFormat(agg) {
- const fieldFormatsService = npStart.plugins.data.fieldFormats;
+ const fieldFormatsService = getFieldFormats();
const formatter = agg.fieldOwnFormatter(
fieldFormats.TEXT_CONTEXT_TYPE,
fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.IP)
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/migrate_include_exclude_format.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/migrate_include_exclude_format.ts
index 77e84e044de55..d94477b588f8d 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/migrate_include_exclude_format.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/migrate_include_exclude_format.ts
@@ -19,10 +19,10 @@
import { isString, isObject } from 'lodash';
import { IBucketAggConfig, BucketAggType, BucketAggParam } from './_bucket_agg_type';
-import { AggConfig } from '../agg_config';
+import { IAggConfig } from '../agg_config';
export const isType = (type: string) => {
- return (agg: AggConfig): boolean => {
+ return (agg: IAggConfig): boolean => {
const field = agg.params.field;
return field && field.type === type;
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/range.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/range.test.ts
index b1b0c4bc30a58..096b19fe7de66 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/range.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/range.test.ts
@@ -17,12 +17,12 @@
* under the License.
*/
+import { rangeBucketAgg } from './range';
import { AggConfigs } from '../agg_configs';
+import { mockDataServices, mockAggTypesRegistry } from '../test_helpers';
import { BUCKET_TYPES } from './bucket_agg_types';
import { FieldFormatsGetConfigFn, fieldFormats } from '../../../../../../../plugins/data/public';
-jest.mock('ui/new_platform');
-
const buckets = [
{
to: 1024,
@@ -44,6 +44,12 @@ const buckets = [
];
describe('Range Agg', () => {
+ beforeEach(() => {
+ mockDataServices();
+ });
+
+ const typesRegistry = mockAggTypesRegistry([rangeBucketAgg]);
+
const getConfig = (() => {}) as FieldFormatsGetConfigFn;
const getAggConfigs = () => {
const field = {
@@ -80,7 +86,7 @@ describe('Range Agg', () => {
},
},
],
- null
+ { typesRegistry }
);
};
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/significant_terms.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/significant_terms.test.ts
index 37b829bfc20fb..cee3ed506c29c 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/significant_terms.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/significant_terms.test.ts
@@ -17,17 +17,16 @@
* under the License.
*/
-import { AggConfigs } from '../index';
-import { IAggConfigs } from '../types';
+import { AggConfigs, IAggConfigs } from '../agg_configs';
+import { mockAggTypesRegistry } from '../test_helpers';
import { BUCKET_TYPES } from './bucket_agg_types';
import { significantTermsBucketAgg } from './significant_terms';
import { IBucketAggConfig } from './_bucket_agg_type';
-jest.mock('ui/new_platform');
-
describe('Significant Terms Agg', () => {
describe('order agg editor UI', () => {
describe('convert include/exclude from old format', () => {
+ const typesRegistry = mockAggTypesRegistry([significantTermsBucketAgg]);
const getAggConfigs = (params: Record = {}) => {
const indexPattern = {
id: '1234',
@@ -53,7 +52,7 @@ describe('Significant Terms Agg', () => {
params,
},
],
- null
+ { typesRegistry }
);
};
diff --git a/src/legacy/core_plugins/data/public/search/aggs/buckets/terms.test.ts b/src/legacy/core_plugins/data/public/search/aggs/buckets/terms.test.ts
index 24ac332ae4d55..9a4f28afd3edf 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/buckets/terms.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/buckets/terms.test.ts
@@ -17,13 +17,13 @@
* under the License.
*/
-import { AggConfigs } from '../index';
+import { AggConfigs } from '../agg_configs';
+import { mockAggTypesRegistry } from '../test_helpers';
import { BUCKET_TYPES } from './bucket_agg_types';
-jest.mock('ui/new_platform');
-
describe('Terms Agg', () => {
describe('order agg editor UI', () => {
+ const typesRegistry = mockAggTypesRegistry();
const getAggConfigs = (params: Record = {}) => {
const indexPattern = {
id: '1234',
@@ -48,7 +48,7 @@ describe('Terms Agg', () => {
type: BUCKET_TYPES.TERMS,
},
],
- null
+ { typesRegistry }
);
};
diff --git a/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.test.ts b/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.test.ts
index cc1288d339692..0de1c31d02f96 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.test.ts
@@ -19,13 +19,12 @@
import { IndexPattern } from '../../../../../../../plugins/data/public';
import { AggTypeFilters } from './agg_type_filters';
-import { AggConfig } from '..';
-import { IAggType } from '../types';
+import { IAggConfig, IAggType } from '../types';
describe('AggTypeFilters', () => {
let registry: AggTypeFilters;
const indexPattern = ({ id: '1234', fields: [], title: 'foo' } as unknown) as IndexPattern;
- const aggConfig = {} as AggConfig;
+ const aggConfig = {} as IAggConfig;
beforeEach(() => {
registry = new AggTypeFilters();
diff --git a/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.ts b/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.ts
index d3b38ce041d7e..13a4cc0856b09 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/filter/agg_type_filters.ts
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
+
import { IndexPattern } from 'src/plugins/data/public';
import { IAggConfig, IAggType } from '../types';
diff --git a/src/legacy/core_plugins/data/public/search/aggs/filter/prop_filter.test.ts b/src/legacy/core_plugins/data/public/search/aggs/filter/prop_filter.test.ts
index 431e1161e0dbd..32cda7b950e93 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/filter/prop_filter.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/filter/prop_filter.test.ts
@@ -17,7 +17,6 @@
* under the License.
*/
-import expect from '@kbn/expect';
import { propFilter } from './prop_filter';
describe('prop filter', () => {
@@ -47,48 +46,48 @@ describe('prop filter', () => {
it('returns list when no filters are provided', () => {
const objects = getObjects('table', 'table', 'pie');
- expect(nameFilter(objects)).to.eql(objects);
+ expect(nameFilter(objects)).toEqual(objects);
});
it('returns list when empty list of filters is provided', () => {
const objects = getObjects('table', 'table', 'pie');
- expect(nameFilter(objects, [])).to.eql(objects);
+ expect(nameFilter(objects, [])).toEqual(objects);
});
it('should keep only the tables', () => {
const objects = getObjects('table', 'table', 'pie');
- expect(nameFilter(objects, 'table')).to.eql(getObjects('table', 'table'));
+ expect(nameFilter(objects, 'table')).toEqual(getObjects('table', 'table'));
});
it('should support comma-separated values', () => {
const objects = getObjects('table', 'line', 'pie');
- expect(nameFilter(objects, 'table,line')).to.eql(getObjects('table', 'line'));
+ expect(nameFilter(objects, 'table,line')).toEqual(getObjects('table', 'line'));
});
it('should support an array of values', () => {
const objects = getObjects('table', 'line', 'pie');
- expect(nameFilter(objects, ['table', 'line'])).to.eql(getObjects('table', 'line'));
+ expect(nameFilter(objects, ['table', 'line'])).toEqual(getObjects('table', 'line'));
});
it('should return all objects', () => {
const objects = getObjects('table', 'line', 'pie');
- expect(nameFilter(objects, '*')).to.eql(objects);
+ expect(nameFilter(objects, '*')).toEqual(objects);
});
it('should allow negation', () => {
const objects = getObjects('table', 'line', 'pie');
- expect(nameFilter(objects, ['!line'])).to.eql(getObjects('table', 'pie'));
+ expect(nameFilter(objects, ['!line'])).toEqual(getObjects('table', 'pie'));
});
it('should support a function for specifying what should be kept', () => {
const objects = getObjects('table', 'line', 'pie');
const line = (value: string) => value === 'line';
- expect(nameFilter(objects, line)).to.eql(getObjects('line'));
+ expect(nameFilter(objects, line)).toEqual(getObjects('line'));
});
it('gracefully handles a filter function with zero arity', () => {
const objects = getObjects('table', 'line', 'pie');
const rejectEverything = () => false;
- expect(nameFilter(objects, rejectEverything)).to.eql([]);
+ expect(nameFilter(objects, rejectEverything)).toEqual([]);
});
});
diff --git a/src/legacy/core_plugins/data/public/search/aggs/index.test.ts b/src/legacy/core_plugins/data/public/search/aggs/index.test.ts
index a867769a77fc1..4d0cd55b09d53 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/index.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/index.test.ts
@@ -25,8 +25,6 @@ import { isMetricAggType } from './metrics/metric_agg_type';
const bucketAggs = aggTypes.buckets;
const metricAggs = aggTypes.metrics;
-jest.mock('ui/new_platform');
-
describe('AggTypesComponent', () => {
describe('bucket aggs', () => {
it('all extend BucketAggType', () => {
diff --git a/src/legacy/core_plugins/data/public/search/aggs/index.ts b/src/legacy/core_plugins/data/public/search/aggs/index.ts
index 0bdb92b8de65e..f6914c36f6c05 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/index.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/index.ts
@@ -17,8 +17,13 @@
* under the License.
*/
-export { aggTypes } from './agg_types';
+export {
+ AggTypesRegistry,
+ AggTypesRegistrySetup,
+ AggTypesRegistryStart,
+} from './agg_types_registry';
export { AggType } from './agg_type';
+export { aggTypes } from './agg_types';
export { AggConfig } from './agg_config';
export { AggConfigs } from './agg_configs';
export { FieldParamType } from './param_types';
@@ -52,4 +57,4 @@ export { METRIC_TYPES } from './metrics/metric_agg_types';
export { ISchemas, Schema, Schemas } from './schemas';
// types
-export { IAggConfig, IAggConfigs } from './types';
+export { CreateAggConfigParams, IAggConfig, IAggConfigs } from './types';
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_avg.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_avg.ts
index 9fb28f8631bc6..11bb559274729 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_avg.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_avg.ts
@@ -19,7 +19,6 @@
import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
-
import { MetricAggType } from './metric_agg_type';
import { makeNestedLabel } from './lib/make_nested_label';
import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper';
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_max.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_max.ts
index 83837f0de5114..0668a9bcf57a8 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_max.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_max.ts
@@ -18,7 +18,6 @@
*/
import { i18n } from '@kbn/i18n';
-
import { MetricAggType } from './metric_agg_type';
import { makeNestedLabel } from './lib/make_nested_label';
import { siblingPipelineAggHelper } from './lib/sibling_pipeline_agg_helper';
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_min.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_min.ts
index d96197693dc2e..8f728cb5e7e42 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_min.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/bucket_min.ts
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
+
import { i18n } from '@kbn/i18n';
import { MetricAggType } from './metric_agg_type';
import { makeNestedLabel } from './lib/make_nested_label';
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/cardinality.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/cardinality.ts
index 147e925521088..4f7b6e555ca33 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/cardinality.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/cardinality.ts
@@ -18,10 +18,11 @@
*/
import { i18n } from '@kbn/i18n';
-import { npStart } from 'ui/new_platform';
import { MetricAggType } from './metric_agg_type';
import { METRIC_TYPES } from './metric_agg_types';
import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { getFieldFormats } from '../../../../../../../plugins/data/public/services';
const uniqueCountTitle = i18n.translate('data.search.aggs.metrics.uniqueCountTitle', {
defaultMessage: 'Unique Count',
@@ -37,7 +38,7 @@ export const cardinalityMetricAgg = new MetricAggType({
});
},
getFormat() {
- const fieldFormatsService = npStart.plugins.data.fieldFormats;
+ const fieldFormatsService = getFieldFormats();
return fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER);
},
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/count.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/count.ts
index 14a9bd073ff2b..8b3e0a488c68a 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/count.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/count.ts
@@ -18,10 +18,11 @@
*/
import { i18n } from '@kbn/i18n';
-import { npStart } from 'ui/new_platform';
-import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public';
import { MetricAggType } from './metric_agg_type';
import { METRIC_TYPES } from './metric_agg_types';
+import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { getFieldFormats } from '../../../../../../../plugins/data/public/services';
export const countMetricAgg = new MetricAggType({
name: METRIC_TYPES.COUNT,
@@ -35,7 +36,7 @@ export const countMetricAgg = new MetricAggType({
});
},
getFormat() {
- const fieldFormatsService = npStart.plugins.data.fieldFormats;
+ const fieldFormatsService = getFieldFormats();
return fieldFormatsService.getDefaultInstance(KBN_FIELD_TYPES.NUMBER);
},
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/get_response_agg_config_class.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/get_response_agg_config_class.ts
index 054543de3dd06..00d866e6f2b3e 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/get_response_agg_config_class.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/get_response_agg_config_class.ts
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
+
import { assign } from 'lodash';
import { IMetricAggConfig } from '../metric_agg_type';
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts
index e24aca08271c7..88549ee3019ee 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/parent_pipeline_agg_helper.ts
@@ -23,7 +23,6 @@ import { noop, identity } from 'lodash';
import { forwardModifyAggConfigOnSearchRequestStart } from './nested_agg_helpers';
import { IMetricAggConfig, MetricAggParam } from '../metric_agg_type';
import { parentPipelineAggWriter } from './parent_pipeline_agg_writer';
-
import { Schemas } from '../../schemas';
import { fieldFormats } from '../../../../../../../../plugins/data/public';
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts
index e7c98e575fdb4..05e009cc9da30 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/lib/sibling_pipeline_agg_helper.ts
@@ -21,7 +21,6 @@ import { identity } from 'lodash';
import { i18n } from '@kbn/i18n';
import { siblingPipelineAggWriter } from './sibling_pipeline_agg_writer';
import { forwardModifyAggConfigOnSearchRequestStart } from './nested_agg_helpers';
-
import { IMetricAggConfig, MetricAggParam } from '../metric_agg_type';
import { Schemas } from '../../schemas';
import { fieldFormats } from '../../../../../../../../plugins/data/public';
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts
index 4755a873e6977..ad55837ec9a30 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.test.ts
@@ -17,15 +17,16 @@
* under the License.
*/
+import { medianMetricAgg } from './median';
import { AggConfigs, IAggConfigs } from '../agg_configs';
+import { mockAggTypesRegistry } from '../test_helpers';
import { METRIC_TYPES } from './metric_agg_types';
-jest.mock('ui/new_platform');
-
describe('AggTypeMetricMedianProvider class', () => {
let aggConfigs: IAggConfigs;
beforeEach(() => {
+ const typesRegistry = mockAggTypesRegistry([medianMetricAgg]);
const field = {
name: 'bytes',
};
@@ -50,7 +51,7 @@ describe('AggTypeMetricMedianProvider class', () => {
},
},
],
- null
+ { typesRegistry }
);
});
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts
index 53a5ffff418f1..68fc98261118c 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/median.ts
@@ -16,12 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
+
import { i18n } from '@kbn/i18n';
import { MetricAggType } from './metric_agg_type';
import { METRIC_TYPES } from './metric_agg_types';
-
-// @ts-ignore
-import { percentilesMetricAgg } from './percentiles';
import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public';
const medianTitle = i18n.translate('data.search.aggs.metrics.medianTitle', {
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/metric_agg_type.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/metric_agg_type.ts
index 3bae7b92618dc..952dcc96de833 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/metric_agg_type.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/metric_agg_type.ts
@@ -18,13 +18,14 @@
*/
import { i18n } from '@kbn/i18n';
-import { npStart } from 'ui/new_platform';
import { AggType, AggTypeConfig } from '../agg_type';
import { AggParamType } from '../param_types/agg';
import { AggConfig } from '../agg_config';
+import { FilterFieldTypes } from '../param_types/field';
import { METRIC_TYPES } from './metric_agg_types';
import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public';
-import { FilterFieldTypes } from '../param_types/field';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { getFieldFormats } from '../../../../../../../plugins/data/public/services';
export interface IMetricAggConfig extends AggConfig {
type: InstanceType;
@@ -78,7 +79,7 @@ export class MetricAggType {
- const fieldFormatsService = npStart.plugins.data.fieldFormats;
+ const fieldFormatsService = getFieldFormats();
const field = agg.getField();
return field
? field.format
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/min.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/min.ts
index 4885105163435..1806c6d9d7710 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/min.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/min.ts
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
+
import { i18n } from '@kbn/i18n';
import { MetricAggType } from './metric_agg_type';
import { METRIC_TYPES } from './metric_agg_types';
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts
index 11fc39c20bdc4..58b4ee530a8c2 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/parent_pipeline.test.ts
@@ -17,12 +17,12 @@
* under the License.
*/
-import sinon from 'sinon';
import { derivativeMetricAgg } from './derivative';
import { cumulativeSumMetricAgg } from './cumulative_sum';
import { movingAvgMetricAgg } from './moving_avg';
import { serialDiffMetricAgg } from './serial_diff';
import { AggConfigs } from '../agg_configs';
+import { mockDataServices, mockAggTypesRegistry } from '../test_helpers';
import { IMetricAggConfig, MetricAggType } from './metric_agg_type';
jest.mock('../schemas', () => {
@@ -34,9 +34,13 @@ jest.mock('../schemas', () => {
};
});
-jest.mock('ui/new_platform');
-
describe('parent pipeline aggs', function() {
+ beforeEach(() => {
+ mockDataServices();
+ });
+
+ const typesRegistry = mockAggTypesRegistry();
+
const metrics = [
{ name: 'derivative', title: 'Derivative', provider: derivativeMetricAgg },
{ name: 'cumulative_sum', title: 'Cumulative Sum', provider: cumulativeSumMetricAgg },
@@ -94,7 +98,7 @@ describe('parent pipeline aggs', function() {
schema: 'metric',
},
],
- null
+ { typesRegistry }
);
// Grab the aggConfig off the vis (we don't actually use the vis for anything else)
@@ -220,16 +224,16 @@ describe('parent pipeline aggs', function() {
});
const searchSource: any = {};
- const customMetricSpy = sinon.spy();
+ const customMetricSpy = jest.fn();
const customMetric = aggConfig.params.customMetric;
// Attach a modifyAggConfigOnSearchRequestStart with a spy to the first parameter
customMetric.type.params[0].modifyAggConfigOnSearchRequestStart = customMetricSpy;
aggConfig.type.params.forEach(param => {
- param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource);
+ param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource, {});
});
- expect(customMetricSpy.calledWith(customMetric, searchSource)).toBe(true);
+ expect(customMetricSpy.mock.calls[0]).toEqual([customMetric, searchSource, {}]);
});
});
});
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts
index 655e918ce07de..628f1cd204ee5 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.test.ts
@@ -19,14 +19,16 @@
import { IPercentileRanksAggConfig, percentileRanksMetricAgg } from './percentile_ranks';
import { AggConfigs, IAggConfigs } from '../agg_configs';
+import { mockDataServices, mockAggTypesRegistry } from '../test_helpers';
import { METRIC_TYPES } from './metric_agg_types';
-jest.mock('ui/new_platform');
-
describe('AggTypesMetricsPercentileRanksProvider class', function() {
let aggConfigs: IAggConfigs;
beforeEach(() => {
+ mockDataServices();
+
+ const typesRegistry = mockAggTypesRegistry([percentileRanksMetricAgg]);
const field = {
name: 'bytes',
};
@@ -58,7 +60,7 @@ describe('AggTypesMetricsPercentileRanksProvider class', function() {
},
},
],
- null
+ { typesRegistry }
);
});
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.ts
index 38b47a7e97d2f..1d640a9c1fa42 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentile_ranks.ts
@@ -18,20 +18,17 @@
*/
import { i18n } from '@kbn/i18n';
-import { npStart } from 'ui/new_platform';
import { MetricAggType } from './metric_agg_type';
import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class';
-
import { getPercentileValue } from './percentiles_get_value';
import { METRIC_TYPES } from './metric_agg_types';
import { fieldFormats, KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { getFieldFormats } from '../../../../../../../plugins/data/public/services';
// required by the values editor
-
export type IPercentileRanksAggConfig = IResponseAggConfig;
-const getFieldFormats = () => npStart.plugins.data.fieldFormats;
-
const valueProps = {
makeLabel(this: IPercentileRanksAggConfig) {
const fieldFormatsService = getFieldFormats();
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.test.ts
index dd1aaca973e47..e077bc0f8c773 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.test.ts
@@ -19,14 +19,14 @@
import { IPercentileAggConfig, percentilesMetricAgg } from './percentiles';
import { AggConfigs, IAggConfigs } from '../agg_configs';
+import { mockAggTypesRegistry } from '../test_helpers';
import { METRIC_TYPES } from './metric_agg_types';
-jest.mock('ui/new_platform');
-
describe('AggTypesMetricsPercentilesProvider class', () => {
let aggConfigs: IAggConfigs;
beforeEach(() => {
+ const typesRegistry = mockAggTypesRegistry([percentilesMetricAgg]);
const field = {
name: 'bytes',
};
@@ -58,7 +58,7 @@ describe('AggTypesMetricsPercentilesProvider class', () => {
},
},
],
- null
+ { typesRegistry }
);
});
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.ts
index 39dc0d0f181e9..49e927d07d8dd 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/percentiles.ts
@@ -18,15 +18,11 @@
*/
import { i18n } from '@kbn/i18n';
-
import { MetricAggType } from './metric_agg_type';
import { METRIC_TYPES } from './metric_agg_types';
import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public';
-
import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class';
import { getPercentileValue } from './percentiles_get_value';
-
-// @ts-ignore
import { ordinalSuffix } from './lib/ordinal_suffix';
export type IPercentileAggConfig = IResponseAggConfig;
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts
index d643cf0d2a478..d3456bacceb6a 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/sibling_pipeline.test.ts
@@ -17,7 +17,6 @@
* under the License.
*/
-import { spy } from 'sinon';
import { bucketSumMetricAgg } from './bucket_sum';
import { bucketAvgMetricAgg } from './bucket_avg';
import { bucketMinMetricAgg } from './bucket_min';
@@ -25,6 +24,7 @@ import { bucketMaxMetricAgg } from './bucket_max';
import { AggConfigs } from '../agg_configs';
import { IMetricAggConfig, MetricAggType } from './metric_agg_type';
+import { mockDataServices, mockAggTypesRegistry } from '../test_helpers';
jest.mock('../schemas', () => {
class MockedSchemas {
@@ -35,9 +35,13 @@ jest.mock('../schemas', () => {
};
});
-jest.mock('ui/new_platform');
-
describe('sibling pipeline aggs', () => {
+ beforeEach(() => {
+ mockDataServices();
+ });
+
+ const typesRegistry = mockAggTypesRegistry();
+
const metrics = [
{ name: 'sum_bucket', title: 'Overall Sum', provider: bucketSumMetricAgg },
{ name: 'avg_bucket', title: 'Overall Average', provider: bucketAvgMetricAgg },
@@ -96,7 +100,7 @@ describe('sibling pipeline aggs', () => {
},
},
],
- null
+ { typesRegistry }
);
// Grab the aggConfig off the vis (we don't actually use the vis for anything else)
@@ -162,8 +166,8 @@ describe('sibling pipeline aggs', () => {
init();
const searchSource: any = {};
- const customMetricSpy = spy();
- const customBucketSpy = spy();
+ const customMetricSpy = jest.fn();
+ const customBucketSpy = jest.fn();
const { customMetric, customBucket } = aggConfig.params;
// Attach a modifyAggConfigOnSearchRequestStart with a spy to the first parameter
@@ -171,11 +175,11 @@ describe('sibling pipeline aggs', () => {
customBucket.type.params[0].modifyAggConfigOnSearchRequestStart = customBucketSpy;
aggConfig.type.params.forEach(param => {
- param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource);
+ param.modifyAggConfigOnSearchRequestStart(aggConfig, searchSource, {});
});
- expect(customMetricSpy.calledWith(customMetric, searchSource)).toBe(true);
- expect(customBucketSpy.calledWith(customBucket, searchSource)).toBe(true);
+ expect(customMetricSpy.mock.calls[0]).toEqual([customMetric, searchSource, {}]);
+ expect(customBucketSpy.mock.calls[0]).toEqual([customBucket, searchSource, {}]);
});
});
});
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/std_deviation.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/std_deviation.test.ts
index 3125026a52185..0679831b1e6ac 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/std_deviation.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/std_deviation.test.ts
@@ -19,11 +19,11 @@
import { IStdDevAggConfig, stdDeviationMetricAgg } from './std_deviation';
import { AggConfigs } from '../agg_configs';
+import { mockAggTypesRegistry } from '../test_helpers';
import { METRIC_TYPES } from './metric_agg_types';
-jest.mock('ui/new_platform');
-
describe('AggTypeMetricStandardDeviationProvider class', () => {
+ const typesRegistry = mockAggTypesRegistry([stdDeviationMetricAgg]);
const getAggConfigs = (customLabel?: string) => {
const field = {
name: 'memory',
@@ -52,7 +52,7 @@ describe('AggTypeMetricStandardDeviationProvider class', () => {
},
},
],
- null
+ { typesRegistry }
);
};
diff --git a/src/legacy/core_plugins/data/public/search/aggs/metrics/top_hit.test.ts b/src/legacy/core_plugins/data/public/search/aggs/metrics/top_hit.test.ts
index a973de4fe8659..ad1f42f5c563e 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/metrics/top_hit.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/metrics/top_hit.test.ts
@@ -20,11 +20,10 @@
import { dropRight, last } from 'lodash';
import { topHitMetricAgg } from './top_hit';
import { AggConfigs } from '../agg_configs';
+import { mockAggTypesRegistry } from '../test_helpers';
import { IMetricAggConfig } from './metric_agg_type';
import { KBN_FIELD_TYPES } from '../../../../../../../plugins/data/public';
-jest.mock('ui/new_platform');
-
describe('Top hit metric', () => {
let aggDsl: Record;
let aggConfig: IMetricAggConfig;
@@ -37,6 +36,7 @@ describe('Top hit metric', () => {
fieldType = KBN_FIELD_TYPES.NUMBER,
size = 1,
}: any) => {
+ const typesRegistry = mockAggTypesRegistry([topHitMetricAgg]);
const field = {
name: fieldName,
displayName: fieldName,
@@ -81,7 +81,7 @@ describe('Top hit metric', () => {
params,
},
],
- null
+ { typesRegistry }
);
// Grab the aggConfig off the vis (we don't actually use the vis for anything else)
diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/agg.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/agg.ts
index 2e7c11004b472..d31abe64491d0 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/param_types/agg.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/agg.ts
@@ -17,10 +17,10 @@
* under the License.
*/
-import { AggConfig } from '../agg_config';
+import { AggConfig, IAggConfig } from '../agg_config';
import { BaseParamType } from './base';
-export class AggParamType extends BaseParamType<
+export class AggParamType extends BaseParamType<
TAggConfig
> {
makeAgg: (agg: TAggConfig, state?: any) => TAggConfig;
diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/base.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/base.ts
index 1523cb03eb966..95ad71a616ab2 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/param_types/base.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/base.ts
@@ -18,10 +18,10 @@
*/
import { IAggConfigs } from '../agg_configs';
-import { AggConfig } from '../agg_config';
+import { IAggConfig } from '../agg_config';
import { FetchOptions, ISearchSource } from '../../../../../../../plugins/data/public';
-export class BaseParamType {
+export class BaseParamType {
name: string;
type: string;
displayName: string;
diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/field.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/field.test.ts
index fa88754ac60b9..7338c41f920d7 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/param_types/field.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/field.test.ts
@@ -25,8 +25,6 @@ import { IAggConfig } from '../agg_config';
import { IMetricAggConfig } from '../metrics/metric_agg_type';
import { Schema } from '../schemas';
-jest.mock('ui/new_platform');
-
describe('Field', () => {
const indexPattern = {
id: '1234',
diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/field.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/field.ts
index 40c30f6210a83..bb5707cbb482e 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/param_types/field.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/field.ts
@@ -19,7 +19,6 @@
import { i18n } from '@kbn/i18n';
import { isFunction } from 'lodash';
-import { npStart } from 'ui/new_platform';
import { IAggConfig } from '../agg_config';
import { SavedObjectNotFound } from '../../../../../../../plugins/kibana_utils/public';
import { BaseParamType } from './base';
@@ -30,6 +29,8 @@ import {
indexPatterns,
KBN_FIELD_TYPES,
} from '../../../../../../../plugins/data/public';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { getNotifications } from '../../../../../../../plugins/data/public/services';
const filterByType = propFilter('type');
@@ -93,7 +94,7 @@ export class FieldParamType extends BaseParamType {
// @ts-ignore
const validField = this.getAvailableFields(aggConfig).find((f: any) => f.name === fieldName);
if (!validField) {
- npStart.core.notifications.toasts.addDanger(
+ getNotifications().toasts.addDanger(
i18n.translate(
'data.search.aggs.paramTypes.field.invalidSavedFieldParameterErrorMessage',
{
diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.test.ts
index bc36bb46d3d16..1a453a225797d 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.test.ts
@@ -17,27 +17,26 @@
* under the License.
*/
-import { IndexedArray } from 'ui/indexed_array';
import { AggTypeFieldFilters } from './field_filters';
-import { AggConfig } from '../../agg_config';
+import { IAggConfig } from '../../agg_config';
import { IndexPatternField } from '../../../../../../../../plugins/data/public';
describe('AggTypeFieldFilters', () => {
let registry: AggTypeFieldFilters;
- const aggConfig = {} as AggConfig;
+ const aggConfig = {} as IAggConfig;
beforeEach(() => {
registry = new AggTypeFieldFilters();
});
it('should filter nothing without registered filters', async () => {
- const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexedArray;
+ const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexPatternField[];
const filtered = registry.filter(fields, aggConfig);
expect(filtered).toEqual(fields);
});
it('should pass all fields to the registered filter', async () => {
- const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexedArray;
+ const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexPatternField[];
const filter = jest.fn();
registry.addFilter(filter);
registry.filter(fields, aggConfig);
@@ -46,7 +45,7 @@ describe('AggTypeFieldFilters', () => {
});
it('should allow registered filters to filter out fields', async () => {
- const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexedArray;
+ const fields = [{ name: 'foo' }, { name: 'bar' }] as IndexPatternField[];
let filtered = registry.filter(fields, aggConfig);
expect(filtered).toEqual(fields);
diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.ts
index 7d1348ab5423b..1cbf0c9ae3624 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/filter/field_filters.ts
@@ -17,9 +17,9 @@
* under the License.
*/
import { IndexPatternField } from 'src/plugins/data/public';
-import { AggConfig } from '../../agg_config';
+import { IAggConfig } from '../../agg_config';
-type AggTypeFieldFilter = (field: IndexPatternField, aggConfig: AggConfig) => boolean;
+type AggTypeFieldFilter = (field: IndexPatternField, aggConfig: IAggConfig) => boolean;
/**
* A registry to store {@link AggTypeFieldFilter} which are used to filter down
@@ -41,11 +41,11 @@ class AggTypeFieldFilters {
/**
* Returns the {@link any|fields} filtered by all registered filters.
*
- * @param fields An IndexedArray of fields that will be filtered down by this registry.
+ * @param fields An array of fields that will be filtered down by this registry.
* @param aggConfig The aggConfig for which the returning list will be used.
* @return A filtered list of the passed fields.
*/
- public filter(fields: IndexPatternField[], aggConfig: AggConfig) {
+ public filter(fields: IndexPatternField[], aggConfig: IAggConfig) {
const allFilters = Array.from(this.filters);
const allowedAggTypeFields = fields.filter(field => {
const isAggTypeFieldAllowed = allFilters.every(filter => filter(field, aggConfig));
diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/json.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/json.test.ts
index 827299814c62a..12fd29b3a1452 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/param_types/json.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/json.test.ts
@@ -19,13 +19,11 @@
import { BaseParamType } from './base';
import { JsonParamType } from './json';
-import { AggConfig } from '../agg_config';
-
-jest.mock('ui/new_platform');
+import { IAggConfig } from '../agg_config';
describe('JSON', function() {
const paramName = 'json_test';
- let aggConfig: AggConfig;
+ let aggConfig: IAggConfig;
let output: Record;
const initAggParam = (config: Record = {}) =>
@@ -36,7 +34,7 @@ describe('JSON', function() {
});
beforeEach(function() {
- aggConfig = { params: {} } as AggConfig;
+ aggConfig = { params: {} } as IAggConfig;
output = { params: {} };
});
diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/json.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/json.ts
index 771919b0bb56b..bf85b3b890c35 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/param_types/json.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/json.ts
@@ -19,7 +19,7 @@
import _ from 'lodash';
-import { AggConfig } from '../agg_config';
+import { IAggConfig } from '../agg_config';
import { BaseParamType } from './base';
export class JsonParamType extends BaseParamType {
@@ -29,7 +29,7 @@ export class JsonParamType extends BaseParamType {
this.name = config.name || 'json';
if (!config.write) {
- this.write = (aggConfig: AggConfig, output: Record) => {
+ this.write = (aggConfig: IAggConfig, output: Record) => {
let paramJson;
const param = aggConfig.params[this.name];
diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.test.ts
index 6b58d81914097..c03d6cdfa1c70 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.test.ts
@@ -20,8 +20,6 @@
import { BaseParamType } from './base';
import { OptionedParamType } from './optioned';
-jest.mock('ui/new_platform');
-
describe('Optioned', () => {
describe('constructor', () => {
it('it is an instance of BaseParamType', () => {
diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.ts
index 5ffda3740af49..9eb7ceda60711 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/optioned.ts
@@ -17,14 +17,14 @@
* under the License.
*/
-import { AggConfig } from '../agg_config';
+import { IAggConfig } from '../agg_config';
import { BaseParamType } from './base';
export interface OptionedValueProp {
value: string;
text: string;
disabled?: boolean;
- isCompatible: (agg: AggConfig) => boolean;
+ isCompatible: (agg: IAggConfig) => boolean;
}
export interface OptionedParamEditorProps {
@@ -40,7 +40,7 @@ export class OptionedParamType extends BaseParamType {
super(config);
if (!config.write) {
- this.write = (aggConfig: AggConfig, output: Record) => {
+ this.write = (aggConfig: IAggConfig, output: Record) => {
output.params[this.name] = aggConfig.params[this.name].value;
};
}
diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/string.test.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/string.test.ts
index fd5ccebde993e..29ec9741611a3 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/param_types/string.test.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/string.test.ts
@@ -19,13 +19,11 @@
import { BaseParamType } from './base';
import { StringParamType } from './string';
-import { AggConfig } from '../agg_config';
-
-jest.mock('ui/new_platform');
+import { IAggConfig } from '../agg_config';
describe('String', function() {
let paramName = 'json_test';
- let aggConfig: AggConfig;
+ let aggConfig: IAggConfig;
let output: Record;
const initAggParam = (config: Record = {}) =>
@@ -36,7 +34,7 @@ describe('String', function() {
});
beforeEach(() => {
- aggConfig = { params: {} } as AggConfig;
+ aggConfig = { params: {} } as IAggConfig;
output = { params: {} };
});
diff --git a/src/legacy/core_plugins/data/public/search/aggs/param_types/string.ts b/src/legacy/core_plugins/data/public/search/aggs/param_types/string.ts
index 58ba99f8a6d63..750606eb8433b 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/param_types/string.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/param_types/string.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { AggConfig } from '../agg_config';
+import { IAggConfig } from '../agg_config';
import { BaseParamType } from './base';
export class StringParamType extends BaseParamType {
@@ -25,7 +25,7 @@ export class StringParamType extends BaseParamType {
super(config);
if (!config.write) {
- this.write = (aggConfig: AggConfig, output: Record) => {
+ this.write = (aggConfig: IAggConfig, output: Record) => {
if (aggConfig.params[this.name] && aggConfig.params[this.name].length) {
output.params[this.name] = aggConfig.params[this.name];
}
diff --git a/src/cli/dev_ssl.js b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/index.ts
similarity index 79%
rename from src/cli/dev_ssl.js
rename to src/legacy/core_plugins/data/public/search/aggs/test_helpers/index.ts
index 110f44ee57b7d..131f921586144 100644
--- a/src/cli/dev_ssl.js
+++ b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/index.ts
@@ -17,6 +17,5 @@
* under the License.
*/
-import { resolve } from 'path';
-export const DEV_SSL_CERT_PATH = resolve(__dirname, '../../test/dev_certs/server.crt');
-export const DEV_SSL_KEY_PATH = resolve(__dirname, '../../test/dev_certs/server.key');
+export { mockAggTypesRegistry } from './mock_agg_types_registry';
+export { mockDataServices } from './mock_data_services';
diff --git a/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts
new file mode 100644
index 0000000000000..d6bb793866493
--- /dev/null
+++ b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_agg_types_registry.ts
@@ -0,0 +1,57 @@
+/*
+ * 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 { AggTypesRegistry, AggTypesRegistryStart } from '../agg_types_registry';
+import { aggTypes } from '../agg_types';
+import { BucketAggType } from '../buckets/_bucket_agg_type';
+import { MetricAggType } from '../metrics/metric_agg_type';
+
+/**
+ * Testing utility which creates a new instance of AggTypesRegistry,
+ * registers the provided agg types, and returns AggTypesRegistry.start()
+ *
+ * This is useful if your test depends on a certain agg type to be present
+ * in the registry.
+ *
+ * @param [types] - Optional array of AggTypes to register.
+ * If no value is provided, all default types will be registered.
+ *
+ * @internal
+ */
+export function mockAggTypesRegistry | MetricAggType>(
+ types?: T[]
+): AggTypesRegistryStart {
+ const registry = new AggTypesRegistry();
+ const registrySetup = registry.setup();
+
+ if (types) {
+ types.forEach(type => {
+ if (type instanceof BucketAggType) {
+ registrySetup.registerBucket(type);
+ } else if (type instanceof MetricAggType) {
+ registrySetup.registerMetric(type);
+ }
+ });
+ } else {
+ aggTypes.buckets.forEach(type => registrySetup.registerBucket(type));
+ aggTypes.metrics.forEach(type => registrySetup.registerMetric(type));
+ }
+
+ return registry.start();
+}
diff --git a/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_data_services.ts b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_data_services.ts
new file mode 100644
index 0000000000000..c4e78ab8f6422
--- /dev/null
+++ b/src/legacy/core_plugins/data/public/search/aggs/test_helpers/mock_data_services.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.
+ */
+
+import { coreMock } from '../../../../../../../../src/core/public/mocks';
+import { dataPluginMock } from '../../../../../../../plugins/data/public/mocks';
+import { searchStartMock } from '../../mocks';
+import { setSearchServiceShim } from '../../../services';
+import {
+ setFieldFormats,
+ setIndexPatterns,
+ setNotifications,
+ setOverlays,
+ setQueryService,
+ setSearchService,
+ setUiSettings,
+ // eslint-disable-next-line @kbn/eslint/no-restricted-paths
+} from '../../../../../../../plugins/data/public/services';
+
+/**
+ * Testing helper which calls all of the service setters used in the
+ * data plugin. Services are added using their provided mocks.
+ *
+ * @internal
+ */
+export function mockDataServices() {
+ const core = coreMock.createStart();
+ const data = dataPluginMock.createStartContract();
+ const searchShim = searchStartMock();
+
+ setSearchServiceShim(searchShim);
+ setFieldFormats(data.fieldFormats);
+ setIndexPatterns(data.indexPatterns);
+ setNotifications(core.notifications);
+ setOverlays(core.overlays);
+ setQueryService(data.query);
+ setSearchService(data.search);
+ setUiSettings(core.uiSettings);
+}
diff --git a/src/legacy/core_plugins/data/public/search/aggs/types.ts b/src/legacy/core_plugins/data/public/search/aggs/types.ts
index 2c918abf99fca..5d02f426b5896 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/types.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/types.ts
@@ -18,7 +18,7 @@
*/
export { IAggConfig } from './agg_config';
-export { IAggConfigs } from './agg_configs';
+export { CreateAggConfigParams, IAggConfigs } from './agg_configs';
export { IAggType } from './agg_type';
export { AggParam, AggParamOption } from './agg_params';
export { IFieldParamType } from './param_types';
diff --git a/src/legacy/core_plugins/data/public/search/aggs/utils.test.tsx b/src/legacy/core_plugins/data/public/search/aggs/utils.test.tsx
index a3c7f24f3927d..c0662c98755a3 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/utils.test.tsx
+++ b/src/legacy/core_plugins/data/public/search/aggs/utils.test.tsx
@@ -19,8 +19,6 @@
import { isValidJson } from './utils';
-jest.mock('ui/new_platform');
-
const input = {
valid: '{ "test": "json input" }',
invalid: 'strings are not json',
diff --git a/src/legacy/core_plugins/data/public/search/aggs/utils.ts b/src/legacy/core_plugins/data/public/search/aggs/utils.ts
index 62f07ce44ab46..67ea373f438fb 100644
--- a/src/legacy/core_plugins/data/public/search/aggs/utils.ts
+++ b/src/legacy/core_plugins/data/public/search/aggs/utils.ts
@@ -26,7 +26,7 @@ import { isValidEsInterval } from '../../../common';
* @param {string} value a string that should be validated
* @returns {boolean} true if value is a valid JSON or if value is an empty string, or a string with whitespaces, otherwise false
*/
-function isValidJson(value: string): boolean {
+export function isValidJson(value: string): boolean {
if (!value || value.length === 0) {
return true;
}
@@ -49,7 +49,7 @@ function isValidJson(value: string): boolean {
}
}
-function isValidInterval(value: string, baseInterval?: string) {
+export function isValidInterval(value: string, baseInterval?: string) {
if (baseInterval) {
return _parseWithBase(value, baseInterval);
} else {
@@ -69,4 +69,37 @@ function _parseWithBase(value: string, baseInterval: string) {
}
}
-export { isValidJson, isValidInterval };
+// An inlined version of angular.toJSON()
+// source: https://github.com/angular/angular.js/blob/master/src/Angular.js#L1312
+// @internal
+export function toAngularJSON(obj: any, pretty?: any): string {
+ if (obj === undefined) return '';
+ if (typeof pretty === 'number') {
+ pretty = pretty ? 2 : null;
+ }
+ return JSON.stringify(obj, toJsonReplacer, pretty);
+}
+
+function isWindow(obj: any) {
+ return obj && obj.window === obj;
+}
+
+function isScope(obj: any) {
+ return obj && obj.$evalAsync && obj.$watch;
+}
+
+function toJsonReplacer(key: any, value: any) {
+ let val = value;
+
+ if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
+ val = undefined;
+ } else if (isWindow(value)) {
+ val = '$WINDOW';
+ } else if (value && window.document === value) {
+ val = '$DOCUMENT';
+ } else if (isScope(value)) {
+ val = '$SCOPE';
+ }
+
+ return val;
+}
diff --git a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts
index 7a5d927d0f219..24dd1c4944bfb 100644
--- a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts
+++ b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts
@@ -19,7 +19,7 @@
import { get, has } from 'lodash';
import { i18n } from '@kbn/i18n';
-import { AggConfigs, IAggConfigs } from 'ui/agg_types';
+import { createAggConfigs, IAggConfigs } from 'ui/agg_types';
import { createFormat } from 'ui/visualize/loader/pipeline_helpers/utilities';
import {
KibanaContext,
@@ -258,7 +258,7 @@ export const esaggs = (): ExpressionFunctionDefinition {
- const aggConfigs = new AggConfigs(indexPattern);
+ const { aggs } = getSearchServiceShim();
+ const aggConfigs = aggs.createAggConfigs(indexPattern);
const aggConfig = aggConfigs.createAggConfig({
enabled: true,
type,
diff --git a/src/legacy/core_plugins/data/public/search/mocks.ts b/src/legacy/core_plugins/data/public/search/mocks.ts
new file mode 100644
index 0000000000000..86b6a928dc5b4
--- /dev/null
+++ b/src/legacy/core_plugins/data/public/search/mocks.ts
@@ -0,0 +1,85 @@
+/*
+ * 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 { SearchSetup, SearchStart } from './search_service';
+import { AggTypesRegistrySetup, AggTypesRegistryStart } from './aggs/agg_types_registry';
+import { AggConfigs } from './aggs/agg_configs';
+import { mockAggTypesRegistry } from './aggs/test_helpers';
+
+const aggTypeBaseParamMock = () => ({
+ name: 'some_param',
+ type: 'some_param_type',
+ displayName: 'some_agg_type_param',
+ required: false,
+ advanced: false,
+ default: {},
+ write: jest.fn(),
+ serialize: jest.fn().mockImplementation(() => {}),
+ deserialize: jest.fn().mockImplementation(() => {}),
+ options: [],
+});
+
+const aggTypeConfigMock = () => ({
+ name: 'some_name',
+ title: 'some_title',
+ params: [aggTypeBaseParamMock()],
+});
+
+export const aggTypesRegistrySetupMock = (): MockedKeys => ({
+ registerBucket: jest.fn(),
+ registerMetric: jest.fn(),
+});
+
+export const aggTypesRegistryStartMock = (): MockedKeys => ({
+ get: jest.fn().mockImplementation(aggTypeConfigMock),
+ getBuckets: jest.fn().mockImplementation(() => [aggTypeConfigMock()]),
+ getMetrics: jest.fn().mockImplementation(() => [aggTypeConfigMock()]),
+ getAll: jest.fn().mockImplementation(() => ({
+ buckets: [aggTypeConfigMock()],
+ metrics: [aggTypeConfigMock()],
+ })),
+});
+
+export const searchSetupMock = (): MockedKeys => ({
+ aggs: {
+ types: aggTypesRegistrySetupMock(),
+ },
+});
+
+export const searchStartMock = (): MockedKeys => ({
+ aggs: {
+ createAggConfigs: jest.fn().mockImplementation((indexPattern, configStates = [], schemas) => {
+ return new AggConfigs(indexPattern, configStates, {
+ schemas,
+ typesRegistry: mockAggTypesRegistry(),
+ });
+ }),
+ types: mockAggTypesRegistry(),
+ __LEGACY: {
+ AggConfig: jest.fn() as any,
+ AggType: jest.fn(),
+ aggTypeFieldFilters: jest.fn() as any,
+ FieldParamType: jest.fn(),
+ MetricAggType: jest.fn(),
+ parentPipelineAggHelper: jest.fn() as any,
+ setBounds: jest.fn(),
+ siblingPipelineAggHelper: jest.fn() as any,
+ },
+ },
+});
diff --git a/src/legacy/core_plugins/data/public/search/search_service.ts b/src/legacy/core_plugins/data/public/search/search_service.ts
index 45f9ff17328ad..6754c0e3551af 100644
--- a/src/legacy/core_plugins/data/public/search/search_service.ts
+++ b/src/legacy/core_plugins/data/public/search/search_service.ts
@@ -18,11 +18,16 @@
*/
import { CoreSetup, CoreStart } from '../../../../../core/public';
+import { IndexPattern } from '../../../../../plugins/data/public';
import {
aggTypes,
AggType,
+ AggTypesRegistry,
+ AggTypesRegistrySetup,
+ AggTypesRegistryStart,
AggConfig,
AggConfigs,
+ CreateAggConfigParams,
FieldParamType,
MetricAggType,
aggTypeFieldFilters,
@@ -32,20 +37,28 @@ import {
} from './aggs';
interface AggsSetup {
- types: typeof aggTypes;
+ types: AggTypesRegistrySetup;
}
-interface AggsStart {
- types: typeof aggTypes;
+interface AggsStartLegacy {
AggConfig: typeof AggConfig;
- AggConfigs: typeof AggConfigs;
AggType: typeof AggType;
aggTypeFieldFilters: typeof aggTypeFieldFilters;
FieldParamType: typeof FieldParamType;
MetricAggType: typeof MetricAggType;
parentPipelineAggHelper: typeof parentPipelineAggHelper;
- siblingPipelineAggHelper: typeof siblingPipelineAggHelper;
setBounds: typeof setBounds;
+ siblingPipelineAggHelper: typeof siblingPipelineAggHelper;
+}
+
+interface AggsStart {
+ createAggConfigs: (
+ indexPattern: IndexPattern,
+ configStates?: CreateAggConfigParams[],
+ schemas?: Record
+ ) => InstanceType;
+ types: AggTypesRegistryStart;
+ __LEGACY: AggsStartLegacy;
}
export interface SearchSetup {
@@ -63,28 +76,41 @@ export interface SearchStart {
* it will move into the existing search service in src/plugins/data/public/search
*/
export class SearchService {
+ private readonly aggTypesRegistry = new AggTypesRegistry();
+
public setup(core: CoreSetup): SearchSetup {
+ const aggTypesSetup = this.aggTypesRegistry.setup();
+ aggTypes.buckets.forEach(b => aggTypesSetup.registerBucket(b));
+ aggTypes.metrics.forEach(m => aggTypesSetup.registerMetric(m));
+
return {
aggs: {
- types: aggTypes, // TODO convert to registry
- // TODO add other items as needed
+ types: aggTypesSetup,
},
};
}
public start(core: CoreStart): SearchStart {
+ const aggTypesStart = this.aggTypesRegistry.start();
return {
aggs: {
- types: aggTypes, // TODO convert to registry
- AggConfig, // TODO make static
- AggConfigs,
- AggType,
- aggTypeFieldFilters,
- FieldParamType,
- MetricAggType,
- parentPipelineAggHelper, // TODO make static
- siblingPipelineAggHelper, // TODO make static
- setBounds, // TODO make static
+ createAggConfigs: (indexPattern, configStates = [], schemas) => {
+ return new AggConfigs(indexPattern, configStates, {
+ schemas,
+ typesRegistry: aggTypesStart,
+ });
+ },
+ types: aggTypesStart,
+ __LEGACY: {
+ AggConfig, // TODO make static
+ AggType,
+ aggTypeFieldFilters,
+ FieldParamType,
+ MetricAggType,
+ parentPipelineAggHelper, // TODO make static
+ setBounds, // TODO make static
+ siblingPipelineAggHelper, // TODO make static
+ },
},
};
}
diff --git a/src/legacy/core_plugins/data/public/search/tabify/buckets.test.ts b/src/legacy/core_plugins/data/public/search/tabify/buckets.test.ts
index ef2748102623a..98048cb25db2f 100644
--- a/src/legacy/core_plugins/data/public/search/tabify/buckets.test.ts
+++ b/src/legacy/core_plugins/data/public/search/tabify/buckets.test.ts
@@ -20,8 +20,6 @@
import { TabifyBuckets } from './buckets';
import { AggGroupNames } from '../aggs';
-jest.mock('ui/new_platform');
-
describe('Buckets wrapper', () => {
const check = (aggResp: any, count: number, keys: string[]) => {
test('reads the length', () => {
diff --git a/src/legacy/core_plugins/data/public/search/tabify/get_columns.test.ts b/src/legacy/core_plugins/data/public/search/tabify/get_columns.test.ts
index cfd4cd7de640b..6c5dc790ef976 100644
--- a/src/legacy/core_plugins/data/public/search/tabify/get_columns.test.ts
+++ b/src/legacy/core_plugins/data/public/search/tabify/get_columns.test.ts
@@ -18,12 +18,17 @@
*/
import { tabifyGetColumns } from './get_columns';
-import { AggConfigs, AggGroupNames, Schemas } from '../aggs';
import { TabbedAggColumn } from './types';
-
-jest.mock('ui/new_platform');
+import { AggConfigs, AggGroupNames, Schemas } from '../aggs';
+import { mockAggTypesRegistry, mockDataServices } from '../aggs/test_helpers';
describe('get columns', () => {
+ beforeEach(() => {
+ mockDataServices();
+ });
+
+ const typesRegistry = mockAggTypesRegistry();
+
const createAggConfigs = (aggs: any[] = []) => {
const field = {
name: '@timestamp',
@@ -38,18 +43,17 @@ describe('get columns', () => {
},
} as any;
- return new AggConfigs(
- indexPattern,
- aggs,
- new Schemas([
+ return new AggConfigs(indexPattern, aggs, {
+ typesRegistry,
+ schemas: new Schemas([
{
group: AggGroupNames.Metrics,
name: 'metric',
min: 1,
defaults: [{ schema: 'metric', type: 'count' }],
},
- ]).all
- );
+ ]).all,
+ });
};
test('should inject a count metric if no aggs exist', () => {
diff --git a/src/legacy/core_plugins/data/public/search/tabify/response_writer.test.ts b/src/legacy/core_plugins/data/public/search/tabify/response_writer.test.ts
index f5df0a683ca00..94301eedac74a 100644
--- a/src/legacy/core_plugins/data/public/search/tabify/response_writer.test.ts
+++ b/src/legacy/core_plugins/data/public/search/tabify/response_writer.test.ts
@@ -19,14 +19,19 @@
import { TabbedAggResponseWriter } from './response_writer';
import { AggConfigs, AggGroupNames, Schemas, BUCKET_TYPES } from '../aggs';
+import { mockDataServices, mockAggTypesRegistry } from '../aggs/test_helpers';
import { TabbedResponseWriterOptions } from './types';
-jest.mock('ui/new_platform');
-
describe('TabbedAggResponseWriter class', () => {
+ beforeEach(() => {
+ mockDataServices();
+ });
+
let responseWriter: TabbedAggResponseWriter;
+ const typesRegistry = mockAggTypesRegistry();
+
const splitAggConfig = [
{
type: BUCKET_TYPES.TERMS,
@@ -66,18 +71,17 @@ describe('TabbedAggResponseWriter class', () => {
} as any;
return new TabbedAggResponseWriter(
- new AggConfigs(
- indexPattern,
- aggs,
- new Schemas([
+ new AggConfigs(indexPattern, aggs, {
+ typesRegistry,
+ schemas: new Schemas([
{
group: AggGroupNames.Metrics,
name: 'metric',
min: 1,
defaults: [{ schema: 'metric', type: 'count' }],
},
- ]).all
- ),
+ ]).all,
+ }),
{
metricsAtAllLevels: false,
partialRows: false,
diff --git a/src/legacy/core_plugins/data/public/search/tabify/tabify.test.ts b/src/legacy/core_plugins/data/public/search/tabify/tabify.test.ts
index 13fe7719b0a85..db4ad3bdea96b 100644
--- a/src/legacy/core_plugins/data/public/search/tabify/tabify.test.ts
+++ b/src/legacy/core_plugins/data/public/search/tabify/tabify.test.ts
@@ -20,11 +20,12 @@
import { IndexPattern } from '../../../../../../plugins/data/public';
import { tabifyAggResponse } from './tabify';
import { IAggConfig, IAggConfigs, AggGroupNames, Schemas, AggConfigs } from '../aggs';
+import { mockAggTypesRegistry } from '../aggs/test_helpers';
import { metricOnly, threeTermBuckets } from 'fixtures/fake_hierarchical_data';
-jest.mock('ui/new_platform');
-
describe('tabifyAggResponse Integration', () => {
+ const typesRegistry = mockAggTypesRegistry();
+
const createAggConfigs = (aggs: IAggConfig[] = []) => {
const field = {
name: '@timestamp',
@@ -39,18 +40,17 @@ describe('tabifyAggResponse Integration', () => {
},
} as unknown) as IndexPattern;
- return new AggConfigs(
- indexPattern,
- aggs,
- new Schemas([
+ return new AggConfigs(indexPattern, aggs, {
+ typesRegistry,
+ schemas: new Schemas([
{
group: AggGroupNames.Metrics,
name: 'metric',
min: 1,
defaults: [{ schema: 'metric', type: 'count' }],
},
- ]).all
- );
+ ]).all,
+ });
};
const mockAggConfig = (agg: any): IAggConfig => (agg as unknown) as IAggConfig;
diff --git a/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.mocks.ts b/src/legacy/core_plugins/data/public/services.ts
similarity index 76%
rename from src/legacy/core_plugins/data/public/actions/filters/brush_event.test.mocks.ts
rename to src/legacy/core_plugins/data/public/services.ts
index 2cecfd0fe8b76..7ecd041c70e22 100644
--- a/src/legacy/core_plugins/data/public/actions/filters/brush_event.test.mocks.ts
+++ b/src/legacy/core_plugins/data/public/services.ts
@@ -17,12 +17,9 @@
* under the License.
*/
-import { chromeServiceMock } from '../../../../../../core/public/mocks';
+import { createGetterSetter } from '../../../../plugins/kibana_utils/public';
+import { SearchStart } from './search/search_service';
-jest.doMock('ui/new_platform', () => ({
- npStart: {
- core: {
- chrome: chromeServiceMock.createStartContract(),
- },
- },
-}));
+export const [getSearchServiceShim, setSearchServiceShim] = createGetterSetter(
+ 'searchShim'
+);
diff --git a/src/legacy/core_plugins/kibana/public/dev_tools/README.md b/src/legacy/core_plugins/kibana/public/dev_tools/README.md
index 0234830d6071c..199ddcc754d04 100644
--- a/src/legacy/core_plugins/kibana/public/dev_tools/README.md
+++ b/src/legacy/core_plugins/kibana/public/dev_tools/README.md
@@ -1,4 +1,3 @@
This folder is just a left-over of the things that can't be moved to Kibana platform just yet:
-* Styling (this can be moved as soon as there is support for styling in Kibana platform)
* Check whether there are no dev tools and hide the link in the nav bar (this can be moved as soon as all dev tools are moved)
\ No newline at end of file
diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable.ts
index 2bb76386bb7ba..738a74d93449d 100644
--- a/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable.ts
@@ -20,7 +20,7 @@ import _ from 'lodash';
import * as Rx from 'rxjs';
import { Subscription } from 'rxjs';
import { i18n } from '@kbn/i18n';
-import { ExecuteTriggerActions } from 'src/plugins/ui_actions/public';
+import { UiActionsStart } from 'src/plugins/ui_actions/public';
import { RequestAdapter, Adapters } from '../../../../../../../plugins/inspector/public';
import {
esFilters,
@@ -110,7 +110,7 @@ export class SearchEmbeddable extends Embeddable
filterManager,
}: SearchEmbeddableConfig,
initialInput: SearchInput,
- private readonly executeTriggerActions: ExecuteTriggerActions,
+ private readonly executeTriggerActions: UiActionsStart['executeTriggerActions'],
parent?: Container
) {
super(
diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable_factory.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable_factory.ts
index 15b3f2d4517ac..90f1549c9f369 100644
--- a/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable_factory.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/search_embeddable_factory.ts
@@ -19,7 +19,7 @@
import { auto } from 'angular';
import { i18n } from '@kbn/i18n';
-import { ExecuteTriggerActions } from 'src/plugins/ui_actions/public';
+import { UiActionsStart } from 'src/plugins/ui_actions/public';
import { getServices } from '../../kibana_services';
import {
EmbeddableFactory,
@@ -43,7 +43,7 @@ export class SearchEmbeddableFactory extends EmbeddableFactory<
public isEditable: () => boolean;
constructor(
- private readonly executeTriggerActions: ExecuteTriggerActions,
+ private readonly executeTriggerActions: UiActionsStart['executeTriggerActions'],
getInjector: () => Promise,
isEditable: () => boolean
) {
diff --git a/src/legacy/core_plugins/kibana/public/home/np_ready/components/__snapshots__/synopsis.test.js.snap b/src/legacy/core_plugins/kibana/public/home/np_ready/components/__snapshots__/synopsis.test.js.snap
index 525cc5bdda9d4..594d67d9c8eb0 100644
--- a/src/legacy/core_plugins/kibana/public/home/np_ready/components/__snapshots__/synopsis.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/home/np_ready/components/__snapshots__/synopsis.test.js.snap
@@ -9,6 +9,7 @@ exports[`props iconType 1`] = `
href="link_to_item"
icon={
diff --git a/src/legacy/core_plugins/kibana/public/home/np_ready/components/synopsis.js b/src/legacy/core_plugins/kibana/public/home/np_ready/components/synopsis.js
index 968b8eb64def5..f43c377b4e5b9 100644
--- a/src/legacy/core_plugins/kibana/public/home/np_ready/components/synopsis.js
+++ b/src/legacy/core_plugins/kibana/public/home/np_ready/components/synopsis.js
@@ -37,13 +37,7 @@ export function Synopsis({
if (iconUrl) {
optionalImg = ;
} else if (iconType) {
- optionalImg = (
-
- );
+ optionalImg = ;
}
const classes = classNames('homSynopsis__card', {
diff --git a/src/legacy/core_plugins/kibana/public/index.scss b/src/legacy/core_plugins/kibana/public/index.scss
index 324458c0814d9..3eef84c32db79 100644
--- a/src/legacy/core_plugins/kibana/public/index.scss
+++ b/src/legacy/core_plugins/kibana/public/index.scss
@@ -10,9 +10,6 @@
// vis_type_vislib UI styles
@import 'src/legacy/core_plugins/vis_type_vislib/public/index';
-// Dev tools styles
-@import './dev_tools/index';
-
// Discover styles
@import 'discover/index';
diff --git a/src/legacy/core_plugins/telemetry/common/constants.ts b/src/legacy/core_plugins/telemetry/common/constants.ts
index 52981c04ad34a..b44bf319e6627 100644
--- a/src/legacy/core_plugins/telemetry/common/constants.ts
+++ b/src/legacy/core_plugins/telemetry/common/constants.ts
@@ -66,6 +66,11 @@ export const TELEMETRY_STATS_TYPE = 'telemetry';
*/
export const UI_METRIC_USAGE_TYPE = 'ui_metric';
+/**
+ * Application Usage type
+ */
+export const APPLICATION_USAGE_TYPE = 'application_usage';
+
/**
* Link to Advanced Settings.
*/
diff --git a/src/legacy/core_plugins/telemetry/index.ts b/src/legacy/core_plugins/telemetry/index.ts
index ec70380d83a0a..1e88e7d65cffd 100644
--- a/src/legacy/core_plugins/telemetry/index.ts
+++ b/src/legacy/core_plugins/telemetry/index.ts
@@ -21,7 +21,7 @@ import * as Rx from 'rxjs';
import { resolve } from 'path';
import JoiNamespace from 'joi';
import { Server } from 'hapi';
-import { CoreSetup, PluginInitializerContext } from 'src/core/server';
+import { PluginInitializerContext } from 'src/core/server';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { getConfigPath } from '../../../core/server/path';
// @ts-ignore
@@ -132,11 +132,6 @@ const telemetry = (kibana: any) => {
},
} as PluginInitializerContext;
- const coreSetup = ({
- http: { server },
- log: server.log,
- } as any) as CoreSetup;
-
try {
await handleOldSettings(server);
} catch (err) {
@@ -147,7 +142,9 @@ const telemetry = (kibana: any) => {
usageCollection,
};
- telemetryPlugin(initializerContext).setup(coreSetup, pluginsSetup, server);
+ const npPlugin = telemetryPlugin(initializerContext);
+ await npPlugin.setup(server.newPlatform.setup.core, pluginsSetup, server);
+ await npPlugin.start(server.newPlatform.start.core);
},
});
};
diff --git a/src/legacy/core_plugins/telemetry/server/collectors/application_usage/index.test.ts b/src/legacy/core_plugins/telemetry/server/collectors/application_usage/index.test.ts
new file mode 100644
index 0000000000000..cdfead2dff3c6
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/collectors/application_usage/index.test.ts
@@ -0,0 +1,144 @@
+/*
+ * 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 { UsageCollectionSetup } from '../../../../../../plugins/usage_collection/server';
+import { savedObjectsRepositoryMock } from '../../../../../../core/server/mocks';
+// eslint-disable-next-line @kbn/eslint/no-restricted-paths
+import { CollectorOptions } from '../../../../../../plugins/usage_collection/server/collector/collector';
+
+import { registerApplicationUsageCollector } from './';
+import {
+ ROLL_INDICES_INTERVAL,
+ SAVED_OBJECTS_TOTAL_TYPE,
+ SAVED_OBJECTS_TRANSACTIONAL_TYPE,
+} from './telemetry_application_usage_collector';
+
+describe('telemetry_application_usage', () => {
+ jest.useFakeTimers();
+
+ let collector: CollectorOptions;
+
+ const usageCollectionMock: jest.Mocked = {
+ makeUsageCollector: jest.fn().mockImplementation(config => (collector = config)),
+ registerCollector: jest.fn(),
+ } as any;
+
+ const getUsageCollector = jest.fn();
+ const callCluster = jest.fn();
+
+ beforeAll(() => registerApplicationUsageCollector(usageCollectionMock, getUsageCollector));
+ afterAll(() => jest.clearAllTimers());
+
+ test('registered collector is set', () => {
+ expect(collector).not.toBeUndefined();
+ });
+
+ test('if no savedObjectClient initialised, return undefined', async () => {
+ expect(await collector.fetch(callCluster)).toBeUndefined();
+ jest.runTimersToTime(ROLL_INDICES_INTERVAL);
+ });
+
+ test('when savedObjectClient is initialised, return something', async () => {
+ const savedObjectClient = savedObjectsRepositoryMock.create();
+ savedObjectClient.find.mockImplementation(
+ async () =>
+ ({
+ saved_objects: [],
+ total: 0,
+ } as any)
+ );
+ getUsageCollector.mockImplementation(() => savedObjectClient);
+
+ jest.runTimersToTime(ROLL_INDICES_INTERVAL); // Force rollTotals to run
+
+ expect(await collector.fetch(callCluster)).toStrictEqual({});
+ expect(savedObjectClient.bulkCreate).not.toHaveBeenCalled();
+ });
+
+ test('paging in findAll works', async () => {
+ const savedObjectClient = savedObjectsRepositoryMock.create();
+ let total = 201;
+ savedObjectClient.find.mockImplementation(async opts => {
+ if (opts.type === SAVED_OBJECTS_TOTAL_TYPE) {
+ return {
+ saved_objects: [
+ {
+ id: 'appId',
+ attributes: {
+ appId: 'appId',
+ minutesOnScreen: 10,
+ numberOfClicks: 10,
+ },
+ },
+ ],
+ total: 1,
+ } as any;
+ }
+ if ((opts.page || 1) > 2) {
+ return { saved_objects: [], total };
+ }
+ const doc = {
+ id: 'test-id',
+ attributes: {
+ appId: 'appId',
+ timestamp: new Date().toISOString(),
+ minutesOnScreen: 1,
+ numberOfClicks: 1,
+ },
+ };
+ const savedObjects = new Array(opts.perPage).fill(doc);
+ total = savedObjects.length * 2 + 1;
+ return { saved_objects: savedObjects, total };
+ });
+
+ getUsageCollector.mockImplementation(() => savedObjectClient);
+
+ jest.runTimersToTime(ROLL_INDICES_INTERVAL); // Force rollTotals to run
+
+ expect(await collector.fetch(callCluster)).toStrictEqual({
+ appId: {
+ clicks_total: total - 1 + 10,
+ clicks_30_days: total - 1,
+ clicks_90_days: total - 1,
+ minutes_on_screen_total: total - 1 + 10,
+ minutes_on_screen_30_days: total - 1,
+ minutes_on_screen_90_days: total - 1,
+ },
+ });
+ expect(savedObjectClient.bulkCreate).toHaveBeenCalledWith(
+ [
+ {
+ id: 'appId',
+ type: SAVED_OBJECTS_TOTAL_TYPE,
+ attributes: {
+ appId: 'appId',
+ minutesOnScreen: total - 1 + 10,
+ numberOfClicks: total - 1 + 10,
+ },
+ },
+ ],
+ { overwrite: true }
+ );
+ expect(savedObjectClient.delete).toHaveBeenCalledTimes(total - 1);
+ expect(savedObjectClient.delete).toHaveBeenCalledWith(
+ SAVED_OBJECTS_TRANSACTIONAL_TYPE,
+ 'test-id'
+ );
+ });
+});
diff --git a/src/legacy/ui/public/vis/__tests__/index.js b/src/legacy/core_plugins/telemetry/server/collectors/application_usage/index.ts
similarity index 89%
rename from src/legacy/ui/public/vis/__tests__/index.js
rename to src/legacy/core_plugins/telemetry/server/collectors/application_usage/index.ts
index 46074f2c5197b..1dac303880375 100644
--- a/src/legacy/ui/public/vis/__tests__/index.js
+++ b/src/legacy/core_plugins/telemetry/server/collectors/application_usage/index.ts
@@ -17,5 +17,4 @@
* under the License.
*/
-import './_agg_config';
-import './_agg_configs';
+export { registerApplicationUsageCollector } from './telemetry_application_usage_collector';
diff --git a/src/legacy/core_plugins/telemetry/server/collectors/application_usage/telemetry_application_usage_collector.ts b/src/legacy/core_plugins/telemetry/server/collectors/application_usage/telemetry_application_usage_collector.ts
new file mode 100644
index 0000000000000..5047ebc4b0454
--- /dev/null
+++ b/src/legacy/core_plugins/telemetry/server/collectors/application_usage/telemetry_application_usage_collector.ts
@@ -0,0 +1,225 @@
+/*
+ * 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 moment from 'moment';
+import { APPLICATION_USAGE_TYPE } from '../../../common/constants';
+import { UsageCollectionSetup } from '../../../../../../plugins/usage_collection/server';
+import {
+ ISavedObjectsRepository,
+ SavedObjectAttributes,
+ SavedObjectsFindOptions,
+ SavedObject,
+} from '../../../../../../core/server';
+
+/**
+ * Roll indices every 24h
+ */
+export const ROLL_INDICES_INTERVAL = 24 * 60 * 60 * 1000;
+
+/**
+ * Start rolling indices after 5 minutes up
+ */
+export const ROLL_INDICES_START = 5 * 60 * 1000;
+
+export const SAVED_OBJECTS_TOTAL_TYPE = 'application_usage_totals';
+export const SAVED_OBJECTS_TRANSACTIONAL_TYPE = 'application_usage_transactional';
+
+interface ApplicationUsageTotal extends SavedObjectAttributes {
+ appId: string;
+ minutesOnScreen: number;
+ numberOfClicks: number;
+}
+
+interface ApplicationUsageTransactional extends ApplicationUsageTotal {
+ timestamp: string;
+}
+
+interface ApplicationUsageTelemetryReport {
+ [appId: string]: {
+ clicks_total: number;
+ clicks_30_days: number;
+ clicks_90_days: number;
+ minutes_on_screen_total: number;
+ minutes_on_screen_30_days: number;
+ minutes_on_screen_90_days: number;
+ };
+}
+
+async function findAll(
+ savedObjectsClient: ISavedObjectsRepository,
+ opts: SavedObjectsFindOptions
+): Promise>> {
+ const { page = 1, perPage = 100, ...options } = opts;
+ const { saved_objects: savedObjects, total } = await savedObjectsClient.find({
+ ...options,
+ page,
+ perPage,
+ });
+ if (page * perPage >= total) {
+ return savedObjects;
+ }
+ return [...savedObjects, ...(await findAll(savedObjectsClient, { ...opts, page: page + 1 }))];
+}
+
+export function registerApplicationUsageCollector(
+ usageCollection: UsageCollectionSetup,
+ getSavedObjectsClient: () => ISavedObjectsRepository | undefined
+) {
+ const collector = usageCollection.makeUsageCollector({
+ type: APPLICATION_USAGE_TYPE,
+ isReady: () => typeof getSavedObjectsClient() !== 'undefined',
+ fetch: async () => {
+ const savedObjectsClient = getSavedObjectsClient();
+ if (typeof savedObjectsClient === 'undefined') {
+ return;
+ }
+ const [rawApplicationUsageTotals, rawApplicationUsageTransactional] = await Promise.all([
+ findAll(savedObjectsClient, { type: SAVED_OBJECTS_TOTAL_TYPE }),
+ findAll(savedObjectsClient, {
+ type: SAVED_OBJECTS_TRANSACTIONAL_TYPE,
+ }),
+ ]);
+
+ const applicationUsageFromTotals = rawApplicationUsageTotals.reduce(
+ (acc, { attributes: { appId, minutesOnScreen, numberOfClicks } }) => {
+ const existing = acc[appId] || { clicks_total: 0, minutes_on_screen_total: 0 };
+ return {
+ ...acc,
+ [appId]: {
+ clicks_total: numberOfClicks + existing.clicks_total,
+ clicks_30_days: 0,
+ clicks_90_days: 0,
+ minutes_on_screen_total: minutesOnScreen + existing.minutes_on_screen_total,
+ minutes_on_screen_30_days: 0,
+ minutes_on_screen_90_days: 0,
+ },
+ };
+ },
+ {} as ApplicationUsageTelemetryReport
+ );
+
+ const nowMinus30 = moment().subtract(30, 'days');
+ const nowMinus90 = moment().subtract(90, 'days');
+
+ const applicationUsage = rawApplicationUsageTransactional.reduce(
+ (acc, { attributes: { appId, minutesOnScreen, numberOfClicks, timestamp } }) => {
+ const existing = acc[appId] || {
+ clicks_total: 0,
+ clicks_30_days: 0,
+ clicks_90_days: 0,
+ minutes_on_screen_total: 0,
+ minutes_on_screen_30_days: 0,
+ minutes_on_screen_90_days: 0,
+ };
+
+ const timeOfEntry = moment(timestamp as string);
+ const isInLast30Days = timeOfEntry.isSameOrAfter(nowMinus30);
+ const isInLast90Days = timeOfEntry.isSameOrAfter(nowMinus90);
+
+ const last30Days = {
+ clicks_30_days: existing.clicks_30_days + numberOfClicks,
+ minutes_on_screen_30_days: existing.minutes_on_screen_30_days + minutesOnScreen,
+ };
+ const last90Days = {
+ clicks_90_days: existing.clicks_90_days + numberOfClicks,
+ minutes_on_screen_90_days: existing.minutes_on_screen_90_days + minutesOnScreen,
+ };
+
+ return {
+ ...acc,
+ [appId]: {
+ ...existing,
+ clicks_total: existing.clicks_total + numberOfClicks,
+ minutes_on_screen_total: existing.minutes_on_screen_total + minutesOnScreen,
+ ...(isInLast30Days ? last30Days : {}),
+ ...(isInLast90Days ? last90Days : {}),
+ },
+ };
+ },
+ applicationUsageFromTotals
+ );
+
+ return applicationUsage;
+ },
+ });
+
+ usageCollection.registerCollector(collector);
+
+ setInterval(() => rollTotals(getSavedObjectsClient()), ROLL_INDICES_INTERVAL);
+ setTimeout(() => rollTotals(getSavedObjectsClient()), ROLL_INDICES_START);
+}
+
+async function rollTotals(savedObjectsClient?: ISavedObjectsRepository) {
+ if (!savedObjectsClient) {
+ return;
+ }
+
+ try {
+ const [rawApplicationUsageTotals, rawApplicationUsageTransactional] = await Promise.all([
+ findAll(savedObjectsClient, { type: SAVED_OBJECTS_TOTAL_TYPE }),
+ findAll(savedObjectsClient, {
+ type: SAVED_OBJECTS_TRANSACTIONAL_TYPE,
+ filter: `${SAVED_OBJECTS_TRANSACTIONAL_TYPE}.attributes.timestamp < now-90d`,
+ }),
+ ]);
+
+ const existingTotals = rawApplicationUsageTotals.reduce(
+ (acc, { attributes: { appId, numberOfClicks, minutesOnScreen } }) => {
+ return {
+ ...acc,
+ // No need to sum because there should be 1 document per appId only
+ [appId]: { appId, numberOfClicks, minutesOnScreen },
+ };
+ },
+ {} as Record
+ );
+
+ const totals = rawApplicationUsageTransactional.reduce((acc, { attributes, id }) => {
+ const { appId, numberOfClicks, minutesOnScreen } = attributes;
+
+ const existing = acc[appId] || { minutesOnScreen: 0, numberOfClicks: 0 };
+
+ return {
+ ...acc,
+ [appId]: {
+ appId,
+ numberOfClicks: numberOfClicks + existing.numberOfClicks,
+ minutesOnScreen: minutesOnScreen + existing.minutesOnScreen,
+ },
+ };
+ }, existingTotals);
+
+ await Promise.all([
+ Object.entries(totals).length &&
+ savedObjectsClient.bulkCreate(
+ Object.entries(totals).map(([id, entry]) => ({
+ type: SAVED_OBJECTS_TOTAL_TYPE,
+ id,
+ attributes: entry,
+ })),
+ { overwrite: true }
+ ),
+ ...rawApplicationUsageTransactional.map(
+ ({ id }) => savedObjectsClient.delete(SAVED_OBJECTS_TRANSACTIONAL_TYPE, id) // There is no bulkDelete :(
+ ),
+ ]);
+ } catch (err) {
+ // Silent failure
+ }
+}
diff --git a/src/legacy/core_plugins/telemetry/server/collectors/index.ts b/src/legacy/core_plugins/telemetry/server/collectors/index.ts
index 04ee4773cd60d..6cb7a38b6414f 100644
--- a/src/legacy/core_plugins/telemetry/server/collectors/index.ts
+++ b/src/legacy/core_plugins/telemetry/server/collectors/index.ts
@@ -23,3 +23,4 @@ export { registerUiMetricUsageCollector } from './ui_metric';
export { registerLocalizationUsageCollector } from './localization';
export { registerTelemetryPluginUsageCollector } from './telemetry_plugin';
export { registerManagementUsageCollector } from './management';
+export { registerApplicationUsageCollector } from './application_usage';
diff --git a/src/legacy/core_plugins/telemetry/server/plugin.ts b/src/legacy/core_plugins/telemetry/server/plugin.ts
index b5b53b1daba55..d859c0cfd4678 100644
--- a/src/legacy/core_plugins/telemetry/server/plugin.ts
+++ b/src/legacy/core_plugins/telemetry/server/plugin.ts
@@ -17,7 +17,12 @@
* under the License.
*/
-import { CoreSetup, PluginInitializerContext } from 'src/core/server';
+import {
+ CoreSetup,
+ PluginInitializerContext,
+ ISavedObjectsRepository,
+ CoreStart,
+} from 'src/core/server';
import { Server } from 'hapi';
import { registerRoutes } from './routes';
import { registerCollection } from './telemetry_collection';
@@ -28,6 +33,7 @@ import {
registerLocalizationUsageCollector,
registerTelemetryPluginUsageCollector,
registerManagementUsageCollector,
+ registerApplicationUsageCollector,
} from './collectors';
export interface PluginsSetup {
@@ -36,6 +42,7 @@ export interface PluginsSetup {
export class TelemetryPlugin {
private readonly currentKibanaVersion: string;
+ private savedObjectsClient?: ISavedObjectsRepository;
constructor(initializerContext: PluginInitializerContext) {
this.currentKibanaVersion = initializerContext.env.packageInfo.version;
@@ -45,12 +52,19 @@ export class TelemetryPlugin {
const currentKibanaVersion = this.currentKibanaVersion;
registerCollection();
- registerRoutes({ core, currentKibanaVersion });
+ registerRoutes({ core, currentKibanaVersion, server });
+
+ const getSavedObjectsClient = () => this.savedObjectsClient;
registerTelemetryPluginUsageCollector(usageCollection, server);
registerLocalizationUsageCollector(usageCollection, server);
registerTelemetryUsageCollector(usageCollection, server);
registerUiMetricUsageCollector(usageCollection, server);
registerManagementUsageCollector(usageCollection, server);
+ registerApplicationUsageCollector(usageCollection, getSavedObjectsClient);
+ }
+
+ public start({ savedObjects }: CoreStart) {
+ this.savedObjectsClient = savedObjects.createInternalRepository();
}
}
diff --git a/src/legacy/core_plugins/telemetry/server/routes/index.ts b/src/legacy/core_plugins/telemetry/server/routes/index.ts
index 30c018ca7796d..31ff1682d6806 100644
--- a/src/legacy/core_plugins/telemetry/server/routes/index.ts
+++ b/src/legacy/core_plugins/telemetry/server/routes/index.ts
@@ -17,6 +17,7 @@
* under the License.
*/
+import { Legacy } from 'kibana';
import { CoreSetup } from 'src/core/server';
import { registerTelemetryOptInRoutes } from './telemetry_opt_in';
import { registerTelemetryUsageStatsRoutes } from './telemetry_usage_stats';
@@ -26,11 +27,12 @@ import { registerTelemetryUserHasSeenNotice } from './telemetry_user_has_seen_no
interface RegisterRoutesParams {
core: CoreSetup;
currentKibanaVersion: string;
+ server: Legacy.Server;
}
-export function registerRoutes({ core, currentKibanaVersion }: RegisterRoutesParams) {
- registerTelemetryOptInRoutes({ core, currentKibanaVersion });
- registerTelemetryUsageStatsRoutes(core);
- registerTelemetryOptInStatsRoutes(core);
- registerTelemetryUserHasSeenNotice(core);
+export function registerRoutes({ core, currentKibanaVersion, server }: RegisterRoutesParams) {
+ registerTelemetryOptInRoutes({ core, currentKibanaVersion, server });
+ registerTelemetryUsageStatsRoutes(server);
+ registerTelemetryOptInStatsRoutes(server);
+ registerTelemetryUserHasSeenNotice(server);
}
diff --git a/src/legacy/core_plugins/telemetry/server/routes/telemetry_opt_in.ts b/src/legacy/core_plugins/telemetry/server/routes/telemetry_opt_in.ts
index 596c5c17c353e..ccbc28f6cbadb 100644
--- a/src/legacy/core_plugins/telemetry/server/routes/telemetry_opt_in.ts
+++ b/src/legacy/core_plugins/telemetry/server/routes/telemetry_opt_in.ts
@@ -21,6 +21,7 @@ import Joi from 'joi';
import moment from 'moment';
import { boomify } from 'boom';
import { CoreSetup } from 'src/core/server';
+import { Legacy } from 'kibana';
import { getTelemetryAllowChangingOptInStatus } from '../telemetry_config';
import { sendTelemetryOptInStatus } from './telemetry_opt_in_stats';
@@ -32,14 +33,13 @@ import {
interface RegisterOptInRoutesParams {
core: CoreSetup;
currentKibanaVersion: string;
+ server: Legacy.Server;
}
export function registerTelemetryOptInRoutes({
- core,
+ server,
currentKibanaVersion,
}: RegisterOptInRoutesParams) {
- const { server } = core.http as any;
-
server.route({
method: 'POST',
path: '/api/telemetry/v2/optIn',
diff --git a/src/legacy/core_plugins/telemetry/server/routes/telemetry_opt_in_stats.ts b/src/legacy/core_plugins/telemetry/server/routes/telemetry_opt_in_stats.ts
index d3bf6dbb77d7a..e64f3f6ff8a94 100644
--- a/src/legacy/core_plugins/telemetry/server/routes/telemetry_opt_in_stats.ts
+++ b/src/legacy/core_plugins/telemetry/server/routes/telemetry_opt_in_stats.ts
@@ -21,7 +21,7 @@
import fetch from 'node-fetch';
import Joi from 'joi';
import moment from 'moment';
-import { CoreSetup } from 'src/core/server';
+import { Legacy } from 'kibana';
import { telemetryCollectionManager, StatsGetterConfig } from '../collection_manager';
interface SendTelemetryOptInStatusConfig {
@@ -45,9 +45,7 @@ export async function sendTelemetryOptInStatus(
});
}
-export function registerTelemetryOptInStatsRoutes(core: CoreSetup) {
- const { server } = core.http as any;
-
+export function registerTelemetryOptInStatsRoutes(server: Legacy.Server) {
server.route({
method: 'POST',
path: '/api/telemetry/v2/clusters/_opt_in_stats',
diff --git a/src/legacy/core_plugins/telemetry/server/routes/telemetry_usage_stats.ts b/src/legacy/core_plugins/telemetry/server/routes/telemetry_usage_stats.ts
index c14314ca4da24..ee3241b0dc2ea 100644
--- a/src/legacy/core_plugins/telemetry/server/routes/telemetry_usage_stats.ts
+++ b/src/legacy/core_plugins/telemetry/server/routes/telemetry_usage_stats.ts
@@ -19,16 +19,14 @@
import Joi from 'joi';
import { boomify } from 'boom';
-import { CoreSetup } from 'src/core/server';
+import { Legacy } from 'kibana';
import { telemetryCollectionManager } from '../collection_manager';
-export function registerTelemetryUsageStatsRoutes(core: CoreSetup) {
- const { server } = core.http as any;
-
+export function registerTelemetryUsageStatsRoutes(server: Legacy.Server) {
server.route({
method: 'POST',
path: '/api/telemetry/v2/clusters/_stats',
- config: {
+ options: {
validate: {
payload: Joi.object({
unencrypted: Joi.bool(),
diff --git a/src/legacy/core_plugins/telemetry/server/routes/telemetry_user_has_seen_notice.ts b/src/legacy/core_plugins/telemetry/server/routes/telemetry_user_has_seen_notice.ts
index 93416058c3277..665e6d9aaeb75 100644
--- a/src/legacy/core_plugins/telemetry/server/routes/telemetry_user_has_seen_notice.ts
+++ b/src/legacy/core_plugins/telemetry/server/routes/telemetry_user_has_seen_notice.ts
@@ -19,7 +19,6 @@
import { Legacy } from 'kibana';
import { Request } from 'hapi';
-import { CoreSetup } from 'src/core/server';
import {
TelemetrySavedObject,
TelemetrySavedObjectAttributes,
@@ -34,9 +33,7 @@ const getInternalRepository = (server: Legacy.Server) => {
return internalRepository;
};
-export function registerTelemetryUserHasSeenNotice(core: CoreSetup) {
- const { server }: { server: Legacy.Server } = core.http as any;
-
+export function registerTelemetryUserHasSeenNotice(server: Legacy.Server) {
server.route({
method: 'PUT',
path: '/api/telemetry/v2/userHasSeenNotice',
diff --git a/src/legacy/core_plugins/ui_metric/index.ts b/src/legacy/core_plugins/ui_metric/index.ts
index 86d75a9f1818a..5a4a0ebf1a632 100644
--- a/src/legacy/core_plugins/ui_metric/index.ts
+++ b/src/legacy/core_plugins/ui_metric/index.ts
@@ -18,7 +18,6 @@
*/
import { resolve } from 'path';
-import { Legacy } from '../../../../kibana';
// eslint-disable-next-line import/no-default-export
export default function(kibana: any) {
@@ -29,13 +28,6 @@ export default function(kibana: any) {
uiExports: {
mappings: require('./mappings.json'),
},
- init(server: Legacy.Server) {
- const { getSavedObjectsRepository } = server.savedObjects;
- const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin');
- const internalRepository = getSavedObjectsRepository(callWithInternalUser);
- const { usageCollection } = server.newPlatform.setup.plugins;
-
- usageCollection.registerLegacySavedObjects(internalRepository);
- },
+ init() {},
});
}
diff --git a/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/state/reducers.ts b/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/state/reducers.ts
index 6591aa5fb53d5..6ae4e415f8caa 100644
--- a/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/state/reducers.ts
+++ b/src/legacy/core_plugins/vis_default_editor/public/components/sidebar/state/reducers.ts
@@ -20,7 +20,8 @@
import { cloneDeep } from 'lodash';
import { Vis, VisState } from 'src/legacy/core_plugins/visualizations/public';
-import { AggConfigs, IAggConfig, AggGroupNames } from '../../../legacy_imports';
+
+import { createAggConfigs, IAggConfig, AggGroupNames } from '../../../legacy_imports';
import { EditorStateActionTypes } from './constants';
import { getEnabledMetricAggsCount } from '../../agg_group_helper';
import { EditorAction } from './actions';
@@ -32,7 +33,8 @@ function initEditorState(vis: Vis) {
function editorStateReducer(state: VisState, action: EditorAction): VisState {
switch (action.type) {
case EditorStateActionTypes.ADD_NEW_AGG: {
- const aggConfig = state.aggs.createAggConfig(action.payload as IAggConfig, {
+ const payloadAggConfig = action.payload as IAggConfig;
+ const aggConfig = state.aggs.createAggConfig(payloadAggConfig, {
addToAggConfigs: false,
});
aggConfig.brandNew = true;
@@ -40,7 +42,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState {
return {
...state,
- aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas),
+ aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas),
};
}
@@ -63,7 +65,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState {
return {
...state,
- aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas),
+ aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas),
};
}
@@ -88,7 +90,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState {
return {
...state,
- aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas),
+ aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas),
};
}
@@ -129,7 +131,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState {
return {
...state,
- aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas),
+ aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas),
};
}
@@ -141,7 +143,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState {
return {
...state,
- aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas),
+ aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas),
};
}
@@ -163,7 +165,7 @@ function editorStateReducer(state: VisState, action: EditorAction): VisState {
return {
...state,
- aggs: new AggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas),
+ aggs: createAggConfigs(state.aggs.indexPattern, newAggs, state.aggs.schemas),
};
}
diff --git a/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts b/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts
index 832f73752a99b..8aed263c4e4d1 100644
--- a/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts
+++ b/src/legacy/core_plugins/vis_default_editor/public/legacy_imports.ts
@@ -22,12 +22,12 @@ export {
AggType,
IAggType,
IAggConfig,
- AggConfigs,
IAggConfigs,
AggParam,
AggGroupNames,
aggGroupNamesMap,
aggTypes,
+ createAggConfigs,
FieldParamType,
IFieldParamType,
BUCKET_TYPES,
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 0e1e48d00a1b2..736152c7014dc 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
@@ -34,7 +34,7 @@ import { stubFields } from '../../../../plugins/data/public/stubs';
import { tableVisResponseHandler } from './table_vis_response_handler';
import { coreMock } from '../../../../core/public/mocks';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { AggConfigs } from 'ui/agg_types';
+import { createAggConfigs } from 'ui/agg_types';
import { tabifyAggResponse, IAggConfig } from './legacy_imports';
jest.mock('ui/new_platform');
@@ -113,7 +113,7 @@ describe('Table Vis - Controller', () => {
return ({
type: tableVisTypeDefinition,
params: Object.assign({}, tableVisTypeDefinition.visConfig.defaults, params),
- aggs: new AggConfigs(
+ aggs: createAggConfigs(
stubIndexPattern,
[
{ type: 'count', schema: 'metric' },
diff --git a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts
index fb7a157b53a9a..0a3b1938436c0 100644
--- a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts
+++ b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts
@@ -18,10 +18,10 @@
*/
export {
- AggConfigs,
IAggConfig,
IAggConfigs,
isDateHistogramBucketAggConfig,
setBounds,
} from '../../data/public';
+export { createAggConfigs } from 'ui/agg_types';
export { createSavedSearchesLoader } from '../../../../plugins/discover/public';
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js
index 2f36322c67256..15a826cc6ddbe 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js
@@ -30,7 +30,7 @@
import { EventEmitter } from 'events';
import _ from 'lodash';
import { PersistedState } from '../../../../../../../src/plugins/visualizations/public';
-import { AggConfigs } from '../../legacy_imports';
+import { createAggConfigs } from '../../legacy_imports';
import { updateVisualizationConfig } from './legacy/vis_update';
import { getTypes } from './services';
@@ -83,7 +83,7 @@ class VisImpl extends EventEmitter {
updateVisualizationConfig(state.params, this.params);
if (state.aggs || !this.aggs) {
- this.aggs = new AggConfigs(
+ this.aggs = createAggConfigs(
this.indexPattern,
state.aggs ? state.aggs.aggs || state.aggs : [],
this.type.schemas.all
@@ -125,7 +125,7 @@ class VisImpl extends EventEmitter {
copyCurrentState(includeDisabled = false) {
const state = this.getCurrentState(includeDisabled);
- state.aggs = new AggConfigs(
+ state.aggs = createAggConfigs(
this.indexPattern,
state.aggs.aggs || state.aggs,
this.type.schemas.all
diff --git a/src/legacy/ui/public/agg_types/index.ts b/src/legacy/ui/public/agg_types/index.ts
index ac5d0bed7ef15..ffc300251c4bb 100644
--- a/src/legacy/ui/public/agg_types/index.ts
+++ b/src/legacy/ui/public/agg_types/index.ts
@@ -27,18 +27,19 @@
import { start as dataStart } from '../../../core_plugins/data/public/legacy';
// runtime contracts
+const { types } = dataStart.search.aggs;
+export const aggTypes = types.getAll();
+export const { createAggConfigs } = dataStart.search.aggs;
export const {
- types: aggTypes,
AggConfig,
- AggConfigs,
AggType,
aggTypeFieldFilters,
FieldParamType,
MetricAggType,
parentPipelineAggHelper,
- siblingPipelineAggHelper,
setBounds,
-} = dataStart.search.aggs;
+ siblingPipelineAggHelper,
+} = dataStart.search.aggs.__LEGACY;
// types
export {
diff --git a/src/legacy/ui/public/chrome/api/sub_url_hooks.js b/src/legacy/ui/public/chrome/api/sub_url_hooks.js
index 3ff262f546e3c..27d147b1ffc72 100644
--- a/src/legacy/ui/public/chrome/api/sub_url_hooks.js
+++ b/src/legacy/ui/public/chrome/api/sub_url_hooks.js
@@ -21,6 +21,7 @@ import url from 'url';
import { unhashUrl } from '../../../../../plugins/kibana_utils/public';
import { toastNotifications } from '../../notify/toasts';
+import { npSetup } from '../../new_platform';
export function registerSubUrlHooks(angularModule, internals) {
angularModule.run(($rootScope, Private, $location) => {
@@ -40,6 +41,7 @@ export function registerSubUrlHooks(angularModule, internals) {
function onRouteChange($event) {
if (subUrlRouteFilter($event)) {
+ updateUsage($event);
updateSubUrls();
}
}
@@ -67,6 +69,13 @@ export function registerSubUrlHooks(angularModule, internals) {
});
}
+function updateUsage($event) {
+ const scope = $event.targetScope;
+ const app = scope.chrome.getApp();
+ const appId = app.id === 'kibana' ? scope.getFirstPathSegment() : app.id;
+ if (npSetup.plugins.usageCollection) npSetup.plugins.usageCollection.__LEGACY.appChanged(appId);
+}
+
/**
* Creates a function that will be called on each route change
* to determine if the event should be used to update the last
diff --git a/src/legacy/ui/public/vis/__tests__/_agg_config.js b/src/legacy/ui/public/vis/__tests__/_agg_config.js
deleted file mode 100644
index 9e53044f681ba..0000000000000
--- a/src/legacy/ui/public/vis/__tests__/_agg_config.js
+++ /dev/null
@@ -1,485 +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 sinon from 'sinon';
-import expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-import { AggType, AggConfig } from '../../agg_types';
-import { start as visualizationsStart } from '../../../../core_plugins/visualizations/public/np_ready/public/legacy';
-
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-
-describe('AggConfig', function() {
- let indexPattern;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(
- ngMock.inject(function(Private) {
- indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
- })
- );
-
- describe('#toDsl', function() {
- it('calls #write()', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'date_histogram',
- schema: 'segment',
- },
- ],
- });
-
- const aggConfig = vis.aggs.byName('date_histogram')[0];
- const stub = sinon.stub(aggConfig, 'write').returns({ params: {} });
-
- aggConfig.toDsl();
- expect(stub.callCount).to.be(1);
- });
-
- it('uses the type name as the agg name', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'date_histogram',
- schema: 'segment',
- },
- ],
- });
-
- const aggConfig = vis.aggs.byName('date_histogram')[0];
- sinon.stub(aggConfig, 'write').returns({ params: {} });
-
- const dsl = aggConfig.toDsl();
- expect(dsl).to.have.property('date_histogram');
- });
-
- it('uses the params from #write() output as the agg params', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'date_histogram',
- schema: 'segment',
- },
- ],
- });
-
- const aggConfig = vis.aggs.byName('date_histogram')[0];
- const football = {};
-
- sinon.stub(aggConfig, 'write').returns({ params: football });
-
- const dsl = aggConfig.toDsl();
- expect(dsl.date_histogram).to.be(football);
- });
-
- it('includes subAggs from #write() output', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'avg',
- schema: 'metric',
- },
- {
- type: 'date_histogram',
- schema: 'segment',
- },
- ],
- });
-
- const histoConfig = vis.aggs.byName('date_histogram')[0];
- const avgConfig = vis.aggs.byName('avg')[0];
- const football = {};
-
- sinon.stub(histoConfig, 'write').returns({ params: {}, subAggs: [avgConfig] });
- sinon.stub(avgConfig, 'write').returns({ params: football });
-
- const dsl = histoConfig.toDsl();
-
- // didn't use .eql() because of variable key names, and final check is strict
- expect(dsl).to.have.property('aggs');
- expect(dsl.aggs).to.have.property(avgConfig.id);
- expect(dsl.aggs[avgConfig.id]).to.have.property('avg');
- expect(dsl.aggs[avgConfig.id].avg).to.be(football);
- });
- });
-
- describe('::ensureIds', function() {
- it('accepts an array of objects and assigns ids to them', function() {
- const objs = [{}, {}, {}, {}];
- AggConfig.ensureIds(objs);
- expect(objs[0]).to.have.property('id', '1');
- expect(objs[1]).to.have.property('id', '2');
- expect(objs[2]).to.have.property('id', '3');
- expect(objs[3]).to.have.property('id', '4');
- });
-
- it('assigns ids relative to the other only item in the list', function() {
- const objs = [{ id: '100' }, {}];
- AggConfig.ensureIds(objs);
- expect(objs[0]).to.have.property('id', '100');
- expect(objs[1]).to.have.property('id', '101');
- });
-
- it('assigns ids relative to the other items in the list', function() {
- const objs = [{ id: '100' }, { id: '200' }, { id: '500' }, { id: '350' }, {}];
- AggConfig.ensureIds(objs);
- expect(objs[0]).to.have.property('id', '100');
- expect(objs[1]).to.have.property('id', '200');
- expect(objs[2]).to.have.property('id', '500');
- expect(objs[3]).to.have.property('id', '350');
- expect(objs[4]).to.have.property('id', '501');
- });
-
- it('uses ::nextId to get the starting value', function() {
- sinon.stub(AggConfig, 'nextId').returns(534);
- const objs = AggConfig.ensureIds([{}]);
- AggConfig.nextId.restore();
- expect(objs[0]).to.have.property('id', '534');
- });
-
- it('only calls ::nextId once', function() {
- const start = 420;
- sinon.stub(AggConfig, 'nextId').returns(start);
- const objs = AggConfig.ensureIds([{}, {}, {}, {}, {}, {}, {}]);
-
- expect(AggConfig.nextId).to.have.property('callCount', 1);
-
- AggConfig.nextId.restore();
- objs.forEach(function(obj, i) {
- expect(obj).to.have.property('id', String(start + i));
- });
- });
- });
-
- describe('::nextId', function() {
- it('accepts a list of objects and picks the next id', function() {
- const next = AggConfig.nextId([{ id: 100 }, { id: 500 }]);
- expect(next).to.be(501);
- });
-
- it('handles an empty list', function() {
- const next = AggConfig.nextId([]);
- expect(next).to.be(1);
- });
-
- it('fails when the list is not defined', function() {
- expect(function() {
- AggConfig.nextId();
- }).to.throwError();
- });
- });
-
- describe('#toJsonDataEquals', function() {
- const testsIdentical = [
- {
- type: 'metric',
- aggs: [
- {
- type: 'count',
- schema: 'metric',
- params: { field: '@timestamp' },
- },
- ],
- },
- {
- type: 'histogram',
- aggs: [
- {
- type: 'avg',
- schema: 'metric',
- },
- {
- type: 'date_histogram',
- schema: 'segment',
- },
- ],
- },
- ];
-
- testsIdentical.forEach((visConfig, index) => {
- it(`identical aggregations (${index})`, function() {
- const vis1 = new visualizationsStart.Vis(indexPattern, visConfig);
- const vis2 = new visualizationsStart.Vis(indexPattern, visConfig);
- expect(vis1.aggs.jsonDataEquals(vis2.aggs.aggs)).to.be(true);
- });
- });
-
- const testsIdenticalDifferentOrder = [
- {
- config1: {
- type: 'histogram',
- aggs: [
- {
- type: 'avg',
- schema: 'metric',
- },
- {
- type: 'date_histogram',
- schema: 'segment',
- },
- ],
- },
- config2: {
- type: 'histogram',
- aggs: [
- {
- schema: 'metric',
- type: 'avg',
- },
- {
- schema: 'segment',
- type: 'date_histogram',
- },
- ],
- },
- },
- ];
-
- testsIdenticalDifferentOrder.forEach((test, index) => {
- it(`identical aggregations (${index}) - init json is in different order`, function() {
- const vis1 = new visualizationsStart.Vis(indexPattern, test.config1);
- const vis2 = new visualizationsStart.Vis(indexPattern, test.config2);
- expect(vis1.aggs.jsonDataEquals(vis2.aggs.aggs)).to.be(true);
- });
- });
-
- const testsDifferent = [
- {
- config1: {
- type: 'histogram',
- aggs: [
- {
- type: 'avg',
- schema: 'metric',
- },
- {
- type: 'date_histogram',
- schema: 'segment',
- },
- ],
- },
- config2: {
- type: 'histogram',
- aggs: [
- {
- type: 'max',
- schema: 'metric',
- },
- {
- type: 'date_histogram',
- schema: 'segment',
- },
- ],
- },
- },
- {
- config1: {
- type: 'metric',
- aggs: [
- {
- type: 'count',
- schema: 'metric',
- params: { field: '@timestamp' },
- },
- ],
- },
- config2: {
- type: 'metric',
- aggs: [
- {
- type: 'count',
- schema: 'metric',
- params: { field: '@timestamp' },
- },
- {
- type: 'date_histogram',
- schema: 'segment',
- },
- ],
- },
- },
- ];
-
- testsDifferent.forEach((test, index) => {
- it(`different aggregations (${index})`, function() {
- const vis1 = new visualizationsStart.Vis(indexPattern, test.config1);
- const vis2 = new visualizationsStart.Vis(indexPattern, test.config2);
- expect(vis1.aggs.jsonDataEquals(vis2.aggs.aggs)).to.be(false);
- });
- });
- });
-
- describe('#toJSON', function() {
- it('includes the aggs id, params, type and schema', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'date_histogram',
- schema: 'segment',
- },
- ],
- });
-
- const aggConfig = vis.aggs.byName('date_histogram')[0];
- expect(aggConfig.id).to.be('1');
- expect(aggConfig.params).to.be.an('object');
- expect(aggConfig.type)
- .to.be.an(AggType)
- .and.have.property('name', 'date_histogram');
- expect(aggConfig.schema)
- .to.be.an('object')
- .and.have.property('name', 'segment');
-
- const state = aggConfig.toJSON();
- expect(state).to.have.property('id', '1');
- expect(state.params).to.be.an('object');
- expect(state).to.have.property('type', 'date_histogram');
- expect(state).to.have.property('schema', 'segment');
- });
-
- it('test serialization order is identical (for visual consistency)', function() {
- const vis1 = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'date_histogram',
- schema: 'segment',
- },
- ],
- });
- const vis2 = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- schema: 'segment',
- type: 'date_histogram',
- },
- ],
- });
-
- //this relies on the assumption that js-engines consistently loop over properties in insertion order.
- //most likely the case, but strictly speaking not guaranteed by the JS and JSON specifications.
- expect(JSON.stringify(vis1.aggs.aggs) === JSON.stringify(vis2.aggs.aggs)).to.be(true);
- });
- });
-
- describe('#makeLabel', function() {
- it('uses the custom label if it is defined', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {});
- const aggConfig = vis.aggs.aggs[0];
- aggConfig.params.customLabel = 'Custom label';
- const label = aggConfig.makeLabel();
- expect(label).to.be(aggConfig.params.customLabel);
- });
- it('default label should be "Count"', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {});
- const aggConfig = vis.aggs.aggs[0];
- const label = aggConfig.makeLabel();
- expect(label).to.be('Count');
- });
- it('default label should be "Percentage of Count" when percentageMode is set to true', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {});
- const aggConfig = vis.aggs.aggs[0];
- const label = aggConfig.makeLabel(true);
- expect(label).to.be('Percentage of Count');
- });
- it('empty label if the visualizationsStart.Vis type is not defined', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {});
- const aggConfig = vis.aggs.aggs[0];
- aggConfig.type = undefined;
- const label = aggConfig.makeLabel();
- expect(label).to.be('');
- });
- });
-
- describe('#fieldFormatter - custom getFormat handler', function() {
- it('returns formatter from getFormat handler', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'metric',
- aggs: [
- {
- type: 'count',
- schema: 'metric',
- params: { field: '@timestamp' },
- },
- ],
- });
-
- const fieldFormatter = vis.aggs.aggs[0].fieldFormatter();
-
- expect(fieldFormatter).to.be.defined;
- expect(fieldFormatter('text')).to.be('text');
- });
- });
-
- describe('#fieldFormatter - no custom getFormat handler', function() {
- const visStateAggWithoutCustomGetFormat = {
- aggs: [
- {
- type: 'histogram',
- schema: 'bucket',
- params: { field: 'bytes' },
- },
- ],
- };
- let vis;
-
- beforeEach(function() {
- vis = new visualizationsStart.Vis(indexPattern, visStateAggWithoutCustomGetFormat);
- });
-
- it("returns the field's formatter", function() {
- expect(vis.aggs.aggs[0].fieldFormatter().toString()).to.be(
- vis.aggs.aggs[0]
- .getField()
- .format.getConverterFor()
- .toString()
- );
- });
-
- it('returns the string format if the field does not have a format', function() {
- const agg = vis.aggs.aggs[0];
- agg.params.field = { type: 'number', format: null };
- const fieldFormatter = agg.fieldFormatter();
- expect(fieldFormatter).to.be.defined;
- expect(fieldFormatter('text')).to.be('text');
- });
-
- it('returns the string format if their is no field', function() {
- const agg = vis.aggs.aggs[0];
- delete agg.params.field;
- const fieldFormatter = agg.fieldFormatter();
- expect(fieldFormatter).to.be.defined;
- expect(fieldFormatter('text')).to.be('text');
- });
-
- it('returns the html converter if "html" is passed in', function() {
- const field = indexPattern.fields.getByName('bytes');
- expect(vis.aggs.aggs[0].fieldFormatter('html').toString()).to.be(
- field.format.getConverterFor('html').toString()
- );
- });
- });
-});
diff --git a/src/legacy/ui/public/vis/__tests__/_agg_configs.js b/src/legacy/ui/public/vis/__tests__/_agg_configs.js
deleted file mode 100644
index 172523ec50c8b..0000000000000
--- a/src/legacy/ui/public/vis/__tests__/_agg_configs.js
+++ /dev/null
@@ -1,420 +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 sinon from 'sinon';
-import expect from '@kbn/expect';
-import ngMock from 'ng_mock';
-import { AggConfig, AggConfigs, AggGroupNames, Schemas } from '../../agg_types';
-import { start as visualizationsStart } from '../../../../core_plugins/visualizations/public/np_ready/public/legacy';
-import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
-
-describe('AggConfigs', function() {
- let indexPattern;
-
- beforeEach(ngMock.module('kibana'));
- beforeEach(
- ngMock.inject(function(Private) {
- // load main deps
- indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
- })
- );
-
- describe('constructor', function() {
- it('handles passing just a vis', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [],
- });
-
- const ac = new AggConfigs(vis.indexPattern, [], vis.type.schemas.all);
- expect(ac.aggs).to.have.length(1);
- });
-
- it('converts configStates into AggConfig objects if they are not already', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [],
- });
-
- const ac = new AggConfigs(
- vis.indexPattern,
- [
- {
- type: 'date_histogram',
- schema: 'segment',
- },
- new AggConfig(vis.aggs, {
- type: 'terms',
- schema: 'split',
- }),
- ],
- vis.type.schemas.all
- );
-
- expect(ac.aggs).to.have.length(3);
- });
-
- it('attempts to ensure that all states have an id', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [],
- });
-
- const states = [
- {
- type: 'date_histogram',
- schema: 'segment',
- },
- {
- type: 'terms',
- schema: 'split',
- },
- ];
-
- const spy = sinon.spy(AggConfig, 'ensureIds');
- new AggConfigs(vis.indexPattern, states, vis.type.schemas.all);
- expect(spy.callCount).to.be(1);
- expect(spy.firstCall.args[0]).to.be(states);
- AggConfig.ensureIds.restore();
- });
-
- describe('defaults', function() {
- let vis;
- beforeEach(function() {
- vis = {
- indexPattern: indexPattern,
- type: {
- schemas: new Schemas([
- {
- group: AggGroupNames.Metrics,
- name: 'metric',
- title: 'Simple',
- min: 1,
- max: 2,
- defaults: [
- { schema: 'metric', type: 'count' },
- { schema: 'metric', type: 'avg' },
- { schema: 'metric', type: 'sum' },
- ],
- },
- {
- group: AggGroupNames.Buckets,
- name: 'segment',
- title: 'Example',
- min: 0,
- max: 1,
- defaults: [
- { schema: 'segment', type: 'terms' },
- { schema: 'segment', type: 'filters' },
- ],
- },
- ]),
- },
- };
- });
-
- it('should only set the number of defaults defined by the max', function() {
- const ac = new AggConfigs(vis.indexPattern, [], vis.type.schemas.all);
- expect(ac.bySchemaName('metric')).to.have.length(2);
- });
-
- it('should set the defaults defined in the schema when none exist', function() {
- const ac = new AggConfigs(vis.indexPattern, [], vis.type.schemas.all);
- expect(ac.aggs).to.have.length(3);
- });
-
- it('should NOT set the defaults defined in the schema when some exist', function() {
- const ac = new AggConfigs(
- vis.indexPattern,
- [{ schema: 'segment', type: 'date_histogram' }],
- vis.type.schemas.all
- );
- expect(ac.aggs).to.have.length(3);
- expect(ac.bySchemaName('segment')[0].type.name).to.equal('date_histogram');
- });
- });
- });
-
- describe('#getRequestAggs', function() {
- it('performs a stable sort, but moves metrics to the bottom', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- { type: 'avg', schema: 'metric' },
- { type: 'terms', schema: 'split' },
- { type: 'histogram', schema: 'split' },
- { type: 'sum', schema: 'metric' },
- { type: 'date_histogram', schema: 'segment' },
- { type: 'filters', schema: 'split' },
- { type: 'percentiles', schema: 'metric' },
- ],
- });
-
- const sorted = vis.aggs.getRequestAggs();
- const aggs = _.indexBy(vis.aggs.aggs, function(agg) {
- return agg.type.name;
- });
-
- expect(sorted.shift()).to.be(aggs.terms);
- expect(sorted.shift()).to.be(aggs.histogram);
- expect(sorted.shift()).to.be(aggs.date_histogram);
- expect(sorted.shift()).to.be(aggs.filters);
- expect(sorted.shift()).to.be(aggs.avg);
- expect(sorted.shift()).to.be(aggs.sum);
- expect(sorted.shift()).to.be(aggs.percentiles);
- expect(sorted).to.have.length(0);
- });
- });
-
- describe('#getResponseAggs', function() {
- it('returns all request aggs for basic aggs', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- { type: 'terms', schema: 'split' },
- { type: 'date_histogram', schema: 'segment' },
- { type: 'count', schema: 'metric' },
- ],
- });
-
- const sorted = vis.aggs.getResponseAggs();
- const aggs = _.indexBy(vis.aggs.aggs, function(agg) {
- return agg.type.name;
- });
-
- expect(sorted.shift()).to.be(aggs.terms);
- expect(sorted.shift()).to.be(aggs.date_histogram);
- expect(sorted.shift()).to.be(aggs.count);
- expect(sorted).to.have.length(0);
- });
-
- it('expands aggs that have multiple responses', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- { type: 'terms', schema: 'split' },
- { type: 'date_histogram', schema: 'segment' },
- { type: 'percentiles', schema: 'metric', params: { percents: [1, 2, 3] } },
- ],
- });
-
- const sorted = vis.aggs.getResponseAggs();
- const aggs = _.indexBy(vis.aggs.aggs, function(agg) {
- return agg.type.name;
- });
-
- expect(sorted.shift()).to.be(aggs.terms);
- expect(sorted.shift()).to.be(aggs.date_histogram);
- expect(sorted.shift().id).to.be(aggs.percentiles.id + '.' + 1);
- expect(sorted.shift().id).to.be(aggs.percentiles.id + '.' + 2);
- expect(sorted.shift().id).to.be(aggs.percentiles.id + '.' + 3);
- expect(sorted).to.have.length(0);
- });
- });
-
- describe('#toDsl', function() {
- it('uses the sorted aggs', function() {
- const vis = new visualizationsStart.Vis(indexPattern, { type: 'histogram' });
- sinon.spy(vis.aggs, 'getRequestAggs');
- vis.aggs.toDsl();
- expect(vis.aggs.getRequestAggs).to.have.property('callCount', 1);
- });
-
- it('calls aggConfig#toDsl() on each aggConfig and compiles the nested output', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- { type: 'date_histogram', schema: 'segment' },
- { type: 'filters', schema: 'split' },
- ],
- });
-
- const aggInfos = vis.aggs.aggs.map(function(aggConfig) {
- const football = {};
-
- sinon.stub(aggConfig, 'toDsl').returns(football);
-
- return {
- id: aggConfig.id,
- football: football,
- };
- });
-
- (function recurse(lvl) {
- const info = aggInfos.shift();
-
- expect(lvl).to.have.property(info.id);
- expect(lvl[info.id]).to.be(info.football);
-
- if (lvl[info.id].aggs) {
- return recurse(lvl[info.id].aggs);
- }
- })(vis.aggs.toDsl());
-
- expect(aggInfos).to.have.length(1);
- });
-
- it("skips aggs that don't have a dsl representation", function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'date_histogram',
- schema: 'segment',
- params: { field: '@timestamp', interval: '10s' },
- },
- { type: 'count', schema: 'metric' },
- ],
- });
-
- const dsl = vis.aggs.toDsl();
- const histo = vis.aggs.byName('date_histogram')[0];
- const count = vis.aggs.byName('count')[0];
-
- expect(dsl).to.have.property(histo.id);
- expect(dsl[histo.id]).to.be.an('object');
- expect(dsl[histo.id]).to.not.have.property('aggs');
- expect(dsl).to.not.have.property(count.id);
- });
-
- it('writes multiple metric aggregations at the same level', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- type: 'date_histogram',
- schema: 'segment',
- params: { field: '@timestamp', interval: '10s' },
- },
- { type: 'avg', schema: 'metric', params: { field: 'bytes' } },
- { type: 'sum', schema: 'metric', params: { field: 'bytes' } },
- { type: 'min', schema: 'metric', params: { field: 'bytes' } },
- { type: 'max', schema: 'metric', params: { field: 'bytes' } },
- ],
- });
-
- const dsl = vis.aggs.toDsl();
-
- const histo = vis.aggs.byName('date_histogram')[0];
- const metrics = vis.aggs.bySchemaGroup('metrics');
-
- expect(dsl).to.have.property(histo.id);
- expect(dsl[histo.id]).to.be.an('object');
- expect(dsl[histo.id]).to.have.property('aggs');
-
- metrics.forEach(function(metric) {
- expect(dsl[histo.id].aggs).to.have.property(metric.id);
- expect(dsl[histo.id].aggs[metric.id]).to.not.have.property('aggs');
- });
- });
-
- it('writes multiple metric aggregations at every level if the vis is hierarchical', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- { type: 'terms', schema: 'segment', params: { field: 'ip', orderBy: 1 } },
- { type: 'terms', schema: 'segment', params: { field: 'extension', orderBy: 1 } },
- { id: 1, type: 'avg', schema: 'metric', params: { field: 'bytes' } },
- { type: 'sum', schema: 'metric', params: { field: 'bytes' } },
- { type: 'min', schema: 'metric', params: { field: 'bytes' } },
- { type: 'max', schema: 'metric', params: { field: 'bytes' } },
- ],
- });
- vis.isHierarchical = _.constant(true);
-
- const topLevelDsl = vis.aggs.toDsl(vis.isHierarchical());
- const buckets = vis.aggs.bySchemaGroup('buckets');
- const metrics = vis.aggs.bySchemaGroup('metrics');
-
- (function checkLevel(dsl) {
- const bucket = buckets.shift();
- expect(dsl).to.have.property(bucket.id);
-
- expect(dsl[bucket.id]).to.be.an('object');
- expect(dsl[bucket.id]).to.have.property('aggs');
-
- metrics.forEach(function(metric) {
- expect(dsl[bucket.id].aggs).to.have.property(metric.id);
- expect(dsl[bucket.id].aggs[metric.id]).to.not.have.property('aggs');
- });
-
- if (buckets.length) {
- checkLevel(dsl[bucket.id].aggs);
- }
- })(topLevelDsl);
- });
-
- it('adds the parent aggs of nested metrics at every level if the vis is hierarchical', function() {
- const vis = new visualizationsStart.Vis(indexPattern, {
- type: 'histogram',
- aggs: [
- {
- id: '1',
- type: 'avg_bucket',
- schema: 'metric',
- params: {
- customBucket: {
- id: '1-bucket',
- type: 'date_histogram',
- schema: 'bucketAgg',
- params: {
- field: '@timestamp',
- interval: '10s',
- },
- },
- customMetric: {
- id: '1-metric',
- type: 'count',
- schema: 'metricAgg',
- params: {},
- },
- },
- },
- {
- id: '2',
- type: 'terms',
- schema: 'bucket',
- params: {
- field: 'geo.src',
- },
- },
- {
- id: '3',
- type: 'terms',
- schema: 'bucket',
- params: {
- field: 'machine.os',
- },
- },
- ],
- });
- vis.isHierarchical = _.constant(true);
-
- const topLevelDsl = vis.aggs.toDsl(vis.isHierarchical())['2'];
- expect(topLevelDsl.aggs).to.have.keys(['1', '1-bucket']);
- expect(topLevelDsl.aggs['1'].avg_bucket).to.have.property('buckets_path', '1-bucket>_count');
- expect(topLevelDsl.aggs['3'].aggs).to.have.keys(['1', '1-bucket']);
- expect(topLevelDsl.aggs['3'].aggs['1'].avg_bucket).to.have.property(
- 'buckets_path',
- '1-bucket>_count'
- );
- });
- });
-});
diff --git a/src/plugins/data/common/field_formats/mocks.ts b/src/plugins/data/common/field_formats/mocks.ts
new file mode 100644
index 0000000000000..bc38374e147cf
--- /dev/null
+++ b/src/plugins/data/common/field_formats/mocks.ts
@@ -0,0 +1,49 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { FieldFormat, IFieldFormatsRegistry } from '.';
+
+const fieldFormatMock = ({
+ convert: jest.fn(),
+ getConverterFor: jest.fn(),
+ getParamDefaults: jest.fn(),
+ param: jest.fn(),
+ params: jest.fn(),
+ toJSON: jest.fn(),
+ type: jest.fn(),
+ setupContentType: jest.fn(),
+} as unknown) as FieldFormat;
+
+export const fieldFormatsMock: IFieldFormatsRegistry = {
+ getByFieldType: jest.fn(),
+ getDefaultConfig: jest.fn(),
+ getDefaultInstance: jest.fn().mockImplementation(() => fieldFormatMock) as any,
+ getDefaultInstanceCacheResolver: jest.fn(),
+ getDefaultInstancePlain: jest.fn(),
+ getDefaultType: jest.fn(),
+ getDefaultTypeName: jest.fn(),
+ getInstance: jest.fn() as any,
+ getType: jest.fn(),
+ getTypeNameByEsTypes: jest.fn(),
+ init: jest.fn(),
+ register: jest.fn(),
+ parseDefaultTypeMap: jest.fn(),
+ deserialize: jest.fn(),
+ getTypeWithoutMetaParams: jest.fn(),
+};
diff --git a/src/plugins/data/common/field_formats/types.ts b/src/plugins/data/common/field_formats/types.ts
index 0c16d9f1ac8bf..7c1d6a8522e52 100644
--- a/src/plugins/data/common/field_formats/types.ts
+++ b/src/plugins/data/common/field_formats/types.ts
@@ -87,6 +87,7 @@ export type IFieldFormatType = (new (
getConfig?: FieldFormatsGetConfigFn
) => FieldFormat) & {
id: FieldFormatId;
+ title: string;
fieldType: string | string[];
};
diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts
index 6a0a33096eaac..27de3b5a29bfd 100644
--- a/src/plugins/data/public/mocks.ts
+++ b/src/plugins/data/public/mocks.ts
@@ -16,13 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-import {
- Plugin,
- DataPublicPluginSetup,
- DataPublicPluginStart,
- IndexPatternsContract,
- IFieldFormatsRegistry,
-} from '.';
+
+import { Plugin, DataPublicPluginSetup, DataPublicPluginStart, IndexPatternsContract } from '.';
+import { fieldFormatsMock } from '../common/field_formats/mocks';
import { searchSetupMock } from './search/mocks';
import { queryServiceMock } from './query/mocks';
@@ -35,24 +31,6 @@ const autocompleteMock: any = {
hasQuerySuggestions: jest.fn(),
};
-const fieldFormatsMock: IFieldFormatsRegistry = {
- getByFieldType: jest.fn(),
- getDefaultConfig: jest.fn(),
- getDefaultInstance: jest.fn() as any,
- getDefaultInstanceCacheResolver: jest.fn(),
- getDefaultInstancePlain: jest.fn(),
- getDefaultType: jest.fn(),
- getDefaultTypeName: jest.fn(),
- getInstance: jest.fn() as any,
- getType: jest.fn(),
- getTypeNameByEsTypes: jest.fn(),
- init: jest.fn(),
- register: jest.fn(),
- parseDefaultTypeMap: jest.fn(),
- deserialize: jest.fn(),
- getTypeWithoutMetaParams: jest.fn(),
-};
-
const createSetupContract = (): Setup => {
const querySetupMock = queryServiceMock.createSetupContract();
const setupContract = {
diff --git a/src/plugins/data/public/search/search_source/mocks.ts b/src/plugins/data/public/search/search_source/mocks.ts
index fd72158012de6..700bea741bd6a 100644
--- a/src/plugins/data/public/search/search_source/mocks.ts
+++ b/src/plugins/data/public/search/search_source/mocks.ts
@@ -17,25 +17,6 @@
* under the License.
*/
-/*
- * 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 { ISearchSource } from './search_source';
export const searchSourceMock: MockedKeys = {
diff --git a/src/plugins/data/public/ui/query_string_input/__snapshots__/language_switcher.test.tsx.snap b/src/plugins/data/public/ui/query_string_input/__snapshots__/language_switcher.test.tsx.snap
deleted file mode 100644
index 6432f8049641a..0000000000000
--- a/src/plugins/data/public/ui/query_string_input/__snapshots__/language_switcher.test.tsx.snap
+++ /dev/null
@@ -1,593 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`LanguageSwitcher should toggle off if language is lucene 1`] = `
-
-
-
-
-