diff --git a/.ci/Dockerfile b/.ci/Dockerfile index 8a972c65f8412..3ca6b6a4b9098 100644 --- a/.ci/Dockerfile +++ b/.ci/Dockerfile @@ -1,7 +1,7 @@ # NOTE: This Dockerfile is ONLY used to run certain tasks in CI. It is not used to run Kibana or as a distributable. # If you're looking for the Kibana Docker image distributable, please see: src/dev/build/tasks/os_packages/docker_generator/templates/dockerfile.template.ts -ARG NODE_VERSION=14.15.3 +ARG NODE_VERSION=14.15.4 FROM node:${NODE_VERSION} AS base diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md index fd620d31a1e64..0e23064385a63 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md @@ -15,6 +15,7 @@ readonly links: { readonly urlDrilldownTemplateSyntax: string; readonly urlDrilldownVariables: string; }; + readonly discover: Record; readonly filebeat: { readonly base: string; readonly installation: string; diff --git a/packages/elastic-datemath/__tests__/index.js b/packages/elastic-datemath/index.test.js similarity index 69% rename from packages/elastic-datemath/__tests__/index.js rename to packages/elastic-datemath/index.test.js index 1a61021b48a6e..a6a576dd713a9 100644 --- a/packages/elastic-datemath/__tests__/index.js +++ b/packages/elastic-datemath/index.test.js @@ -17,22 +17,21 @@ * under the License. */ -const dateMath = require('../index'); +const dateMath = require('./index'); const moment = require('moment'); -const sinon = require('sinon'); -const expect = require('@kbn/expect'); /** - * Require a new instance of the moment library, bypassing the require cache. + * Require a new instance of the moment library, bypassing the require cache + * by using jest.resetModules(). * This is needed, since we are trying to test whether or not this library works * when passing in a different configured moment instance. If we would change * the locales on the imported moment, it would automatically apply * to the source code, even without passing it in to the method, since they share * the same global state. This method avoids this, by loading a separate instance - * of moment, by deleting the require cache and require the library again. + * of moment, by resetting the jest require modules cache and require the library again. */ function momentClone() { - delete require.cache[require.resolve('moment')]; + jest.resetModules(); return require('moment'); } @@ -43,44 +42,43 @@ describe('dateMath', function () { const anchoredDate = new Date(Date.parse(anchor)); const unix = moment(anchor).valueOf(); const format = 'YYYY-MM-DDTHH:mm:ss.SSSZ'; - let clock; describe('errors', function () { it('should return undefined if passed something falsy', function () { - expect(dateMath.parse()).to.be(undefined); + expect(dateMath.parse()).toBeUndefined(); }); it('should return undefined if I pass an operator besides [+-/]', function () { - expect(dateMath.parse('now&1d')).to.be(undefined); + expect(dateMath.parse('now&1d')).toBeUndefined(); }); it('should return undefined if I pass a unit besides' + spans.toString(), function () { - expect(dateMath.parse('now+5f')).to.be(undefined); + expect(dateMath.parse('now+5f')).toBeUndefined(); }); it('should return undefined if rounding unit is not 1', function () { - expect(dateMath.parse('now/2y')).to.be(undefined); - expect(dateMath.parse('now/0.5y')).to.be(undefined); + expect(dateMath.parse('now/2y')).toBeUndefined(); + expect(dateMath.parse('now/0.5y')).toBeUndefined(); }); it('should not go into an infinite loop when missing a unit', function () { - expect(dateMath.parse('now-0')).to.be(undefined); - expect(dateMath.parse('now-00')).to.be(undefined); - expect(dateMath.parse('now-000')).to.be(undefined); + expect(dateMath.parse('now-0')).toBeUndefined(); + expect(dateMath.parse('now-00')).toBeUndefined(); + expect(dateMath.parse('now-000')).toBeUndefined(); }); describe('forceNow', function () { it('should throw an Error if passed a string', function () { const fn = () => dateMath.parse('now', { forceNow: '2000-01-01T00:00:00.000Z' }); - expect(fn).to.throwError(); + expect(fn).toThrowError(); }); it('should throw an Error if passed a moment', function () { - expect(() => dateMath.parse('now', { forceNow: moment() })).to.throwError(); + expect(() => dateMath.parse('now', { forceNow: moment() })).toThrowError(); }); it('should throw an Error if passed an invalid date', function () { - expect(() => dateMath.parse('now', { forceNow: new Date('foobar') })).to.throwError(); + expect(() => dateMath.parse('now', { forceNow: new Date('foobar') })).toThrowError(); }); }); }); @@ -92,7 +90,8 @@ describe('dateMath', function () { let now; beforeEach(function () { - clock = sinon.useFakeTimers(unix); + jest.useFakeTimers('modern'); + jest.setSystemTime(unix); now = moment(); mmnt = moment(anchor); date = mmnt.toDate(); @@ -100,27 +99,27 @@ describe('dateMath', function () { }); afterEach(function () { - clock.restore(); + jest.useRealTimers(); }); it('should return the same moment if passed a moment', function () { - expect(dateMath.parse(mmnt)).to.eql(mmnt); + expect(dateMath.parse(mmnt)).toEqual(mmnt); }); it('should return a moment if passed a date', function () { - expect(dateMath.parse(date).format(format)).to.eql(mmnt.format(format)); + expect(dateMath.parse(date).format(format)).toEqual(mmnt.format(format)); }); it('should return a moment if passed an ISO8601 string', function () { - expect(dateMath.parse(string).format(format)).to.eql(mmnt.format(format)); + expect(dateMath.parse(string).format(format)).toEqual(mmnt.format(format)); }); it('should return the current time when parsing now', function () { - expect(dateMath.parse('now').format(format)).to.eql(now.format(format)); + expect(dateMath.parse('now').format(format)).toEqual(now.format(format)); }); it('should use the forceNow parameter when parsing now', function () { - expect(dateMath.parse('now', { forceNow: anchoredDate }).valueOf()).to.eql(unix); + expect(dateMath.parse('now', { forceNow: anchoredDate }).valueOf()).toEqual(unix); }); }); @@ -129,13 +128,14 @@ describe('dateMath', function () { let anchored; beforeEach(function () { - clock = sinon.useFakeTimers(unix); + jest.useFakeTimers('modern'); + jest.setSystemTime(unix); now = moment(); anchored = moment(anchor); }); afterEach(function () { - clock.restore(); + jest.useRealTimers(); }); [5, 12, 247].forEach((len) => { @@ -145,17 +145,17 @@ describe('dateMath', function () { it('should return ' + len + span + ' ago', function () { const parsed = dateMath.parse(nowEx).format(format); - expect(parsed).to.eql(now.subtract(len, span).format(format)); + expect(parsed).toEqual(now.subtract(len, span).format(format)); }); it('should return ' + len + span + ' before ' + anchor, function () { const parsed = dateMath.parse(thenEx).format(format); - expect(parsed).to.eql(anchored.subtract(len, span).format(format)); + expect(parsed).toEqual(anchored.subtract(len, span).format(format)); }); it('should return ' + len + span + ' before forceNow', function () { const parsed = dateMath.parse(nowEx, { forceNow: anchoredDate }).valueOf(); - expect(parsed).to.eql(anchored.subtract(len, span).valueOf()); + expect(parsed).toEqual(anchored.subtract(len, span).valueOf()); }); }); }); @@ -166,13 +166,14 @@ describe('dateMath', function () { let anchored; beforeEach(function () { - clock = sinon.useFakeTimers(unix); + jest.useFakeTimers('modern'); + jest.setSystemTime(unix); now = moment(); anchored = moment(anchor); }); afterEach(function () { - clock.restore(); + jest.useRealTimers(); }); [5, 12, 247].forEach((len) => { @@ -181,17 +182,17 @@ describe('dateMath', function () { const thenEx = `${anchor}||+${len}${span}`; it('should return ' + len + span + ' from now', function () { - expect(dateMath.parse(nowEx).format(format)).to.eql(now.add(len, span).format(format)); + expect(dateMath.parse(nowEx).format(format)).toEqual(now.add(len, span).format(format)); }); it('should return ' + len + span + ' after ' + anchor, function () { - expect(dateMath.parse(thenEx).format(format)).to.eql( + expect(dateMath.parse(thenEx).format(format)).toEqual( anchored.add(len, span).format(format) ); }); it('should return ' + len + span + ' after forceNow', function () { - expect(dateMath.parse(nowEx, { forceNow: anchoredDate }).valueOf()).to.eql( + expect(dateMath.parse(nowEx, { forceNow: anchoredDate }).valueOf()).toEqual( anchored.add(len, span).valueOf() ); }); @@ -204,30 +205,31 @@ describe('dateMath', function () { let anchored; beforeEach(function () { - clock = sinon.useFakeTimers(unix); + jest.useFakeTimers('modern'); + jest.setSystemTime(unix); now = moment(); anchored = moment(anchor); }); afterEach(function () { - clock.restore(); + jest.useRealTimers(); }); spans.forEach((span) => { it(`should round now to the beginning of the ${span}`, function () { - expect(dateMath.parse('now/' + span).format(format)).to.eql( + expect(dateMath.parse('now/' + span).format(format)).toEqual( now.startOf(span).format(format) ); }); it(`should round now to the beginning of forceNow's ${span}`, function () { - expect(dateMath.parse('now/' + span, { forceNow: anchoredDate }).valueOf()).to.eql( + expect(dateMath.parse('now/' + span, { forceNow: anchoredDate }).valueOf()).toEqual( anchored.startOf(span).valueOf() ); }); it(`should round now to the end of the ${span}`, function () { - expect(dateMath.parse('now/' + span, { roundUp: true }).format(format)).to.eql( + expect(dateMath.parse('now/' + span, { roundUp: true }).format(format)).toEqual( now.endOf(span).format(format) ); }); @@ -235,7 +237,7 @@ describe('dateMath', function () { it(`should round now to the end of forceNow's ${span}`, function () { expect( dateMath.parse('now/' + span, { roundUp: true, forceNow: anchoredDate }).valueOf() - ).to.eql(anchored.endOf(span).valueOf()); + ).toEqual(anchored.endOf(span).valueOf()); }); }); }); @@ -245,38 +247,39 @@ describe('dateMath', function () { let anchored; beforeEach(function () { - clock = sinon.useFakeTimers(unix); + jest.useFakeTimers('modern'); + jest.setSystemTime(unix); now = moment(); anchored = moment(anchor); }); afterEach(function () { - clock.restore(); + jest.useRealTimers(); }); it('should round to the nearest second with 0 value', function () { const val = dateMath.parse('now-0s/s').format(format); - expect(val).to.eql(now.startOf('s').format(format)); + expect(val).toEqual(now.startOf('s').format(format)); }); it('should subtract 17s, rounded to the nearest second', function () { const val = dateMath.parse('now-17s/s').format(format); - expect(val).to.eql(now.startOf('s').subtract(17, 's').format(format)); + expect(val).toEqual(now.startOf('s').subtract(17, 's').format(format)); }); it('should add 555ms, rounded to the nearest millisecond', function () { const val = dateMath.parse('now+555ms/ms').format(format); - expect(val).to.eql(now.add(555, 'ms').startOf('ms').format(format)); + expect(val).toEqual(now.add(555, 'ms').startOf('ms').format(format)); }); it('should subtract 555ms, rounded to the nearest second', function () { const val = dateMath.parse('now-555ms/s').format(format); - expect(val).to.eql(now.subtract(555, 'ms').startOf('s').format(format)); + expect(val).toEqual(now.subtract(555, 'ms').startOf('s').format(format)); }); it('should round weeks to Sunday by default', function () { const val = dateMath.parse('now-1w/w'); - expect(val.isoWeekday()).to.eql(7); + expect(val.isoWeekday()).toEqual(7); }); it('should round weeks based on the passed moment locale start of week setting', function () { @@ -286,7 +289,7 @@ describe('dateMath', function () { week: { dow: 2 }, }); const val = dateMath.parse('now-1w/w', { momentInstance: m }); - expect(val.isoWeekday()).to.eql(2); + expect(val.isoWeekday()).toEqual(2); }); it('should round up weeks based on the passed moment locale start of week setting', function () { @@ -301,79 +304,79 @@ describe('dateMath', function () { }); // The end of the range (rounding up) should be the last day of the week (so one day before) // our start of the week, that's why 3 - 1 - expect(val.isoWeekday()).to.eql(3 - 1); + expect(val.isoWeekday()).toEqual(3 - 1); }); it('should round relative to forceNow', function () { const val = dateMath.parse('now-0s/s', { forceNow: anchoredDate }).valueOf(); - expect(val).to.eql(anchored.startOf('s').valueOf()); + expect(val).toEqual(anchored.startOf('s').valueOf()); }); it('should parse long expressions', () => { - expect(dateMath.parse('now-1d/d+8h+50m')).to.be.ok(); + expect(dateMath.parse('now-1d/d+8h+50m')).toBeTruthy(); }); }); describe('used momentjs instance', function () { it('should use the default moment instance if parameter not specified', function () { - const momentSpy = sinon.spy(moment, 'isMoment'); + const momentSpy = jest.spyOn(moment, 'isMoment'); dateMath.parse('now'); - expect(momentSpy.called).to.be(true); - momentSpy.restore(); + expect(momentSpy).toHaveBeenCalled(); + momentSpy.mockRestore(); }); it('should not use default moment instance if parameter is specified', function () { const m = momentClone(); - const momentSpy = sinon.spy(moment, 'isMoment'); - const cloneSpy = sinon.spy(m, 'isMoment'); + const momentSpy = jest.spyOn(moment, 'isMoment'); + const cloneSpy = jest.spyOn(m, 'isMoment'); dateMath.parse('now', { momentInstance: m }); - expect(momentSpy.called).to.be(false); - expect(cloneSpy.called).to.be(true); - momentSpy.restore(); - cloneSpy.restore(); + expect(momentSpy).not.toHaveBeenCalled(); + expect(cloneSpy).toHaveBeenCalled(); + momentSpy.mockRestore(); + cloneSpy.mockRestore(); }); it('should work with multiple different instances', function () { const m1 = momentClone(); const m2 = momentClone(); - const m1Spy = sinon.spy(m1, 'isMoment'); - const m2Spy = sinon.spy(m2, 'isMoment'); + const m1Spy = jest.spyOn(m1, 'isMoment'); + const m2Spy = jest.spyOn(m2, 'isMoment'); dateMath.parse('now', { momentInstance: m1 }); - expect(m1Spy.called).to.be(true); - expect(m2Spy.called).to.be(false); - m1Spy.resetHistory(); - m2Spy.resetHistory(); + expect(m1Spy).toHaveBeenCalled(); + expect(m2Spy).not.toHaveBeenCalled(); + m1Spy.mockClear(); + m2Spy.mockClear(); dateMath.parse('now', { momentInstance: m2 }); - expect(m1Spy.called).to.be(false); - expect(m2Spy.called).to.be(true); - m1Spy.restore(); - m2Spy.restore(); + expect(m1Spy).not.toHaveBeenCalled(); + expect(m2Spy).toHaveBeenCalled(); + m1Spy.mockRestore(); + m2Spy.mockRestore(); }); it('should use global instance after passing an instance', function () { const m = momentClone(); - const momentSpy = sinon.spy(moment, 'isMoment'); - const cloneSpy = sinon.spy(m, 'isMoment'); + const momentSpy = jest.spyOn(moment, 'isMoment'); + const cloneSpy = jest.spyOn(m, 'isMoment'); dateMath.parse('now', { momentInstance: m }); - expect(momentSpy.called).to.be(false); - expect(cloneSpy.called).to.be(true); - momentSpy.resetHistory(); - cloneSpy.resetHistory(); + expect(momentSpy).not.toHaveBeenCalled(); + expect(cloneSpy).toHaveBeenCalled(); + momentSpy.mockClear(); + cloneSpy.mockClear(); dateMath.parse('now'); - expect(momentSpy.called).to.be(true); - expect(cloneSpy.called).to.be(false); - momentSpy.restore(); - cloneSpy.restore(); + expect(momentSpy).toHaveBeenCalled(); + expect(cloneSpy).not.toHaveBeenCalled(); + momentSpy.mockRestore(); + cloneSpy.mockRestore(); }); }); describe('units', function () { it('should have units descending for unitsDesc', function () { - expect(dateMath.unitsDesc).to.eql(['y', 'M', 'w', 'd', 'h', 'm', 's', 'ms']); + expect(dateMath.unitsDesc).toEqual(['y', 'M', 'w', 'd', 'h', 'm', 's', 'ms']); }); it('should have units ascending for unitsAsc', function () { - expect(dateMath.unitsAsc).to.eql(['ms', 's', 'm', 'h', 'd', 'w', 'M', 'y']); + expect(dateMath.unitsAsc).toEqual(['ms', 's', 'm', 'h', 'd', 'w', 'M', 'y']); }); }); }); diff --git a/packages/elastic-datemath/jest.config.js b/packages/elastic-datemath/jest.config.js new file mode 100644 index 0000000000000..6a0bd891f1c58 --- /dev/null +++ b/packages/elastic-datemath/jest.config.js @@ -0,0 +1,25 @@ +/* + * 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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../..', + roots: ['/packages/elastic-datemath'], + testEnvironment: 'jsdom', +}; diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index a9e55fdc22dc6..927f94c10fc42 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -43,6 +43,9 @@ export class DocLinksService { urlDrilldownTemplateSyntax: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/url_templating-language.html`, urlDrilldownVariables: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/url_templating-language.html#url-template-variables`, }, + discover: { + guide: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/discover.html`, + }, filebeat: { base: `${ELASTIC_WEBSITE_URL}guide/en/beats/filebeat/${DOC_LINK_VERSION}`, installation: `${ELASTIC_WEBSITE_URL}guide/en/beats/filebeat/${DOC_LINK_VERSION}/filebeat-installation-configuration.html`, @@ -243,6 +246,7 @@ export interface DocLinksStart { readonly urlDrilldownTemplateSyntax: string; readonly urlDrilldownVariables: string; }; + readonly discover: Record; readonly filebeat: { readonly base: string; readonly installation: string; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 26ce358cc9ade..dd06022dc4831 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -494,6 +494,7 @@ export interface DocLinksStart { readonly urlDrilldownTemplateSyntax: string; readonly urlDrilldownVariables: string; }; + readonly discover: Record; readonly filebeat: { readonly base: string; readonly installation: string; diff --git a/src/dev/build/tasks/create_archives_task.ts b/src/dev/build/tasks/create_archives_task.ts index a05e383394ecf..2e5b54ccb09d5 100644 --- a/src/dev/build/tasks/create_archives_task.ts +++ b/src/dev/build/tasks/create_archives_task.ts @@ -21,7 +21,7 @@ import Path from 'path'; import Fs from 'fs'; import { promisify } from 'util'; -import { CiStatsReporter, CiStatsMetrics } from '@kbn/dev-utils'; +import { CiStatsMetrics } from '@kbn/dev-utils'; import { mkdirp, compressTar, compressZip, Task } from '../lib'; @@ -99,6 +99,7 @@ export const CreateArchives: Task = { } log.debug('archive metrics:', metrics); - await CiStatsReporter.fromEnv(log).metrics(metrics); + // FLAKY: https://github.com/elastic/kibana/issues/87529 + // await CiStatsReporter.fromEnv(log).metrics(metrics); }, }; diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker index 3e440c89b82d8..6822fcddc3ac5 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/bin/kibana-docker @@ -169,6 +169,7 @@ kibana_vars=( xpack.fleet.agents.elasticsearch.host xpack.fleet.agents.kibana.host xpack.fleet.agents.tlsCheckDisabled + xpack.fleet.registryUrl xpack.graph.enabled xpack.graph.canEditDrillDownUrls xpack.graph.savePolicy diff --git a/src/plugins/dashboard/public/application/lib/help_menu_util.ts b/src/plugins/dashboard/public/application/lib/help_menu_util.ts index efdff051a25a0..ee06e7bc5ecf2 100644 --- a/src/plugins/dashboard/public/application/lib/help_menu_util.ts +++ b/src/plugins/dashboard/public/application/lib/help_menu_util.ts @@ -31,7 +31,7 @@ export function addHelpMenuToAppChrome( links: [ { linkType: 'documentation', - href: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/dashboard.html`, + href: `${docLinks.links.dashboard.guide}`, }, ], }); diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index bb8ed92e9bfce..c58cd11bbc5bc 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -38,7 +38,6 @@ import { IUiSettingsClient } from 'src/core/server'; import { IUiSettingsClient as IUiSettingsClient_3 } from 'kibana/server'; import { KibanaRequest } from 'kibana/server'; import { KibanaRequest as KibanaRequest_2 } from 'src/core/server'; -import { LegacyAPICaller } from 'src/core/server'; import { Logger } from 'src/core/server'; import { Logger as Logger_2 } from 'kibana/server'; import { LoggerFactory } from '@kbn/logging'; diff --git a/src/plugins/discover/public/application/components/help_menu/help_menu_util.js b/src/plugins/discover/public/application/components/help_menu/help_menu_util.js index 03ab44966f796..e3c2adf587d91 100644 --- a/src/plugins/discover/public/application/components/help_menu/help_menu_util.js +++ b/src/plugins/discover/public/application/components/help_menu/help_menu_util.js @@ -29,7 +29,7 @@ export function addHelpMenuToAppChrome(chrome) { links: [ { linkType: 'documentation', - href: `${docLinks.ELASTIC_WEBSITE_URL}guide/en/kibana/${docLinks.DOC_LINK_VERSION}/discover.html`, + href: `${docLinks.links.discover.guide}`, }, ], }); diff --git a/src/plugins/telemetry/server/fetcher.ts b/src/plugins/telemetry/server/fetcher.ts index 820f2c7c4c4af..23b4b0640e978 100644 --- a/src/plugins/telemetry/server/fetcher.ts +++ b/src/plugins/telemetry/server/fetcher.ts @@ -31,7 +31,7 @@ import { SavedObjectsClientContract, SavedObjectsClient, CoreStart, - ILegacyCustomClusterClient, + ICustomClusterClient, } from '../../../core/server'; import { getTelemetryOptIn, @@ -65,7 +65,7 @@ export class FetcherTask { private isSending = false; private internalRepository?: SavedObjectsClientContract; private telemetryCollectionManager?: TelemetryCollectionManagerPluginStart; - private elasticsearchClient?: ILegacyCustomClusterClient; + private elasticsearchClient?: ICustomClusterClient; constructor(initializerContext: PluginInitializerContext) { this.config$ = initializerContext.config.create(); @@ -79,7 +79,7 @@ export class FetcherTask { ) { this.internalRepository = new SavedObjectsClient(savedObjects.createInternalRepository()); this.telemetryCollectionManager = telemetryCollectionManager; - this.elasticsearchClient = elasticsearch.legacy.createClient('telemetry-fetcher'); + this.elasticsearchClient = elasticsearch.createClient('telemetry-fetcher'); this.intervalId = timer(this.initialCheckDelayMs, this.checkIntervalMs).subscribe(() => this.sendIfDue() diff --git a/src/plugins/telemetry/server/plugin.ts b/src/plugins/telemetry/server/plugin.ts index f40c38b2cbbd0..95b44ae560f20 100644 --- a/src/plugins/telemetry/server/plugin.ts +++ b/src/plugins/telemetry/server/plugin.ts @@ -99,7 +99,7 @@ export class TelemetryPlugin implements Plugin { - const usage = await usageCollection.bulkFetch( - callWithInternalUser, - asInternalUser, - soClient, - kibanaRequest - ); + const usage = await usageCollection.bulkFetch(asInternalUser, soClient, kibanaRequest); return usageCollection.toObject(usage); } diff --git a/src/plugins/telemetry/server/telemetry_collection/get_local_stats.ts b/src/plugins/telemetry/server/telemetry_collection/get_local_stats.ts index 12245ce62305e..866aed520bd2e 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_local_stats.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_local_stats.ts @@ -71,7 +71,7 @@ export const getLocalStats: StatsGetter = async ( config, context ) => { - const { callCluster, usageCollection, esClient, soClient, kibanaRequest } = config; + const { usageCollection, esClient, soClient, kibanaRequest } = config; return await Promise.all( clustersDetails.map(async (clustersDetail) => { @@ -79,7 +79,7 @@ export const getLocalStats: StatsGetter = async ( getClusterInfo(esClient), // cluster info getClusterStats(esClient), // cluster stats (not to be confused with cluster _state_) getNodesUsage(esClient), // nodes_usage info - getKibana(usageCollection, callCluster, esClient, soClient, kibanaRequest), + getKibana(usageCollection, esClient, soClient, kibanaRequest), getDataTelemetry(esClient), ]); return handleLocalStats( diff --git a/src/plugins/telemetry_collection_manager/server/plugin.ts b/src/plugins/telemetry_collection_manager/server/plugin.ts index a135f4b115b21..247d9ce2c366c 100644 --- a/src/plugins/telemetry_collection_manager/server/plugin.ts +++ b/src/plugins/telemetry_collection_manager/server/plugin.ts @@ -26,7 +26,6 @@ import { Logger, IClusterClient, SavedObjectsServiceStart, - ILegacyClusterClient, } from 'src/core/server'; import { @@ -53,7 +52,6 @@ export class TelemetryCollectionManagerPlugin private collectionStrategy: CollectionStrategy | undefined; private usageGetterMethodPriority = -1; private usageCollection?: UsageCollectionSetup; - private legacyElasticsearchClient?: ILegacyClusterClient; private elasticsearchClient?: IClusterClient; private savedObjectsService?: SavedObjectsServiceStart; private readonly isDistributable: boolean; @@ -77,7 +75,6 @@ export class TelemetryCollectionManagerPlugin } public start(core: CoreStart) { - this.legacyElasticsearchClient = core.elasticsearch.legacy.client; // TODO: Remove when all the collectors have migrated this.elasticsearchClient = core.elasticsearch.client; this.savedObjectsService = core.savedObjects; @@ -129,9 +126,6 @@ export class TelemetryCollectionManagerPlugin config: StatsGetterConfig, usageCollection: UsageCollectionSetup ): StatsCollectionConfig | undefined { - const callCluster = config.unencrypted - ? this.legacyElasticsearchClient?.asScoped(config.request).callAsCurrentUser - : this.legacyElasticsearchClient?.callAsInternalUser; // Scope the new elasticsearch Client appropriately and pass to the stats collection config const esClient = config.unencrypted ? this.elasticsearchClient?.asScoped(config.request).asCurrentUser @@ -143,8 +137,8 @@ export class TelemetryCollectionManagerPlugin // Provide the kibanaRequest so opted-in plugins can scope their custom clients only if the request is not encrypted const kibanaRequest = config.unencrypted ? config.request : void 0; - if (callCluster && esClient && soClient) { - return { callCluster, usageCollection, esClient, soClient, kibanaRequest }; + if (esClient && soClient) { + return { usageCollection, esClient, soClient, kibanaRequest }; } } diff --git a/src/plugins/telemetry_collection_manager/server/types.ts b/src/plugins/telemetry_collection_manager/server/types.ts index 05641d5064593..49e217b9e3d75 100644 --- a/src/plugins/telemetry_collection_manager/server/types.ts +++ b/src/plugins/telemetry_collection_manager/server/types.ts @@ -18,7 +18,6 @@ */ import { - LegacyAPICaller, ElasticsearchClient, Logger, KibanaRequest, @@ -68,7 +67,6 @@ export interface ClusterDetails { export interface StatsCollectionConfig { usageCollection: UsageCollectionSetup; - callCluster: LegacyAPICaller; esClient: ElasticsearchClient; soClient: SavedObjectsClientContract | ISavedObjectsRepository; kibanaRequest: KibanaRequest | undefined; // intentionally `| undefined` to enforce providing the parameter diff --git a/src/plugins/usage_collection/README.md b/src/plugins/usage_collection/README.md index 85c910cd09bf1..76404bf6329dd 100644 --- a/src/plugins/usage_collection/README.md +++ b/src/plugins/usage_collection/README.md @@ -95,10 +95,10 @@ Some background: - `isReady` (added in v7.2.0 and v6.8.4) is a way for a usage collector to announce that some async process must finish first before it can return data in the `fetch` method (e.g. a client needs to ne initialized, or the task manager needs to run a task first). If any collector reports that it is not ready when we call its `fetch` method, we reset a flag to try again and, after a set amount of time, collect data from those collectors that are ready and skip any that are not. This means that if a collector returns `true` for `isReady` and it actually isn't ready to return data, there won't be telemetry data from that collector in that telemetry report (usually once per day). You should consider what it means if your collector doesn't return data in the first few documents when Kibana starts or, if we should wait for any other reason (e.g. the task manager needs to run your task first). If you need to tell telemetry collection to wait, you should implement this function with custom logic. If your `fetch` method can run without the need of any previous dependencies, then you can return true for `isReady` as shown in the example below. -- The `fetch` method needs to support multiple contexts in which it is called. For example, when a user requests the example of what we collect in the **Kibana>Advanced Settings>Usage data** section, the clients provided in the context of the function (`CollectorFetchContext`) are scoped to that user's privileges. The reason is to avoid exposing via telemetry any data that user should not have access to (i.e.: if the user does not have access to certain indices, they shouldn't be allowed to see the number of documents that exists in it). In this case, the `fetch` method receives the clients `callCluster`, `esClient` and `soClient` scoped to the user who performed the HTTP API request. Alternatively, when requesting the usage data to be reported to the Remote Telemetry Service, the clients are scoped to the internal Kibana user (`kibana_system`). Please, mind it might have lower-level access than the default super-admin `elastic` test user. +- The `fetch` method needs to support multiple contexts in which it is called. For example, when a user requests the example of what we collect in the **Kibana>Advanced Settings>Usage data** section, the clients provided in the context of the function (`CollectorFetchContext`) are scoped to that user's privileges. The reason is to avoid exposing via telemetry any data that user should not have access to (i.e.: if the user does not have access to certain indices, they shouldn't be allowed to see the number of documents that exists in it). In this case, the `fetch` method receives the clients `esClient` and `soClient` scoped to the user who performed the HTTP API request. Alternatively, when requesting the usage data to be reported to the Remote Telemetry Service, the clients are scoped to the internal Kibana user (`kibana_system`). Please, mind it might have lower-level access than the default super-admin `elastic` test user. In some scenarios, your collector might need to maintain its own client. An example of that is the `monitoring` plugin, that maintains a connection to the Remote Monitoring Cluster to push its monitoring data. If that's the case, your plugin can opt-in to receive the additional `kibanaRequest` parameter by adding `extendFetchContext.kibanaRequest: true` to the collector's config: it will be appended to the context of the `fetch` method only if the request needs to be scoped to a user other than Kibana Internal, so beware that your collector will need to work for both scenarios (especially for the scenario when `kibanaRequest` is missing). -Note: there will be many cases where you won't need to use the `callCluster`, `esClient` or `soClient` function that gets passed in to your `fetch` method at all. Your feature might have an accumulating value in server memory, or read something from the OS. +Note: there will be many cases where you won't need to use the `esClient` or `soClient` function that gets passed in to your `fetch` method at all. Your feature might have an accumulating value in server memory, or read something from the OS. In the case of using a custom SavedObjects client, it is up to the plugin to initialize the client to save the data and it is strongly recommended to scope that client to the `kibana_system` user. @@ -302,7 +302,7 @@ New fields added to the telemetry payload currently mean that telemetry cluster There are a few ways you can test that your usage collector is working properly. -1. The `/api/stats?extended=true&legacy=true` HTTP API in Kibana (added in 6.4.0) will call the fetch methods of all the registered collectors, and add them to a stats object you can see in a browser or in curl. To test that your usage collector has been registered correctly and that it has the model of data you expected it to have, call that HTTP API manually and you should see a key in the `usage` object of the response named after your usage collector's `type` field. This method tests the Metricbeat scenario described above where `callCluster` wraps `callWithRequest`. +1. The `/api/stats?extended=true&legacy=true` HTTP API in Kibana (added in 6.4.0) will call the fetch methods of all the registered collectors, and add them to a stats object you can see in a browser or in curl. To test that your usage collector has been registered correctly and that it has the model of data you expected it to have, call that HTTP API manually and you should see a key in the `usage` object of the response named after your usage collector's `type` field. This method tests the Metricbeat scenario described above where the elasticsearch client wraps the call with the request. 2. There is a dev script in x-pack that will give a sample of a payload of data that gets sent up to the telemetry cluster for the sending phase of telemetry. Collected data comes from: - The `.monitoring-*` indices, when Monitoring is enabled. Monitoring enhances the sent payload of telemetry by producing usage data potentially of multiple clusters that exist in the monitoring data. Monitoring data is time-based, and the time frame of collection is the last 15 minutes. - Live-pulled from ES API endpoints. This will get just real-time stats without context of historical data. diff --git a/src/plugins/usage_collection/server/collector/collector.ts b/src/plugins/usage_collection/server/collector/collector.ts index 8e86bc3d1cd26..afd5b5883ff17 100644 --- a/src/plugins/usage_collection/server/collector/collector.ts +++ b/src/plugins/usage_collection/server/collector/collector.ts @@ -19,7 +19,6 @@ import { Logger, - LegacyAPICaller, ElasticsearchClient, ISavedObjectsRepository, SavedObjectsClientContract, @@ -54,10 +53,6 @@ export type MakeSchemaFrom = { * @remark Bear in mind when testing your collector that your user has the same privileges as the Kibana Internal user to ensure the expected data is sent to the remote cluster. */ export type CollectorFetchContext = { - /** - * @deprecated Scoped Legacy Elasticsearch client: use esClient instead - */ - callCluster: LegacyAPICaller; /** * Request-scoped Elasticsearch client * @remark Bear in mind when testing your collector that your user has the same privileges as the Kibana Internal user to ensure the expected data is sent to the remote cluster (more info: {@link CollectorFetchContext}) diff --git a/src/plugins/usage_collection/server/collector/collector_set.test.ts b/src/plugins/usage_collection/server/collector/collector_set.test.ts index 90a69043e0635..310714cc2a48a 100644 --- a/src/plugins/usage_collection/server/collector/collector_set.test.ts +++ b/src/plugins/usage_collection/server/collector/collector_set.test.ts @@ -44,7 +44,6 @@ describe('CollectorSet', () => { loggerSpies.debug.mockRestore(); loggerSpies.warn.mockRestore(); }); - const mockCallCluster = jest.fn().mockResolvedValue({ passTest: 1000 }); const mockEsClient = elasticsearchServiceMock.createClusterClient().asInternalUser; const mockSoClient = savedObjectsRepositoryMock.create(); const req = void 0; // No need to instantiate any KibanaRequest in these tests @@ -83,18 +82,19 @@ describe('CollectorSet', () => { }); it('should log debug status of fetching from the collector', async () => { + mockEsClient.get.mockResolvedValue({ passTest: 1000 } as any); const collectors = new CollectorSet({ logger }); collectors.registerCollector( new Collector(logger, { type: 'MY_TEST_COLLECTOR', fetch: (collectorFetchContext: any) => { - return collectorFetchContext.callCluster(); + return collectorFetchContext.esClient.get(); }, isReady: () => true, }) ); - const result = await collectors.bulkFetch(mockCallCluster, mockEsClient, mockSoClient, req); + const result = await collectors.bulkFetch(mockEsClient, mockSoClient, req); expect(loggerSpies.debug).toHaveBeenCalledTimes(1); expect(loggerSpies.debug).toHaveBeenCalledWith( 'Fetching data from MY_TEST_COLLECTOR collector' @@ -119,7 +119,7 @@ describe('CollectorSet', () => { let result; try { - result = await collectors.bulkFetch(mockCallCluster, mockEsClient, mockSoClient, req); + result = await collectors.bulkFetch(mockEsClient, mockSoClient, req); } catch (err) { // Do nothing } @@ -137,7 +137,7 @@ describe('CollectorSet', () => { }) ); - const result = await collectors.bulkFetch(mockCallCluster, mockEsClient, mockSoClient, req); + const result = await collectors.bulkFetch(mockEsClient, mockSoClient, req); expect(result).toStrictEqual([ { type: 'MY_TEST_COLLECTOR', @@ -155,7 +155,7 @@ describe('CollectorSet', () => { } as any) ); - const result = await collectors.bulkFetch(mockCallCluster, mockEsClient, mockSoClient, req); + const result = await collectors.bulkFetch(mockEsClient, mockSoClient, req); expect(result).toStrictEqual([ { type: 'MY_TEST_COLLECTOR', diff --git a/src/plugins/usage_collection/server/collector/collector_set.ts b/src/plugins/usage_collection/server/collector/collector_set.ts index 3555b05518fdb..fc47bbcd16649 100644 --- a/src/plugins/usage_collection/server/collector/collector_set.ts +++ b/src/plugins/usage_collection/server/collector/collector_set.ts @@ -20,7 +20,6 @@ import { snakeCase } from 'lodash'; import { Logger, - LegacyAPICaller, ElasticsearchClient, ISavedObjectsRepository, SavedObjectsClientContract, @@ -171,7 +170,6 @@ export class CollectorSet { }; public bulkFetch = async ( - callCluster: LegacyAPICaller, esClient: ElasticsearchClient, soClient: SavedObjectsClientContract | ISavedObjectsRepository, kibanaRequest: KibanaRequest | undefined, // intentionally `| undefined` to enforce providing the parameter @@ -182,7 +180,6 @@ export class CollectorSet { this.logger.debug(`Fetching data from ${collector.type} collector`); try { const context = { - callCluster, esClient, soClient, ...(collector.extendFetchContext.kibanaRequest && { kibanaRequest }), @@ -212,14 +209,12 @@ export class CollectorSet { }; public bulkFetchUsage = async ( - callCluster: LegacyAPICaller, esClient: ElasticsearchClient, savedObjectsClient: SavedObjectsClientContract | ISavedObjectsRepository, kibanaRequest: KibanaRequest | undefined // intentionally `| undefined` to enforce providing the parameter ) => { const usageCollectors = this.getFilteredCollectorSet((c) => c instanceof UsageCollector); return await this.bulkFetch( - callCluster, esClient, savedObjectsClient, kibanaRequest, diff --git a/src/plugins/usage_collection/server/routes/stats/stats.ts b/src/plugins/usage_collection/server/routes/stats/stats.ts index 16a1c2c742f04..bbb4c94e02d5f 100644 --- a/src/plugins/usage_collection/server/routes/stats/stats.ts +++ b/src/plugins/usage_collection/server/routes/stats/stats.ts @@ -28,7 +28,6 @@ import { IRouter, ISavedObjectsRepository, KibanaRequest, - LegacyAPICaller, MetricsServiceSetup, SavedObjectsClientContract, ServiceStatus, @@ -66,17 +65,11 @@ export function registerStatsRoute({ overallStatus$: Observable; }) { const getUsage = async ( - callCluster: LegacyAPICaller, esClient: ElasticsearchClient, savedObjectsClient: SavedObjectsClientContract | ISavedObjectsRepository, kibanaRequest: KibanaRequest ): Promise => { - const usage = await collectorSet.bulkFetchUsage( - callCluster, - esClient, - savedObjectsClient, - kibanaRequest - ); + const usage = await collectorSet.bulkFetchUsage(esClient, savedObjectsClient, kibanaRequest); return collectorSet.toObject(usage); }; @@ -110,7 +103,6 @@ export function registerStatsRoute({ let extended; if (isExtended) { - const callCluster = context.core.elasticsearch.legacy.client.callAsCurrentUser; const { asCurrentUser } = context.core.elasticsearch.client; const savedObjectsClient = context.core.savedObjects.client; @@ -122,7 +114,7 @@ export function registerStatsRoute({ } const usagePromise = shouldGetUsage - ? getUsage(callCluster, asCurrentUser, savedObjectsClient, req) + ? getUsage(asCurrentUser, savedObjectsClient, req) : Promise.resolve({}); const [usage, clusterUuid] = await Promise.all([ usagePromise, diff --git a/src/plugins/usage_collection/server/usage_collection.mock.ts b/src/plugins/usage_collection/server/usage_collection.mock.ts index fb0a2e56ff3c9..1295572335a66 100644 --- a/src/plugins/usage_collection/server/usage_collection.mock.ts +++ b/src/plugins/usage_collection/server/usage_collection.mock.ts @@ -50,7 +50,6 @@ export const createUsageCollectionSetupMock = () => { export function createCollectorFetchContextMock(): jest.Mocked> { const collectorFetchClientsMock: jest.Mocked> = { - callCluster: elasticsearchServiceMock.createLegacyClusterClient().callAsInternalUser, esClient: elasticsearchServiceMock.createClusterClient().asInternalUser, soClient: savedObjectsRepositoryMock.create(), }; @@ -61,7 +60,6 @@ export function createCollectorFetchContextWithKibanaMock(): jest.Mocked< CollectorFetchContext > { const collectorFetchClientsMock: jest.Mocked> = { - callCluster: elasticsearchServiceMock.createLegacyClusterClient().callAsInternalUser, esClient: elasticsearchServiceMock.createClusterClient().asInternalUser, soClient: savedObjectsRepositoryMock.create(), kibanaRequest: httpServerMock.createKibanaRequest(), diff --git a/src/plugins/visualizations/public/index.ts b/src/plugins/visualizations/public/index.ts index 662350bfc3bd0..3ddf0757ba4c8 100644 --- a/src/plugins/visualizations/public/index.ts +++ b/src/plugins/visualizations/public/index.ts @@ -57,5 +57,5 @@ export { VisToExpressionAst, } from './types'; export { ExprVisAPIEvents } from './expressions/vis'; -export { VisualizationListItem } from './vis_types/vis_type_alias_registry'; +export { VisualizationListItem, VisualizationStage } from './vis_types/vis_type_alias_registry'; export { VISUALIZE_ENABLE_LABS_SETTING } from '../common/constants'; diff --git a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts index c05f42d684dbe..c16ddf436381d 100644 --- a/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts +++ b/src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts @@ -16,6 +16,9 @@ * specific language governing permissions and limitations * under the License. */ +import { SavedObject } from '../../../../core/types/saved_objects'; + +export type VisualizationStage = 'experimental' | 'beta' | 'production'; export interface VisualizationListItem { editUrl: string; @@ -23,7 +26,7 @@ export interface VisualizationListItem { error?: string; icon: string; id: string; - stage: 'experimental' | 'beta' | 'production'; + stage: VisualizationStage; savedObjectType: string; title: string; description?: string; @@ -35,11 +38,7 @@ export interface VisualizationListItem { export interface VisualizationsAppExtension { docTypes: string[]; searchFields?: string[]; - toListItem: (savedObject: { - id: string; - type: string; - attributes: object; - }) => VisualizationListItem; + toListItem: (savedObject: SavedObject) => VisualizationListItem; } export interface VisTypeAliasPromoTooltip { @@ -59,7 +58,7 @@ export interface VisTypeAlias { note?: string; disabled?: boolean; getSupportedTriggers?: () => string[]; - stage: 'experimental' | 'beta' | 'production'; + stage: VisualizationStage; appExtensions?: { visualizations: VisualizationsAppExtension; diff --git a/x-pack/plugins/beats_management/public/lib/__tests__/config_blocks.test.ts b/x-pack/plugins/beats_management/public/lib/config_blocks.test.ts similarity index 93% rename from x-pack/plugins/beats_management/public/lib/__tests__/config_blocks.test.ts rename to x-pack/plugins/beats_management/public/lib/config_blocks.test.ts index 179df6c19e21d..1a1286e32f1c0 100644 --- a/x-pack/plugins/beats_management/public/lib/__tests__/config_blocks.test.ts +++ b/x-pack/plugins/beats_management/public/lib/config_blocks.test.ts @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { configBlockSchemas } from '../../../common/config_schemas'; -import { translateConfigSchema } from '../../../common/config_schemas_translations_map'; -import { ConfigBlocksLib } from '../configuration_blocks'; -import { MemoryConfigBlocksAdapter } from './../adapters/configuration_blocks/memory_config_blocks_adapter'; +import { configBlockSchemas } from '../../common/config_schemas'; +import { translateConfigSchema } from '../../common/config_schemas_translations_map'; +import { ConfigBlocksLib } from './configuration_blocks'; +import { MemoryConfigBlocksAdapter } from './adapters/configuration_blocks/memory_config_blocks_adapter'; describe('Tags Client Domain Lib', () => { let lib: ConfigBlocksLib; diff --git a/x-pack/plugins/canvas/__tests__/fixtures/elasticsearch.js b/x-pack/plugins/canvas/__fixtures__/elasticsearch.js similarity index 100% rename from x-pack/plugins/canvas/__tests__/fixtures/elasticsearch.js rename to x-pack/plugins/canvas/__fixtures__/elasticsearch.js diff --git a/x-pack/plugins/canvas/__tests__/fixtures/elasticsearch_plugin.js b/x-pack/plugins/canvas/__fixtures__/elasticsearch_plugin.js similarity index 100% rename from x-pack/plugins/canvas/__tests__/fixtures/elasticsearch_plugin.js rename to x-pack/plugins/canvas/__fixtures__/elasticsearch_plugin.js diff --git a/x-pack/plugins/canvas/__tests__/fixtures/function_specs.ts b/x-pack/plugins/canvas/__fixtures__/function_specs.ts similarity index 63% rename from x-pack/plugins/canvas/__tests__/fixtures/function_specs.ts rename to x-pack/plugins/canvas/__fixtures__/function_specs.ts index 125dd20a66d8a..2d35fdae48985 100644 --- a/x-pack/plugins/canvas/__tests__/fixtures/function_specs.ts +++ b/x-pack/plugins/canvas/__fixtures__/function_specs.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functions as browserFns } from '../../canvas_plugin_src/functions/browser'; -import { ExpressionFunction } from '../../../../../src/plugins/expressions'; -import { initFunctions } from '../../public/functions'; +import { functions as browserFns } from '../canvas_plugin_src/functions/browser'; +import { ExpressionFunction } from '../../../../src/plugins/expressions'; +import { initFunctions } from '../public/functions'; export const functionSpecs = browserFns .concat(...(initFunctions({} as any) as any)) diff --git a/x-pack/plugins/canvas/__tests__/fixtures/kibana.js b/x-pack/plugins/canvas/__fixtures__/kibana.js similarity index 100% rename from x-pack/plugins/canvas/__tests__/fixtures/kibana.js rename to x-pack/plugins/canvas/__fixtures__/kibana.js diff --git a/x-pack/plugins/canvas/__tests__/fixtures/workpads.ts b/x-pack/plugins/canvas/__fixtures__/workpads.ts similarity index 99% rename from x-pack/plugins/canvas/__tests__/fixtures/workpads.ts rename to x-pack/plugins/canvas/__fixtures__/workpads.ts index 0d2939ed0e8a5..886d38759d099 100644 --- a/x-pack/plugins/canvas/__tests__/fixtures/workpads.ts +++ b/x-pack/plugins/canvas/__fixtures__/workpads.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { CanvasWorkpad, CanvasElement, CanvasPage, CanvasVariable } from '../../types'; +import { CanvasWorkpad, CanvasElement, CanvasPage, CanvasVariable } from '../types'; const BaseWorkpad: CanvasWorkpad = { '@created': '2019-02-08T18:35:23.029Z', diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/markdown.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/markdown.test.js index 1c75f5b7e0fbc..cf20f9830310f 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/markdown.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/browser/markdown.test.js @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { testTable } from '../common/__tests__/fixtures/test_tables'; -import { fontStyle } from '../common/__tests__/fixtures/test_styles'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { testTable } from '../common/__fixtures__/test_tables'; +import { fontStyle } from '../common/__fixtures__/test_styles'; import { markdown } from './markdown'; describe('markdown', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_filters.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_filters.js similarity index 100% rename from x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_filters.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_filters.js diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_pointseries.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_pointseries.js similarity index 100% rename from x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_pointseries.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_pointseries.js diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_styles.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_styles.js similarity index 96% rename from x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_styles.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_styles.js index 1848d796c61c5..7694cb699d6be 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_styles.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_styles.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { elasticLogo } from '../../../../lib/elastic_logo'; +import { elasticLogo } from '../../../lib/elastic_logo'; export const fontStyle = { type: 'style', diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_tables.ts similarity index 98% rename from x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_tables.ts index ffb76500a35d6..f2c325b6d75f9 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/fixtures/test_tables.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_tables.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { Datatable } from '../../../../../types'; +import { Datatable } from '../../../../types'; const emptyTable: Datatable = { type: 'datatable', diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js deleted file mode 100644 index 2a255ff742962..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/compare.js +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { compare } from '../compare'; -import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; -import { getFunctionErrors } from '../../../../i18n'; - -const errors = getFunctionErrors().compare; - -describe('compare', () => { - const fn = functionWrapper(compare); - - describe('args', () => { - describe('op', () => { - it('sets the operator', () => { - expect(fn(0, { op: 'lt', to: 1 })).to.be(true); - }); - - it("defaults to 'eq'", () => { - expect(fn(0, { to: 1 })).to.be(false); - expect(fn(0, { to: 0 })).to.be(true); - }); - - it('throws when invalid op is provided', () => { - expect(() => fn(1, { op: 'boo', to: 2 })).to.throwException( - new RegExp(errors.invalidCompareOperator('boo').message) - ); - expect(() => fn(1, { op: 'boo' })).to.throwException( - new RegExp(errors.invalidCompareOperator('boo').message) - ); - }); - }); - - describe('to', () => { - it('sets the value that context is compared to', () => { - expect(fn(0, { to: 1 })).to.be(false); - }); - - it('if not provided, ne returns true while every other operator returns false', () => { - expect(fn(null, { op: 'ne' })).to.be(true); - expect(fn(0, { op: 'ne' })).to.be(true); - expect(fn(true, { op: 'lte' })).to.be(false); - expect(fn(1, { op: 'gte' })).to.be(false); - expect(fn('foo', { op: 'lt' })).to.be(false); - expect(fn(null, { op: 'gt' })).to.be(false); - expect(fn(null, { op: 'eq' })).to.be(false); - }); - }); - }); - - describe('same type comparisons', () => { - describe('null', () => { - it('returns true', () => { - expect(fn(null, { op: 'eq', to: null })).to.be(true); - expect(fn(null, { op: 'lte', to: null })).to.be(true); - expect(fn(null, { op: 'gte', to: null })).to.be(true); - }); - - it('returns false', () => { - expect(fn(null, { op: 'ne', to: null })).to.be(false); - expect(fn(null, { op: 'lt', to: null })).to.be(false); - expect(fn(null, { op: 'gt', to: null })).to.be(false); - }); - }); - - describe('number', () => { - it('returns true', () => { - expect(fn(-2.34, { op: 'lt', to: 10 })).to.be(true); - expect(fn(2, { op: 'gte', to: 2 })).to.be(true); - }); - - it('returns false', () => { - expect(fn(2, { op: 'eq', to: 10 })).to.be(false); - expect(fn(10, { op: 'ne', to: 10 })).to.be(false); - expect(fn(1, { op: 'lte', to: -3 })).to.be(false); - expect(fn(2, { op: 'gt', to: 2 })).to.be(false); - }); - }); - - describe('string', () => { - it('returns true', () => { - expect(fn('foo', { op: 'gte', to: 'foo' })).to.be(true); - expect(fn('foo', { op: 'lte', to: 'foo' })).to.be(true); - expect(fn('bar', { op: 'lt', to: 'foo' })).to.be(true); - }); - - it('returns false', () => { - expect(fn('foo', { op: 'eq', to: 'bar' })).to.be(false); - expect(fn('foo', { op: 'ne', to: 'foo' })).to.be(false); - expect(fn('foo', { op: 'gt', to: 'foo' })).to.be(false); - }); - }); - - describe('boolean', () => { - it('returns true', () => { - expect(fn(true, { op: 'eq', to: true })).to.be(true); - expect(fn(false, { op: 'eq', to: false })).to.be(true); - expect(fn(true, { op: 'ne', to: false })).to.be(true); - expect(fn(false, { op: 'ne', to: true })).to.be(true); - }); - it('returns false', () => { - expect(fn(true, { op: 'eq', to: false })).to.be(false); - expect(fn(false, { op: 'eq', to: true })).to.be(false); - expect(fn(true, { op: 'ne', to: true })).to.be(false); - expect(fn(false, { op: 'ne', to: false })).to.be(false); - }); - }); - }); - - describe('different type comparisons', () => { - it("returns true for 'ne' only", () => { - expect(fn(0, { op: 'ne', to: '0' })).to.be(true); - }); - - it('otherwise always returns false', () => { - expect(fn(0, { op: 'eq', to: '0' })).to.be(false); - expect(fn('foo', { op: 'lt', to: 10 })).to.be(false); - expect(fn('foo', { op: 'lte', to: true })).to.be(false); - expect(fn(0, { op: 'gte', to: null })).to.be(false); - expect(fn(0, { op: 'eq', to: false })).to.be(false); - expect(fn(true, { op: 'gte', to: null })).to.be(false); - }); - }); -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/all.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/all.test.js index 63a3facc833d3..697bc2bb10e5d 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/all.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/all.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { all } from './all'; describe('all', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js index a8c01f0b2791f..1b4141c6e2cb0 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { getFunctionErrors } from '../../../i18n'; -import { emptyTable, testTable } from './__tests__/fixtures/test_tables'; +import { emptyTable, testTable } from './__fixtures__/test_tables'; import { alterColumn } from './alterColumn'; const errors = getFunctionErrors().alterColumn; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/any.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/any.test.js index dcff9b299832c..ed411b162685b 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/any.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/any.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { any } from './any'; describe('any', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.test.js index 49d14622e80f0..8da92e5b6720c 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/as.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { asFn } from './as'; describe('as', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/axis_config.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/axis_config.test.js index 04552b988e561..a58c52358f648 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/axis_config.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/axis_config.test.js @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { getFunctionErrors } from '../../../i18n'; -import { testTable } from './__tests__/fixtures/test_tables'; +import { testTable } from './__fixtures__/test_tables'; import { axisConfig } from './axisConfig'; const errors = getFunctionErrors().axisConfig; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js index 41ec526d1b853..f1ddf88388eac 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { caseFn } from './case'; describe('case', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/clear.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/clear.test.js index b89cbc976a63f..a4177d1fe05ba 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/clear.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/clear.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { testTable } from './__tests__/fixtures/test_tables'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { testTable } from './__fixtures__/test_tables'; import { clear } from './clear'; describe('clear', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.test.js index e2da579e5e0a3..8e0ae1b7a4fd5 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/columns.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { emptyTable, testTable } from './__tests__/fixtures/test_tables'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { emptyTable, testTable } from './__fixtures__/test_tables'; import { columns } from './columns'; describe('columns', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/compare.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/compare.test.js new file mode 100644 index 0000000000000..ddc20ccf7be75 --- /dev/null +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/compare.test.js @@ -0,0 +1,127 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { getFunctionErrors } from '../../../i18n'; +import { compare } from './compare'; + +const errors = getFunctionErrors().compare; + +describe('compare', () => { + const fn = functionWrapper(compare); + + describe('args', () => { + describe('op', () => { + it('sets the operator', () => { + expect(fn(0, { op: 'lt', to: 1 })).toBe(true); + }); + + it("defaults to 'eq'", () => { + expect(fn(0, { to: 1 })).toBe(false); + expect(fn(0, { to: 0 })).toBe(true); + }); + + it('throws when invalid op is provided', () => { + expect(() => fn(1, { op: 'boo', to: 2 })).toThrowError( + new RegExp(errors.invalidCompareOperator('boo').message) + ); + expect(() => fn(1, { op: 'boo' })).toThrowError( + new RegExp(errors.invalidCompareOperator('boo').message) + ); + }); + }); + + describe('to', () => { + it('sets the value that context is compared to', () => { + expect(fn(0, { to: 1 })).toBe(false); + }); + + it('if not provided, ne returns true while every other operator returns false', () => { + expect(fn(null, { op: 'ne' })).toBe(true); + expect(fn(0, { op: 'ne' })).toBe(true); + expect(fn(true, { op: 'lte' })).toBe(false); + expect(fn(1, { op: 'gte' })).toBe(false); + expect(fn('foo', { op: 'lt' })).toBe(false); + expect(fn(null, { op: 'gt' })).toBe(false); + expect(fn(null, { op: 'eq' })).toBe(false); + }); + }); + }); + + describe('same type comparisons', () => { + describe('null', () => { + it('returns true', () => { + expect(fn(null, { op: 'eq', to: null })).toBe(true); + expect(fn(null, { op: 'lte', to: null })).toBe(true); + expect(fn(null, { op: 'gte', to: null })).toBe(true); + }); + + it('returns false', () => { + expect(fn(null, { op: 'ne', to: null })).toBe(false); + expect(fn(null, { op: 'lt', to: null })).toBe(false); + expect(fn(null, { op: 'gt', to: null })).toBe(false); + }); + }); + + describe('number', () => { + it('returns true', () => { + expect(fn(-2.34, { op: 'lt', to: 10 })).toBe(true); + expect(fn(2, { op: 'gte', to: 2 })).toBe(true); + }); + + it('returns false', () => { + expect(fn(2, { op: 'eq', to: 10 })).toBe(false); + expect(fn(10, { op: 'ne', to: 10 })).toBe(false); + expect(fn(1, { op: 'lte', to: -3 })).toBe(false); + expect(fn(2, { op: 'gt', to: 2 })).toBe(false); + }); + }); + + describe('string', () => { + it('returns true', () => { + expect(fn('foo', { op: 'gte', to: 'foo' })).toBe(true); + expect(fn('foo', { op: 'lte', to: 'foo' })).toBe(true); + expect(fn('bar', { op: 'lt', to: 'foo' })).toBe(true); + }); + + it('returns false', () => { + expect(fn('foo', { op: 'eq', to: 'bar' })).toBe(false); + expect(fn('foo', { op: 'ne', to: 'foo' })).toBe(false); + expect(fn('foo', { op: 'gt', to: 'foo' })).toBe(false); + }); + }); + + describe('boolean', () => { + it('returns true', () => { + expect(fn(true, { op: 'eq', to: true })).toBe(true); + expect(fn(false, { op: 'eq', to: false })).toBe(true); + expect(fn(true, { op: 'ne', to: false })).toBe(true); + expect(fn(false, { op: 'ne', to: true })).toBe(true); + }); + it('returns false', () => { + expect(fn(true, { op: 'eq', to: false })).toBe(false); + expect(fn(false, { op: 'eq', to: true })).toBe(false); + expect(fn(true, { op: 'ne', to: true })).toBe(false); + expect(fn(false, { op: 'ne', to: false })).toBe(false); + }); + }); + }); + + describe('different type comparisons', () => { + it("returns true for 'ne' only", () => { + expect(fn(0, { op: 'ne', to: '0' })).toBe(true); + }); + + it('otherwise always returns false', () => { + expect(fn(0, { op: 'eq', to: '0' })).toBe(false); + expect(fn('foo', { op: 'lt', to: 10 })).toBe(false); + expect(fn('foo', { op: 'lte', to: true })).toBe(false); + expect(fn(0, { op: 'gte', to: null })).toBe(false); + expect(fn(0, { op: 'eq', to: false })).toBe(false); + expect(fn(true, { op: 'gte', to: null })).toBe(false); + }); + }); +}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/container_style.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/container_style.test.js index 3edae257ce69a..574ac15573b4b 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/container_style.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/container_style.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { elasticLogo } from '../../lib/elastic_logo'; import { getFunctionErrors } from '../../../i18n'; import { containerStyle } from './containerStyle'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/context.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/context.test.js index 904406f1a703b..32b00bddd4607 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/context.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/context.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { testTable, emptyTable } from './__tests__/fixtures/test_tables'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { testTable, emptyTable } from './__fixtures__/test_tables'; import { context } from './context'; describe('context', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/csv.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/csv.test.js index 8cd30e3b1915e..4083187c75aae 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/csv.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/csv.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { getFunctionErrors } from '../../../i18n'; import { csv } from './csv'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/date.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/date.test.js index 96b122d8a0776..4cf892b41dc35 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/date.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/date.test.js @@ -5,7 +5,7 @@ */ import sinon from 'sinon'; -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { getFunctionErrors } from '../../../i18n'; import { date } from './date'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/do.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/do.test.js index 46e0e22f53a6d..43310b68f1851 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/do.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/do.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { doFn } from './do'; describe('do', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdown_control.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdown_control.test.js index 3ce44948cd6d0..7eaf005cf1409 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdown_control.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdown_control.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { testTable } from './__tests__/fixtures/test_tables'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { testTable } from './__fixtures__/test_tables'; import { dropdownControl } from './dropdownControl'; describe('dropdownControl', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/eq.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/eq.test.js index cfe4dc3c9ba82..a890b67dfe1ef 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/eq.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/eq.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { eq } from './eq'; describe('eq', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/exactly.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/exactly.test.js index 2b9bdb59afbdf..409570da756ca 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/exactly.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/exactly.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { emptyFilter } from './__tests__/fixtures/test_filters'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { emptyFilter } from './__fixtures__/test_filters'; import { exactly } from './exactly'; describe('exactly', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js index 179be8aff2e19..c0d3ce658d0d1 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { testTable } from './__tests__/fixtures/test_tables'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { testTable } from './__fixtures__/test_tables'; import { filterrows } from './filterrows'; const inStock = (datatable) => datatable.rows[0].in_stock; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatdate.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatdate.test.js index 968727f4aa19d..27a793620d0b5 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatdate.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatdate.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { formatdate } from './formatdate'; describe('formatdate', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.test.js index adab2d4075550..5f751be4bb6c7 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/formatnumber.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { formatnumber } from './formatnumber'; describe('formatnumber', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/getCell.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/getCell.test.js index 976681f98260f..c23221298ab9f 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/getCell.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/getCell.test.js @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { getFunctionErrors } from '../../../i18n'; -import { emptyTable, testTable } from './__tests__/fixtures/test_tables'; +import { emptyTable, testTable } from './__fixtures__/test_tables'; import { getCell } from './getCell'; const errors = getFunctionErrors().getCell; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/gt.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/gt.test.js index 6c8c8de4f5763..71c27bd9e701b 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/gt.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/gt.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { gt } from './gt'; describe('gt', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/gte.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/gte.test.js index b5f31dbcba2ba..2e996d61da391 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/gte.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/gte.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { gte } from './gte'; describe('gte', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/head.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/head.test.js index bfbd548cdce01..74f9252878851 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/head.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/head.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { emptyTable, testTable } from './__tests__/fixtures/test_tables'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { emptyTable, testTable } from './__fixtures__/test_tables'; import { head } from './head'; describe('head', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js index 408d02ea175f1..6e1a6b4e225a6 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { ifFn } from './if'; describe('if', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/image.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/image.test.js similarity index 84% rename from x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/image.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/image.test.js index 0d1c80665f570..993d38b5e108e 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/image.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/image.test.js @@ -5,13 +5,15 @@ */ import expect from '@kbn/expect'; -import { image } from '../image'; -import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; -import { elasticLogo } from '../../../lib/elastic_logo'; -import { elasticOutline } from '../../../lib/elastic_outline'; +// import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { elasticLogo } from '../../lib/elastic_logo'; +import { elasticOutline } from '../../lib/elastic_outline'; +// import { image } from './image'; -describe('image', () => { - const fn = functionWrapper(image); +// TODO: the test was not running and is not up to date +describe.skip('image', () => { + // const fn = functionWrapper(image); + const fn = jest.fn(); it('returns an image object using a dataUrl', () => { const result = fn(null, { dataurl: elasticOutline, mode: 'cover' }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/join_rows.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/join_rows.test.js index 5c778300133a0..7479fb1763b9e 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/join_rows.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/join_rows.test.js @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { getFunctionErrors } from '../../../i18n'; -import { testTable } from './__tests__/fixtures/test_tables'; +import { testTable } from './__fixtures__/test_tables'; import { joinRows } from './join_rows'; const errors = getFunctionErrors().joinRows; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/lt.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/lt.test.js index ba1af11e5b92d..4a34e496bdfe2 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/lt.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/lt.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { lt } from './lt'; describe('lt', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/lte.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/lte.test.js index d4ebcb5417f22..9aa12d321532e 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/lte.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/lte.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { lte } from './lte'; describe('lte', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.test.js index 652d61fd77398..cc360a48c7f56 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/mapColumn.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { testTable, emptyTable } from './__tests__/fixtures/test_tables'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { testTable, emptyTable } from './__fixtures__/test_tables'; import { mapColumn } from './mapColumn'; const pricePlusTwo = (datatable) => Promise.resolve(datatable.rows[0].price + 2); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/math.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/math.test.js index 530a0043a7ef1..ff0819ad3ee55 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/math.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/math.test.js @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { getFunctionErrors } from '../../../i18n'; -import { emptyTable, testTable } from './__tests__/fixtures/test_tables'; +import { emptyTable, testTable } from './__fixtures__/test_tables'; import { math } from './math'; const errors = getFunctionErrors().math; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/metric.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/metric.test.js index 50a952d836251..f88e04fafc9db 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/metric.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/metric.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { fontStyle } from './__tests__/fixtures/test_styles'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { fontStyle } from './__fixtures__/test_styles'; import { metric } from './metric'; describe('metric', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/neq.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/neq.test.js index d1083131cfa2f..ecc5fce0300e3 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/neq.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/neq.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { neq } from './neq'; describe('neq', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js index 07d436007c816..3651cd84873d2 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/ply.test.js @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { getFunctionErrors } from '../../../i18n'; -import { testTable } from './__tests__/fixtures/test_tables'; +import { testTable } from './__fixtures__/test_tables'; import { ply } from './ply'; const errors = getFunctionErrors().ply; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/progress.test.js similarity index 93% rename from x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js rename to x-pack/plugins/canvas/canvas_plugin_src/functions/common/progress.test.js index 17f9defa15dc3..1558f26e26201 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__tests__/progress.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/progress.test.js @@ -5,14 +5,15 @@ */ import expect from '@kbn/expect'; -import { progress } from '../progress'; -import { functionWrapper } from '../../../../__tests__/helpers/function_wrapper'; -import { getFunctionErrors } from '../../../../i18n'; -import { fontStyle } from './fixtures/test_styles'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { getFunctionErrors } from '../../../i18n'; +import { progress } from './progress'; +import { fontStyle } from './__fixtures__/test_styles'; const errors = getFunctionErrors().progress; -describe('progress', () => { +// TODO: this test was not running and is not up to date +describe.skip('progress', () => { const fn = functionWrapper(progress); const value = 0.33; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/render.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/render.test.js index 152d7fb4df7ec..ddc4fcee08296 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/render.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/render.test.js @@ -4,10 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { DEFAULT_ELEMENT_CSS } from '../../../common/lib/constants'; -import { testTable } from './__tests__/fixtures/test_tables'; -import { fontStyle, containerStyle } from './__tests__/fixtures/test_styles'; +import { testTable } from './__fixtures__/test_tables'; +import { fontStyle, containerStyle } from './__fixtures__/test_styles'; import { render } from './render'; const renderTable = { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.test.js index f7c1ecc94a240..f03e8f127e3a2 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { elasticOutline } from '../../lib/elastic_outline'; import { elasticLogo } from '../../lib/elastic_logo'; import { repeatImage } from './repeat_image'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/replace.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/replace.test.js index e4a371ad82e1c..853127768604f 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/replace.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/replace.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { replace } from './replace'; describe('replace', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/reveal_image.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/reveal_image.test.js index 2efc91e93ddc2..7052fc81b62e0 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/reveal_image.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/reveal_image.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { elasticOutline } from '../../lib/elastic_outline'; import { elasticLogo } from '../../lib/elastic_logo'; import { getFunctionErrors } from '../../../i18n'; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rounddate.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rounddate.test.js index eed8b0aa6c6bf..651117b9bb818 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rounddate.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rounddate.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { rounddate } from './rounddate'; describe('rounddate', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rowCount.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rowCount.test.js index 798ed3a749ad4..52a9b56a4cc4c 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rowCount.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rowCount.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { emptyTable, testTable } from './__tests__/fixtures/test_tables'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { emptyTable, testTable } from './__fixtures__/test_tables'; import { rowCount } from './rowCount'; describe('rowCount', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/series_style.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/series_style.test.js index da2183f6dfbac..236a6cdc25a03 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/series_style.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/series_style.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { seriesStyle } from './seriesStyle'; describe('seriesStyle', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/sort.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/sort.test.js index 88eb31da2552c..37d42f0e7b3d3 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/sort.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/sort.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { testTable } from './__tests__/fixtures/test_tables'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { testTable } from './__fixtures__/test_tables'; import { sort } from './sort'; describe('sort', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.test.js index d137ce05ccc19..c4ba9f200e9b4 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/staticColumn.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { testTable, emptyTable } from './__tests__/fixtures/test_tables'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { testTable, emptyTable } from './__fixtures__/test_tables'; import { staticColumn } from './staticColumn'; describe('staticColumn', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/string.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/string.test.js index fbb7ab1b72eed..1250c5228d505 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/string.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/string.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { string } from './string'; describe('string', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js index 7ecccdd5ee544..5c71e101c8262 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { switchFn } from './switch'; describe('switch', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/table.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/table.test.js index c34c437e332ae..6ba450d94c557 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/table.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/table.test.js @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { testTable } from './__tests__/fixtures/test_tables'; -import { fontStyle } from './__tests__/fixtures/test_styles'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { testTable } from './__fixtures__/test_tables'; +import { fontStyle } from './__fixtures__/test_styles'; import { table } from './table'; describe('table', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/tail.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/tail.test.js index 45d6cba46716a..a95ac31b00079 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/tail.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/tail.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; -import { emptyTable, testTable } from './__tests__/fixtures/test_tables'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; +import { emptyTable, testTable } from './__fixtures__/test_tables'; import { tail } from './tail'; describe('tail', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.test.js index 2edbba278ffde..d650a6ca792e8 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.test.js @@ -5,9 +5,9 @@ */ import sinon from 'sinon'; -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { getFunctionErrors } from '../../../i18n'; -import { emptyFilter } from './__tests__/fixtures/test_filters'; +import { emptyFilter } from './__fixtures__/test_filters'; import { timefilter } from './timefilter'; const errors = getFunctionErrors().timefilter; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter_control.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter_control.test.js index fa7b26554f65b..edc57994c7d57 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter_control.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter_control.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../../__tests__/helpers/function_wrapper'; +import { functionWrapper } from '../../../test_helpers/function_wrapper'; import { timefilterControl } from './timefilterControl'; describe('timefilterControl', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/get_expression_type.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/get_expression_type.test.js index 237e80f0c1ee3..0dbc7ca833f05 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/get_expression_type.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/get_expression_type.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { emptyTable, testTable } from '../common/__tests__/fixtures/test_tables'; +import { emptyTable, testTable } from '../common/__fixtures__/test_tables'; import { getExpressionType } from './pointseries/lib/get_expression_type'; describe('getExpressionType', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries.test.js index 2029388115bcc..1adb7bc53987d 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/server/pointseries.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { emptyTable, testTable } from '../common/__tests__/fixtures/test_tables'; +import { emptyTable, testTable } from '../common/__fixtures__/test_tables'; import { pointseries } from './pointseries'; describe('pointseries', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/__tests__/get_form_object.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/__tests__/get_form_object.js deleted file mode 100644 index cb8e999489fbf..0000000000000 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/__tests__/get_form_object.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import expect from '@kbn/expect'; -import { getFormObject } from '../get_form_object'; - -describe('getFormObject', () => { - describe('valid input', () => { - it('string', () => { - expect(getFormObject('field')).to.be.eql({ fn: '', column: 'field' }); - }); - it('simple expression', () => { - expect(getFormObject('mean(field)')).to.be.eql({ fn: 'mean', column: 'field' }); - }); - }); - describe('invalid input', () => { - it('number', () => { - expect(getFormObject) - .withArgs('2') - .to.throwException((e) => { - expect(e.message).to.be('Cannot render scalar values or complex math expressions'); - }); - }); - it('complex expression', () => { - expect(getFormObject) - .withArgs('mean(field * 3)') - .to.throwException((e) => { - expect(e.message).to.be('Cannot render scalar values or complex math expressions'); - }); - }); - }); -}); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/get_form_object.test.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/get_form_object.test.js new file mode 100644 index 0000000000000..9458f0fd095d3 --- /dev/null +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/datacolumn/get_form_object.test.js @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getFormObject } from './get_form_object'; + +describe('getFormObject', () => { + describe('valid input', () => { + it('string', () => { + expect(getFormObject('field')).toEqual({ fn: '', column: 'field' }); + }); + it('simple expression', () => { + expect(getFormObject('mean(field)')).toEqual({ fn: 'mean', column: 'field' }); + }); + }); + describe('invalid input', () => { + it('number', () => { + expect(() => { + getFormObject('2'); + }).toThrow('Cannot render scalar values or complex math expressions'); + }); + it('complex expression', () => { + expect(() => { + getFormObject('mean(field * 3)'); + }).toThrow('Cannot render scalar values or complex math expressions'); + }); + }); +}); diff --git a/x-pack/plugins/canvas/common/lib/autocomplete.test.ts b/x-pack/plugins/canvas/common/lib/autocomplete.test.ts index 777810cad05ba..128fb6795f854 100644 --- a/x-pack/plugins/canvas/common/lib/autocomplete.test.ts +++ b/x-pack/plugins/canvas/common/lib/autocomplete.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionSpecs } from '../../__tests__/fixtures/function_specs'; +import { functionSpecs } from '../../__fixtures__/function_specs'; import { FunctionSuggestion, @@ -17,7 +17,7 @@ describe('autocomplete', () => { it('should return function definition for plot', () => { const expression = 'plot '; const def = getFnArgDefAtPosition(functionSpecs, expression, expression.length); - const plotFn = functionSpecs.find((spec) => spec.name === 'plot'); + const plotFn = functionSpecs.find((spec: any) => spec.name === 'plot'); expect(def.fnDef).toBe(plotFn); }); }); @@ -33,7 +33,7 @@ describe('autocomplete', () => { it('should suggest arguments', () => { const expression = 'plot '; const suggestions = getAutocompleteSuggestions(functionSpecs, expression, expression.length); - const plotFn = functionSpecs.find((spec) => spec.name === 'plot'); + const plotFn = functionSpecs.find((spec: any) => spec.name === 'plot'); expect(suggestions.length).toBe(Object.keys(plotFn!.args).length); expect(suggestions[0].start).toBe(expression.length); expect(suggestions[0].end).toBe(expression.length); @@ -42,7 +42,7 @@ describe('autocomplete', () => { it('should suggest values', () => { const expression = 'shape shape='; const suggestions = getAutocompleteSuggestions(functionSpecs, expression, expression.length); - const shapeFn = functionSpecs.find((spec) => spec.name === 'shape'); + const shapeFn = functionSpecs.find((spec: any) => spec.name === 'shape'); expect(suggestions.length).toBe(shapeFn!.args.shape.options.length); expect(suggestions[0].start).toBe(expression.length); expect(suggestions[0].end).toBe(expression.length); @@ -110,7 +110,7 @@ describe('autocomplete', () => { expression, expression.length - 1 ); - const ltFn = functionSpecs.find((spec) => spec.name === 'lt'); + const ltFn = functionSpecs.find((spec: any) => spec.name === 'lt'); expect(suggestions.length).toBe(Object.keys(ltFn!.args).length); expect(suggestions[0].start).toBe(expression.length - 1); expect(suggestions[0].end).toBe(expression.length - 1); @@ -123,7 +123,7 @@ describe('autocomplete', () => { expression, expression.length - 1 ); - const shapeFn = functionSpecs.find((spec) => spec.name === 'shape'); + const shapeFn = functionSpecs.find((spec: any) => spec.name === 'shape'); expect(suggestions.length).toBe(shapeFn!.args.shape.options.length); expect(suggestions[0].start).toBe(expression.length - 1); expect(suggestions[0].end).toBe(expression.length - 1); @@ -136,7 +136,7 @@ describe('autocomplete', () => { expression, expression.length - 1 ); - const shapeFn = functionSpecs.find((spec) => spec.name === 'shape'); + const shapeFn = functionSpecs.find((spec: any) => spec.name === 'shape'); expect(suggestions.length).toBe(shapeFn!.args.shape.options.length); expect(suggestions[0].start).toBe(expression.length - '"ar"'.length); expect(suggestions[0].end).toBe(expression.length); diff --git a/x-pack/plugins/canvas/common/lib/get_field_type.test.ts b/x-pack/plugins/canvas/common/lib/get_field_type.test.ts index 82e724c33ecc8..3e8f99750671c 100644 --- a/x-pack/plugins/canvas/common/lib/get_field_type.test.ts +++ b/x-pack/plugins/canvas/common/lib/get_field_type.test.ts @@ -7,7 +7,7 @@ import { emptyTable, testTable, -} from '../../canvas_plugin_src/functions/common/__tests__/fixtures/test_tables'; +} from '../../canvas_plugin_src/functions/common/__fixtures__/test_tables'; import { getFieldType } from './get_field_type'; describe('getFieldType', () => { diff --git a/x-pack/plugins/canvas/common/lib/handlebars.test.js b/x-pack/plugins/canvas/common/lib/handlebars.test.js index 5fcb2d42395fa..20574279bad96 100644 --- a/x-pack/plugins/canvas/common/lib/handlebars.test.js +++ b/x-pack/plugins/canvas/common/lib/handlebars.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { testTable } from '../../canvas_plugin_src/functions/common/__tests__/fixtures/test_tables'; +import { testTable } from '../../canvas_plugin_src/functions/common/__fixtures__/test_tables'; import { Handlebars } from './handlebars'; describe('handlebars', () => { diff --git a/x-pack/plugins/canvas/public/apps/export/export/__tests__/__snapshots__/export_app.test.tsx.snap b/x-pack/plugins/canvas/public/apps/export/export/__snapshots__/export_app.test.tsx.snap similarity index 100% rename from x-pack/plugins/canvas/public/apps/export/export/__tests__/__snapshots__/export_app.test.tsx.snap rename to x-pack/plugins/canvas/public/apps/export/export/__snapshots__/export_app.test.tsx.snap diff --git a/x-pack/plugins/canvas/public/apps/export/export/__tests__/export_app.test.tsx b/x-pack/plugins/canvas/public/apps/export/export/export_app.test.tsx similarity index 84% rename from x-pack/plugins/canvas/public/apps/export/export/__tests__/export_app.test.tsx rename to x-pack/plugins/canvas/public/apps/export/export/export_app.test.tsx index 1bb58919b7fa6..6a483b23e8e98 100644 --- a/x-pack/plugins/canvas/public/apps/export/export/__tests__/export_app.test.tsx +++ b/x-pack/plugins/canvas/public/apps/export/export/export_app.test.tsx @@ -6,18 +6,18 @@ import React from 'react'; import { mount } from 'enzyme'; -import { ExportApp } from '../export_app.component'; -import { CanvasWorkpad } from '../../../../../types'; +import { ExportApp } from './export_app.component'; +import { CanvasWorkpad } from '../../../../types'; jest.mock('style-it', () => ({ it: (css: string, Component: any) => Component, })); -jest.mock('../../../../components/workpad_page', () => ({ +jest.mock('../../../components/workpad_page', () => ({ WorkpadPage: (props: any) =>
Page
, })); -jest.mock('../../../../components/link', () => ({ +jest.mock('../../../components/link', () => ({ Link: (props: any) =>
Link
, })); diff --git a/x-pack/plugins/canvas/public/components/download/__tests__/download.test.tsx b/x-pack/plugins/canvas/public/components/download/download.test.tsx similarity index 95% rename from x-pack/plugins/canvas/public/components/download/__tests__/download.test.tsx rename to x-pack/plugins/canvas/public/components/download/download.test.tsx index 3bbe8193deeea..a4ea446e9fce3 100644 --- a/x-pack/plugins/canvas/public/components/download/__tests__/download.test.tsx +++ b/x-pack/plugins/canvas/public/components/download/download.test.tsx @@ -6,7 +6,7 @@ import { render } from 'enzyme'; import React from 'react'; -import { Download } from '..'; +import { Download } from '.'; describe('', () => { test('has canvasDownload class', () => { diff --git a/x-pack/plugins/canvas/public/components/workpad_header/share_menu/utils.test.ts b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/utils.test.ts index 443eb06846d2e..a2e5353a01ab2 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/share_menu/utils.test.ts +++ b/x-pack/plugins/canvas/public/components/workpad_header/share_menu/utils.test.ts @@ -7,7 +7,7 @@ jest.mock('../../../../common/lib/fetch'); import { getPdfUrl, createPdf, LayoutType } from './utils'; -import { workpads } from '../../../../__tests__/fixtures/workpads'; +import { workpads } from '../../../../__fixtures__/workpads'; import { fetch } from '../../../../common/lib/fetch'; import { IBasePath } from 'kibana/public'; diff --git a/x-pack/plugins/canvas/public/functions/pie.test.js b/x-pack/plugins/canvas/public/functions/pie.test.js index 99f61cfb5d922..1ba82a3573d75 100644 --- a/x-pack/plugins/canvas/public/functions/pie.test.js +++ b/x-pack/plugins/canvas/public/functions/pie.test.js @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../__tests__/helpers/function_wrapper'; -import { testPie } from '../../canvas_plugin_src/functions/common/__tests__/fixtures/test_pointseries'; +import { functionWrapper } from '../../test_helpers/function_wrapper'; +import { testPie } from '../../canvas_plugin_src/functions/common/__fixtures__/test_pointseries'; import { fontStyle, grayscalePalette, seriesStyle, -} from '../../canvas_plugin_src/functions/common/__tests__/fixtures/test_styles'; +} from '../../canvas_plugin_src/functions/common/__fixtures__/test_styles'; import { pieFunctionFactory } from './pie'; describe('pie', () => { diff --git a/x-pack/plugins/canvas/public/functions/plot.test.js b/x-pack/plugins/canvas/public/functions/plot.test.js index 426e9a23efe5d..55414878f504f 100644 --- a/x-pack/plugins/canvas/public/functions/plot.test.js +++ b/x-pack/plugins/canvas/public/functions/plot.test.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { functionWrapper } from '../../__tests__/helpers/function_wrapper'; -import { testPlot } from '../../canvas_plugin_src/functions/common/__tests__/fixtures/test_pointseries'; +import { functionWrapper } from '../../test_helpers/function_wrapper'; +import { testPlot } from '../../canvas_plugin_src/functions/common/__fixtures__/test_pointseries'; import { fontStyle, grayscalePalette, @@ -13,7 +13,7 @@ import { xAxisConfig, seriesStyle, defaultStyle, -} from '../../canvas_plugin_src/functions/common/__tests__/fixtures/test_styles'; +} from '../../canvas_plugin_src/functions/common/__fixtures__/test_styles'; import { plotFunctionFactory } from './plot'; describe('plot', () => { diff --git a/x-pack/plugins/canvas/public/functions/plot/get_flot_axis_config.test.js b/x-pack/plugins/canvas/public/functions/plot/get_flot_axis_config.test.js index c0ab3bb316b73..ad988fd533d01 100644 --- a/x-pack/plugins/canvas/public/functions/plot/get_flot_axis_config.test.js +++ b/x-pack/plugins/canvas/public/functions/plot/get_flot_axis_config.test.js @@ -8,7 +8,7 @@ import { xAxisConfig, yAxisConfig, hideAxis, -} from '../../../canvas_plugin_src/functions/common/__tests__/fixtures/test_styles'; +} from '../../../canvas_plugin_src/functions/common/__fixtures__/test_styles'; import { getFlotAxisConfig } from './get_flot_axis_config'; describe('getFlotAxisConfig', () => { diff --git a/x-pack/plugins/canvas/public/functions/plot/get_font_spec.test.js b/x-pack/plugins/canvas/public/functions/plot/get_font_spec.test.js index dfaf510a94718..a60e0c038a0c1 100644 --- a/x-pack/plugins/canvas/public/functions/plot/get_font_spec.test.js +++ b/x-pack/plugins/canvas/public/functions/plot/get_font_spec.test.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { fontStyle } from '../../../canvas_plugin_src/functions/common/__tests__/fixtures/test_styles'; +import { fontStyle } from '../../../canvas_plugin_src/functions/common/__fixtures__/test_styles'; import { defaultSpec, getFontSpec } from './get_font_spec'; describe('getFontSpec', () => { diff --git a/x-pack/plugins/canvas/public/lib/clipboard.test.ts b/x-pack/plugins/canvas/public/lib/clipboard.test.ts index 53f92e2184edc..4df6062f9329a 100644 --- a/x-pack/plugins/canvas/public/lib/clipboard.test.ts +++ b/x-pack/plugins/canvas/public/lib/clipboard.test.ts @@ -8,7 +8,7 @@ jest.mock('../../../../../src/plugins/kibana_utils/public'); import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { setClipboardData, getClipboardData } from './clipboard'; import { LOCALSTORAGE_CLIPBOARD } from '../../common/lib/constants'; -import { elements } from '../../__tests__/fixtures/workpads'; +import { elements } from '../../__fixtures__/workpads'; const set = jest.fn(); const get = jest.fn(); diff --git a/x-pack/plugins/canvas/public/state/middleware/__tests__/in_flight.test.ts b/x-pack/plugins/canvas/public/state/middleware/in_flight.test.ts similarity index 93% rename from x-pack/plugins/canvas/public/state/middleware/__tests__/in_flight.test.ts rename to x-pack/plugins/canvas/public/state/middleware/in_flight.test.ts index b78c3ffcfcb1d..6a47289b8b826 100644 --- a/x-pack/plugins/canvas/public/state/middleware/__tests__/in_flight.test.ts +++ b/x-pack/plugins/canvas/public/state/middleware/in_flight.test.ts @@ -4,13 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - inFlightActive, - inFlightComplete, - setLoading, - setValue, -} from '../../actions/resolved_args'; -import { inFlightMiddlewareFactory } from '../in_flight'; +import { inFlightActive, inFlightComplete, setLoading, setValue } from '../actions/resolved_args'; +import { inFlightMiddlewareFactory } from './in_flight'; const next = jest.fn(); const dispatch = jest.fn(); diff --git a/x-pack/plugins/canvas/public/state/middleware/__tests__/workpad_autoplay.test.ts b/x-pack/plugins/canvas/public/state/middleware/workpad_autoplay.test.ts similarity index 91% rename from x-pack/plugins/canvas/public/state/middleware/__tests__/workpad_autoplay.test.ts rename to x-pack/plugins/canvas/public/state/middleware/workpad_autoplay.test.ts index bb7b26919ef20..6bbb2dbf9d8ba 100644 --- a/x-pack/plugins/canvas/public/state/middleware/__tests__/workpad_autoplay.test.ts +++ b/x-pack/plugins/canvas/public/state/middleware/workpad_autoplay.test.ts @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -jest.mock('../../../lib/app_state'); -jest.mock('../../../lib/router_provider'); +jest.mock('../../lib/app_state'); +jest.mock('../../lib/router_provider'); -import { workpadAutoplay } from '../workpad_autoplay'; -import { setAutoplayInterval } from '../../../lib/app_state'; -import { createTimeInterval } from '../../../lib/time_interval'; +import { workpadAutoplay } from './workpad_autoplay'; +import { setAutoplayInterval } from '../../lib/app_state'; +import { createTimeInterval } from '../../lib/time_interval'; // @ts-expect-error untyped local -import { routerProvider } from '../../../lib/router_provider'; +import { routerProvider } from '../../lib/router_provider'; const next = jest.fn(); const dispatch = jest.fn(); diff --git a/x-pack/plugins/canvas/public/state/middleware/__tests__/workpad_refresh.test.ts b/x-pack/plugins/canvas/public/state/middleware/workpad_refresh.test.ts similarity index 92% rename from x-pack/plugins/canvas/public/state/middleware/__tests__/workpad_refresh.test.ts rename to x-pack/plugins/canvas/public/state/middleware/workpad_refresh.test.ts index e451a39df06db..71d3ad3a92f09 100644 --- a/x-pack/plugins/canvas/public/state/middleware/__tests__/workpad_refresh.test.ts +++ b/x-pack/plugins/canvas/public/state/middleware/workpad_refresh.test.ts @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ -jest.mock('../../../lib/app_state'); +jest.mock('../../lib/app_state'); -import { workpadRefresh } from '../workpad_refresh'; -import { inFlightComplete } from '../../actions/resolved_args'; -import { setRefreshInterval } from '../../actions/workpad'; -import { setRefreshInterval as setAppStateRefreshInterval } from '../../../lib/app_state'; +import { workpadRefresh } from './workpad_refresh'; +import { inFlightComplete } from '../actions/resolved_args'; +import { setRefreshInterval } from '../actions/workpad'; +import { setRefreshInterval as setAppStateRefreshInterval } from '../../lib/app_state'; -import { createTimeInterval } from '../../../lib/time_interval'; +import { createTimeInterval } from '../../lib/time_interval'; const next = jest.fn(); const dispatch = jest.fn(); diff --git a/x-pack/plugins/canvas/server/collectors/workpad_collector.test.ts b/x-pack/plugins/canvas/server/collectors/workpad_collector.test.ts index 32665cc42dc4e..919f1537e81b3 100644 --- a/x-pack/plugins/canvas/server/collectors/workpad_collector.test.ts +++ b/x-pack/plugins/canvas/server/collectors/workpad_collector.test.ts @@ -6,7 +6,7 @@ import { cloneDeep } from 'lodash'; import { summarizeWorkpads } from './workpad_collector'; -import { workpads } from '../../__tests__/fixtures/workpads'; +import { workpads } from '../../__fixtures__/workpads'; describe('usage collector handle es response data', () => { it('should summarize workpads, pages, and elements', () => { diff --git a/x-pack/plugins/canvas/server/routes/workpad/get.test.ts b/x-pack/plugins/canvas/server/routes/workpad/get.test.ts index a51cbefd4031e..0e0db5a1093df 100644 --- a/x-pack/plugins/canvas/server/routes/workpad/get.test.ts +++ b/x-pack/plugins/canvas/server/routes/workpad/get.test.ts @@ -8,7 +8,7 @@ import { CANVAS_TYPE } from '../../../common/lib/constants'; import { initializeGetWorkpadRoute } from './get'; import { kibanaResponseFactory, RequestHandlerContext, RequestHandler } from 'src/core/server'; import { savedObjectsClientMock, httpServerMock } from 'src/core/server/mocks'; -import { workpadWithGroupAsElement } from '../../../__tests__/fixtures/workpads'; +import { workpadWithGroupAsElement } from '../../../__fixtures__/workpads'; import { CanvasWorkpad } from '../../../types'; import { getMockedRouterDeps } from '../test_helpers'; diff --git a/x-pack/plugins/canvas/server/routes/workpad/update.test.ts b/x-pack/plugins/canvas/server/routes/workpad/update.test.ts index 0d97145c90298..e2e84a9a88cb6 100644 --- a/x-pack/plugins/canvas/server/routes/workpad/update.test.ts +++ b/x-pack/plugins/canvas/server/routes/workpad/update.test.ts @@ -9,7 +9,7 @@ import { CANVAS_TYPE } from '../../../common/lib/constants'; import { initializeUpdateWorkpadRoute, initializeUpdateWorkpadAssetsRoute } from './update'; import { kibanaResponseFactory, RequestHandlerContext, RequestHandler } from 'src/core/server'; import { savedObjectsClientMock, httpServerMock } from 'src/core/server/mocks'; -import { workpads } from '../../../__tests__/fixtures/workpads'; +import { workpads } from '../../../__fixtures__/workpads'; import { okResponse } from '../ok_response'; import { getMockedRouterDeps } from '../test_helpers'; diff --git a/x-pack/plugins/canvas/shareable_runtime/api/__tests__/__snapshots__/shareable.test.tsx.snap b/x-pack/plugins/canvas/shareable_runtime/api/__snapshots__/shareable.test.tsx.snap similarity index 100% rename from x-pack/plugins/canvas/shareable_runtime/api/__tests__/__snapshots__/shareable.test.tsx.snap rename to x-pack/plugins/canvas/shareable_runtime/api/__snapshots__/shareable.test.tsx.snap diff --git a/x-pack/plugins/canvas/shareable_runtime/api/__tests__/shareable.test.tsx b/x-pack/plugins/canvas/shareable_runtime/api/shareable.test.tsx similarity index 96% rename from x-pack/plugins/canvas/shareable_runtime/api/__tests__/shareable.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/api/shareable.test.tsx index 0851ae8d04eb0..9efb8db805268 100644 --- a/x-pack/plugins/canvas/shareable_runtime/api/__tests__/shareable.test.tsx +++ b/x-pack/plugins/canvas/shareable_runtime/api/shareable.test.tsx @@ -6,11 +6,11 @@ import { mount } from 'enzyme'; import React from 'react'; -import { sharedWorkpads, tick } from '../../test'; -import { share } from '../shareable'; +import { sharedWorkpads, tick } from '../test'; +import { share } from './shareable'; // Mock the renderers within this test. -jest.mock('../../supported_renderers'); +jest.mock('../supported_renderers'); describe('Canvas Shareable Workpad API', () => { // Mock the AJAX load of the workpad. diff --git a/x-pack/plugins/canvas/shareable_runtime/components/__tests__/__snapshots__/app.test.tsx.snap b/x-pack/plugins/canvas/shareable_runtime/components/__snapshots__/app.test.tsx.snap similarity index 100% rename from x-pack/plugins/canvas/shareable_runtime/components/__tests__/__snapshots__/app.test.tsx.snap rename to x-pack/plugins/canvas/shareable_runtime/components/__snapshots__/app.test.tsx.snap diff --git a/x-pack/plugins/canvas/shareable_runtime/components/__tests__/app.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/app.test.tsx similarity index 95% rename from x-pack/plugins/canvas/shareable_runtime/components/__tests__/app.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/app.test.tsx index 755f6907a4d5b..13e7738b9fd6b 100644 --- a/x-pack/plugins/canvas/shareable_runtime/components/__tests__/app.test.tsx +++ b/x-pack/plugins/canvas/shareable_runtime/components/app.test.tsx @@ -13,8 +13,8 @@ import { mount, ReactWrapper } from 'enzyme'; import React from 'react'; // import { act } from 'react-dom/test-utils'; -import { App } from '../app'; -import { sharedWorkpads, WorkpadNames, tick } from '../../test'; +import { App } from './app'; +import { sharedWorkpads, WorkpadNames, tick } from '../test'; import { getScrubber as scrubber, getScrubberSlideContainer as scrubberContainer, @@ -27,11 +27,11 @@ import { getFooter as footer, getPageControlsPrevious as previous, getPageControlsNext as next, -} from '../../test/selectors'; -import { openSettings, selectMenuItem } from '../../test/interactions'; +} from '../test/selectors'; +import { openSettings, selectMenuItem } from '../test/interactions'; // Mock the renderers -jest.mock('../../supported_renderers'); +jest.mock('../supported_renderers'); // Mock the EuiPortal - `insertAdjacentElement is not supported in // `jsdom` 12. We're just going to render a `div` with the children diff --git a/x-pack/plugins/canvas/shareable_runtime/components/__tests__/canvas.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/canvas.test.tsx similarity index 84% rename from x-pack/plugins/canvas/shareable_runtime/components/__tests__/canvas.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/canvas.test.tsx index deb524ed56bc5..b1e6284f6e6a9 100644 --- a/x-pack/plugins/canvas/shareable_runtime/components/__tests__/canvas.test.tsx +++ b/x-pack/plugins/canvas/shareable_runtime/components/canvas.test.tsx @@ -6,11 +6,11 @@ import { mount, ReactWrapper } from 'enzyme'; import React from 'react'; -import { JestContext } from '../../test/context_jest'; -import { getScrubber as scrubber, getPageControlsCenter as center } from '../../test/selectors'; -import { Canvas } from '../canvas'; +import { JestContext } from '../test/context_jest'; +import { getScrubber as scrubber, getPageControlsCenter as center } from '../test/selectors'; +import { Canvas } from './canvas'; -jest.mock('../../supported_renderers'); +jest.mock('../supported_renderers'); describe('', () => { test('null workpad renders nothing', () => { diff --git a/x-pack/plugins/canvas/shareable_runtime/components/footer/__stories__/scrubber.stories.tsx b/x-pack/plugins/canvas/shareable_runtime/components/footer/__stories__/scrubber.stories.tsx index ba938b57f1ead..371f646bf8619 100644 --- a/x-pack/plugins/canvas/shareable_runtime/components/footer/__stories__/scrubber.stories.tsx +++ b/x-pack/plugins/canvas/shareable_runtime/components/footer/__stories__/scrubber.stories.tsx @@ -10,7 +10,7 @@ import { storiesOf } from '@storybook/react'; import { CanvasRenderedPage } from '../../../types'; import { ExampleContext } from '../../../test/context_example'; import { Scrubber, ScrubberComponent } from '../scrubber'; -import { workpads } from '../../../../__tests__/fixtures/workpads'; +import { workpads } from '../../../../__fixtures__/workpads'; storiesOf('shareables/Footer/Scrubber', module) .add('contextual: hello', () => ( diff --git a/x-pack/plugins/canvas/shareable_runtime/components/__tests__/page.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/page.test.tsx similarity index 93% rename from x-pack/plugins/canvas/shareable_runtime/components/__tests__/page.test.tsx rename to x-pack/plugins/canvas/shareable_runtime/components/page.test.tsx index 7e3f5b1cd3555..8e780e24eecfb 100644 --- a/x-pack/plugins/canvas/shareable_runtime/components/__tests__/page.test.tsx +++ b/x-pack/plugins/canvas/shareable_runtime/components/page.test.tsx @@ -6,7 +6,7 @@ import { mount } from 'enzyme'; import React from 'react'; -import { Page } from '../page'; +import { Page } from './page'; describe('', () => { test('null workpad renders nothing', () => { diff --git a/x-pack/plugins/canvas/__tests__/helpers/function_wrapper.js b/x-pack/plugins/canvas/test_helpers/function_wrapper.js similarity index 100% rename from x-pack/plugins/canvas/__tests__/helpers/function_wrapper.js rename to x-pack/plugins/canvas/test_helpers/function_wrapper.js diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts index e8944b15978a9..57f4a9f66b987 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/index.ts @@ -10,7 +10,13 @@ export { mockLicensingValues } from './licensing_logic.mock'; export { mockHttpValues } from './http_logic.mock'; export { mockTelemetryActions } from './telemetry_logic.mock'; export { mockFlashMessagesValues, mockFlashMessagesActions } from './flash_messages_logic.mock'; -export { mockAllValues, mockAllActions, setMockValues, setMockActions } from './kea.mock'; +export { + mockAllValues, + mockAllActions, + setMockValues, + setMockActions, + LogicMounter, +} from './kea.mock'; export { mountAsync } from './mount_async.mock'; export { mountWithIntl } from './mount_with_i18n.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea.mock.ts index 0176f8c03c632..78ffbcfa3526f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea.mock.ts @@ -40,14 +40,18 @@ jest.mock('kea', () => ({ })); /** + * React component helpers + * * Call this function to override a specific set of Kea values while retaining all other defaults - * Example usage within a component test: * - * import '../../../__mocks__/kea'; - * import { setMockValues } from ''../../../__mocks__'; + * Example usage: + * + * import { setMockValues } from '../../../__mocks__/kea.mock'; + * import { SomeComponent } from './'; * * it('some test', () => { * setMockValues({ someValue: 'hello' }); + * shallow(); * }); */ import { useValues, useActions } from 'kea'; @@ -58,3 +62,62 @@ export const setMockValues = (values: object) => { export const setMockActions = (actions: object) => { (useActions as jest.Mock).mockImplementation(() => ({ ...mockAllActions, ...actions })); }; + +/** + * Kea logic helpers + * + * Call this function to mount a logic file and optionally override default values. + * Automatically DRYs out a lot of cruft for us, such as resetting context, creating the + * nested defaults path obj (see https://kea.js.org/docs/api/context#resetcontext), and + * returning an unmount function + * + * Example usage: + * + * import { LogicMounter } from '../../../__mocks__/kea.mock'; + * import { SomeLogic } from './'; + * + * const { mount, unmount } = new LogicMounter(SomeLogic); + * + * it('some test', () => { + * mount({ someValue: 'hello' }); + * unmount(); + * }); + */ +import { resetContext, Logic, LogicInput } from 'kea'; + +interface LogicFile { + inputs: Array>; + mount(): Function; +} +export class LogicMounter { + private logicFile: LogicFile; + private unmountFn!: Function; + + constructor(logicFile: LogicFile) { + this.logicFile = logicFile; + } + + // Reset context with optional default value overrides + public resetContext = (values?: object) => { + if (!values) { + resetContext({}); + } else { + const path = this.logicFile.inputs[0].path as string[]; // example: ['x', 'y', 'z'] + const defaults = path.reduceRight((value: object, key: string) => ({ [key]: value }), values); // example: { x: { y: { z: values } } } + resetContext({ defaults }); + } + }; + + // Automatically reset context & mount the logic file + public mount = (values?: object) => { + this.resetContext(values); + const unmount = this.logicFile.mount(); + this.unmountFn = unmount; + return unmount; // Keep Kea behavior of returning an unmount fn from mount + }; + + // Also add unmount as a class method that can be destructured on init without becoming stale later + public unmount = () => { + this.unmountFn(); + }; +} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts index 6523b4fb110b0..48be2b0ae8dfd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_logic.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; +import { LogicMounter } from '../../../__mocks__/kea.mock'; import { mockHttpValues } from '../../../__mocks__'; jest.mock('../../../shared/http', () => ({ @@ -57,24 +57,7 @@ describe('CredentialsLogic', () => { fullEngineAccessChecked: false, }; - const mount = (defaults?: object) => { - if (!defaults) { - resetContext({}); - } else { - resetContext({ - defaults: { - enterprise_search: { - app_search: { - credentials_logic: { - ...defaults, - }, - }, - }, - }, - }); - } - CredentialsLogic.mount(); - }; + const { mount } = new LogicMounter(CredentialsLogic); const newToken = { id: 1, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.test.ts index bb0103b07b072..c2a0d29cc1f40 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/document_creation_logic.test.ts @@ -4,7 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; +import { LogicMounter } from '../../../__mocks__/kea.mock'; + import dedent from 'dedent'; jest.mock('./utils', () => ({ @@ -39,24 +40,7 @@ describe('DocumentCreationLogic', () => { }; const mockFile = new File(['mockFile'], 'mockFile.json'); - const mount = (defaults?: object) => { - if (!defaults) { - resetContext({}); - } else { - resetContext({ - defaults: { - enterprise_search: { - app_search: { - document_creation_logic: { - ...defaults, - }, - }, - }, - }, - }); - } - DocumentCreationLogic.mount(); - }; + const { mount } = new LogicMounter(DocumentCreationLogic); beforeEach(() => { jest.clearAllMocks(); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts index d9a3de7c078cc..fe735f70247c6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail_logic.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; +import { LogicMounter } from '../../../__mocks__/kea.mock'; import { mockHttpValues } from '../../../__mocks__'; jest.mock('../../../shared/http', () => ({ @@ -36,24 +36,7 @@ describe('DocumentDetailLogic', () => { fields: [], }; - const mount = (defaults?: object) => { - if (!defaults) { - resetContext({}); - } else { - resetContext({ - defaults: { - enterprise_search: { - app_search: { - document_detail_logic: { - ...defaults, - }, - }, - }, - }, - }); - } - DocumentDetailLogic.mount(); - }; + const { mount } = new LogicMounter(DocumentDetailLogic); beforeEach(() => { jest.clearAllMocks(); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents_logic.test.ts index 236172f0f7bdf..2863a39535ef4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents_logic.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; +import { LogicMounter } from '../../../__mocks__/kea.mock'; import { DocumentsLogic } from './documents_logic'; @@ -13,24 +13,7 @@ describe('DocumentsLogic', () => { isDocumentCreationOpen: false, }; - const mount = (defaults?: object) => { - if (!defaults) { - resetContext({}); - } else { - resetContext({ - defaults: { - enterprise_search: { - app_search: { - documents_logic: { - ...defaults, - }, - }, - }, - }, - }); - } - DocumentsLogic.mount(); - }; + const { mount } = new LogicMounter(DocumentsLogic); describe('actions', () => { describe('openDocumentCreation', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.test.ts index 13db440df739e..094260b6df095 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; +import { LogicMounter } from '../../../__mocks__/kea.mock'; import { mockHttpValues } from '../../../__mocks__'; jest.mock('../../../shared/http', () => ({ @@ -46,24 +46,7 @@ describe('EngineLogic', () => { engineNotFound: false, }; - const mount = (values?: object) => { - if (!values) { - resetContext({}); - } else { - resetContext({ - defaults: { - enterprise_search: { - app_search: { - engine_logic: { - ...values, - }, - }, - }, - }, - }); - } - EngineLogic.mount(); - }; + const { mount } = new LogicMounter(EngineLogic); beforeEach(() => { jest.clearAllMocks(); @@ -153,6 +136,18 @@ describe('EngineLogic', () => { }); }); + describe('engineName', () => { + it('should be reset to an empty string', () => { + mount({ engineName: 'hello-world' }); + EngineLogic.actions.clearEngine(); + + expect(EngineLogic.values).toEqual({ + ...DEFAULT_VALUES, + engineName: '', + }); + }); + }); + describe('dataLoading', () => { it('should be set to true', () => { mount({ dataLoading: false }); @@ -164,6 +159,18 @@ describe('EngineLogic', () => { }); }); }); + + describe('engineNotFound', () => { + it('should be set to false', () => { + mount({ engineNotFound: true }); + EngineLogic.actions.clearEngine(); + + expect(EngineLogic.values).toEqual({ + ...DEFAULT_VALUES, + engineNotFound: false, + }); + }); + }); }); describe('initializeEngine', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.ts index e1ce7cea0fa91..9f3fe721b74de 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_logic.ts @@ -64,12 +64,14 @@ export const EngineLogic = kea>({ '', { setEngineName: (_, { engineName }) => engineName, + clearEngine: () => '', }, ], engineNotFound: [ false, { setEngineNotFound: (_, { notFound }) => notFound, + clearEngine: () => false, }, ], }, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.test.ts index d35bde20f4f1e..2063f706a4741 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_logic.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; +import { LogicMounter } from '../../../__mocks__/kea.mock'; import { mockHttpValues } from '../../../__mocks__'; jest.mock('../../../shared/http', () => ({ @@ -48,10 +48,7 @@ describe('EngineOverviewLogic', () => { timeoutId: null, }; - const mount = () => { - resetContext({}); - EngineOverviewLogic.mount(); - }; + const { mount, unmount } = new LogicMounter(EngineOverviewLogic); beforeEach(() => { jest.clearAllMocks(); @@ -141,12 +138,9 @@ describe('EngineOverviewLogic', () => { }); describe('unmount', () => { - let unmount: Function; - beforeEach(() => { jest.useFakeTimers(); - resetContext({}); - unmount = EngineOverviewLogic.mount(); + mount(); }); it('clears existing polling timeouts on unmount', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts index c86d7e3e915e2..8310e2abe045b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_logic.test.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; +import { LogicMounter } from '../../../../__mocks__/kea.mock'; import { mockHttpValues } from '../../../../__mocks__'; jest.mock('../../../../shared/http', () => ({ @@ -53,24 +53,7 @@ describe('LogRetentionLogic', () => { isLogRetentionUpdating: false, }; - const mount = (defaults?: object) => { - if (!defaults) { - resetContext({}); - } else { - resetContext({ - defaults: { - enterprise_search: { - app_search: { - log_retention_logic: { - ...defaults, - }, - }, - }, - }, - }); - } - LogRetentionLogic.mount(); - }; + const { mount } = new LogicMounter(LogRetentionLogic); beforeEach(() => { jest.clearAllMocks(); diff --git a/x-pack/plugins/fleet/kibana.json b/x-pack/plugins/fleet/kibana.json index 2fcbef75b9832..aa0761c8a39bd 100644 --- a/x-pack/plugins/fleet/kibana.json +++ b/x-pack/plugins/fleet/kibana.json @@ -4,8 +4,15 @@ "server": true, "ui": true, "configPath": ["xpack", "fleet"], - "requiredPlugins": ["licensing", "data", "encryptedSavedObjects"], - "optionalPlugins": ["security", "features", "cloud", "usageCollection", "home"], + "requiredPlugins": ["licensing", "data"], + "optionalPlugins": [ + "security", + "features", + "cloud", + "usageCollection", + "home", + "encryptedSavedObjects" + ], "extraPublicDirs": ["common"], "requiredBundles": ["kibanaReact", "esUiShared", "home", "infra", "kibanaUtils"] } diff --git a/x-pack/plugins/fleet/server/plugin.ts b/x-pack/plugins/fleet/server/plugin.ts index 4a3412954d50c..8ce17a00acf33 100644 --- a/x-pack/plugins/fleet/server/plugin.ts +++ b/x-pack/plugins/fleet/server/plugin.ts @@ -91,12 +91,12 @@ export interface FleetSetupDeps { } export interface FleetStartDeps { - encryptedSavedObjects: EncryptedSavedObjectsPluginStart; + encryptedSavedObjects?: EncryptedSavedObjectsPluginStart; security?: SecurityPluginStart; } export interface FleetAppContext { - encryptedSavedObjectsStart: EncryptedSavedObjectsPluginStart; + encryptedSavedObjectsStart?: EncryptedSavedObjectsPluginStart; encryptedSavedObjectsSetup?: EncryptedSavedObjectsPluginSetup; security?: SecurityPluginStart; config$?: Observable; @@ -250,8 +250,7 @@ export class FleetPlugin // Conditional config routes if (config.agents.enabled) { - const isESOUsingEphemeralEncryptionKey = - deps.encryptedSavedObjects.usingEphemeralEncryptionKey; + const isESOUsingEphemeralEncryptionKey = !deps.encryptedSavedObjects; if (isESOUsingEphemeralEncryptionKey) { if (this.logger) { this.logger.warn( diff --git a/x-pack/plugins/fleet/server/routes/setup/handlers.ts b/x-pack/plugins/fleet/server/routes/setup/handlers.ts index f87cf8026c560..cafccd1895d11 100644 --- a/x-pack/plugins/fleet/server/routes/setup/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/setup/handlers.ts @@ -22,8 +22,7 @@ export const getFleetStatusHandler: RequestHandler = async (context, request, re const isProductionMode = appContextService.getIsProductionMode(); const isCloud = appContextService.getCloud()?.isCloudEnabled ?? false; const isTLSCheckDisabled = appContextService.getConfig()?.agents?.tlsCheckDisabled ?? false; - const isUsingEphemeralEncryptionKey = appContextService.getEncryptedSavedObjectsSetup() - .usingEphemeralEncryptionKey; + const isUsingEphemeralEncryptionKey = !appContextService.getEncryptedSavedObjectsSetup(); const missingRequirements: GetFleetStatusResponse['missing_requirements'] = []; if (!isAdminUserSetup) { diff --git a/x-pack/plugins/fleet/server/services/app_context.ts b/x-pack/plugins/fleet/server/services/app_context.ts index bcf056c9482cb..d6b62458ed1f4 100644 --- a/x-pack/plugins/fleet/server/services/app_context.ts +++ b/x-pack/plugins/fleet/server/services/app_context.ts @@ -114,10 +114,6 @@ class AppContextService { } public getEncryptedSavedObjectsSetup() { - if (!this.encryptedSavedObjectsSetup) { - throw new Error('encryptedSavedObjectsSetup is not set'); - } - return this.encryptedSavedObjectsSetup; } diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts index 6d851eeaab542..254cac0cb8e75 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts @@ -24,7 +24,7 @@ import { buildErrorAlertReason, buildFiredAlertReason, buildNoDataAlertReason, - buildRecoveredAlertReason, + // buildRecoveredAlertReason, stateToAlertMessage, } from '../common/messages'; import { evaluateCondition } from './evaluate_condition'; @@ -99,9 +99,14 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) = .map((result) => buildReasonWithVerboseMetricName(result[item], buildFiredAlertReason)) .join('\n'); } else if (nextState === AlertStates.OK && prevState?.alertState === AlertStates.ALERT) { - reason = results - .map((result) => buildReasonWithVerboseMetricName(result[item], buildRecoveredAlertReason)) - .join('\n'); + /* + * Custom recovery actions aren't yet available in the alerting framework + * Uncomment the code below once they've been implemented + * Reference: https://github.com/elastic/kibana/issues/87048 + */ + // reason = results + // .map((result) => buildReasonWithVerboseMetricName(result[item], buildRecoveredAlertReason)) + // .join('\n'); } if (alertOnNoData) { if (nextState === AlertStates.NO_DATA) { diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts index 6c9fac9d1133c..31561a8f6b145 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts @@ -6,7 +6,7 @@ import { createMetricThresholdExecutor, FIRED_ACTIONS } from './metric_threshold_executor'; import { Comparator, AlertStates } from './types'; import * as mocks from './test_mocks'; -import { RecoveredActionGroup } from '../../../../../alerts/common'; +// import { RecoveredActionGroup } from '../../../../../alerts/common'; import { alertsMock, AlertServicesMock, @@ -21,7 +21,7 @@ interface AlertTestInstance { state: any; } -let persistAlertInstances = false; +let persistAlertInstances = false; // eslint-disable-line prefer-const const mockOptions = { alertId: '', @@ -366,6 +366,13 @@ describe('The metric threshold alert type', () => { }); }); + /* + * Custom recovery actions aren't yet available in the alerting framework + * Uncomment the code below once they've been implemented + * Reference: https://github.com/elastic/kibana/issues/87048 + */ + + /* describe('querying a metric that later recovers', () => { const instanceID = '*'; const execute = (threshold: number[]) => @@ -410,6 +417,7 @@ describe('The metric threshold alert type', () => { expect(getState(instanceID).alertState).toBe(AlertStates.OK); }); }); + */ describe('querying a metric with a percentage metric', () => { const instanceID = '*'; diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts index d63b42cd3b146..1b8e018659ee5 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts @@ -12,7 +12,7 @@ import { buildErrorAlertReason, buildFiredAlertReason, buildNoDataAlertReason, - buildRecoveredAlertReason, + // buildRecoveredAlertReason, stateToAlertMessage, } from '../common/messages'; import { createFormatter } from '../../../../common/formatters'; @@ -77,9 +77,14 @@ export const createMetricThresholdExecutor = ( .map((result) => buildFiredAlertReason(formatAlertResult(result[group]))) .join('\n'); } else if (nextState === AlertStates.OK && prevState?.alertState === AlertStates.ALERT) { - reason = alertResults - .map((result) => buildRecoveredAlertReason(formatAlertResult(result[group]))) - .join('\n'); + /* + * Custom recovery actions aren't yet available in the alerting framework + * Uncomment the code below once they've been implemented + * Reference: https://github.com/elastic/kibana/issues/87048 + */ + // reason = alertResults + // .map((result) => buildRecoveredAlertReason(formatAlertResult(result[group]))) + // .join('\n'); } if (alertOnNoData) { if (nextState === AlertStates.NO_DATA) { diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index c267052e6dfe5..6a7448ddc8448 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -28,6 +28,9 @@ export const MAP_SAVED_OBJECT_TYPE = 'map'; export const APP_ID = 'maps'; export const APP_ICON = 'gisApp'; export const APP_ICON_SOLUTION = 'logoKibana'; +export const APP_NAME = i18n.translate('xpack.maps.visTypeAlias.title', { + defaultMessage: 'Maps', +}); export const INITIAL_LAYERS_KEY = 'initialLayers'; export const MAPS_APP_PATH = `app/${APP_ID}`; @@ -50,6 +53,9 @@ export function getNewMapPath() { export function getExistingMapPath(id: string) { return `${MAP_BASE_URL}/${id}`; } +export function getEditPath(id: string) { + return `/${MAP_PATH}/${id}`; +} export enum LAYER_TYPE { TILE = 'TILE', diff --git a/x-pack/plugins/maps/public/maps_vis_type_alias.js b/x-pack/plugins/maps/public/maps_vis_type_alias.js deleted file mode 100644 index a2e76216c7def..0000000000000 --- a/x-pack/plugins/maps/public/maps_vis_type_alias.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; -import { APP_ID, APP_ICON, MAP_PATH } from '../common/constants'; - -export function getMapsVisTypeAlias(visualizations, showMapVisualizationTypes) { - if (!showMapVisualizationTypes) { - visualizations.hideTypes(['region_map', 'tile_map']); - } - - const description = i18n.translate('xpack.maps.visTypeAlias.description', { - defaultMessage: 'Create and style maps with multiple layers and indices.', - }); - - return { - aliasApp: APP_ID, - aliasPath: `/${MAP_PATH}`, - name: APP_ID, - title: i18n.translate('xpack.maps.visTypeAlias.title', { - defaultMessage: 'Maps', - }), - description: description, - icon: APP_ICON, - stage: 'production', - }; -} diff --git a/x-pack/plugins/maps/public/maps_vis_type_alias.ts b/x-pack/plugins/maps/public/maps_vis_type_alias.ts new file mode 100644 index 0000000000000..e2d364fef6209 --- /dev/null +++ b/x-pack/plugins/maps/public/maps_vis_type_alias.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { + VisualizationsSetup, + VisualizationStage, +} from '../../../../src/plugins/visualizations/public'; +import { SavedObject } from '../../../../src/core/types/saved_objects'; +import { MapSavedObject } from '../common/map_saved_object_type'; +import { + APP_ID, + APP_ICON, + APP_NAME, + getEditPath, + MAP_PATH, + MAP_SAVED_OBJECT_TYPE, +} from '../common/constants'; + +export function getMapsVisTypeAlias( + visualizations: VisualizationsSetup, + showMapVisualizationTypes: boolean +) { + if (!showMapVisualizationTypes) { + visualizations.hideTypes(['region_map', 'tile_map']); + } + + const appDescription = i18n.translate('xpack.maps.visTypeAlias.description', { + defaultMessage: 'Create and style maps with multiple layers and indices.', + }); + + return { + aliasApp: APP_ID, + aliasPath: `/${MAP_PATH}`, + name: APP_ID, + title: APP_NAME, + description: appDescription, + icon: APP_ICON, + stage: 'production' as VisualizationStage, + appExtensions: { + visualizations: { + docTypes: [MAP_SAVED_OBJECT_TYPE], + searchFields: ['title^3'], + toListItem(savedObject: SavedObject) { + const { id, type, attributes } = savedObject as MapSavedObject; + const { title, description } = attributes; + return { + id, + title, + description, + editUrl: getEditPath(id), + editApp: APP_ID, + icon: APP_ICON, + stage: 'production' as VisualizationStage, + savedObjectType: type, + typeTitle: APP_NAME, + }; + }, + }, + }, + }; +} diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 3ce45fbc0babe..8bffea3ce5a87 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -27,7 +27,6 @@ import { setStartServices, } from './kibana_services'; import { featureCatalogueEntry } from './feature_catalogue_entry'; -// @ts-ignore import { getMapsVisTypeAlias } from './maps_vis_type_alias'; import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; import { diff --git a/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx b/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx index a579e3f122cc6..405b13ff0d0dd 100644 --- a/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx +++ b/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx @@ -11,7 +11,7 @@ import { EuiLink } from '@elastic/eui'; import { EuiBasicTableColumn } from '@elastic/eui/src/components/basic_table/basic_table'; import { TableListView } from '../../../../../../src/plugins/kibana_react/public'; import { goToSpecifiedPath } from '../../render_app'; -import { APP_ID, MAP_PATH, MAP_SAVED_OBJECT_TYPE } from '../../../common/constants'; +import { APP_ID, getEditPath, MAP_PATH, MAP_SAVED_OBJECT_TYPE } from '../../../common/constants'; import { getMapsCapabilities, getToasts, @@ -47,7 +47,7 @@ const tableColumns: Array> = [ { e.preventDefault(); - goToSpecifiedPath(`/${MAP_PATH}/${record.id}`); + goToSpecifiedPath(getEditPath(record.id)); }} data-test-subj={`mapListingTitleLink-${record.title.split(' ').join('-')}`} > diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/get_beats_stats.ts b/x-pack/plugins/monitoring/server/telemetry_collection/get_beats_stats.ts index a7f001f166d7d..2aee9bbda77b7 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/get_beats_stats.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/get_beats_stats.ts @@ -6,7 +6,7 @@ import { get } from 'lodash'; import { SearchResponse } from 'elasticsearch'; -import { StatsCollectionConfig } from 'src/plugins/telemetry_collection_manager/server'; +import { LegacyAPICaller } from 'kibana/server'; import { createQuery } from './create_query'; import { INDEX_PATTERN_BEATS } from '../../common/constants'; @@ -318,7 +318,7 @@ export function processResults( * @return {Promise} */ async function fetchBeatsByType( - callCluster: StatsCollectionConfig['callCluster'], + callCluster: LegacyAPICaller, clusterUuids: string[], start: string, end: string, @@ -382,7 +382,7 @@ async function fetchBeatsByType( } export async function fetchBeatsStats( - callCluster: StatsCollectionConfig['callCluster'], + callCluster: LegacyAPICaller, clusterUuids: string[], start: string, end: string, @@ -392,7 +392,7 @@ export async function fetchBeatsStats( } export async function fetchBeatsStates( - callCluster: StatsCollectionConfig['callCluster'], + callCluster: LegacyAPICaller, clusterUuids: string[], start: string, end: string, @@ -410,7 +410,7 @@ export interface BeatsStatsByClusterUuid { * @return {Object} - Beats stats in an object keyed by the cluster UUIDs */ export async function getBeatsStats( - callCluster: StatsCollectionConfig['callCluster'], + callCluster: LegacyAPICaller, clusterUuids: string[], start: string, end: string diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/get_es_stats.ts b/x-pack/plugins/monitoring/server/telemetry_collection/get_es_stats.ts index 6325ed0c4b052..455327336462f 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/get_es_stats.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/get_es_stats.ts @@ -5,7 +5,7 @@ */ import { SearchResponse } from 'elasticsearch'; -import { StatsCollectionConfig } from 'src/plugins/telemetry_collection_manager/server'; +import { LegacyAPICaller } from 'kibana/server'; import { INDEX_PATTERN_ELASTICSEARCH } from '../../common/constants'; /** @@ -16,7 +16,7 @@ import { INDEX_PATTERN_ELASTICSEARCH } from '../../common/constants'; * @param {Array} clusterUuids The string Cluster UUIDs to fetch details for */ export async function getElasticsearchStats( - callCluster: StatsCollectionConfig['callCluster'], + callCluster: LegacyAPICaller, clusterUuids: string[], maxBucketSize: number ) { @@ -34,7 +34,7 @@ export async function getElasticsearchStats( * Returns the response for the aggregations to fetch details for the product. */ export function fetchElasticsearchStats( - callCluster: StatsCollectionConfig['callCluster'], + callCluster: LegacyAPICaller, clusterUuids: string[], maxBucketSize: number ) { diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/get_high_level_stats.ts b/x-pack/plugins/monitoring/server/telemetry_collection/get_high_level_stats.ts index ce1c6ccd4b106..464c3ae406a53 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/get_high_level_stats.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/get_high_level_stats.ts @@ -6,7 +6,7 @@ import { get } from 'lodash'; import { SearchResponse } from 'elasticsearch'; -import { StatsCollectionConfig } from 'src/plugins/telemetry_collection_manager/server'; +import { LegacyAPICaller } from 'kibana/server'; import { createQuery } from './create_query'; import { INDEX_PATTERN_KIBANA, @@ -247,7 +247,7 @@ function getIndexPatternForStackProduct(product: string) { * Returns an object keyed by the cluster UUIDs to make grouping easier. */ export async function getHighLevelStats( - callCluster: StatsCollectionConfig['callCluster'], + callCluster: LegacyAPICaller, clusterUuids: string[], start: string, end: string, @@ -268,7 +268,7 @@ export async function getHighLevelStats( export async function fetchHighLevelStats< T extends { cluster_uuid?: string } = { cluster_uuid?: string } >( - callCluster: StatsCollectionConfig['callCluster'], + callCluster: LegacyAPICaller, clusterUuids: string[], start: string, end: string, diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/get_kibana_stats.ts b/x-pack/plugins/monitoring/server/telemetry_collection/get_kibana_stats.ts index 57e75d9c9c12e..cf9ac7768048b 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/get_kibana_stats.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/get_kibana_stats.ts @@ -7,7 +7,7 @@ import moment from 'moment'; import { isEmpty } from 'lodash'; import { SearchResponse } from 'elasticsearch'; -import { StatsCollectionConfig } from 'src/plugins/telemetry_collection_manager/server'; +import { LegacyAPICaller } from 'kibana/server'; import { KIBANA_SYSTEM_ID, TELEMETRY_COLLECTION_INTERVAL } from '../../common/constants'; import { fetchHighLevelStats, @@ -182,7 +182,7 @@ export function ensureTimeSpan( * specialized usage data that comes with kibana stats (kibana_stats.usage). */ export async function getKibanaStats( - callCluster: StatsCollectionConfig['callCluster'], + callCluster: LegacyAPICaller, clusterUuids: string[], start: string, end: string, diff --git a/x-pack/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts b/x-pack/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts index 27ea14e3e8ffe..e23e0c79e20ba 100644 --- a/x-pack/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts +++ b/x-pack/plugins/reporting/server/browsers/chromium/driver/chromium_driver.ts @@ -196,14 +196,17 @@ export class HeadlessChromiumDriver { } public async setViewport( - { width, height, zoom }: ViewZoomWidthHeight, + { width: _width, height: _height, zoom }: ViewZoomWidthHeight, logger: LevelLogger ): Promise { - logger.debug(`Setting viewport to width: ${width}, height: ${height}, zoom: ${zoom}`); + const width = Math.floor(_width); + const height = Math.floor(_height); + + logger.debug(`Setting viewport to: width=${width} height=${height} zoom=${zoom}`); await this.page.setViewport({ - width: Math.floor(width / zoom), - height: Math.floor(height / zoom), + width, + height, deviceScaleFactor: zoom, isMobile: false, }); @@ -243,7 +246,7 @@ export class HeadlessChromiumDriver { } if (this._shouldUseCustomHeaders(conditionalHeaders.conditions, interceptedUrl)) { - logger.debug(`Using custom headers for ${interceptedUrl}`); + logger.trace(`Using custom headers for ${interceptedUrl}`); const headers = map( { ...interceptedRequest.request.headers, @@ -270,7 +273,7 @@ export class HeadlessChromiumDriver { } } else { const loggedUrl = isData ? this.truncateUrl(interceptedUrl) : interceptedUrl; - logger.debug(`No custom headers for ${loggedUrl}`); + logger.trace(`No custom headers for ${loggedUrl}`); try { await client.send('Fetch.continueRequest', { requestId }); } catch (err) { diff --git a/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/args.ts b/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/args.ts index 4f4b41fe0545f..dcec9b571102e 100644 --- a/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/args.ts +++ b/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/args.ts @@ -41,6 +41,9 @@ export const args = ({ userDataDir, viewport, disableSandbox, proxy: proxyConfig '--disable-gpu', '--headless', '--hide-scrollbars', + // NOTE: setting the window size does NOT set the viewport size: viewport and window size are different. + // The viewport may later need to be resized depending on the position of the clip area. + // These numbers come from the job parameters, so this is a close guess. `--window-size=${Math.floor(viewport.width)},${Math.floor(viewport.height)}`, ]; diff --git a/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/index.ts b/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/index.ts index 4b42e2cc59425..3fe336d7d635a 100644 --- a/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/index.ts +++ b/x-pack/plugins/reporting/server/browsers/chromium/driver_factory/index.ts @@ -65,6 +65,7 @@ export class HeadlessChromiumDriverFactory { logger.info(`Creating browser page driver`); const chromiumArgs = this.getChromiumArgs(viewport); + logger.debug(`Chromium launch args set to: ${chromiumArgs}`); let browser: puppeteer.Browser; let page: puppeteer.Page; diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf/lib/generate_pdf.ts b/x-pack/plugins/reporting/server/export_types/printable_pdf/lib/generate_pdf.ts index 6d03e39f45f8f..6b8d3da54deb9 100644 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf/lib/generate_pdf.ts +++ b/x-pack/plugins/reporting/server/export_types/printable_pdf/lib/generate_pdf.ts @@ -43,6 +43,7 @@ export async function generatePdfObservableFactory(reporting: ReportingCore) { tracker.startLayout(); const layout = createLayout(captureConfig, layoutParams); + logger.debug(`Layout: width=${layout.width} height=${layout.height}`); tracker.endLayout(); tracker.startScreenshots(); diff --git a/x-pack/plugins/reporting/server/lib/layouts/canvas_layout.ts b/x-pack/plugins/reporting/server/lib/layouts/canvas_layout.ts index f96addc2d7705..3ebcaee71c6dd 100644 --- a/x-pack/plugins/reporting/server/lib/layouts/canvas_layout.ts +++ b/x-pack/plugins/reporting/server/lib/layouts/canvas_layout.ts @@ -64,8 +64,8 @@ export class CanvasLayout extends Layout implements LayoutInstance { public getViewport() { return { - height: this.scaledHeight, - width: this.scaledWidth, + height: this.height, + width: this.width, zoom: ZOOM, }; } diff --git a/x-pack/plugins/reporting/server/lib/layouts/layout.ts b/x-pack/plugins/reporting/server/lib/layouts/layout.ts index c3f06d6a69dad..cb068632063a5 100644 --- a/x-pack/plugins/reporting/server/lib/layouts/layout.ts +++ b/x-pack/plugins/reporting/server/lib/layouts/layout.ts @@ -33,6 +33,8 @@ export abstract class Layout { pageSizeParams: PageSizeParams ): CustomPageSize | PredefinedPageSize; + // Return the dimensions unscaled dimensions (before multiplying the zoom factor) + // driver.setViewport() Adds a top and left margin to the viewport, and then multiplies by the scaling factor public abstract getViewport(itemsCount: number): ViewZoomWidthHeight | null; public abstract getBrowserZoom(): number; diff --git a/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts b/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts index 549e898d8a13e..ccd08e01fec19 100644 --- a/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts +++ b/x-pack/plugins/reporting/server/lib/layouts/preserve_layout.ts @@ -51,8 +51,8 @@ export class PreserveLayout extends Layout implements LayoutInstance { public getViewport() { return { - height: this.scaledHeight, - width: this.scaledWidth, + height: this.height, + width: this.width, zoom: ZOOM, }; } diff --git a/x-pack/plugins/reporting/server/lib/level_logger.ts b/x-pack/plugins/reporting/server/lib/level_logger.ts index 9db5274a93db8..921bd5b0b4428 100644 --- a/x-pack/plugins/reporting/server/lib/level_logger.ts +++ b/x-pack/plugins/reporting/server/lib/level_logger.ts @@ -49,6 +49,10 @@ export class LevelLogger implements GenericLevelLogger { this.getLogger(tags).debug(msg); } + public trace(msg: string, tags: string[] = []) { + this.getLogger(tags).trace(msg); + } + public info(msg: string, tags: string[] = []) { this.getLogger(tags).info(trimStr(msg)); } diff --git a/x-pack/plugins/reporting/server/lib/screenshots/constants.ts b/x-pack/plugins/reporting/server/lib/screenshots/constants.ts index 854763e499135..918014c52349b 100644 --- a/x-pack/plugins/reporting/server/lib/screenshots/constants.ts +++ b/x-pack/plugins/reporting/server/lib/screenshots/constants.ts @@ -7,6 +7,7 @@ export const DEFAULT_PAGELOAD_SELECTOR = '.application'; export const CONTEXT_GETNUMBEROFITEMS = 'GetNumberOfItems'; +export const CONTEXT_GETBROWSERDIMENSIONS = 'GetBrowserDimensions'; export const CONTEXT_INJECTCSS = 'InjectCss'; export const CONTEXT_WAITFORRENDER = 'WaitForRender'; export const CONTEXT_GETTIMERANGE = 'GetTimeRange'; diff --git a/x-pack/plugins/reporting/server/lib/screenshots/get_screenshots.ts b/x-pack/plugins/reporting/server/lib/screenshots/get_screenshots.ts index 1ed8687bea23e..e274d36c6c7ef 100644 --- a/x-pack/plugins/reporting/server/lib/screenshots/get_screenshots.ts +++ b/x-pack/plugins/reporting/server/lib/screenshots/get_screenshots.ts @@ -7,10 +7,60 @@ import { i18n } from '@kbn/i18n'; import { LevelLogger, startTrace } from '../'; import { HeadlessChromiumDriver } from '../../browsers'; +import { LayoutInstance } from '../layouts'; import { ElementsPositionAndAttribute, Screenshot } from './'; +import { CONTEXT_GETBROWSERDIMENSIONS } from './constants'; + +// In Puppeteer 5.4+, the viewport size limits what the screenshot can take, even if a clip is specified. The clip area must +// be visible in the viewport. This workaround resizes the viewport to the actual content height and width. +// NOTE: this will fire a window resize event +const resizeToClipArea = async ( + item: ElementsPositionAndAttribute, + browser: HeadlessChromiumDriver, + zoom: number, + logger: LevelLogger +) => { + // Check current viewport size + const { width, height, left, top } = item.position.boundingClientRect; // the "unscaled" pixel sizes + const [viewWidth, viewHeight] = await browser.evaluate( + { + fn: () => [document.body.clientWidth, document.body.clientHeight], + args: [], + }, + { context: CONTEXT_GETBROWSERDIMENSIONS }, + logger + ); + + logger.debug(`Browser viewport: width=${viewWidth} height=${viewHeight}`); + + // Resize the viewport if the clip area is not visible + if (viewWidth < width + left || viewHeight < height + top) { + logger.debug(`Item's position is not within the viewport.`); + + // add left and top margin to unscaled measurements + const newWidth = width + left; + const newHeight = height + top; + + logger.debug( + `Resizing browser viewport to: width=${newWidth} height=${newHeight} zoom=${zoom}` + ); + + await browser.setViewport( + { + width: newWidth, + height: newHeight, + zoom, + }, + logger + ); + } + + logger.debug(`Capturing item: width=${width} height=${height} left=${left} top=${top}`); +}; export const getScreenshots = async ( browser: HeadlessChromiumDriver, + layout: LayoutInstance, elementsPositionAndAttributes: ElementsPositionAndAttribute[], logger: LevelLogger ): Promise => { @@ -25,6 +75,8 @@ export const getScreenshots = async ( for (let i = 0; i < elementsPositionAndAttributes.length; i++) { const endTrace = startTrace('get_screenshots', 'read'); const item = elementsPositionAndAttributes[i]; + + await resizeToClipArea(item, browser, layout.getBrowserZoom(), logger); const base64EncodedData = await browser.screenshot(item.position); screenshots.push({ diff --git a/x-pack/plugins/reporting/server/lib/screenshots/observable.test.ts b/x-pack/plugins/reporting/server/lib/screenshots/observable.test.ts index c945801dd49c2..eb1bbaaf1db51 100644 --- a/x-pack/plugins/reporting/server/lib/screenshots/observable.test.ts +++ b/x-pack/plugins/reporting/server/lib/screenshots/observable.test.ts @@ -243,10 +243,10 @@ describe('Screenshot Observable Pipeline', () => { "attributes": Object {}, "position": Object { "boundingClientRect": Object { - "height": 200, + "height": 100, "left": 0, "top": 0, - "width": 200, + "width": 100, }, "scroll": Object { "x": 0, @@ -271,10 +271,10 @@ describe('Screenshot Observable Pipeline', () => { "attributes": Object {}, "position": Object { "boundingClientRect": Object { - "height": 200, + "height": 100, "left": 0, "top": 0, - "width": 200, + "width": 100, }, "scroll": Object { "x": 0, @@ -339,6 +339,8 @@ describe('Screenshot Observable Pipeline', () => { if (mockCall === contexts.CONTEXT_ELEMENTATTRIBUTES) { return Promise.resolve(null); + } else if (mockCall === contexts.CONTEXT_GETBROWSERDIMENSIONS) { + return Promise.resolve([800, 600]); } else { return Promise.resolve(); } diff --git a/x-pack/plugins/reporting/server/lib/screenshots/observable.ts b/x-pack/plugins/reporting/server/lib/screenshots/observable.ts index 342293d113d24..476f04cf665fe 100644 --- a/x-pack/plugins/reporting/server/lib/screenshots/observable.ts +++ b/x-pack/plugins/reporting/server/lib/screenshots/observable.ts @@ -87,6 +87,7 @@ export function screenshotsObservableFactory( }), mergeMap(() => getNumberOfItems(captureConfig, driver, layout, logger)), mergeMap(async (itemsCount) => { + // set the viewport to the dimentions from the job, to allow elements to flow into the expected layout const viewport = layout.getViewport(itemsCount) || getDefaultViewPort(); await Promise.all([ driver.setViewport(viewport, logger), @@ -133,7 +134,7 @@ export function screenshotsObservableFactory( const elements = data.elementsPositionAndAttributes ? data.elementsPositionAndAttributes : getDefaultElementPosition(layout.getViewport(1)); - const screenshots = await getScreenshots(driver, elements, logger); + const screenshots = await getScreenshots(driver, layout, elements, logger); const { timeRange, error: setupError } = data; return { timeRange, diff --git a/x-pack/plugins/reporting/server/test_helpers/create_mock_browserdriverfactory.ts b/x-pack/plugins/reporting/server/test_helpers/create_mock_browserdriverfactory.ts index d6996d2caf1bc..dc08c3c07d871 100644 --- a/x-pack/plugins/reporting/server/test_helpers/create_mock_browserdriverfactory.ts +++ b/x-pack/plugins/reporting/server/test_helpers/create_mock_browserdriverfactory.ts @@ -64,6 +64,9 @@ mockBrowserEvaluate.mockImplementation(() => { if (mockCall === contexts.CONTEXT_GETNUMBEROFITEMS) { return Promise.resolve(1); } + if (mockCall === contexts.CONTEXT_GETBROWSERDIMENSIONS) { + return Promise.resolve([600, 800]); + } if (mockCall === contexts.CONTEXT_INJECTCSS) { return Promise.resolve(); } diff --git a/x-pack/plugins/security/common/licensing/index.mock.ts b/x-pack/plugins/security/common/licensing/index.mock.ts index df7d8cd7b416b..88cb3206a253c 100644 --- a/x-pack/plugins/security/common/licensing/index.mock.ts +++ b/x-pack/plugins/security/common/licensing/index.mock.ts @@ -5,14 +5,14 @@ */ import { of } from 'rxjs'; -import { SecurityLicense } from '.'; +import { SecurityLicense, SecurityLicenseFeatures } from '.'; export const licenseMock = { - create: (): jest.Mocked => ({ + create: (features?: Partial): jest.Mocked => ({ isLicenseAvailable: jest.fn(), isEnabled: jest.fn().mockReturnValue(true), getType: jest.fn().mockReturnValue('basic'), getFeatures: jest.fn(), - features$: of(), + features$: features ? of(features as SecurityLicenseFeatures) : of(), }), }; diff --git a/x-pack/plugins/security/server/audit/audit_service.test.ts b/x-pack/plugins/security/server/audit/audit_service.test.ts index 91c656ad69f18..e828f0135d44b 100644 --- a/x-pack/plugins/security/server/audit/audit_service.test.ts +++ b/x-pack/plugins/security/server/audit/audit_service.test.ts @@ -3,7 +3,12 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { AuditService, filterEvent, createLoggingConfig } from './audit_service'; +import { + AuditService, + filterEvent, + createLoggingConfig, + RECORD_USAGE_INTERVAL, +} from './audit_service'; import { AuditEvent, EventCategory, EventType, EventOutcome } from './audit_events'; import { coreMock, @@ -16,6 +21,8 @@ import { ConfigSchema, ConfigType } from '../config'; import { SecurityLicenseFeatures } from '../../common/licensing'; import { BehaviorSubject, Observable, of } from 'rxjs'; +jest.useFakeTimers(); + const createConfig = (settings: Partial) => { return ConfigSchema.validate(settings); }; @@ -28,18 +35,20 @@ const http = httpServiceMock.createSetupContract(); const getCurrentUser = jest.fn().mockReturnValue({ username: 'jdoe', roles: ['admin'] }); const getSpaceId = jest.fn().mockReturnValue('default'); const getSID = jest.fn().mockResolvedValue('SESSION_ID'); +const recordAuditLoggingUsage = jest.fn(); beforeEach(() => { logger.info.mockClear(); logging.configure.mockClear(); + recordAuditLoggingUsage.mockClear(); http.registerOnPostAuth.mockClear(); }); describe('#setup', () => { it('returns the expected contract', () => { - const auditService = new AuditService(logger); + const audit = new AuditService(logger); expect( - auditService.setup({ + audit.setup({ license, config, logging, @@ -47,6 +56,7 @@ describe('#setup', () => { getCurrentUser, getSpaceId, getSID, + recordAuditLoggingUsage, }) ).toMatchInlineSnapshot(` Object { @@ -54,10 +64,12 @@ describe('#setup', () => { "getLogger": [Function], } `); + audit.stop(); }); it('configures logging correctly when using ecs logger', async () => { - new AuditService(logger).setup({ + const audit = new AuditService(logger); + audit.setup({ license, config: { enabled: true, @@ -73,12 +85,67 @@ describe('#setup', () => { getCurrentUser, getSpaceId, getSID, + recordAuditLoggingUsage, }); expect(logging.configure).toHaveBeenCalledWith(expect.any(Observable)); + audit.stop(); + }); + + it('records feature usage correctly when using ecs logger', async () => { + const audit = new AuditService(logger); + audit.setup({ + license: licenseMock.create({ + allowAuditLogging: true, + }), + config: { + enabled: true, + appender: { + kind: 'console', + layout: { + kind: 'pattern', + }, + }, + }, + logging, + http, + getCurrentUser, + getSpaceId, + getSID, + recordAuditLoggingUsage, + }); + expect(recordAuditLoggingUsage).toHaveBeenCalledTimes(1); + jest.advanceTimersByTime(RECORD_USAGE_INTERVAL); + expect(recordAuditLoggingUsage).toHaveBeenCalledTimes(2); + jest.advanceTimersByTime(RECORD_USAGE_INTERVAL); + expect(recordAuditLoggingUsage).toHaveBeenCalledTimes(3); + audit.stop(); + }); + + it('does not record feature usage when disabled', async () => { + const audit = new AuditService(logger); + audit.setup({ + license, + config: { + enabled: false, + }, + logging, + http, + getCurrentUser, + getSpaceId, + getSID, + recordAuditLoggingUsage, + }); + expect(recordAuditLoggingUsage).not.toHaveBeenCalled(); + jest.advanceTimersByTime(RECORD_USAGE_INTERVAL); + expect(recordAuditLoggingUsage).not.toHaveBeenCalled(); + jest.advanceTimersByTime(RECORD_USAGE_INTERVAL); + expect(recordAuditLoggingUsage).not.toHaveBeenCalled(); + audit.stop(); }); it('registers post auth hook', () => { - new AuditService(logger).setup({ + const audit = new AuditService(logger); + audit.setup({ license, config, logging, @@ -86,14 +153,17 @@ describe('#setup', () => { getCurrentUser, getSpaceId, getSID, + recordAuditLoggingUsage, }); expect(http.registerOnPostAuth).toHaveBeenCalledWith(expect.any(Function)); + audit.stop(); }); }); describe('#asScoped', () => { it('logs event enriched with meta data', async () => { - const audit = new AuditService(logger).setup({ + const audit = new AuditService(logger); + const auditSetup = audit.setup({ license, config, logging, @@ -101,12 +171,13 @@ describe('#asScoped', () => { getCurrentUser, getSpaceId, getSID, + recordAuditLoggingUsage, }); const request = httpServerMock.createKibanaRequest({ kibanaRequestState: { requestId: 'REQUEST_ID', requestUuid: 'REQUEST_UUID' }, }); - await audit.asScoped(request).log({ message: 'MESSAGE', event: { action: 'ACTION' } }); + await auditSetup.asScoped(request).log({ message: 'MESSAGE', event: { action: 'ACTION' } }); expect(logger.info).toHaveBeenCalledWith('MESSAGE', { ecs: { version: '1.6.0' }, event: { action: 'ACTION' }, @@ -115,10 +186,12 @@ describe('#asScoped', () => { trace: { id: 'REQUEST_ID' }, user: { name: 'jdoe', roles: ['admin'] }, }); + audit.stop(); }); it('does not log to audit logger if event matches ignore filter', async () => { - const audit = new AuditService(logger).setup({ + const audit = new AuditService(logger); + const auditSetup = audit.setup({ license, config: { enabled: true, @@ -129,17 +202,20 @@ describe('#asScoped', () => { getCurrentUser, getSpaceId, getSID, + recordAuditLoggingUsage, }); const request = httpServerMock.createKibanaRequest({ kibanaRequestState: { requestId: 'REQUEST_ID', requestUuid: 'REQUEST_UUID' }, }); - await audit.asScoped(request).log({ message: 'MESSAGE', event: { action: 'ACTION' } }); + await auditSetup.asScoped(request).log({ message: 'MESSAGE', event: { action: 'ACTION' } }); expect(logger.info).not.toHaveBeenCalled(); + audit.stop(); }); it('does not log to audit logger if no event was generated', async () => { - const audit = new AuditService(logger).setup({ + const audit = new AuditService(logger); + const auditSetup = audit.setup({ license, config: { enabled: true, @@ -150,13 +226,15 @@ describe('#asScoped', () => { getCurrentUser, getSpaceId, getSID, + recordAuditLoggingUsage, }); const request = httpServerMock.createKibanaRequest({ kibanaRequestState: { requestId: 'REQUEST_ID', requestUuid: 'REQUEST_UUID' }, }); - await audit.asScoped(request).log(undefined); + await auditSetup.asScoped(request).log(undefined); expect(logger.info).not.toHaveBeenCalled(); + audit.stop(); }); }); @@ -376,6 +454,7 @@ describe('#getLogger', () => { getCurrentUser, getSpaceId, getSID, + recordAuditLoggingUsage, }); const auditLogger = auditService.getLogger(pluginId); @@ -407,6 +486,7 @@ describe('#getLogger', () => { getCurrentUser, getSpaceId, getSID, + recordAuditLoggingUsage, }); const auditLogger = auditService.getLogger(pluginId); @@ -446,6 +526,7 @@ describe('#getLogger', () => { getCurrentUser, getSpaceId, getSID, + recordAuditLoggingUsage, }); const auditLogger = auditService.getLogger(pluginId); @@ -475,6 +556,7 @@ describe('#getLogger', () => { getCurrentUser, getSpaceId, getSID, + recordAuditLoggingUsage, }); const auditLogger = auditService.getLogger(pluginId); @@ -505,6 +587,7 @@ describe('#getLogger', () => { getCurrentUser, getSpaceId, getSID, + recordAuditLoggingUsage, }); const auditLogger = auditService.getLogger(pluginId); diff --git a/x-pack/plugins/security/server/audit/audit_service.ts b/x-pack/plugins/security/server/audit/audit_service.ts index 4ad1f873581c9..7ecdef0ab4e4e 100644 --- a/x-pack/plugins/security/server/audit/audit_service.ts +++ b/x-pack/plugins/security/server/audit/audit_service.ts @@ -20,6 +20,7 @@ import { AuditEvent, httpRequestEvent } from './audit_events'; import { SecurityPluginSetup } from '..'; export const ECS_VERSION = '1.6.0'; +export const RECORD_USAGE_INTERVAL = 60 * 60 * 1000; // 1 hour /** * @deprecated @@ -58,6 +59,7 @@ interface AuditServiceSetupParams { getSpaceId( request: KibanaRequest ): ReturnType | undefined; + recordAuditLoggingUsage(): void; } export class AuditService { @@ -69,8 +71,8 @@ export class AuditService { * @deprecated */ private allowLegacyAuditLogging = false; - private ecsLogger: Logger; + private usageIntervalId?: NodeJS.Timeout; constructor(private readonly logger: Logger) { this.ecsLogger = logger.get('ecs'); @@ -84,6 +86,7 @@ export class AuditService { getCurrentUser, getSID, getSpaceId, + recordAuditLoggingUsage, }: AuditServiceSetupParams): AuditServiceSetup { if (config.enabled && !config.appender) { this.licenseFeaturesSubscription = license.features$.subscribe( @@ -101,6 +104,20 @@ export class AuditService { ) ); + // Record feature usage at a regular interval if enabled and license allows + if (config.enabled && config.appender) { + license.features$.subscribe((features) => { + clearInterval(this.usageIntervalId!); + if (features.allowAuditLogging) { + recordAuditLoggingUsage(); + this.usageIntervalId = setInterval(recordAuditLoggingUsage, RECORD_USAGE_INTERVAL); + if (this.usageIntervalId.unref) { + this.usageIntervalId.unref(); + } + } + }); + } + /** * Creates an {@link AuditLogger} scoped to the current request. * @@ -198,6 +215,7 @@ export class AuditService { this.licenseFeaturesSubscription.unsubscribe(); this.licenseFeaturesSubscription = undefined; } + clearInterval(this.usageIntervalId!); } } diff --git a/x-pack/plugins/security/server/feature_usage/feature_usage_service.test.ts b/x-pack/plugins/security/server/feature_usage/feature_usage_service.test.ts index 46796fa73ef26..e8ad9a77b5d5f 100644 --- a/x-pack/plugins/security/server/feature_usage/feature_usage_service.test.ts +++ b/x-pack/plugins/security/server/feature_usage/feature_usage_service.test.ts @@ -11,11 +11,12 @@ describe('#setup', () => { const featureUsage = { register: jest.fn() }; const securityFeatureUsage = new SecurityFeatureUsageService(); securityFeatureUsage.setup({ featureUsage }); - expect(featureUsage.register).toHaveBeenCalledTimes(2); + expect(featureUsage.register).toHaveBeenCalledTimes(3); expect(featureUsage.register.mock.calls.map((c) => c[0])).toMatchInlineSnapshot(` Array [ "Subfeature privileges", "Pre-access agreement", + "Audit logging", ] `); }); @@ -39,4 +40,13 @@ describe('start contract', () => { expect(featureUsage.notifyUsage).toHaveBeenCalledTimes(1); expect(featureUsage.notifyUsage).toHaveBeenCalledWith('Pre-access agreement'); }); + + it('notifies when audit logging is used', () => { + const featureUsage = { notifyUsage: jest.fn(), getLastUsages: jest.fn() }; + const securityFeatureUsage = new SecurityFeatureUsageService(); + const startContract = securityFeatureUsage.start({ featureUsage }); + startContract.recordAuditLoggingUsage(); + expect(featureUsage.notifyUsage).toHaveBeenCalledTimes(1); + expect(featureUsage.notifyUsage).toHaveBeenCalledWith('Audit logging'); + }); }); diff --git a/x-pack/plugins/security/server/feature_usage/feature_usage_service.ts b/x-pack/plugins/security/server/feature_usage/feature_usage_service.ts index 1bc1e664981bf..98338e172bb12 100644 --- a/x-pack/plugins/security/server/feature_usage/feature_usage_service.ts +++ b/x-pack/plugins/security/server/feature_usage/feature_usage_service.ts @@ -17,12 +17,14 @@ interface StartDeps { export interface SecurityFeatureUsageServiceStart { recordPreAccessAgreementUsage: () => void; recordSubFeaturePrivilegeUsage: () => void; + recordAuditLoggingUsage: () => void; } export class SecurityFeatureUsageService { public setup({ featureUsage }: SetupDeps) { featureUsage.register('Subfeature privileges', 'gold'); featureUsage.register('Pre-access agreement', 'gold'); + featureUsage.register('Audit logging', 'gold'); } public start({ featureUsage }: StartDeps): SecurityFeatureUsageServiceStart { @@ -33,6 +35,9 @@ export class SecurityFeatureUsageService { recordSubFeaturePrivilegeUsage() { featureUsage.notifyUsage('Subfeature privileges'); }, + recordAuditLoggingUsage() { + featureUsage.notifyUsage('Audit logging'); + }, }; } } diff --git a/x-pack/plugins/security/server/feature_usage/index.mock.ts b/x-pack/plugins/security/server/feature_usage/index.mock.ts index 6ed42145abd76..e934222ab22af 100644 --- a/x-pack/plugins/security/server/feature_usage/index.mock.ts +++ b/x-pack/plugins/security/server/feature_usage/index.mock.ts @@ -11,6 +11,7 @@ export const securityFeatureUsageServiceMock = { return { recordPreAccessAgreementUsage: jest.fn(), recordSubFeaturePrivilegeUsage: jest.fn(), + recordAuditLoggingUsage: jest.fn(), } as jest.Mocked; }, }; diff --git a/x-pack/plugins/security/server/plugin.ts b/x-pack/plugins/security/server/plugin.ts index 070e187e869b1..450de2fc31329 100644 --- a/x-pack/plugins/security/server/plugin.ts +++ b/x-pack/plugins/security/server/plugin.ts @@ -204,6 +204,7 @@ export class Plugin { getSpaceId: (request) => spaces?.spacesService.getSpaceId(request), getSID: (request) => session.getSID(request), getCurrentUser: (request) => authenticationSetup.getCurrentUser(request), + recordAuditLoggingUsage: () => this.featureUsageServiceStart?.recordAuditLoggingUsage(), }); const legacyAuditLogger = new SecurityAuditLogger(audit.getLogger()); diff --git a/x-pack/plugins/security_solution/public/cases/containers/use_post_push_to_service.test.tsx b/x-pack/plugins/security_solution/public/cases/containers/use_post_push_to_service.test.tsx index c8d00a4c5cf0f..645dd80a21e66 100644 --- a/x-pack/plugins/security_solution/public/cases/containers/use_post_push_to_service.test.tsx +++ b/x-pack/plugins/security_solution/public/cases/containers/use_post_push_to_service.test.tsx @@ -21,7 +21,7 @@ import { import * as api from './api'; import { CaseServices } from './use_get_case_user_actions'; import { CaseConnector, ConnectorTypes, CommentType } from '../../../../case/common/api'; - +import moment from 'moment'; jest.mock('./api'); jest.mock('../../common/components/link_to', () => { const originalModule = jest.requireActual('../../common/components/link_to'); @@ -31,7 +31,6 @@ jest.mock('../../common/components/link_to', () => { useFormatUrl: jest.fn().mockReturnValue({ formatUrl: jest.fn(), search: 'urlSearch' }), }; }); - describe('usePostPushToService', () => { const abortCtrl = new AbortController(); const updateCase = jest.fn(); @@ -306,6 +305,8 @@ describe('usePostPushToService', () => { }); it('formatServiceRequestData - Alert comment content', () => { + const mockDuration = moment.duration(1); + jest.spyOn(moment, 'duration').mockReturnValue(mockDuration); formatUrl.mockReturnValue('https://app.com/detections'); const caseServices = sampleCaseServices; const result = formatServiceRequestData({ @@ -327,7 +328,7 @@ describe('usePostPushToService', () => { }); expect(result.comments![0].comment).toEqual( - '[Alert](https://app.com/detections?filters=!((%27$state%27:(store:appState),meta:(alias:!n,disabled:!f,key:_id,negate:!f,params:(query:alert-id-1),type:phrase),query:(match:(_id:(query:alert-id-1,type:phrase)))))&sourcerer=(default:!())&timerange=(global:(linkTo:!(timeline),timerange:(from:%272020-11-20T15:29:28.373Z%27,kind:absolute,to:%272020-11-20T15:35:28.373Z%27)),timeline:(linkTo:!(global),timerange:(from:%272020-11-20T15:29:28.373Z%27,kind:absolute,to:%272020-11-20T15:35:28.373Z%27)))) added to case.' + '[Alert](https://app.com/detections?filters=!((%27$state%27:(store:appState),meta:(alias:!n,disabled:!f,key:_id,negate:!f,params:(query:alert-id-1),type:phrase),query:(match:(_id:(query:alert-id-1,type:phrase)))))&sourcerer=(default:!())&timerange=(global:(linkTo:!(timeline),timerange:(from:%272020-11-20T15:35:28.372Z%27,kind:absolute,to:%272020-11-20T15:35:28.373Z%27)),timeline:(linkTo:!(global),timerange:(from:%272020-11-20T15:35:28.372Z%27,kind:absolute,to:%272020-11-20T15:35:28.373Z%27)))) added to case.' ); }); diff --git a/x-pack/plugins/security_solution/public/common/components/autocomplete/field.tsx b/x-pack/plugins/security_solution/public/common/components/autocomplete/field.tsx index f87bf3137765f..2aa71f0d9b5ad 100644 --- a/x-pack/plugins/security_solution/public/common/components/autocomplete/field.tsx +++ b/x-pack/plugins/security_solution/public/common/components/autocomplete/field.tsx @@ -122,16 +122,16 @@ const getAvailableFields = ( selectedFields: IFieldType[], fieldTypeFilter: string[] ): IFieldType[] => { - const map = new Map(); + const fieldsByName = new Map(); - existingFields.forEach((f) => map.set(f.name, f)); - selectedFields.forEach((f) => map.set(f.name, f)); + existingFields.forEach((f) => fieldsByName.set(f.name, f)); + selectedFields.forEach((f) => fieldsByName.set(f.name, f)); - const array = Array.from(map.values()); + const uniqueFields = Array.from(fieldsByName.values()); if (fieldTypeFilter.length > 0) { - return array.filter(({ type }) => fieldTypeFilter.includes(type)); + return uniqueFields.filter(({ type }) => fieldTypeFilter.includes(type)); } - return array; + return uniqueFields; }; diff --git a/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx b/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx index e8a17d78644df..5bb1081de22e8 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/header_global/index.tsx @@ -6,7 +6,7 @@ import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui'; import { pickBy } from 'lodash/fp'; -import React, { forwardRef, useCallback } from 'react'; +import React, { forwardRef, useCallback, useMemo } from 'react'; import styled from 'styled-components'; import { OutPortal } from 'react-reverse-portal'; @@ -72,7 +72,16 @@ export const HeaderGlobal = React.memo( const { timelineFullScreen } = useTimelineFullScreen(); const search = useGetUrlSearch(navTabs.overview); const { application, http } = useKibana().services; - const { navigateToApp } = application; + const { navigateToApp, getUrlForApp } = application; + const overviewPath = useMemo( + () => getUrlForApp(APP_ID, { path: SecurityPageName.overview }), + [getUrlForApp] + ); + const overviewHref = useMemo(() => getAppOverviewUrl(overviewPath, search), [ + overviewPath, + search, + ]); + const basePath = http.basePath.get(); const goToOverview = useCallback( (ev) => { @@ -93,7 +102,7 @@ export const HeaderGlobal = React.memo( - + diff --git a/x-pack/plugins/security_solution/public/common/components/link_to/redirect_to_overview.tsx b/x-pack/plugins/security_solution/public/common/components/link_to/redirect_to_overview.tsx index d0cf46bd90521..9bf2d28f3f332 100644 --- a/x-pack/plugins/security_solution/public/common/components/link_to/redirect_to_overview.tsx +++ b/x-pack/plugins/security_solution/public/common/components/link_to/redirect_to_overview.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { APP_OVERVIEW_PATH } from '../../../../common/constants'; import { appendSearch } from './helpers'; -export const getAppOverviewUrl = (search?: string) => `${APP_OVERVIEW_PATH}${appendSearch(search)}`; +export const getAppOverviewUrl = (overviewPath: string, search?: string) => + `${overviewPath}${appendSearch(search)}`; diff --git a/x-pack/plugins/security_solution/public/common/components/links_to_docs/doc_link.tsx b/x-pack/plugins/security_solution/public/common/components/links_to_docs/doc_link.tsx index f02e4390db02f..6bd180c6fd510 100644 --- a/x-pack/plugins/security_solution/public/common/components/links_to_docs/doc_link.tsx +++ b/x-pack/plugins/security_solution/public/common/components/links_to_docs/doc_link.tsx @@ -22,7 +22,11 @@ const DocLink: FC = ({ guidePath = 'security', docPath, linkText } const url = `${ELASTIC_WEBSITE_URL}guide/en/${guidePath}/${DOC_LINK_VERSION}/${docPath}`; const ariaLabel = `${linkText} - ${COMMON_ARIA_LABEL_ENDING}`; - return ; + return ( + + {linkText} + + ); }; /** diff --git a/x-pack/plugins/security_solution/public/common/components/links_to_docs/external_link.tsx b/x-pack/plugins/security_solution/public/common/components/links_to_docs/external_link.tsx index f83c6f8fe31e4..d953ed2d706e5 100644 --- a/x-pack/plugins/security_solution/public/common/components/links_to_docs/external_link.tsx +++ b/x-pack/plugins/security_solution/public/common/components/links_to_docs/external_link.tsx @@ -5,21 +5,34 @@ */ import React, { FC } from 'react'; -import { EuiLink } from '@elastic/eui'; +import { EuiLink, EuiToolTip } from '@elastic/eui'; interface ExternalLinkProps { url: string; - text: string; + children?: React.ReactNode; ariaLabel?: string; } /** - * A simplistic text link for opening external urls in a new browser tab. + * A link for opening external urls in a new browser tab. */ -export const ExternalLink: FC = ({ url, text, ariaLabel }) => { +export const ExternalLink: FC = ({ url, children, ariaLabel }) => { + if (!children) { + return null; + } + return ( - - {text} - + + + {children} + + ); }; diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts index 891e7bfffe868..f219f9bef5f80 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.test.ts @@ -5,7 +5,6 @@ */ import '../../../mock/match_media'; import { encodeIpv6 } from '../../../lib/helpers'; - import { getBreadcrumbsForRoute, setBreadcrumbs } from '.'; import { HostsTableType } from '../../../../hosts/store/model'; import { RouteSpyState, SiemRouteType } from '../../../utils/route/types'; @@ -110,6 +109,7 @@ const getMockObject = ( sourcerer: {}, }); +// The string returned is different from what getUrlForApp returns, but does not matter for the purposes of this test. const getUrlForAppMock = (appId: string, options?: { path?: string; absolute?: boolean }) => `${appId}${options?.path ?? ''}`; @@ -128,7 +128,7 @@ describe('Navigation Breadcrumbs', () => { ); expect(breadcrumbs).toEqual([ { - href: '/app/security/overview', + href: 'securitySolutionoverview', text: 'Security', }, { @@ -149,7 +149,7 @@ describe('Navigation Breadcrumbs', () => { getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Network', href: @@ -168,7 +168,7 @@ describe('Navigation Breadcrumbs', () => { getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Timelines', href: @@ -183,7 +183,7 @@ describe('Navigation Breadcrumbs', () => { getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Hosts', href: @@ -204,7 +204,7 @@ describe('Navigation Breadcrumbs', () => { getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Network', href: @@ -224,7 +224,7 @@ describe('Navigation Breadcrumbs', () => { getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Network', href: @@ -244,7 +244,7 @@ describe('Navigation Breadcrumbs', () => { getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Detections', href: @@ -258,7 +258,7 @@ describe('Navigation Breadcrumbs', () => { getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Cases', href: @@ -279,7 +279,7 @@ describe('Navigation Breadcrumbs', () => { getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Cases', href: @@ -297,7 +297,7 @@ describe('Navigation Breadcrumbs', () => { getUrlForAppMock ); expect(breadcrumbs).toEqual([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Administration', href: 'securitySolution:administration', @@ -310,7 +310,7 @@ describe('Navigation Breadcrumbs', () => { test('should call chrome breadcrumb service with correct breadcrumbs', () => { setBreadcrumbs(getMockObject('hosts', '/', hostName), chromeMock, getUrlForAppMock); expect(setBreadcrumbsMock).toBeCalledWith([ - { text: 'Security', href: '/app/security/overview' }, + { text: 'Security', href: 'securitySolutionoverview' }, { text: 'Hosts', href: diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts index 2964572cb7cf3..410fdd0cb4a5f 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts @@ -7,7 +7,7 @@ import { getOr, omit } from 'lodash/fp'; import { ChromeBreadcrumb } from '../../../../../../../../src/core/public'; -import { APP_NAME } from '../../../../../common/constants'; +import { APP_NAME, APP_ID } from '../../../../../common/constants'; import { StartServices } from '../../../../types'; import { getBreadcrumbs as getHostDetailsBreadcrumbs } from '../../../../hosts/pages/details/utils'; import { getBreadcrumbs as getIPDetailsBreadcrumbs } from '../../../../network/pages/details'; @@ -40,13 +40,6 @@ export const setBreadcrumbs = ( } }; -export const siemRootBreadcrumb: ChromeBreadcrumb[] = [ - { - text: APP_NAME, - href: getAppOverviewUrl(), - }, -]; - const isNetworkRoutes = (spyState: RouteSpyState): spyState is NetworkRouteSpyState => spyState != null && spyState.pageName === SecurityPageName.network; @@ -71,6 +64,11 @@ export const getBreadcrumbsForRoute = ( getUrlForApp: GetUrlForApp ): ChromeBreadcrumb[] | null => { const spyState: RouteSpyState = omit('navTabs', object); + const overviewPath = getUrlForApp(APP_ID, { path: SecurityPageName.overview }); + const siemRootBreadcrumb: ChromeBreadcrumb = { + text: APP_NAME, + href: getAppOverviewUrl(overviewPath), + }; if (isHostsRoutes(spyState) && object.navTabs) { const tempNav: SearchNavTab = { urlKey: 'host', isDetailPage: false }; let urlStateKeys = [getOr(tempNav, spyState.pageName, object.navTabs)]; @@ -78,7 +76,7 @@ export const getBreadcrumbsForRoute = ( urlStateKeys = [...urlStateKeys, getOr(tempNav, spyState.tabName, object.navTabs)]; } return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, ...getHostDetailsBreadcrumbs( spyState, urlStateKeys.reduce( @@ -96,7 +94,7 @@ export const getBreadcrumbsForRoute = ( urlStateKeys = [...urlStateKeys, getOr(tempNav, spyState.tabName, object.navTabs)]; } return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, ...getIPDetailsBreadcrumbs( spyState, urlStateKeys.reduce( @@ -115,7 +113,7 @@ export const getBreadcrumbsForRoute = ( } return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, ...getDetectionRulesBreadcrumbs( spyState, urlStateKeys.reduce( @@ -134,7 +132,7 @@ export const getBreadcrumbsForRoute = ( } return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, ...getCaseDetailsBreadcrumbs( spyState, urlStateKeys.reduce( @@ -153,7 +151,7 @@ export const getBreadcrumbsForRoute = ( } return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, ...getTimelinesBreadcrumbs( spyState, urlStateKeys.reduce( @@ -173,7 +171,7 @@ export const getBreadcrumbsForRoute = ( } return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, ...getAdminBreadcrumbs( spyState, urlStateKeys.reduce( @@ -192,7 +190,7 @@ export const getBreadcrumbsForRoute = ( object.navTabs[spyState.pageName] ) { return [ - ...siemRootBreadcrumb, + siemRootBreadcrumb, { text: object.navTabs[spyState.pageName].name, href: '', diff --git a/x-pack/plugins/task_manager/server/MONITORING.md b/x-pack/plugins/task_manager/server/MONITORING.md index 4960086411e9a..3595b86317489 100644 --- a/x-pack/plugins/task_manager/server/MONITORING.md +++ b/x-pack/plugins/task_manager/server/MONITORING.md @@ -179,9 +179,21 @@ For example, if you _curl_ the `/api/task_manager/_health` endpoint, you might g /* What is the frequency of polling cycle result? Here we see 94% of "NoTasksClaimed" and 6% "PoolFilled" */ "result_frequency_percent_as_number": { + /* This tells us that the polling cycle didnt claim any new tasks */ "NoTasksClaimed": 94, - "RanOutOfCapacity": 0, /* This is a legacy result, we might want to rename - it tells us when a polling cycle resulted in claiming more tasks than we had workers for, butt he name doesn't make much sense outside of the context of the code */ - "PoolFilled": 6 + /* This is a legacy result we are renaming in 8.0.0 - + it tells us when a polling cycle resulted in claiming more tasks + than we had workers for, butt he name doesn't make much sense outside of the context of the code */ + "RanOutOfCapacity": 0, + /* This is a legacy result we are renaming in 8.0.0 - + it tells us when a polling cycle resulted in tasks being claimed but less the the available workers */ + "PoolFilled": 6, + /* This tells us when a polling cycle resulted in no tasks being claimed due to there being no available workers */ + "NoAvailableWorkers": 0, + /* This tells us when a polling cycle resulted in tasks being claimed at 100% capacity of the available workers */ + "RunningAtCapacity": 0, + /* This tells us when the poller failed to claim */ + "Failed": 0 } }, /* on average, the tasks in this deployment run 1.7s after their scheduled time */ diff --git a/x-pack/plugins/task_manager/server/lib/fill_pool.test.ts b/x-pack/plugins/task_manager/server/lib/fill_pool.test.ts index ebb72c3ed36d6..a2c1eb514aebc 100644 --- a/x-pack/plugins/task_manager/server/lib/fill_pool.test.ts +++ b/x-pack/plugins/task_manager/server/lib/fill_pool.test.ts @@ -8,6 +8,7 @@ import _ from 'lodash'; import sinon from 'sinon'; import { fillPool } from './fill_pool'; import { TaskPoolRunResult } from '../task_pool'; +import { asOk } from './result_type'; describe('fillPool', () => { test('stops filling when pool runs all claimed tasks, even if there is more capacity', async () => { @@ -16,7 +17,7 @@ describe('fillPool', () => { [4, 5], ]; let index = 0; - const fetchAvailableTasks = async () => tasks[index++] || []; + const fetchAvailableTasks = async () => asOk(tasks[index++] || []); const run = sinon.spy(async () => TaskPoolRunResult.RunningAllClaimedTasks); const converter = _.identity; @@ -31,7 +32,7 @@ describe('fillPool', () => { [4, 5], ]; let index = 0; - const fetchAvailableTasks = async () => tasks[index++] || []; + const fetchAvailableTasks = async () => asOk(tasks[index++] || []); const run = sinon.spy(async () => TaskPoolRunResult.RanOutOfCapacity); const converter = _.identity; @@ -46,7 +47,7 @@ describe('fillPool', () => { [4, 5], ]; let index = 0; - const fetchAvailableTasks = async () => tasks[index++] || []; + const fetchAvailableTasks = async () => asOk(tasks[index++] || []); const run = sinon.spy(async () => TaskPoolRunResult.RanOutOfCapacity); const converter = (x: number) => x.toString(); @@ -80,7 +81,7 @@ describe('fillPool', () => { [4, 5], ]; let index = 0; - const fetchAvailableTasks = async () => tasks[index++] || []; + const fetchAvailableTasks = async () => asOk(tasks[index++] || []); await fillPool(fetchAvailableTasks, converter, run); } catch (err) { @@ -95,7 +96,7 @@ describe('fillPool', () => { [4, 5], ]; let index = 0; - const fetchAvailableTasks = async () => tasks[index++] || []; + const fetchAvailableTasks = async () => asOk(tasks[index++] || []); const run = sinon.spy(async () => TaskPoolRunResult.RanOutOfCapacity); const converter = (x: number) => { throw new Error(`can not convert ${x}`); diff --git a/x-pack/plugins/task_manager/server/lib/fill_pool.ts b/x-pack/plugins/task_manager/server/lib/fill_pool.ts index 9e4894587203d..5ab173755662f 100644 --- a/x-pack/plugins/task_manager/server/lib/fill_pool.ts +++ b/x-pack/plugins/task_manager/server/lib/fill_pool.ts @@ -6,15 +6,19 @@ import { performance } from 'perf_hooks'; import { TaskPoolRunResult } from '../task_pool'; +import { Result, map } from './result_type'; export enum FillPoolResult { + Failed = 'Failed', + NoAvailableWorkers = 'NoAvailableWorkers', NoTasksClaimed = 'NoTasksClaimed', + RunningAtCapacity = 'RunningAtCapacity', RanOutOfCapacity = 'RanOutOfCapacity', PoolFilled = 'PoolFilled', } type BatchRun = (tasks: T[]) => Promise; -type Fetcher = () => Promise; +type Fetcher = () => Promise>; type Converter = (t: T1) => T2; /** @@ -30,33 +34,43 @@ type Converter = (t: T1) => T2; * @param converter - a function that converts task records to the appropriate task runner */ export async function fillPool( - fetchAvailableTasks: Fetcher, + fetchAvailableTasks: Fetcher, converter: Converter, run: BatchRun ): Promise { performance.mark('fillPool.start'); - const instances = await fetchAvailableTasks(); + return map>( + await fetchAvailableTasks(), + async (instances) => { + if (!instances.length) { + performance.mark('fillPool.bailNoTasks'); + performance.measure( + 'fillPool.activityDurationUntilNoTasks', + 'fillPool.start', + 'fillPool.bailNoTasks' + ); + return FillPoolResult.NoTasksClaimed; + } - if (!instances.length) { - performance.mark('fillPool.bailNoTasks'); - performance.measure( - 'fillPool.activityDurationUntilNoTasks', - 'fillPool.start', - 'fillPool.bailNoTasks' - ); - return FillPoolResult.NoTasksClaimed; - } - const tasks = instances.map(converter); + const tasks = instances.map(converter); - if ((await run(tasks)) === TaskPoolRunResult.RanOutOfCapacity) { - performance.mark('fillPool.bailExhaustedCapacity'); - performance.measure( - 'fillPool.activityDurationUntilExhaustedCapacity', - 'fillPool.start', - 'fillPool.bailExhaustedCapacity' - ); - return FillPoolResult.RanOutOfCapacity; - } - performance.mark('fillPool.cycle'); - return FillPoolResult.PoolFilled; + switch (await run(tasks)) { + case TaskPoolRunResult.RanOutOfCapacity: + performance.mark('fillPool.bailExhaustedCapacity'); + performance.measure( + 'fillPool.activityDurationUntilExhaustedCapacity', + 'fillPool.start', + 'fillPool.bailExhaustedCapacity' + ); + return FillPoolResult.RanOutOfCapacity; + case TaskPoolRunResult.RunningAtCapacity: + performance.mark('fillPool.cycle'); + return FillPoolResult.RunningAtCapacity; + default: + performance.mark('fillPool.cycle'); + return FillPoolResult.PoolFilled; + } + }, + async (result) => result + ); } diff --git a/x-pack/plugins/task_manager/server/monitoring/task_run_statistics.test.ts b/x-pack/plugins/task_manager/server/monitoring/task_run_statistics.test.ts index 538acd51bb792..7d5a8811dbe2b 100644 --- a/x-pack/plugins/task_manager/server/monitoring/task_run_statistics.test.ts +++ b/x-pack/plugins/task_manager/server/monitoring/task_run_statistics.test.ts @@ -427,25 +427,95 @@ describe('Task Run Statistics', () => { taskStats.map((taskStat) => taskStat.value.polling.result_frequency_percent_as_number) ).toEqual([ // NoTasksClaimed - { NoTasksClaimed: 100, RanOutOfCapacity: 0, PoolFilled: 0 }, + { + NoTasksClaimed: 100, + RanOutOfCapacity: 0, + PoolFilled: 0, + Failed: 0, + NoAvailableWorkers: 0, + RunningAtCapacity: 0, + }, // NoTasksClaimed, NoTasksClaimed, - { NoTasksClaimed: 100, RanOutOfCapacity: 0, PoolFilled: 0 }, + { + NoTasksClaimed: 100, + RanOutOfCapacity: 0, + PoolFilled: 0, + Failed: 0, + NoAvailableWorkers: 0, + RunningAtCapacity: 0, + }, // NoTasksClaimed, NoTasksClaimed, NoTasksClaimed - { NoTasksClaimed: 100, RanOutOfCapacity: 0, PoolFilled: 0 }, + { + NoTasksClaimed: 100, + RanOutOfCapacity: 0, + PoolFilled: 0, + Failed: 0, + NoAvailableWorkers: 0, + RunningAtCapacity: 0, + }, // NoTasksClaimed, NoTasksClaimed, NoTasksClaimed, PoolFilled - { NoTasksClaimed: 75, RanOutOfCapacity: 0, PoolFilled: 25 }, + { + NoTasksClaimed: 75, + RanOutOfCapacity: 0, + PoolFilled: 25, + Failed: 0, + NoAvailableWorkers: 0, + RunningAtCapacity: 0, + }, // NoTasksClaimed, NoTasksClaimed, NoTasksClaimed, PoolFilled, PoolFilled - { NoTasksClaimed: 60, RanOutOfCapacity: 0, PoolFilled: 40 }, + { + NoTasksClaimed: 60, + RanOutOfCapacity: 0, + PoolFilled: 40, + Failed: 0, + NoAvailableWorkers: 0, + RunningAtCapacity: 0, + }, // NoTasksClaimed, NoTasksClaimed, PoolFilled, PoolFilled, PoolFilled - { NoTasksClaimed: 40, RanOutOfCapacity: 0, PoolFilled: 60 }, + { + NoTasksClaimed: 40, + RanOutOfCapacity: 0, + PoolFilled: 60, + Failed: 0, + NoAvailableWorkers: 0, + RunningAtCapacity: 0, + }, // NoTasksClaimed, PoolFilled, PoolFilled, PoolFilled, RanOutOfCapacity - { NoTasksClaimed: 20, RanOutOfCapacity: 20, PoolFilled: 60 }, + { + NoTasksClaimed: 20, + RanOutOfCapacity: 20, + PoolFilled: 60, + Failed: 0, + NoAvailableWorkers: 0, + RunningAtCapacity: 0, + }, // PoolFilled, PoolFilled, PoolFilled, RanOutOfCapacity, RanOutOfCapacity - { NoTasksClaimed: 0, RanOutOfCapacity: 40, PoolFilled: 60 }, + { + NoTasksClaimed: 0, + RanOutOfCapacity: 40, + PoolFilled: 60, + Failed: 0, + NoAvailableWorkers: 0, + RunningAtCapacity: 0, + }, // PoolFilled, PoolFilled, RanOutOfCapacity, RanOutOfCapacity, NoTasksClaimed - { NoTasksClaimed: 20, RanOutOfCapacity: 40, PoolFilled: 40 }, + { + NoTasksClaimed: 20, + RanOutOfCapacity: 40, + PoolFilled: 40, + Failed: 0, + NoAvailableWorkers: 0, + RunningAtCapacity: 0, + }, // PoolFilled, RanOutOfCapacity, RanOutOfCapacity, NoTasksClaimed, NoTasksClaimed - { NoTasksClaimed: 40, RanOutOfCapacity: 40, PoolFilled: 20 }, + { + NoTasksClaimed: 40, + RanOutOfCapacity: 40, + PoolFilled: 20, + Failed: 0, + NoAvailableWorkers: 0, + RunningAtCapacity: 0, + }, ]); resolve(); } catch (e) { diff --git a/x-pack/plugins/task_manager/server/monitoring/task_run_statistics.ts b/x-pack/plugins/task_manager/server/monitoring/task_run_statistics.ts index 3e0d517172d01..c1851789a769d 100644 --- a/x-pack/plugins/task_manager/server/monitoring/task_run_statistics.ts +++ b/x-pack/plugins/task_manager/server/monitoring/task_run_statistics.ts @@ -52,8 +52,11 @@ export interface TaskRunStat extends JsonObject { interface FillPoolRawStat extends JsonObject { last_successful_poll: string; result_frequency_percent_as_number: { + [FillPoolResult.Failed]: number; + [FillPoolResult.NoAvailableWorkers]: number; [FillPoolResult.NoTasksClaimed]: number; [FillPoolResult.RanOutOfCapacity]: number; + [FillPoolResult.RunningAtCapacity]: number; [FillPoolResult.PoolFilled]: number; }; } @@ -163,8 +166,11 @@ const DEFAULT_TASK_RUN_FREQUENCIES = { [TaskRunResult.Failed]: 0, }; const DEFAULT_POLLING_FREQUENCIES = { + [FillPoolResult.Failed]: 0, + [FillPoolResult.NoAvailableWorkers]: 0, [FillPoolResult.NoTasksClaimed]: 0, [FillPoolResult.RanOutOfCapacity]: 0, + [FillPoolResult.RunningAtCapacity]: 0, [FillPoolResult.PoolFilled]: 0, }; diff --git a/x-pack/plugins/task_manager/server/polling_lifecycle.ts b/x-pack/plugins/task_manager/server/polling_lifecycle.ts index 1a8108e34078d..1876c52b0029e 100644 --- a/x-pack/plugins/task_manager/server/polling_lifecycle.ts +++ b/x-pack/plugins/task_manager/server/polling_lifecycle.ts @@ -12,7 +12,7 @@ import { Option, some, map as mapOptional } from 'fp-ts/lib/Option'; import { tap } from 'rxjs/operators'; import { Logger } from '../../../../src/core/server'; -import { Result, asErr, mapErr } from './lib/result_type'; +import { Result, asErr, mapErr, asOk } from './lib/result_type'; import { ManagedConfiguration } from './lib/create_managed_configuration'; import { TaskManagerConfig } from './config'; @@ -232,7 +232,7 @@ export async function claimAvailableTasks( claim: (opts: OwnershipClaimingOpts) => Promise, availableWorkers: number, logger: Logger -) { +): Promise> { if (availableWorkers > 0) { performance.mark('claimAvailableTasks_start'); @@ -260,12 +260,13 @@ export async function claimAvailableTasks( } task(s) were fetched (${docs.map((doc) => doc.id).join(', ')})` ); } - return docs; + return asOk(docs); } catch (ex) { if (identifyEsError(ex).includes('cannot execute [inline] scripts')) { logger.warn( `Task Manager cannot operate when inline scripts are disabled in Elasticsearch` ); + return asErr(FillPoolResult.Failed); } else { throw ex; } @@ -275,6 +276,6 @@ export async function claimAvailableTasks( logger.debug( `[Task Ownership]: Task Manager has skipped Claiming Ownership of available tasks at it has ran out Available Workers.` ); + return asErr(FillPoolResult.NoAvailableWorkers); } - return []; } diff --git a/x-pack/plugins/task_manager/server/task_pool.test.ts b/x-pack/plugins/task_manager/server/task_pool.test.ts index a174af71ef18f..95768bb2f1afa 100644 --- a/x-pack/plugins/task_manager/server/task_pool.test.ts +++ b/x-pack/plugins/task_manager/server/task_pool.test.ts @@ -92,7 +92,7 @@ describe('TaskPool', () => { ] `); - expect(result).toEqual(TaskPoolRunResult.RunningAllClaimedTasks); + expect(result).toEqual(TaskPoolRunResult.RunningAtCapacity); }); test('should log when running a Task fails', async () => { @@ -242,7 +242,7 @@ describe('TaskPool', () => { }, ]); - expect(result).toEqual(TaskPoolRunResult.RunningAllClaimedTasks); + expect(result).toEqual(TaskPoolRunResult.RunningAtCapacity); expect(pool.occupiedWorkers).toEqual(2); expect(pool.availableWorkers).toEqual(0); diff --git a/x-pack/plugins/task_manager/server/task_pool.ts b/x-pack/plugins/task_manager/server/task_pool.ts index acd2ea59ad30b..6946cd613e0a7 100644 --- a/x-pack/plugins/task_manager/server/task_pool.ts +++ b/x-pack/plugins/task_manager/server/task_pool.ts @@ -22,7 +22,11 @@ interface Opts { } export enum TaskPoolRunResult { + // This means we're running all the tasks we claimed RunningAllClaimedTasks = 'RunningAllClaimedTasks', + // This means we're running all the tasks we claimed and we're at capacity + RunningAtCapacity = 'RunningAtCapacity', + // This means we're prematurely out of capacity and have accidentally claimed more tasks than we had capacity for RanOutOfCapacity = 'RanOutOfCapacity', } @@ -123,6 +127,8 @@ export class TaskPool { return this.attemptToRun(leftOverTasks); } return TaskPoolRunResult.RanOutOfCapacity; + } else if (!this.availableWorkers) { + return TaskPoolRunResult.RunningAtCapacity; } return TaskPoolRunResult.RunningAllClaimedTasks; } diff --git a/x-pack/plugins/transform/common/types/transform.ts b/x-pack/plugins/transform/common/types/transform.ts index 8ebbfe6e70944..d4852f0144539 100644 --- a/x-pack/plugins/transform/common/types/transform.ts +++ b/x-pack/plugins/transform/common/types/transform.ts @@ -49,9 +49,7 @@ export function isPivotTransform( return transform.hasOwnProperty('pivot'); } -export function isLatestTransform( - transform: TransformBaseConfig -): transform is TransformLatestConfig { +export function isLatestTransform(transform: any): transform is TransformLatestConfig { return transform.hasOwnProperty('latest'); } diff --git a/x-pack/plugins/transform/common/utils/object_utils.ts b/x-pack/plugins/transform/common/utils/object_utils.ts index f21460e08098d..8dd017fdaa48e 100644 --- a/x-pack/plugins/transform/common/utils/object_utils.ts +++ b/x-pack/plugins/transform/common/utils/object_utils.ts @@ -6,17 +6,32 @@ // This is similar to lodash's get() except that it's TypeScript aware and is able to infer return types. // It splits the attribute key string and uses reduce with an idx check to access nested attributes. -export const getNestedProperty = ( +export function getNestedProperty( obj: Record, accessor: string, defaultValue?: any -) => { - const value = accessor.split('.').reduce((o, i) => o?.[i], obj); +): any { + const accessorKeys = accessor.split('.'); - if (value === undefined) return defaultValue; + let o = obj; + for (let i = 0; i < accessorKeys.length; i++) { + const keyPart = accessorKeys[i]; + o = o?.[keyPart]; + if (Array.isArray(o)) { + o = o.map((v) => + typeof v === 'object' + ? // from this point we need to resolve path for each element in the collection + getNestedProperty(v, accessorKeys.slice(i + 1, accessorKeys.length).join('.')) + : v + ); + break; + } + } - return value; -}; + if (o === undefined) return defaultValue; + + return o; +} export const setNestedProperty = (obj: Record, accessor: string, value: any) => { let ref = obj; diff --git a/x-pack/plugins/transform/public/app/__mocks__/app_dependencies.tsx b/x-pack/plugins/transform/public/app/__mocks__/app_dependencies.tsx index 53297cd7d2661..11d6daf01b3b8 100644 --- a/x-pack/plugins/transform/public/app/__mocks__/app_dependencies.tsx +++ b/x-pack/plugins/transform/public/app/__mocks__/app_dependencies.tsx @@ -31,7 +31,7 @@ const appDependencies = { export const useAppDependencies = () => { const ml = useContext(MlSharedContext); - return { ...appDependencies, ml, savedObjects: jest.fn(), data: jest.fn() }; + return { ...appDependencies, ml, savedObjects: jest.fn() }; }; export const useToastNotifications = () => { diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_latest_function_config.ts b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_latest_function_config.ts index 53f38a7bad44e..7df6b11dc27ec 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_latest_function_config.ts +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/hooks/use_latest_function_config.ts @@ -11,6 +11,8 @@ import { LatestFunctionConfigUI } from '../../../../../../../common/types/transf import { StepDefineFormProps } from '../step_define_form'; import { StepDefineExposedState } from '../common'; import { LatestFunctionConfig } from '../../../../../../../common/api_schemas/transforms'; +import { AggConfigs, FieldParamType } from '../../../../../../../../../../src/plugins/data/common'; +import { useAppDependencies } from '../../../../../app_dependencies'; /** * Latest function config mapper between API and UI @@ -32,26 +34,33 @@ export const latestConfigMapper = { /** * Provides available options for unique_key and sort fields * @param indexPattern + * @param aggConfigs */ -function getOptions(indexPattern: StepDefineFormProps['searchItems']['indexPattern']) { - const uniqueKeyOptions: Array> = []; - const sortFieldOptions: Array> = []; - - const ignoreFieldNames = new Set(['_id', '_index', '_type']); - - for (const field of indexPattern.fields) { - if (ignoreFieldNames.has(field.name)) { - continue; - } - - if (field.aggregatable) { - uniqueKeyOptions.push({ label: field.displayName, value: field.name }); - } - - if (field.sortable) { - sortFieldOptions.push({ label: field.displayName, value: field.name }); - } - } +function getOptions( + indexPattern: StepDefineFormProps['searchItems']['indexPattern'], + aggConfigs: AggConfigs +) { + const aggConfig = aggConfigs.aggs[0]; + const param = aggConfig.type.params.find((p) => p.type === 'field'); + const filteredIndexPatternFields = param + ? ((param as unknown) as FieldParamType).getAvailableFields(aggConfig) + : []; + + const ignoreFieldNames = new Set(['_source', '_type', '_index', '_id', '_version', '_score']); + + const uniqueKeyOptions: Array> = filteredIndexPatternFields + .filter((v) => !ignoreFieldNames.has(v.name)) + .map((v) => ({ + label: v.displayName, + value: v.name, + })); + + const sortFieldOptions: Array> = indexPattern.fields + .filter((v) => !ignoreFieldNames.has(v.name) && v.sortable) + .map((v) => ({ + label: v.displayName, + value: v.name, + })); return { uniqueKeyOptions, sortFieldOptions }; } @@ -92,9 +101,12 @@ export function useLatestFunctionConfig( sort: defaults.sort, }); - const { uniqueKeyOptions, sortFieldOptions } = useMemo(() => getOptions(indexPattern), [ - indexPattern, - ]); + const { data } = useAppDependencies(); + + const { uniqueKeyOptions, sortFieldOptions } = useMemo(() => { + const aggConfigs = data.search.aggs.createAggConfigs(indexPattern, [{ type: 'terms' }]); + return getOptions(indexPattern, aggConfigs); + }, [indexPattern, data.search.aggs]); const updateLatestFunctionConfig = useCallback( (update) => diff --git a/x-pack/plugins/transform/server/routes/api/transforms.ts b/x-pack/plugins/transform/server/routes/api/transforms.ts index fd93e3055eab5..07e06ec3af3db 100644 --- a/x-pack/plugins/transform/server/routes/api/transforms.ts +++ b/x-pack/plugins/transform/server/routes/api/transforms.ts @@ -57,6 +57,7 @@ import { addBasePath } from '../index'; import { isRequestTimeout, fillResultsWithTimeouts, wrapError, wrapEsError } from './error_utils'; import { registerTransformsAuditMessagesRoutes } from './transforms_audit_messages'; import { IIndexPattern } from '../../../../../../src/plugins/data/common/index_patterns'; +import { isLatestTransform } from '../../../common/types/transform'; enum TRANSFORM_ACTIONS { STOP = 'stop', @@ -531,9 +532,36 @@ const previewTransformHandler: RequestHandler< PostTransformsPreviewRequestSchema > = async (ctx, req, res) => { try { + const reqBody = req.body; const { body } = await ctx.core.elasticsearch.client.asCurrentUser.transform.previewTransform({ - body: req.body, + body: reqBody, }); + if (isLatestTransform(reqBody)) { + // for the latest transform mappings properties have to be retrieved from the source + const fieldCapsResponse = await ctx.core.elasticsearch.client.asCurrentUser.fieldCaps({ + index: reqBody.source.index, + fields: '*', + include_unmapped: false, + }); + + const fieldNamesSet = new Set(Object.keys(fieldCapsResponse.body.fields)); + + const fields = Object.entries( + fieldCapsResponse.body.fields as Record> + ).reduce((acc, [fieldName, fieldCaps]) => { + const fieldDefinition = Object.values(fieldCaps)[0]; + const isMetaField = fieldDefinition.type.startsWith('_') || fieldName === '_doc_count'; + const isKeywordDuplicate = + fieldName.endsWith('.keyword') && fieldNamesSet.has(fieldName.split('.keyword')[0]); + if (isMetaField || isKeywordDuplicate) { + return acc; + } + acc[fieldName] = { ...fieldDefinition }; + return acc; + }, {} as Record); + + body.generated_dest_index.mappings.properties = fields; + } return res.ok({ body }); } catch (e) { return res.customError(wrapError(wrapEsError(e))); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 4d15f444ad1a8..fef61667168a9 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -84,12 +84,14 @@ "advancedSettings.categoryNames.dashboardLabel": "ダッシュボード", "advancedSettings.categoryNames.discoverLabel": "発見", "advancedSettings.categoryNames.generalLabel": "一般", + "advancedSettings.categoryNames.machineLearningLabel": "機械学習", "advancedSettings.categoryNames.notificationsLabel": "通知", + "advancedSettings.categoryNames.observabilityLabel": "オブザーバビリティ", "advancedSettings.categoryNames.reportingLabel": "レポート", "advancedSettings.categoryNames.searchLabel": "検索", "advancedSettings.categoryNames.securitySolutionLabel": "セキュリティソリューション", "advancedSettings.categoryNames.timelionLabel": "Timelion", - "advancedSettings.categoryNames.visualizationsLabel": "可視化", + "advancedSettings.categoryNames.visualizationsLabel": "ビジュアライゼーション", "advancedSettings.categorySearchLabel": "カテゴリー", "advancedSettings.featureCatalogueTitle": "日付形式の変更、ダークモードの有効化など、Kibanaエクスペリエンスをカスタマイズします。", "advancedSettings.field.changeImageLinkAriaLabel": "{ariaName} を変更", @@ -113,7 +115,7 @@ "advancedSettings.form.cancelButtonLabel": "変更をキャンセル", "advancedSettings.form.clearNoSearchResultText": "(検索結果を消去)", "advancedSettings.form.clearSearchResultText": "(検索結果を消去)", - "advancedSettings.form.countOfSettingsChanged": "{unsavedCount} unsaved {unsavedCount, plural, one {setting} other {settings} }{hiddenCount, plural, =0 {} other {, # hidden} }", + "advancedSettings.form.countOfSettingsChanged": "{unsavedCount}保存されていない {unsavedCount, plural, other {個の設定} }{hiddenCount, plural, =0 {} other {, # 非表示} }", "advancedSettings.form.noSearchResultText": "設定が見つかりませんでした {clearSearch}", "advancedSettings.form.requiresPageReloadToastButtonLabel": "ページを再読み込み", "advancedSettings.form.requiresPageReloadToastDescription": "設定を有効にするためにページの再読み込みが必要です。", @@ -125,8 +127,8 @@ "advancedSettings.searchBar.unableToParseQueryErrorMessage": "クエリをパースできません", "advancedSettings.searchBarAriaLabel": "高度な設定を検索", "advancedSettings.voiceAnnouncement.ariaLabel": "詳細設定結果情報", - "advancedSettings.voiceAnnouncement.noSearchResultScreenReaderMessage": "{sectionLenght, plural, one {# セクション} other {# セクション}}に{optionLenght, plural, one {# オプション} other {# オプション}}があります。", - "advancedSettings.voiceAnnouncement.searchResultScreenReaderMessage": "{query} を検索しました。{sectionLenght, plural, one {# セクション} other {# セクション}}に{optionLenght, plural, one {# オプション} other {# オプション}}があります。", + "advancedSettings.voiceAnnouncement.noSearchResultScreenReaderMessage": "{sectionLenght, plural, other {# セクション}}に{optionLenght, plural, other {# オプション}}があります。", + "advancedSettings.voiceAnnouncement.searchResultScreenReaderMessage": "{query} を検索しました。{sectionLenght, plural, other {# セクション}}に{optionLenght, plural, other {# オプション}}があります。", "apmOss.tutorial.apmAgents.statusCheck.btnLabel": "エージェントステータスを確認", "apmOss.tutorial.apmAgents.statusCheck.errorMessage": "エージェントからまだデータを受け取っていません", "apmOss.tutorial.apmAgents.statusCheck.successMessage": "1 つまたは複数のエージェントからデータを受け取りました", @@ -144,9 +146,10 @@ "apmOss.tutorial.djangoClient.configure.commands.addAgentComment": "インストールされたアプリにエージェントを追加します", "apmOss.tutorial.djangoClient.configure.commands.addTracingMiddlewareComment": "パフォーマンスメトリックを送信するには、追跡ミドルウェアを追加します。", "apmOss.tutorial.djangoClient.configure.commands.allowedCharactersComment": "a-z、A-Z、0-9、-、_、スペース", - "apmOss.tutorial.djangoClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL (デフォルト: {defaultApmServerUrl})", - "apmOss.tutorial.djangoClient.configure.commands.setRequiredServiceNameComment": "必要なサーバー名を設定します。使用できる文字:", - "apmOss.tutorial.djangoClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Server にトークンが必要な場合に使います", + "apmOss.tutorial.djangoClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL(デフォルト:{defaultApmServerUrl})を設定します", + "apmOss.tutorial.djangoClient.configure.commands.setRequiredServiceNameComment": "任意のサービス名を設定します。使用できる文字:", + "apmOss.tutorial.djangoClient.configure.commands.setServiceEnvironmentComment": "サービス環境を設定します", + "apmOss.tutorial.djangoClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Server でシークレットトークンが必要な場合に使います", "apmOss.tutorial.djangoClient.configure.textPost": "高度な用途に関しては [ドキュメンテーション]({documentationLink}) をご覧ください。", "apmOss.tutorial.djangoClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは「SERVICE_NAME」に基づいてプログラムで作成されます。", "apmOss.tutorial.djangoClient.configure.title": "エージェントの構成", @@ -167,19 +170,21 @@ "apmOss.tutorial.flaskClient.configure.commands.allowedCharactersComment": "a-z、A-Z、0-9、-、_、スペース", "apmOss.tutorial.flaskClient.configure.commands.configureElasticApmComment": "またはアプリケーションの設定で ELASTIC_APM を使用するよう構成します。", "apmOss.tutorial.flaskClient.configure.commands.initializeUsingEnvironmentVariablesComment": "環境変数を使用して初期化します", - "apmOss.tutorial.flaskClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL (デフォルト: {defaultApmServerUrl})", - "apmOss.tutorial.flaskClient.configure.commands.setRequiredServiceNameComment": "必要なサーバー名を設定します。使用できる文字:", - "apmOss.tutorial.flaskClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Server にトークンが必要な場合に使います", + "apmOss.tutorial.flaskClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL(デフォルト:{defaultApmServerUrl})を設定します", + "apmOss.tutorial.flaskClient.configure.commands.setRequiredServiceNameComment": "任意のサービス名を設定します。使用できる文字:", + "apmOss.tutorial.flaskClient.configure.commands.setServiceEnvironmentComment": "サービス環境を設定します", + "apmOss.tutorial.flaskClient.configure.commands.useIfApmServerRequiresTokenComment": "APM Server でシークレットトークンが必要な場合に使います", "apmOss.tutorial.flaskClient.configure.textPost": "高度な用途に関しては [ドキュメンテーション]({documentationLink}) をご覧ください。", "apmOss.tutorial.flaskClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは「SERVICE_NAME」に基づいてプログラムで作成されます。", "apmOss.tutorial.flaskClient.configure.title": "エージェントの構成", "apmOss.tutorial.flaskClient.install.textPre": "Python 用の APM エージェントを依存関係としてインストールします。", "apmOss.tutorial.flaskClient.install.title": "APM エージェントのインストール", "apmOss.tutorial.goClient.configure.commands.initializeUsingEnvironmentVariablesComment": "環境変数を使用して初期化します:", - "apmOss.tutorial.goClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL (デフォルト: {defaultApmServerUrl})", + "apmOss.tutorial.goClient.configure.commands.setCustomApmServerUrlComment": "カスタム APM Server URL(デフォルト:{defaultApmServerUrl})を設定します", + "apmOss.tutorial.goClient.configure.commands.setServiceEnvironment": "サービス環境を設定します", "apmOss.tutorial.goClient.configure.commands.setServiceNameComment": "サービス名を設定します。使用できる文字は # a-z、A-Z、0-9、-、_、スペースです。", - "apmOss.tutorial.goClient.configure.commands.usedExecutableNameComment": "ELASTIC_APM_SERVICE_NAME が指定されていない場合、実行可能な名前が使用されます。", - "apmOss.tutorial.goClient.configure.commands.useIfApmRequiresTokenComment": "APM Server にトークンが必要な場合に使います", + "apmOss.tutorial.goClient.configure.commands.usedExecutableNameComment": "ELASTIC_APM_SERVICE_NAME が指定されていない場合、実行ファイルの名前が使用されます。", + "apmOss.tutorial.goClient.configure.commands.useIfApmRequiresTokenComment": "APM Server でシークレットトークンが必要な場合に使います", "apmOss.tutorial.goClient.configure.textPost": "高度な構成に関しては [ドキュメンテーション]({documentationLink}) をご覧ください。", "apmOss.tutorial.goClient.configure.textPre": "エージェントとは、アプリケーションプロセス内で実行されるライブラリです。APM サービスは実行ファイル名または「ELASTIC_APM_SERVICE_NAME」環境変数に基づいてプログラムで作成されます。", "apmOss.tutorial.goClient.configure.title": "エージェントの構成", @@ -192,23 +197,25 @@ "apmOss.tutorial.javaClient.download.textPre": "[Maven Central]({mavenCentralLink}) からエージェントをダウンロードします。アプリケーションにエージェントを依存関係として「追加しない」でください。", "apmOss.tutorial.javaClient.download.title": "APM エージェントのダウンロード", "apmOss.tutorial.javaClient.startApplication.textPost": "構成オプションと高度な用途に関しては、[ドキュメンテーション]({documentationLink}) をご覧ください。", - "apmOss.tutorial.javaClient.startApplication.textPre": "「-javaagent」フラグを追加してエージェントをシステムプロパティで構成します。\n\n * 必要なサービス名を設定します (使用可能な文字は a-z、A-Z、0-9、-、_、スペースです)\n * カスタム APM Server URL (デフォルト: {customApmServerUrl})\n * アプリケーションのベースパッケージを設定します", + "apmOss.tutorial.javaClient.startApplication.textPre": "「-javaagent」フラグを追加し、システムプロパティを使用してエージェントを構成します。\n\n * 任意のサービス名を設定します (使用可能な文字は a-z、A-Z、0-9、-、_、スペースです)\n * カスタム APM Server URL(デフォルト:{customApmServerUrl})を設定します\n * APM Server シークレットトークンを設定します\n * サービス環境を設定します\n * アプリケーションのベースパッケージを設定します", "apmOss.tutorial.javaClient.startApplication.title": "javaagent フラグでアプリケーションを起動", "apmOss.tutorial.jsClient.enableRealUserMonitoring.textPre": "デフォルトでは、APM Server を実行すると RUM サポートは無効になります。RUM サポートを有効にする手順については、[ドキュメンテーション]({documentationLink}) をご覧ください。", "apmOss.tutorial.jsClient.enableRealUserMonitoring.title": "APMサーバーのリアルユーザー監視サポートを有効にする", - "apmOss.tutorial.jsClient.installDependency.commands.setCustomApmServerUrlComment": "カスタム APM Server URL (デフォルト: {defaultApmServerUrl})", - "apmOss.tutorial.jsClient.installDependency.commands.setRequiredServiceNameComment": "必要なサービス名を設定します (使用可能な文字は a-z、A-Z、0-9、-、_、スペースです)", - "apmOss.tutorial.jsClient.installDependency.commands.setServiceVersionComment": "サービスバージョンを設定します (ソースマップ機能に必要)", + "apmOss.tutorial.jsClient.installDependency.commands.setCustomApmServerUrlComment": "カスタム APM Server URL(デフォルト:{defaultApmServerUrl})を設定します", + "apmOss.tutorial.jsClient.installDependency.commands.setRequiredServiceNameComment": "任意のサービス名を設定します (使用可能な文字は a-z、A-Z、0-9、-、_、スペースです)", + "apmOss.tutorial.jsClient.installDependency.commands.setServiceEnvironmentComment": "サービス環境を設定します", + "apmOss.tutorial.jsClient.installDependency.commands.setServiceVersionComment": "サービスバージョンを設定します(ソースマップ機能に必要)", "apmOss.tutorial.jsClient.installDependency.textPost": "React や Angular などのフレームワーク統合には、カスタム依存関係があります。詳細は [統合ドキュメント]({docLink}) をご覧ください。", "apmOss.tutorial.jsClient.installDependency.textPre": "「npm install @elastic/apm-rum --save」でエージェントをアプリケーションへの依存関係としてインストールできます。\n\nその後で以下のようにアプリケーションでエージェントを初期化して構成できます。", "apmOss.tutorial.jsClient.installDependency.title": "エージェントを依存関係としてセットアップ", "apmOss.tutorial.jsClient.scriptTags.textPre": "または、スクリプトタグを使用してエージェントのセットアップと構成ができます。` を追加