diff --git a/.teamcity/src/builds/PullRequestCi.kt b/.teamcity/src/builds/PullRequestCi.kt index f3fd1c0dfdf75d..c38591fe850ac9 100644 --- a/.teamcity/src/builds/PullRequestCi.kt +++ b/.teamcity/src/builds/PullRequestCi.kt @@ -3,6 +3,7 @@ package builds import builds.default.DefaultSavedObjectFieldMetrics import dependsOn import getProjectBranch +import isReportingEnabled import jetbrains.buildServer.configs.kotlin.v2019_2.BuildType import jetbrains.buildServer.configs.kotlin.v2019_2.buildFeatures.commitStatusPublisher import vcs.Kibana @@ -63,6 +64,7 @@ object PullRequestCi : BuildType({ features { commitStatusPublisher { + enabled = isReportingEnabled() vcsRootExtId = "${Kibana.id}" publisher = github { githubUrl = "https://api.github.com" diff --git a/.teamcity/src/builds/test/QuickTests.kt b/.teamcity/src/builds/test/QuickTests.kt index 086f65e4ee26b8..6ea15bf5350e6f 100644 --- a/.teamcity/src/builds/test/QuickTests.kt +++ b/.teamcity/src/builds/test/QuickTests.kt @@ -13,7 +13,7 @@ object QuickTests : BuildType({ val testScripts = mapOf( "Test Hardening" to ".ci/teamcity/checks/test_hardening.sh", - "Test Projects" to ".ci/teamcity/tests/test_projects.sh", + "Test Projects" to ".ci/teamcity/tests/test_projects.sh" ) steps { diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationmap.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationmap.md index 016442ce67d437..2ab9fcaf428b9e 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationmap.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationmap.md @@ -18,7 +18,7 @@ export interface SavedObjectMigrationMap ```typescript -const migrations: SavedObjectMigrationMap = { +const migrationsMap: SavedObjectMigrationMap = { '1.0.0': migrateToV1, '2.1.0': migrateToV21 } diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md index 54e01d3110a2dd..aa813bb7b29566 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.registertype.md @@ -38,7 +38,7 @@ export const myType: SavedObjectsType = { }, migrations: { '2.0.0': migrations.migrateToV2, - '2.1.0': migrations.migrateToV2_1 + '2.1.0': migrations.migrateToV2_1, }, }; diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md index a8894286de9100..e5c3fa2b3e92d6 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.md @@ -23,7 +23,7 @@ This is only internal for now, and will only be public when we expose the regist | [indexPattern](./kibana-plugin-core-server.savedobjectstype.indexpattern.md) | string | If defined, the type instances will be stored in the given index instead of the default one. | | [management](./kibana-plugin-core-server.savedobjectstype.management.md) | SavedObjectsTypeManagementDefinition | An optional [saved objects management section](./kibana-plugin-core-server.savedobjectstypemanagementdefinition.md) definition for the type. | | [mappings](./kibana-plugin-core-server.savedobjectstype.mappings.md) | SavedObjectsTypeMappingDefinition | The [mapping definition](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) for the type. | -| [migrations](./kibana-plugin-core-server.savedobjectstype.migrations.md) | SavedObjectMigrationMap | An optional map of [migrations](./kibana-plugin-core-server.savedobjectmigrationfn.md) to be used to migrate the type. | +| [migrations](./kibana-plugin-core-server.savedobjectstype.migrations.md) | SavedObjectMigrationMap | (() => SavedObjectMigrationMap) | An optional map of [migrations](./kibana-plugin-core-server.savedobjectmigrationfn.md) or a function returning a map of [migrations](./kibana-plugin-core-server.savedobjectmigrationfn.md) to be used to migrate the type. | | [name](./kibana-plugin-core-server.savedobjectstype.name.md) | string | The name of the type, which is also used as the internal id. | | [namespaceType](./kibana-plugin-core-server.savedobjectstype.namespacetype.md) | SavedObjectsNamespaceType | The [namespace type](./kibana-plugin-core-server.savedobjectsnamespacetype.md) for the type. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.migrations.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.migrations.md index 22513880ab40ec..6550d48a1c26a2 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.migrations.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectstype.migrations.md @@ -4,10 +4,10 @@ ## SavedObjectsType.migrations property -An optional map of [migrations](./kibana-plugin-core-server.savedobjectmigrationfn.md) to be used to migrate the type. +An optional map of [migrations](./kibana-plugin-core-server.savedobjectmigrationfn.md) or a function returning a map of [migrations](./kibana-plugin-core-server.savedobjectmigrationfn.md) to be used to migrate the type. Signature: ```typescript -migrations?: SavedObjectMigrationMap; +migrations?: SavedObjectMigrationMap | (() => SavedObjectMigrationMap); ``` diff --git a/package.json b/package.json index 053b2060dc4d3d..ff6df054be220a 100644 --- a/package.json +++ b/package.json @@ -165,7 +165,7 @@ "apollo-server-core": "^1.3.6", "apollo-server-errors": "^2.0.2", "apollo-server-hapi": "^1.3.6", - "archiver": "^3.1.1", + "archiver": "^5.2.0", "axios": "^0.21.1", "bluebird": "3.5.5", "brace": "0.11.1", @@ -406,7 +406,7 @@ "@types/accept": "3.1.1", "@types/angular": "^1.6.56", "@types/angular-mocks": "^1.7.0", - "@types/archiver": "^3.1.0", + "@types/archiver": "^5.1.0", "@types/babel__core": "^7.1.10", "@types/base64-js": "^1.2.5", "@types/bluebird": "^3.1.1", diff --git a/src/core/server/saved_objects/migrations/core/document_migrator.test.ts b/src/core/server/saved_objects/migrations/core/document_migrator.test.ts index 4cc4f696d307c9..3f4522aed8e001 100644 --- a/src/core/server/saved_objects/migrations/core/document_migrator.test.ts +++ b/src/core/server/saved_objects/migrations/core/document_migrator.test.ts @@ -52,50 +52,84 @@ describe('DocumentMigrator', () => { }; } - it('validates individual migration definitions', () => { - const invalidDefinition = { - kibanaVersion: '3.2.3', - typeRegistry: createRegistry({ - name: 'foo', - migrations: _.noop as any, - }), - log: mockLogger, - }; - expect(() => new DocumentMigrator(invalidDefinition)).toThrow( - /Migration for type foo should be an object/i - ); + const createDefinition = (migrations: any) => ({ + kibanaVersion: '3.2.3', + typeRegistry: createRegistry({ + name: 'foo', + migrations: migrations as any, + }), + log: mockLogger, }); - it('validates individual migration semvers', () => { - const invalidDefinition = { - kibanaVersion: '3.2.3', - typeRegistry: createRegistry({ - name: 'foo', - migrations: { - bar: (doc) => doc, - }, - }), - log: mockLogger, - }; - expect(() => new DocumentMigrator(invalidDefinition)).toThrow( - /Expected all properties to be semvers/i + it('validates migration definition', () => { + expect(() => new DocumentMigrator(createDefinition(() => {}))).not.toThrow(); + expect(() => new DocumentMigrator(createDefinition({}))).not.toThrow(); + expect(() => new DocumentMigrator(createDefinition(123))).toThrow( + /Migration for type foo should be an object or a function/i ); }); - it('validates the migration function', () => { - const invalidDefinition = { - kibanaVersion: '3.2.3', + describe('#prepareMigrations', () => { + it('validates individual migration definitions', () => { + const invalidMigrator = new DocumentMigrator(createDefinition(() => 123)); + const voidMigrator = new DocumentMigrator(createDefinition(() => {})); + const emptyObjectMigrator = new DocumentMigrator(createDefinition(() => ({}))); + + expect(invalidMigrator.prepareMigrations).toThrow( + /Migrations map for type foo should be an object/i + ); + expect(voidMigrator.prepareMigrations).not.toThrow(); + expect(emptyObjectMigrator.prepareMigrations).not.toThrow(); + }); + + it('validates individual migration semvers', () => { + const withInvalidVersion = { + bar: (doc: any) => doc, + '1.2.3': (doc: any) => doc, + }; + const migrationFn = new DocumentMigrator(createDefinition(() => withInvalidVersion)); + const migrationObj = new DocumentMigrator(createDefinition(withInvalidVersion)); + + expect(migrationFn.prepareMigrations).toThrow(/Expected all properties to be semvers/i); + expect(migrationObj.prepareMigrations).toThrow(/Expected all properties to be semvers/i); + }); + + it('validates the migration function', () => { + const invalidVersionFunction = { '1.2.3': 23 as any }; + const migrationFn = new DocumentMigrator(createDefinition(() => invalidVersionFunction)); + const migrationObj = new DocumentMigrator(createDefinition(invalidVersionFunction)); + + expect(migrationFn.prepareMigrations).toThrow(/expected a function, but got 23/i); + expect(migrationObj.prepareMigrations).toThrow(/expected a function, but got 23/i); + }); + it('validates definitions with migrations: Function | Objects', () => { + const validMigrationMap = { '1.2.3': () => {} }; + const migrationFn = new DocumentMigrator(createDefinition(() => validMigrationMap)); + const migrationObj = new DocumentMigrator(createDefinition(validMigrationMap)); + expect(migrationFn.prepareMigrations).not.toThrow(); + expect(migrationObj.prepareMigrations).not.toThrow(); + }); + }); + + it('throws if #prepareMigrations is not called before #migrate is called', () => { + const migrator = new DocumentMigrator({ + ...testOpts(), typeRegistry: createRegistry({ - name: 'foo', + name: 'user', migrations: { - '1.2.3': 23 as any, + '1.2.3': setAttr('attributes.name', 'Chris'), }, }), - log: mockLogger, - }; - expect(() => new DocumentMigrator(invalidDefinition)).toThrow( - /expected a function, but got 23/i - ); + }); + + expect(() => + migrator.migrate({ + id: 'me', + type: 'user', + attributes: { name: 'Christopher' }, + migrationVersion: {}, + }) + ).toThrow(/Migrations are not ready. Make sure prepareMigrations is called first./i); }); it('migrates type and attributes', () => { @@ -108,6 +142,8 @@ describe('DocumentMigrator', () => { }, }), }); + migrator.prepareMigrations(); + const actual = migrator.migrate({ id: 'me', type: 'user', @@ -141,6 +177,7 @@ describe('DocumentMigrator', () => { attributes: {}, migrationVersion: {}, }; + migrator.prepareMigrations(); const migratedDoc = migrator.migrate(originalDoc); expect(_.get(originalDoc, 'attributes.name')).toBeUndefined(); expect(_.get(migratedDoc, 'attributes.name')).toBe('Mike'); @@ -156,6 +193,7 @@ describe('DocumentMigrator', () => { }, }), }); + migrator.prepareMigrations(); const actual = migrator.migrate({ id: 'me', type: 'user', @@ -196,6 +234,7 @@ describe('DocumentMigrator', () => { } ), }); + migrator.prepareMigrations(); const actual = migrator.migrate({ id: 'me', type: 'user', @@ -233,6 +272,7 @@ describe('DocumentMigrator', () => { } ), }); + migrator.prepareMigrations(); const actual = migrator.migrate({ id: 'me', type: 'user', @@ -263,6 +303,7 @@ describe('DocumentMigrator', () => { }, }), }); + migrator.prepareMigrations(); const actual = migrator.migrate({ id: 'smelly', type: 'dog', @@ -282,6 +323,7 @@ describe('DocumentMigrator', () => { ...testOpts(), kibanaVersion: '8.0.1', }); + migrator.prepareMigrations(); expect(() => migrator.migrate({ id: 'smelly', @@ -304,6 +346,7 @@ describe('DocumentMigrator', () => { }, }), }); + migrator.prepareMigrations(); expect(() => migrator.migrate({ id: 'fleabag', @@ -329,6 +372,7 @@ describe('DocumentMigrator', () => { }, }), }); + migrator.prepareMigrations(); const actual = migrator.migrate({ id: 'smelly', type: 'dog', @@ -361,6 +405,7 @@ describe('DocumentMigrator', () => { } ), }); + migrator.prepareMigrations(); const actual = migrator.migrate({ id: 'smelly', type: 'dog', @@ -396,6 +441,7 @@ describe('DocumentMigrator', () => { } ), }); + migrator.prepareMigrations(); const actual = migrator.migrate({ id: 'smelly', type: 'foo', @@ -430,6 +476,7 @@ describe('DocumentMigrator', () => { } ), }); + migrator.prepareMigrations(); const actual = migrator.migrate({ id: 'smelly', type: 'dog', @@ -454,6 +501,7 @@ describe('DocumentMigrator', () => { }, }), }); + migrator.prepareMigrations(); expect(() => migrator.migrate({ @@ -477,6 +525,7 @@ describe('DocumentMigrator', () => { }, }), }); + migrator.prepareMigrations(); expect(() => migrator.migrate({ id: 'smelly', @@ -506,6 +555,7 @@ describe('DocumentMigrator', () => { }, }), }); + migrator.prepareMigrations(); const actual = migrator.migrate({ id: 'smelly', type: 'cat', @@ -530,6 +580,7 @@ describe('DocumentMigrator', () => { }, }), }); + migrator.prepareMigrations(); const actual = migrator.migrate({ id: 'smelly', type: 'cat', @@ -565,6 +616,7 @@ describe('DocumentMigrator', () => { migrationVersion: {}, }; try { + migrator.prepareMigrations(); migrator.migrate(_.cloneDeep(failedDoc)); expect('Did not throw').toEqual('But it should have!'); } catch (error) { @@ -597,13 +649,14 @@ describe('DocumentMigrator', () => { attributes: {}, migrationVersion: {}, }; + migrator.prepareMigrations(); migrator.migrate(doc); expect(loggingSystemMock.collect(mockLoggerFactory).info[0][0]).toEqual(logTestMsg); expect(loggingSystemMock.collect(mockLoggerFactory).warn[1][0]).toEqual(logTestMsg); }); test('extracts the latest migration version info', () => { - const { migrationVersion } = new DocumentMigrator({ + const migrator = new DocumentMigrator({ ...testOpts(), typeRegistry: createRegistry( { @@ -624,7 +677,8 @@ describe('DocumentMigrator', () => { ), }); - expect(migrationVersion).toEqual({ + migrator.prepareMigrations(); + expect(migrator.migrationVersion).toEqual({ aaa: '10.4.0', bbb: '3.2.3', }); diff --git a/src/core/server/saved_objects/migrations/core/document_migrator.ts b/src/core/server/saved_objects/migrations/core/document_migrator.ts index f30ec4634fb7a4..9e89f5967b511c 100644 --- a/src/core/server/saved_objects/migrations/core/document_migrator.ts +++ b/src/core/server/saved_objects/migrations/core/document_migrator.ts @@ -69,7 +69,7 @@ import { SavedObjectUnsanitizedDoc } from '../../serialization'; import { SavedObjectsMigrationVersion } from '../../types'; import { MigrationLogger } from './migration_logger'; import { ISavedObjectTypeRegistry } from '../../saved_objects_type_registry'; -import { SavedObjectMigrationFn } from '../types'; +import { SavedObjectMigrationFn, SavedObjectMigrationMap } from '../types'; export type TransformFn = (doc: SavedObjectUnsanitizedDoc) => SavedObjectUnsanitizedDoc; @@ -94,6 +94,7 @@ interface ActiveMigrations { */ export interface VersionedTransformer { migrationVersion: SavedObjectsMigrationVersion; + prepareMigrations: () => void; migrate: TransformFn; } @@ -101,8 +102,9 @@ export interface VersionedTransformer { * A concrete implementation of the VersionedTransformer interface. */ export class DocumentMigrator implements VersionedTransformer { - private migrations: ActiveMigrations; - private transformDoc: TransformFn; + private documentMigratorOptions: DocumentMigratorOptions; + private migrations?: ActiveMigrations; + private transformDoc?: TransformFn; /** * Creates an instance of DocumentMigrator. @@ -115,12 +117,7 @@ export class DocumentMigrator implements VersionedTransformer { */ constructor({ typeRegistry, kibanaVersion, log }: DocumentMigratorOptions) { validateMigrationDefinition(typeRegistry); - - this.migrations = buildActiveMigrations(typeRegistry, log); - this.transformDoc = buildDocumentTransform({ - kibanaVersion, - migrations: this.migrations, - }); + this.documentMigratorOptions = { typeRegistry, kibanaVersion, log }; } /** @@ -131,9 +128,28 @@ export class DocumentMigrator implements VersionedTransformer { * @memberof DocumentMigrator */ public get migrationVersion(): SavedObjectsMigrationVersion { + if (!this.migrations) { + throw new Error('Migrations are not ready. Make sure prepareMigrations is called first.'); + } return _.mapValues(this.migrations, ({ latestVersion }) => latestVersion); } + /** + * Prepares active migrations and document transformer function. + * + * @returns {void} + * @memberof DocumentMigrator + */ + + public prepareMigrations = () => { + const { typeRegistry, kibanaVersion, log } = this.documentMigratorOptions; + this.migrations = buildActiveMigrations(typeRegistry, log); + this.transformDoc = buildDocumentTransform({ + kibanaVersion, + migrations: this.migrations, + }); + }; + /** * Migrates a document to the latest version. * @@ -142,6 +158,10 @@ export class DocumentMigrator implements VersionedTransformer { * @memberof DocumentMigrator */ public migrate = (doc: SavedObjectUnsanitizedDoc): SavedObjectUnsanitizedDoc => { + if (!this.migrations || !this.transformDoc) { + throw new Error('Migrations are not ready. Make sure prepareMigrations is called first.'); + } + // Clone the document to prevent accidental mutations on the original data // Ex: Importing sample data that is cached at import level, migrations would // execute on mutated data the second time. @@ -150,13 +170,7 @@ export class DocumentMigrator implements VersionedTransformer { }; } -/** - * Basic validation that the migraiton definition matches our expectations. We can't - * rely on TypeScript here, as the caller may be JavaScript / ClojureScript / any compile-to-js - * language. So, this is just to provide a little developer-friendly error messaging. Joi was - * giving weird errors, so we're just doing manual validation. - */ -function validateMigrationDefinition(registry: ISavedObjectTypeRegistry) { +function validateMigrationsMapObject(name: string, migrationsMap?: SavedObjectMigrationMap) { function assertObject(obj: any, prefix: string) { if (!obj || typeof obj !== 'object') { throw new Error(`${prefix} Got ${obj}.`); @@ -177,16 +191,38 @@ function validateMigrationDefinition(registry: ISavedObjectTypeRegistry) { } } + if (migrationsMap) { + assertObject( + migrationsMap, + `Migrations map for type ${name} should be an object like { '2.0.0': (doc) => doc }.` + ); + + Object.entries(migrationsMap).forEach(([version, fn]) => { + assertValidSemver(version, name); + assertValidTransform(fn, version, name); + }); + } +} + +/** + * Basic validation that the migraiton definition matches our expectations. We can't + * rely on TypeScript here, as the caller may be JavaScript / ClojureScript / any compile-to-js + * language. So, this is just to provide a little developer-friendly error messaging. Joi was + * giving weird errors, so we're just doing manual validation. + */ +function validateMigrationDefinition(registry: ISavedObjectTypeRegistry) { + function assertObjectOrFunction(entity: any, prefix: string) { + if (!entity || (typeof entity !== 'function' && typeof entity !== 'object')) { + throw new Error(`${prefix} Got! ${typeof entity}, ${JSON.stringify(entity)}.`); + } + } + registry.getAllTypes().forEach((type) => { if (type.migrations) { - assertObject( + assertObjectOrFunction( type.migrations, - `Migration for type ${type.name} should be an object like { '2.0.0': (doc) => doc }.` + `Migration for type ${type.name} should be an object or a function returning an object like { '2.0.0': (doc) => doc }.` ); - Object.entries(type.migrations).forEach(([version, fn]) => { - assertValidSemver(version, type.name); - assertValidTransform(fn, version, type.name); - }); } }); } @@ -201,11 +237,22 @@ function buildActiveMigrations( typeRegistry: ISavedObjectTypeRegistry, log: Logger ): ActiveMigrations { - return typeRegistry + const typesWithMigrationMaps = typeRegistry .getAllTypes() - .filter((type) => type.migrations && Object.keys(type.migrations).length > 0) + .map((type) => ({ + ...type, + migrationsMap: typeof type.migrations === 'function' ? type.migrations() : type.migrations, + })) + .filter((type) => typeof type.migrationsMap !== 'undefined'); + + typesWithMigrationMaps.forEach((type) => + validateMigrationsMapObject(type.name, type.migrationsMap) + ); + + return typesWithMigrationMaps + .filter((type) => type.migrationsMap && Object.keys(type.migrationsMap).length > 0) .reduce((migrations, type) => { - const transforms = Object.entries(type.migrations!) + const transforms = Object.entries(type.migrationsMap!) .map(([version, transform]) => ({ version, transform: wrapWithTry(version, type.name, transform, log), @@ -220,7 +267,6 @@ function buildActiveMigrations( }; }, {} as ActiveMigrations); } - /** * Creates a function which migrates and validates any document that is passed to it. */ diff --git a/src/core/server/saved_objects/migrations/core/index_migrator.test.ts b/src/core/server/saved_objects/migrations/core/index_migrator.test.ts index 13f771c16bc67b..5d2597483f5fd5 100644 --- a/src/core/server/saved_objects/migrations/core/index_migrator.test.ts +++ b/src/core/server/saved_objects/migrations/core/index_migrator.test.ts @@ -42,6 +42,7 @@ describe('IndexMigrator', () => { documentMigrator: { migrationVersion: {}, migrate: _.identity, + prepareMigrations: jest.fn(), }, serializer: new SavedObjectsSerializer(new SavedObjectTypeRegistry()), }; @@ -326,6 +327,7 @@ describe('IndexMigrator', () => { testOpts.documentMigrator = { migrationVersion: { foo: '1.2.3' }, + prepareMigrations: jest.fn(), migrate: migrateDoc, }; @@ -378,6 +380,7 @@ describe('IndexMigrator', () => { testOpts.documentMigrator = { migrationVersion: { foo: '1.2.3' }, + prepareMigrations: jest.fn(), migrate: migrateDoc, }; diff --git a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts index da4d39f435038f..997945776cfee4 100644 --- a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts +++ b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.mock.ts @@ -32,7 +32,7 @@ const defaultSavedObjectTypes: SavedObjectsType[] = [ name: { type: 'keyword' }, }, }, - migrations: {}, + migrations: () => ({}), }, ]; @@ -56,6 +56,7 @@ const createMigrator = ( runMigrations: jest.fn(), getActiveMappings: jest.fn(), migrateDocument: jest.fn(), + prepareMigrations: jest.fn(), getStatus$: jest.fn( () => new BehaviorSubject({ diff --git a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts index 4248f6fdbeca44..cca78089888964 100644 --- a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts +++ b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts @@ -65,7 +65,53 @@ describe('KibanaMigrator', () => { }); }); + describe('migrateDocument', () => { + it('throws an error if documentMigrator.prepareMigrations is not called previously', () => { + const options = mockOptions(); + const kibanaMigrator = new KibanaMigrator(options); + const doc = {} as any; + expect(() => kibanaMigrator.migrateDocument(doc)).toThrowError( + /Migrations are not ready. Make sure prepareMigrations is called first./i + ); + }); + + it('calls documentMigrator.migrate', () => { + const options = mockOptions(); + const kibanaMigrator = new KibanaMigrator(options); + const mockDocumentMigrator = { migrate: jest.fn() }; + // @ts-expect-error `documentMigrator` is readonly. + kibanaMigrator.documentMigrator = mockDocumentMigrator; + const doc = {} as any; + + expect(() => kibanaMigrator.migrateDocument(doc)).not.toThrowError(); + expect(mockDocumentMigrator.migrate).toBeCalledTimes(1); + }); + }); + describe('runMigrations', () => { + it('throws if prepareMigrations is not called first', async () => { + const options = mockOptions(); + + options.client.cat.templates.mockReturnValue( + elasticsearchClientMock.createSuccessTransportRequestPromise( + { templates: [] }, + { statusCode: 404 } + ) + ); + options.client.indices.get.mockReturnValue( + elasticsearchClientMock.createSuccessTransportRequestPromise({}, { statusCode: 404 }) + ); + options.client.indices.getAlias.mockReturnValue( + elasticsearchClientMock.createSuccessTransportRequestPromise({}, { statusCode: 404 }) + ); + + const migrator = new KibanaMigrator(options); + + expect(() => migrator.runMigrations()).rejects.toThrow( + /Migrations are not ready. Make sure prepareMigrations is called first./i + ); + }); + it('only runs migrations once if called multiple times', async () => { const options = mockOptions(); @@ -84,6 +130,7 @@ describe('KibanaMigrator', () => { const migrator = new KibanaMigrator(options); + migrator.prepareMigrations(); await migrator.runMigrations(); await migrator.runMigrations(); @@ -120,6 +167,8 @@ describe('KibanaMigrator', () => { const migrator = new KibanaMigrator(options); const migratorStatus = migrator.getStatus$().pipe(take(3)).toPromise(); + + migrator.prepareMigrations(); await migrator.runMigrations(); expect(options.client.indices.create).toHaveBeenCalledTimes(3); @@ -145,6 +194,7 @@ describe('KibanaMigrator', () => { const migrator = new KibanaMigrator(options); const migratorStatus = migrator.getStatus$().pipe(take(3)).toPromise(); + migrator.prepareMigrations(); await migrator.runMigrations(); const { status, result } = await migratorStatus; expect(status).toEqual('completed'); @@ -171,6 +221,7 @@ describe('KibanaMigrator', () => { const options = mockV2MigrationOptions(); const migrator = new KibanaMigrator(options); const migratorStatus = migrator.getStatus$().pipe(take(3)).toPromise(); + migrator.prepareMigrations(); await migrator.runMigrations(); // Basic assertions that we're creating and reindexing the expected indices @@ -212,6 +263,7 @@ describe('KibanaMigrator', () => { const options = mockV2MigrationOptions(); const migrator = new KibanaMigrator(options); const migratorStatus = migrator.getStatus$().pipe(take(3)).toPromise(); + migrator.prepareMigrations(); await migrator.runMigrations(); const { status, result } = await migratorStatus; @@ -247,6 +299,7 @@ describe('KibanaMigrator', () => { ); const migrator = new KibanaMigrator(options); + migrator.prepareMigrations(); return expect(migrator.runMigrations()).rejects.toMatchInlineSnapshot( `[Error: Unable to complete saved object migrations for the [.my-index] index: The .my-index alias is pointing to a newer version of Kibana: v8.2.4]` ); @@ -263,7 +316,7 @@ describe('KibanaMigrator', () => { ); const migrator = new KibanaMigrator(options); - + migrator.prepareMigrations(); await expect(migrator.runMigrations()).rejects.toMatchInlineSnapshot(` [Error: Unable to complete saved object migrations for the [.my-index] index. Please check the health of your Elasticsearch cluster and try again. Error: Reindex failed with the following error: {"_tag":"Some","value":{"type":"elatsicsearch_exception","reason":"task failed with an error"}}] diff --git a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts index 12db79a1067ed7..4618802eb24ac3 100644 --- a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts +++ b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts @@ -158,6 +158,10 @@ export class KibanaMigrator { return this.migrationResult; } + public prepareMigrations() { + this.documentMigrator.prepareMigrations(); + } + public getStatus$() { return this.status$.asObservable(); } diff --git a/src/core/server/saved_objects/migrations/types.ts b/src/core/server/saved_objects/migrations/types.ts index 5e55a34193a962..33375cec078d59 100644 --- a/src/core/server/saved_objects/migrations/types.ts +++ b/src/core/server/saved_objects/migrations/types.ts @@ -79,7 +79,7 @@ export interface SavedObjectMigrationContext { * * @example * ```typescript - * const migrations: SavedObjectMigrationMap = { + * const migrationsMap: SavedObjectMigrationMap = { * '1.0.0': migrateToV1, * '2.1.0': migrateToV21 * } diff --git a/src/core/server/saved_objects/saved_objects_service.ts b/src/core/server/saved_objects/saved_objects_service.ts index c34da35a355314..277f94c3cdf2f4 100644 --- a/src/core/server/saved_objects/saved_objects_service.ts +++ b/src/core/server/saved_objects/saved_objects_service.ts @@ -388,6 +388,12 @@ export class SavedObjectsService */ const skipMigrations = this.config.migration.skip || !pluginsInitialized; + /** + * Note: Prepares all migrations maps. If a saved object type was registered with property `migrations` + * of type function; this function will be called to get the type's SavedObjectMigrationMap. + */ + migrator.prepareMigrations(); + if (skipMigrations) { this.logger.warn( 'Skipping Saved Object migrations on startup. Note: Individual documents will still be migrated when read or written.' diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index 309a817d4d04f3..44c290946345cb 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -217,6 +217,7 @@ describe('SavedObjectsRepository', () => { beforeEach(() => { client = elasticsearchClientMock.createElasticsearchClient(); migrator = mockKibanaMigrator.create(); + documentMigrator.prepareMigrations(); migrator.migrateDocument = jest.fn().mockImplementation(documentMigrator.migrate); migrator.runMigrations = async () => ({ status: 'skipped' }); diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index c8f8b47949ca50..6834fff0de78f7 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -245,9 +245,9 @@ export interface SavedObjectsType { */ mappings: SavedObjectsTypeMappingDefinition; /** - * An optional map of {@link SavedObjectMigrationFn | migrations} to be used to migrate the type. + * An optional map of {@link SavedObjectMigrationFn | migrations} or a function returning a map of {@link SavedObjectMigrationFn | migrations} to be used to migrate the type. */ - migrations?: SavedObjectMigrationMap; + migrations?: SavedObjectMigrationMap | (() => SavedObjectMigrationMap); /** * An optional {@link SavedObjectsTypeManagementDefinition | saved objects management section} definition for the type. */ diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 75f1580ceba8e7..905a237090bc54 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2774,7 +2774,7 @@ export interface SavedObjectsType { indexPattern?: string; management?: SavedObjectsTypeManagementDefinition; mappings: SavedObjectsTypeMappingDefinition; - migrations?: SavedObjectMigrationMap; + migrations?: SavedObjectMigrationMap | (() => SavedObjectMigrationMap); name: string; namespaceType: SavedObjectsNamespaceType; } diff --git a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts index c0e39c2a1d9b35..400e5c7f97969f 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts @@ -48,8 +48,7 @@ const commonSchema: MakeSchemaFrom = { }, }; -// These keys obtained by searching for `/application\w*\.register\(/` and checking the value of the attr `id`. -// TODO: Find a way to update these keys automatically. +// There is a test in x-pack/test/usage_collection that validates that the keys in here match all the registered apps export const applicationUsageSchema = { // OSS dashboards: commonSchema, @@ -61,10 +60,12 @@ export const applicationUsageSchema = { short_url_redirect: commonSchema, // It's a forward app so we'll likely never report it timelion: commonSchema, visualize: commonSchema, + error: commonSchema, + status: commonSchema, + kibanaOverview: commonSchema, // X-Pack apm: commonSchema, - csm: commonSchema, canvas: commonSchema, dashboard_mode: commonSchema, // It's a forward app so we'll likely never report it enterpriseSearch: commonSchema, @@ -75,6 +76,7 @@ export const applicationUsageSchema = { metrics: commonSchema, infra: commonSchema, // It's a forward app so we'll likely never report it fleet: commonSchema, + ingestManager: commonSchema, lens: commonSchema, maps: commonSchema, ml: commonSchema, @@ -98,4 +100,5 @@ export const applicationUsageSchema = { siem: commonSchema, space_selector: commonSchema, uptime: commonSchema, + ux: commonSchema, }; diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index e1c369dc003bd7..bed142f165d642 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -719,7 +719,7 @@ } } }, - "apm": { + "error": { "properties": { "appId": { "type": "keyword" @@ -790,7 +790,149 @@ } } }, - "csm": { + "status": { + "properties": { + "appId": { + "type": "keyword" + }, + "viewId": { + "type": "keyword" + }, + "clicks_total": { + "type": "long" + }, + "clicks_7_days": { + "type": "long" + }, + "clicks_30_days": { + "type": "long" + }, + "clicks_90_days": { + "type": "long" + }, + "minutes_on_screen_total": { + "type": "float" + }, + "minutes_on_screen_7_days": { + "type": "float" + }, + "minutes_on_screen_30_days": { + "type": "float" + }, + "minutes_on_screen_90_days": { + "type": "float" + }, + "views": { + "type": "array", + "items": { + "properties": { + "appId": { + "type": "keyword" + }, + "viewId": { + "type": "keyword" + }, + "clicks_total": { + "type": "long" + }, + "clicks_7_days": { + "type": "long" + }, + "clicks_30_days": { + "type": "long" + }, + "clicks_90_days": { + "type": "long" + }, + "minutes_on_screen_total": { + "type": "float" + }, + "minutes_on_screen_7_days": { + "type": "float" + }, + "minutes_on_screen_30_days": { + "type": "float" + }, + "minutes_on_screen_90_days": { + "type": "float" + } + } + } + } + } + }, + "kibanaOverview": { + "properties": { + "appId": { + "type": "keyword" + }, + "viewId": { + "type": "keyword" + }, + "clicks_total": { + "type": "long" + }, + "clicks_7_days": { + "type": "long" + }, + "clicks_30_days": { + "type": "long" + }, + "clicks_90_days": { + "type": "long" + }, + "minutes_on_screen_total": { + "type": "float" + }, + "minutes_on_screen_7_days": { + "type": "float" + }, + "minutes_on_screen_30_days": { + "type": "float" + }, + "minutes_on_screen_90_days": { + "type": "float" + }, + "views": { + "type": "array", + "items": { + "properties": { + "appId": { + "type": "keyword" + }, + "viewId": { + "type": "keyword" + }, + "clicks_total": { + "type": "long" + }, + "clicks_7_days": { + "type": "long" + }, + "clicks_30_days": { + "type": "long" + }, + "clicks_90_days": { + "type": "long" + }, + "minutes_on_screen_total": { + "type": "float" + }, + "minutes_on_screen_7_days": { + "type": "float" + }, + "minutes_on_screen_30_days": { + "type": "float" + }, + "minutes_on_screen_90_days": { + "type": "float" + } + } + } + } + } + }, + "apm": { "properties": { "appId": { "type": "keyword" @@ -1571,6 +1713,77 @@ } } }, + "ingestManager": { + "properties": { + "appId": { + "type": "keyword" + }, + "viewId": { + "type": "keyword" + }, + "clicks_total": { + "type": "long" + }, + "clicks_7_days": { + "type": "long" + }, + "clicks_30_days": { + "type": "long" + }, + "clicks_90_days": { + "type": "long" + }, + "minutes_on_screen_total": { + "type": "float" + }, + "minutes_on_screen_7_days": { + "type": "float" + }, + "minutes_on_screen_30_days": { + "type": "float" + }, + "minutes_on_screen_90_days": { + "type": "float" + }, + "views": { + "type": "array", + "items": { + "properties": { + "appId": { + "type": "keyword" + }, + "viewId": { + "type": "keyword" + }, + "clicks_total": { + "type": "long" + }, + "clicks_7_days": { + "type": "long" + }, + "clicks_30_days": { + "type": "long" + }, + "clicks_90_days": { + "type": "long" + }, + "minutes_on_screen_total": { + "type": "float" + }, + "minutes_on_screen_7_days": { + "type": "float" + }, + "minutes_on_screen_30_days": { + "type": "float" + }, + "minutes_on_screen_90_days": { + "type": "float" + } + } + } + } + } + }, "lens": { "properties": { "appId": { @@ -3203,6 +3416,77 @@ } } } + }, + "ux": { + "properties": { + "appId": { + "type": "keyword" + }, + "viewId": { + "type": "keyword" + }, + "clicks_total": { + "type": "long" + }, + "clicks_7_days": { + "type": "long" + }, + "clicks_30_days": { + "type": "long" + }, + "clicks_90_days": { + "type": "long" + }, + "minutes_on_screen_total": { + "type": "float" + }, + "minutes_on_screen_7_days": { + "type": "float" + }, + "minutes_on_screen_30_days": { + "type": "float" + }, + "minutes_on_screen_90_days": { + "type": "float" + }, + "views": { + "type": "array", + "items": { + "properties": { + "appId": { + "type": "keyword" + }, + "viewId": { + "type": "keyword" + }, + "clicks_total": { + "type": "long" + }, + "clicks_7_days": { + "type": "long" + }, + "clicks_30_days": { + "type": "long" + }, + "clicks_90_days": { + "type": "long" + }, + "minutes_on_screen_total": { + "type": "float" + }, + "minutes_on_screen_7_days": { + "type": "float" + }, + "minutes_on_screen_30_days": { + "type": "float" + }, + "minutes_on_screen_90_days": { + "type": "float" + } + } + } + } + } } } }, diff --git a/test/api_integration/apis/saved_objects/migrations.ts b/test/api_integration/apis/saved_objects/migrations.ts index fa9c2fd1a2d7fe..e15f0a35cb43c7 100644 --- a/test/api_integration/apis/saved_objects/migrations.ts +++ b/test/api_integration/apis/saved_objects/migrations.ts @@ -400,6 +400,8 @@ async function migrateIndex({ log: getLogMock(), }); + documentMigrator.prepareMigrations(); + const migrator = new IndexMigrator({ client: createMigrationEsClient(esClient, getLogMock()), documentMigrator, diff --git a/test/scripts/jenkins_xpack_build_plugins.sh b/test/scripts/jenkins_xpack_build_plugins.sh index 37b63985987884..06e8ce8b2fe599 100755 --- a/test/scripts/jenkins_xpack_build_plugins.sh +++ b/test/scripts/jenkins_xpack_build_plugins.sh @@ -12,5 +12,6 @@ node scripts/build_kibana_platform_plugins \ --scan-dir "$XPACK_DIR/test/plugin_api_integration/plugins" \ --scan-dir "$XPACK_DIR/test/plugin_api_perf/plugins" \ --scan-dir "$XPACK_DIR/test/licensing_plugin/plugins" \ + --scan-dir "$XPACK_DIR/test/usage_collection/plugins" \ --workers 12 \ --verbose diff --git a/vars/prChanges.groovy b/vars/prChanges.groovy index d082672c065a8c..2cc22e73857b03 100644 --- a/vars/prChanges.groovy +++ b/vars/prChanges.groovy @@ -11,8 +11,10 @@ def getSkippablePaths() { /^.ci\/.+\.yml$/, /^.ci\/es-snapshots\//, /^.ci\/pipeline-library\//, + /^.ci\/teamcity\//, /^.ci\/Jenkinsfile_[^\/]+$/, /^\.github\//, + /^\.teamcity\//, /\.md$/, ] } diff --git a/x-pack/plugins/actions/server/actions_config.ts b/x-pack/plugins/actions/server/actions_config.ts index d351d728712d8a..396f59094a2d9b 100644 --- a/x-pack/plugins/actions/server/actions_config.ts +++ b/x-pack/plugins/actions/server/actions_config.ts @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; import { tryCatch, map, mapNullable, getOrElse } from 'fp-ts/lib/Option'; -import { URL } from 'url'; +import url from 'url'; import { curry } from 'lodash'; import { pipe } from 'fp-ts/lib/pipeable'; @@ -23,7 +23,7 @@ export enum EnabledActionTypes { } enum AllowListingField { - url = 'url', + URL = 'url', hostname = 'hostname', } @@ -59,17 +59,17 @@ function disabledActionTypeErrorMessage(actionType: string) { }); } -function isAllowed({ allowedHosts }: ActionsConfig, hostname: string): boolean { +function isAllowed({ allowedHosts }: ActionsConfig, hostname: string | null): boolean { const allowed = new Set(allowedHosts); if (allowed.has(AllowedHosts.Any)) return true; - if (allowed.has(hostname)) return true; + if (hostname && allowed.has(hostname)) return true; return false; } function isHostnameAllowedInUri(config: ActionsConfig, uri: string): boolean { return pipe( - tryCatch(() => new URL(uri)), - map((url) => url.hostname), + tryCatch(() => url.parse(uri)), + map((parsedUrl) => parsedUrl.hostname), mapNullable((hostname) => isAllowed(config, hostname)), getOrElse(() => false) ); @@ -111,7 +111,7 @@ export function getActionsConfigurationUtilities( isRejectUnauthorizedCertificatesEnabled: () => config.rejectUnauthorized, ensureUriAllowed(uri: string) { if (!isUriAllowed(uri)) { - throw new Error(allowListErrorMessage(AllowListingField.url, uri)); + throw new Error(allowListErrorMessage(AllowListingField.URL, uri)); } }, ensureHostnameAllowed(hostname: string) { diff --git a/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts b/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts index f8932fba20edfb..cfac23e624a04e 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/slack.test.ts @@ -117,7 +117,7 @@ describe('validateActionTypeSecrets()', () => { logger: mockedLogger, configurationUtilities: { ...actionsConfigMock.create(), - ensureHostnameAllowed: () => { + ensureUriAllowed: () => { throw new Error(`target hostname is not added to allowedHosts`); }, }, diff --git a/x-pack/plugins/actions/server/builtin_action_types/slack.ts b/x-pack/plugins/actions/server/builtin_action_types/slack.ts index 676c41d87256e7..5d2c5a24b3edd1 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/slack.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/slack.ts @@ -69,7 +69,7 @@ export function getActionType({ }), validate: { secrets: schema.object(secretsSchemaProps, { - validate: curry(valdiateActionTypeConfig)(configurationUtilities), + validate: curry(validateActionTypeConfig)(configurationUtilities), }), params: ParamsSchema, }, @@ -87,13 +87,13 @@ function renderParameterTemplates( }; } -function valdiateActionTypeConfig( +function validateActionTypeConfig( configurationUtilities: ActionsConfigurationUtilities, secretsObject: ActionTypeSecretsType ) { - let url: URL; + const configuredUrl = secretsObject.webhookUrl; try { - url = new URL(secretsObject.webhookUrl); + new URL(configuredUrl); } catch (err) { return i18n.translate('xpack.actions.builtin.slack.slackConfigurationErrorNoHostname', { defaultMessage: 'error configuring slack action: unable to parse host name from webhookUrl', @@ -101,7 +101,7 @@ function valdiateActionTypeConfig( } try { - configurationUtilities.ensureHostnameAllowed(url.hostname); + configurationUtilities.ensureUriAllowed(configuredUrl); } catch (allowListError) { return i18n.translate('xpack.actions.builtin.slack.slackConfigurationError', { defaultMessage: 'error configuring slack action: {message}', diff --git a/x-pack/plugins/actions/server/builtin_action_types/teams.test.ts b/x-pack/plugins/actions/server/builtin_action_types/teams.test.ts index c0e9ce1181b225..4ca25013e9691b 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/teams.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/teams.test.ts @@ -117,7 +117,7 @@ describe('validateActionTypeSecrets()', () => { logger: mockedLogger, configurationUtilities: { ...actionsConfigMock.create(), - ensureHostnameAllowed: () => { + ensureUriAllowed: () => { throw new Error(`target hostname is not added to allowedHosts`); }, }, diff --git a/x-pack/plugins/actions/server/builtin_action_types/teams.ts b/x-pack/plugins/actions/server/builtin_action_types/teams.ts index 76689ba273c81c..857110d2f53c45 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/teams.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/teams.ts @@ -71,9 +71,9 @@ function validateActionTypeConfig( configurationUtilities: ActionsConfigurationUtilities, secretsObject: ActionTypeSecretsType ) { - let url: URL; + const configuredUrl = secretsObject.webhookUrl; try { - url = new URL(secretsObject.webhookUrl); + new URL(configuredUrl); } catch (err) { return i18n.translate('xpack.actions.builtin.teams.teamsConfigurationErrorNoHostname', { defaultMessage: 'error configuring teams action: unable to parse host name from webhookUrl', @@ -81,7 +81,7 @@ function validateActionTypeConfig( } try { - configurationUtilities.ensureHostnameAllowed(url.hostname); + configurationUtilities.ensureUriAllowed(configuredUrl); } catch (allowListError) { return i18n.translate('xpack.actions.builtin.teams.teamsConfigurationError', { defaultMessage: 'error configuring teams action: {message}', diff --git a/x-pack/plugins/actions/server/builtin_action_types/webhook.ts b/x-pack/plugins/actions/server/builtin_action_types/webhook.ts index 991012d7e0c1e3..05c38a2b336375 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/webhook.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/webhook.ts @@ -112,9 +112,9 @@ function validateActionTypeConfig( configurationUtilities: ActionsConfigurationUtilities, configObject: ActionTypeConfigType ) { - let url: URL; + const configuredUrl = configObject.url; try { - url = new URL(configObject.url); + new URL(configuredUrl); } catch (err) { return i18n.translate('xpack.actions.builtin.webhook.webhookConfigurationErrorNoHostname', { defaultMessage: 'error configuring webhook action: unable to parse url: {err}', @@ -125,7 +125,7 @@ function validateActionTypeConfig( } try { - configurationUtilities.ensureUriAllowed(url.toString()); + configurationUtilities.ensureUriAllowed(configuredUrl); } catch (allowListError) { return i18n.translate('xpack.actions.builtin.webhook.webhookConfigurationError', { defaultMessage: 'error configuring webhook action: {message}', diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/ExternalLinks.ts b/x-pack/plugins/apm/public/components/shared/Links/apm/ExternalLinks.ts index 40b51098c4094a..819c6eafe80b4d 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/ExternalLinks.ts +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/ExternalLinks.ts @@ -3,7 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import url from 'url'; export const getTraceUrl = ({ traceId, @@ -14,8 +13,8 @@ export const getTraceUrl = ({ rangeFrom: string; rangeTo: string; }) => { - return url.format({ - pathname: `/link-to/trace/${traceId}`, - query: { rangeFrom, rangeTo }, - }); + return ( + `/link-to/trace/${traceId}?` + + new URLSearchParams({ rangeFrom, rangeTo }).toString() + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.test.ts index 9410b9ef7cb03a..68c5ef8f8782ab 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/app_logic.test.ts @@ -4,15 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; +import { LogicMounter } from '../__mocks__'; import { DEFAULT_INITIAL_APP_DATA } from '../../../common/__mocks__'; import { AppLogic } from './app_logic'; describe('AppLogic', () => { + const { mount } = new LogicMounter(AppLogic); + beforeEach(() => { - resetContext({}); - AppLogic.mount(); + mount(); }); const DEFAULT_VALUES = { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.test.tsx index d0bbf868aa90c7..6fa230447d5ded 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_flyout/form_components/key_engine_access.test.tsx @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { setMockValues, setMockActions } from '../../../../../__mocks__/kea.mock'; -import { rerender } from '../../../../../__mocks__'; +import { setMockValues, setMockActions, rerender } from '../../../../../__mocks__'; import React from 'react'; import { shallow } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.test.tsx index 39c6abcaab7b34..d327f8112219d7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/paste_json_text.test.tsx @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { setMockValues, setMockActions } from '../../../../__mocks__/kea.mock'; -import { rerender } from '../../../../__mocks__'; +import { setMockValues, setMockActions, rerender } from '../../../../__mocks__'; import React from 'react'; import { shallow } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.test.tsx index a5cb1885d9a042..7b97df23feebef 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/document_creation/creation_mode_components/upload_json_file.test.tsx @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { setMockValues, setMockActions } from '../../../../__mocks__/kea.mock'; -import { rerender } from '../../../../__mocks__'; +import { setMockValues, setMockActions, rerender } from '../../../../__mocks__'; import React from 'react'; import { shallow } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx index dca06988478eab..607b2ce3c0d78f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_detail.test.tsx @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { setMockValues, setMockActions } from '../../../__mocks__/kea.mock'; + import '../../../__mocks__/react_router_history.mock'; +import { setMockValues, setMockActions } from '../../../__mocks__/kea.mock'; import { unmountHandler } from '../../../__mocks__/shallow_useeffect.mock'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.test.tsx index 8940cc259c6476..0a241520940961 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.test.tsx @@ -3,6 +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 { setMockValues } from '../../../__mocks__/kea.mock'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx index 250cd00943d7e4..5df132a27bbb31 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx @@ -3,9 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; -import { setMockValues } from '../../../../__mocks__'; + import '../../../../__mocks__/enterprise_search_url.mock'; +import { setMockValues } from '../../../../__mocks__'; const mockSetFields = jest.fn(); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/paging_view.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/paging_view.test.tsx index 32468c153949f6..6633e844471f4e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/paging_view.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/paging_view.test.tsx @@ -3,6 +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 React from 'react'; import { shallow } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.test.tsx index eea91e475de94b..637f67b63c2553 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/views/results_per_page_view.test.tsx @@ -3,6 +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 React from 'react'; import { shallow } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.test.tsx index 2e419168f2e1bb..95c9beb9b866ed 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_nav.test.tsx @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { setMockValues } from '../../../__mocks__/kea.mock'; -import { rerender } from '../../../__mocks__'; +import { setMockValues, rerender } from '../../../__mocks__'; import React from 'react'; import { shallow } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx index 2cedec3c670b5e..e2d366e5e5817a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx @@ -5,8 +5,7 @@ */ import '../../../__mocks__/shallow_useeffect.mock'; -import { rerender } from '../../../__mocks__'; -import { setMockValues, setMockActions } from '../../../__mocks__/kea.mock'; +import { setMockValues, setMockActions, rerender } from '../../../__mocks__'; import React from 'react'; import { shallow, ShallowWrapper } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx index 973fc6226910a8..6491ee40345970 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result.test.tsx @@ -5,7 +5,6 @@ */ import React from 'react'; - import { shallow, ShallowWrapper } from 'enzyme'; import { EuiPanel } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.test.tsx index 921e2324d39181..4fab1196089cb1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_field.test.tsx @@ -5,7 +5,6 @@ */ import React from 'react'; - import { shallow } from 'enzyme'; import { ResultField } from './result_field'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx index 4ccebb90eb6fec..9aab6fb5d55ce6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header.test.tsx @@ -5,7 +5,6 @@ */ import React from 'react'; - import { shallow } from 'enzyme'; import { ResultHeader } from './result_header'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx index b4368f83b18336..04e6f1d8bf3cd6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result/result_header_item.test.tsx @@ -5,7 +5,6 @@ */ import React from 'react'; - import { mount } from 'enzyme'; import { ResultHeaderItem } from './result_header_item'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_confirmation_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_confirmation_modal.test.tsx index bcda85cd49b9a0..555822622dd3e3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_confirmation_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_confirmation_modal.test.tsx @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; import { setMockActions, setMockValues } from '../../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx index 9140704ece3f82..2c145b2fd535de 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; import '../../../../__mocks__/shallow_useeffect.mock'; - import { setMockActions, setMockValues } from '../../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.test.tsx index 8a51d911803905..e62964bf4ef45b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.test.tsx @@ -3,6 +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 React from 'react'; import { shallow } from 'enzyme'; import { EuiPageContentBody } from '@elastic/eui'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx index 11387734e9f9e3..31007c90ef7ccd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx @@ -5,7 +5,6 @@ */ import '../__mocks__/shallow_useeffect.mock'; -import '../__mocks__/kea.mock'; import '../__mocks__/enterprise_search_url.mock'; import { setMockValues, setMockActions } from '../__mocks__'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx index 8ba2da11604c2c..86eb075d1c6ba8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/components/product_card/product_card.test.tsx @@ -4,11 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../__mocks__/kea.mock'; -import { mockTelemetryActions } from '../../../__mocks__'; +import { setMockValues, mockTelemetryActions } from '../../../__mocks__'; import React from 'react'; -import { useValues } from 'kea'; import { shallow } from 'enzyme'; import { EuiCard } from '@elastic/eui'; @@ -59,7 +57,7 @@ describe('ProductCard', () => { }); it('renders correct button text when host not present', () => { - (useValues as jest.Mock).mockImplementation(() => ({ config: { host: '' } })); + setMockValues({ config: { host: '' } }); const wrapper = shallow(); const card = wrapper.find(EuiCard).dive().shallow(); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx index 7f638c64b445d8..33c5f326b7a803 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search/index.test.tsx @@ -7,8 +7,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { setMockValues } from '../__mocks__/kea.mock'; -import { rerender } from '../__mocks__'; +import { setMockValues, rerender } from '../__mocks__'; import { EnterpriseSearch } from './'; import { SetupGuide } from './components/setup_guide'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status.test.tsx index 42cb6c229ad638..b8e5c8771dd421 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/indexing_status/indexing_status.test.tsx @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../__mocks__/kea.mock'; import '../../__mocks__/shallow_useeffect.mock'; - import { setMockActions, setMockValues } from '../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts index aa74d94837eecb..10491a9bf121d1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.test.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { setMockValues } from '../../__mocks__/kea.mock'; -import { mockKibanaValues, mockHistory } from '../../__mocks__'; +import { setMockValues, mockKibanaValues, mockHistory } from '../../__mocks__'; jest.mock('../react_router_helpers', () => ({ letBrowserHandleEvent: jest.fn(() => false), diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx index dcc04100d85a48..06a77ba275c083 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.test.tsx @@ -5,8 +5,7 @@ */ import '../../__mocks__/shallow_useeffect.mock'; -import { setMockValues } from '../../__mocks__/kea.mock'; -import { mockKibanaValues, mockHistory } from '../../__mocks__'; +import { setMockValues, mockKibanaValues, mockHistory } from '../../__mocks__'; import React from 'react'; import { shallow } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx index 083173c8e7a4cf..f40de39de0b55f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx @@ -4,10 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../__mocks__/kea.mock'; +import { setMockValues } from '../../__mocks__/kea.mock'; import React from 'react'; -import { useValues } from 'kea'; import { shallow } from 'enzyme'; import { EuiButton as EuiButtonExternal, EuiEmptyPrompt } from '@elastic/eui'; @@ -45,7 +44,7 @@ describe('NotFound', () => { }); it('changes the support URL if the user has a gold+ license', () => { - (useValues as jest.Mock).mockReturnValueOnce({ hasGoldLicense: true }); + setMockValues({ hasGoldLicense: true }); const wrapper = shallow(); const prompt = wrapper.find(EuiEmptyPrompt).dive().shallow(); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/setup_guide.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/setup_guide.test.tsx index 748f4b06f7cac6..1968b76a45f2c5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/setup_guide.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/setup_guide/setup_guide.test.tsx @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { setMockValues } from '../../__mocks__/kea.mock'; -import { rerender } from '../../__mocks__'; +import { setMockValues, rerender } from '../../__mocks__'; import React from 'react'; import { shallow, ShallowWrapper } from 'enzyme'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.test.ts index d77faf471facc5..620162113a9b4f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.test.ts @@ -4,15 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; +import { LogicMounter } from '../__mocks__'; import { DEFAULT_INITIAL_APP_DATA } from '../../../common/__mocks__'; import { AppLogic } from './app_logic'; describe('AppLogic', () => { + const { mount } = new LogicMounter(AppLogic); + beforeEach(() => { - resetContext({}); - AppLogic.mount(); + mount(); }); const DEFAULT_VALUES = { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx index 20b15bcfc45ca5..b5a6d5fc1e2f56 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx @@ -5,7 +5,6 @@ */ import '../__mocks__/shallow_useeffect.mock'; -import '../__mocks__/kea.mock'; import { setMockValues, setMockActions, mockKibanaValues } from '../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_list.test.tsx index 184cd7ad48643f..c6a2a07708ff6f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_list.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_list.test.tsx @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../../__mocks__/kea.mock'; import '../../../../../__mocks__/shallow_useeffect.mock'; - import { setMockActions, setMockValues } from '../../../../../__mocks__'; import { contentSources, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts index 1cd7da56dbe73d..d08f807691c2be 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source_logic.test.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; - import { + LogicMounter, mockFlashMessageHelpers, mockHttpValues, expectedAsyncError, @@ -30,6 +29,7 @@ import { } from './add_source_logic'; describe('AddSourceLogic', () => { + const { mount } = new LogicMounter(AddSourceLogic); const { http } = mockHttpValues; const { clearFlashMessages, flashAPIErrors } = mockFlashMessageHelpers; @@ -71,8 +71,7 @@ describe('AddSourceLogic', () => { beforeEach(() => { jest.clearAllMocks(); - resetContext({}); - AddSourceLogic.mount(); + mount(); }); it('has expected default values', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/available_sources_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/available_sources_list.test.tsx index bb024178ea2fba..00ea5922a56c67 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/available_sources_list.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/available_sources_list.test.tsx @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../../__mocks__/kea.mock'; import '../../../../../__mocks__/shallow_useeffect.mock'; - import { setMockValues } from '../../../../../__mocks__'; import { mergedAvailableSources } from '../../../../__mocks__/content_sources.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_custom.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_custom.test.tsx index 45c0e0eb9d2a12..52ab3cefaffee1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_custom.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_custom.test.tsx @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../../__mocks__/kea.mock'; import '../../../../../__mocks__/shallow_useeffect.mock'; - import { setMockActions, setMockValues } from '../../../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_oauth.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_oauth.test.tsx index 37cf516f1791b3..9c19f32e48f1f9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_oauth.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configure_oauth.test.tsx @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../../__mocks__/kea.mock'; import '../../../../../__mocks__/shallow_useeffect.mock'; - import { setMockActions, setMockValues } from '../../../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.test.tsx index 43adc0e6817773..91e0f3185f5199 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/connect_instance.test.tsx @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../../__mocks__/kea.mock'; import '../../../../../__mocks__/shallow_useeffect.mock'; - import { setMockActions, setMockValues } from '../../../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/re_authenticate.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/re_authenticate.test.tsx index 583e52b62d67bd..cab6a754c58ea1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/re_authenticate.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/re_authenticate.test.tsx @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../../__mocks__/kea.mock'; import '../../../../../__mocks__/shallow_useeffect.mock'; - import { setMockActions, setMockValues } from '../../../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_config.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_config.test.tsx index c92427035646c8..29e2c438b5c842 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_config.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/save_config.test.tsx @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../../__mocks__/kea.mock'; import '../../../../../__mocks__/shallow_useeffect.mock'; - import { setMockActions, setMockValues } from '../../../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.test.tsx index f5bcfe1354c0a5..7f497a508bba32 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/source_features.test.tsx @@ -4,9 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../../__mocks__/kea.mock'; -import '../../../../../__mocks__/shallow_useeffect.mock'; - import { mountAsync, setMockValues } from '../../../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/add_group_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/add_group_modal.test.tsx index 59216126a23724..b0ddc8d3896c13 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/add_group_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/add_group_modal.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockValues, setMockActions } from '../../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/clear_filters_link.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/clear_filters_link.test.tsx index 6a781f52c9e958..a9c4ca22af6bf8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/clear_filters_link.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/clear_filters_link.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockActions } from '../../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_list.test.tsx index 07fae45b6b7141..b607834ab7d26e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_list.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_list.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { users } from '../../../__mocks__/users.mock'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_popover.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_popover.test.tsx index 215a0e3eecdd81..2fdbb77c11b250 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_popover.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/filterable_users_popover.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockActions } from '../../../../__mocks__'; import { users } from '../../../__mocks__/users.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_manager_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_manager_modal.test.tsx index 2826d740d53397..3644def0ce8ad1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_manager_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_manager_modal.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockValues } from '../../../../__mocks__'; import { groups } from '../../../__mocks__/groups.mock'; import { contentSources } from '../../../__mocks__/content_sources.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.test.tsx index 74dee238ee826b..e0bda91cb0c8aa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockActions, setMockValues } from '../../../../__mocks__'; import { groups } from '../../../__mocks__/groups.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.test.tsx index c7eea8ab64d453..5bfdf8f9248222 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockValues } from '../../../../__mocks__'; import { groups } from '../../../__mocks__/groups.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_sources_dropdown.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_sources_dropdown.test.tsx index 9493e52e08b815..560c616d61f09c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_sources_dropdown.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_sources_dropdown.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { contentSources } from '../../../__mocks__/content_sources.mock'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_users_dropdown.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_users_dropdown.test.tsx index 039a2620f1fd44..7bd66573673748 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_users_dropdown.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row_users_dropdown.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockActions, setMockValues } from '../../../../__mocks__'; import { users } from '../../../__mocks__/users.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_source_prioritization.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_source_prioritization.test.tsx index 367f1862b2bb95..52ab262503a928 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_source_prioritization.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_source_prioritization.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockActions, setMockValues } from '../../../../__mocks__'; import { groups } from '../../../__mocks__/groups.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sources.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sources.test.tsx index 8ab3ace7aed93a..5b5b995c051402 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sources.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sources.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { contentSources } from '../../../__mocks__/content_sources.mock'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sub_nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sub_nav.test.tsx index 7ddecc21c22c44..04caf5c85f1c3c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sub_nav.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_sub_nav.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockValues } from '../../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users.test.tsx index 581486141d0b01..776a6a5e507356 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { users } from '../../../__mocks__/users.mock'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.test.tsx index 479fd5668cf409..b8618b0e3cf809 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockValues } from '../../../../__mocks__'; import { groups } from '../../../__mocks__/groups.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.test.tsx index 38d035cbca9087..a57e272c20589c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockActions, setMockValues } from '../../../../__mocks__'; import { groups } from '../../../__mocks__/groups.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/manage_users_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/manage_users_modal.test.tsx index 34f748e8a7169f..2fca103a9809fd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/manage_users_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/manage_users_modal.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockActions, setMockValues } from '../../../../__mocks__'; import { users } from '../../../__mocks__/users.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/shared_sources_modal.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/shared_sources_modal.test.tsx index 8c5ead2509d9e1..50228ec80563aa 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/shared_sources_modal.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/shared_sources_modal.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockActions, setMockValues } from '../../../../__mocks__'; import { groups } from '../../../__mocks__/groups.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/source_option_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/source_option_item.test.tsx index 8a3901f5462dff..8cb72bf1378a62 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/source_option_item.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/source_option_item.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { contentSources } from '../../../__mocks__/content_sources.mock'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/sources_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/sources_list.test.tsx index 05754f3846bb0c..bc64faa5af03c4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/sources_list.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/sources_list.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { contentSources } from '../../../__mocks__/content_sources.mock'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_sources_dropdown.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_sources_dropdown.test.tsx index e75feb42549298..889f7e55b23b96 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_sources_dropdown.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_sources_dropdown.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockActions, setMockValues } from '../../../../__mocks__'; import { contentSources } from '../../../__mocks__/content_sources.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_users_dropdown.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_users_dropdown.test.tsx index 9d461e06a77ecd..8de10fbf022708 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_users_dropdown.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filter_users_dropdown.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockActions, setMockValues } from '../../../../__mocks__'; import { users } from '../../../__mocks__/users.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.test.tsx index 80662bc0974a16..cee767db40e67b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { setMockActions, setMockValues } from '../../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/user_option_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/user_option_item.test.tsx index 72611f254d01c6..a96cf44a05cdde 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/user_option_item.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/user_option_item.test.tsx @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../../__mocks__/kea.mock'; - import { users } from '../../../__mocks__/users.mock'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts index cfd4c279c6f8c4..e90acd929a9909 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_logic.test.ts @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; - import { + LogicMounter, mockKibanaValues, mockFlashMessageHelpers, mockHttpValues, @@ -20,6 +19,7 @@ import { GroupLogic } from './group_logic'; import { GROUPS_PATH } from '../../routes'; describe('GroupLogic', () => { + const { mount } = new LogicMounter(GroupLogic); const { http } = mockHttpValues; const { navigateToUrl } = mockKibanaValues; const { @@ -37,8 +37,7 @@ describe('GroupLogic', () => { beforeEach(() => { jest.clearAllMocks(); - resetContext({}); - GroupLogic.mount(); + mount(); }); it('has expected default values', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_router.test.tsx index 6f293920fa387d..8cc40b22b2cf55 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/group_router.test.tsx @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../__mocks__/kea.mock'; import '../../../__mocks__/shallow_useeffect.mock'; - import { setMockValues, setMockActions } from '../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx index 85175d156f886b..5412924438ca6f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../__mocks__/kea.mock'; import '../../../__mocks__/shallow_useeffect.mock'; - import { setMockActions, setMockValues } from '../../../__mocks__'; import { groups } from '../../__mocks__/groups.mock'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts index bbeded9207d019..76352a66706500 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_logic.test.ts @@ -4,9 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; +import { + LogicMounter, + mockFlashMessageHelpers, + mockHttpValues, + expectedAsyncError, +} from '../../../__mocks__'; -import { mockFlashMessageHelpers, mockHttpValues, expectedAsyncError } from '../../../__mocks__'; import { DEFAULT_META } from '../../../shared/constants'; import { JSON_HEADER as headers } from '../../../../../common/constants'; @@ -21,6 +25,7 @@ const TIMEOUT = 400; const delay = () => new Promise((resolve) => setTimeout(resolve, TIMEOUT)); describe('GroupsLogic', () => { + const { mount } = new LogicMounter(GroupsLogic); const { http } = mockHttpValues; const { clearFlashMessages, flashAPIErrors } = mockFlashMessageHelpers; @@ -31,8 +36,7 @@ describe('GroupsLogic', () => { beforeEach(() => { jest.clearAllMocks(); - resetContext({}); - GroupsLogic.mount(); + mount(); }); it('has expected default values', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_router.test.tsx index 0b2b1ad05dfd73..c94a75612e72a7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups_router.test.tsx @@ -4,9 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import '../../../__mocks__/kea.mock'; import '../../../__mocks__/shallow_useeffect.mock'; - import { setMockActions } from '../../../__mocks__'; import React from 'react'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.test.ts index fb55d11be1f0fc..a56235caca5ec6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/overview_logic.test.ts @@ -4,20 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -import { resetContext } from 'kea'; - -import { mockHttpValues } from '../../../__mocks__'; +import { LogicMounter, mockHttpValues } from '../../../__mocks__'; import { mockOverviewValues } from './__mocks__'; import { OverviewLogic } from './overview_logic'; describe('OverviewLogic', () => { + const { mount } = new LogicMounter(OverviewLogic); const { http } = mockHttpValues; beforeEach(() => { jest.clearAllMocks(); - resetContext({}); - OverviewLogic.mount(); + mount(); }); it('has expected default values', () => { diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts index d563960fe42847..ff070a7f08bb1c 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts @@ -700,33 +700,60 @@ describe('', () => { describe('searchable snapshot', () => { describe('on cloud', () => { - beforeEach(async () => { - httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('my_policy')]); - httpRequestsMockHelpers.setListNodes({ - isUsingDeprecatedDataRoleConfig: false, - nodesByAttributes: { test: ['123'] }, - nodesByRoles: { data: ['123'] }, - }); - httpRequestsMockHelpers.setListSnapshotRepos({ repositories: ['found-snapshots'] }); + describe('new policy', () => { + beforeEach(async () => { + // simulate creating a new policy + httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('')]); + httpRequestsMockHelpers.setListNodes({ + isUsingDeprecatedDataRoleConfig: false, + nodesByAttributes: { test: ['123'] }, + nodesByRoles: { data: ['123'] }, + }); + httpRequestsMockHelpers.setListSnapshotRepos({ repositories: ['found-snapshots'] }); - await act(async () => { - testBed = await setup({ appServicesContext: { cloud: { isCloudEnabled: true } } }); - }); + await act(async () => { + testBed = await setup({ appServicesContext: { cloud: { isCloudEnabled: true } } }); + }); - const { component } = testBed; - component.update(); + const { component } = testBed; + component.update(); + }); + test('defaults searchable snapshot to true on cloud', async () => { + const { find, actions } = testBed; + await actions.cold.enable(true); + expect( + find('searchableSnapshotField-cold.searchableSnapshotToggle').props()['aria-checked'] + ).toBe(true); + }); }); + describe('existing policy', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('my_policy')]); + httpRequestsMockHelpers.setListNodes({ + isUsingDeprecatedDataRoleConfig: false, + nodesByAttributes: { test: ['123'] }, + nodesByRoles: { data: ['123'] }, + }); + httpRequestsMockHelpers.setListSnapshotRepos({ repositories: ['found-snapshots'] }); - test('correctly sets snapshot repository default to "found-snapshots"', async () => { - const { actions } = testBed; - await actions.cold.enable(true); - await actions.cold.toggleSearchableSnapshot(true); - await actions.savePolicy(); - const latestRequest = server.requests[server.requests.length - 1]; - const request = JSON.parse(JSON.parse(latestRequest.requestBody).body); - expect(request.phases.cold.actions.searchable_snapshot.snapshot_repository).toEqual( - 'found-snapshots' - ); + await act(async () => { + testBed = await setup({ appServicesContext: { cloud: { isCloudEnabled: true } } }); + }); + + const { component } = testBed; + component.update(); + }); + test('correctly sets snapshot repository default to "found-snapshots"', async () => { + const { actions } = testBed; + await actions.cold.enable(true); + await actions.cold.toggleSearchableSnapshot(true); + await actions.savePolicy(); + const latestRequest = server.requests[server.requests.length - 1]; + const request = JSON.parse(JSON.parse(latestRequest.requestBody).body); + expect(request.phases.cold.actions.searchable_snapshot.snapshot_repository).toEqual( + 'found-snapshots' + ); + }); }); }); describe('on non-enterprise license', () => { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx index 3157c0a51accf0..5fa192158fb3b8 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx @@ -51,7 +51,7 @@ export const SearchableSnapshotField: FunctionComponent = ({ phase }) => const { services: { cloud }, } = useKibana(); - const { getUrlForApp, policy, license } = useEditPolicyContext(); + const { getUrlForApp, policy, license, isNewPolicy } = useEditPolicyContext(); const { isUsingSearchableSnapshotInHotPhase, isUsingRollover } = useConfigurationIssues(); const searchableSnapshotPath = `phases.${phase}.actions.searchable_snapshot.snapshot_repository`; @@ -59,15 +59,20 @@ export const SearchableSnapshotField: FunctionComponent = ({ phase }) => const [formData] = useFormData({ watch: searchableSnapshotPath }); const searchableSnapshotRepo = get(formData, searchableSnapshotPath); + const isColdPhase = phase === 'cold'; const isDisabledDueToLicense = !license.canUseSearchableSnapshot(); - const isDisabledInColdDueToHotPhase = phase === 'cold' && isUsingSearchableSnapshotInHotPhase; - const isDisabledInColdDueToRollover = phase === 'cold' && !isUsingRollover; + const isDisabledInColdDueToHotPhase = isColdPhase && isUsingSearchableSnapshotInHotPhase; + const isDisabledInColdDueToRollover = isColdPhase && !isUsingRollover; const isDisabled = isDisabledDueToLicense || isDisabledInColdDueToHotPhase || isDisabledInColdDueToRollover; const [isFieldToggleChecked, setIsFieldToggleChecked] = useState(() => - Boolean(policy.phases[phase]?.actions?.searchable_snapshot?.snapshot_repository) + Boolean( + // New policy on cloud should have searchable snapshot on in cold phase + (isColdPhase && isNewPolicy && cloud?.isCloudEnabled) || + policy.phases[phase]?.actions?.searchable_snapshot?.snapshot_repository + ) ); useEffect(() => { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx index f7b9b1af1ee3a2..3f6eac9b7a8afe 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy_context.tsx @@ -32,7 +32,7 @@ export const EditPolicyContextProvider = ({ return {children}; }; -export const useEditPolicyContext = () => { +export const useEditPolicyContext = (): EditPolicyContextValue => { const ctx = useContext(EditPolicyContext); if (!ctx) { throw new Error('useEditPolicyContext can only be called inside of EditPolicyContext!'); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.scss b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.scss index 6bd6808f17b35f..bf833c4a369325 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.scss +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_editor.scss @@ -15,6 +15,12 @@ column-gap: $euiSizeXL; } +// overrides the .euiListGroupItem display flex. +// The parent container has a column-count property that only works properly with block elements. +.lnsIndexPatternDimensionEditor__operation { + display: block; +} + .lnsIndexPatternDimensionEditor__operation .euiListGroupItem__label { width: 100%; } diff --git a/x-pack/plugins/maps/public/classes/layers/layer_wizard_registry.ts b/x-pack/plugins/maps/public/classes/layers/layer_wizard_registry.ts index aac8afd4f292d6..1fa65d372fe660 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer_wizard_registry.ts +++ b/x-pack/plugins/maps/public/classes/layers/layer_wizard_registry.ts @@ -29,13 +29,18 @@ export type LayerWizard = { checkVisibility?: () => Promise; description: string; disabledReason?: string; + getIsDisabled?: () => Promise | boolean; icon: string | FunctionComponent; - getIsDisabled?: () => boolean; prerequisiteSteps?: Array<{ id: string; label: string }>; renderWizard(renderWizardArguments: RenderWizardArguments): ReactElement; title: string; }; +export type LayerWizardWithMeta = LayerWizard & { + isVisible: boolean; + isDisabled: boolean; +}; + const registry: LayerWizard[] = []; export function registerLayerWizard(layerWizard: LayerWizard) { @@ -43,16 +48,19 @@ export function registerLayerWizard(layerWizard: LayerWizard) { checkVisibility: async () => { return true; }, + getIsDisabled: async () => { + return false; + }, ...layerWizard, }); } -export async function getLayerWizards(): Promise { - const promises = registry.map(async (layerWizard) => { +export async function getLayerWizards(): Promise { + const promises = registry.map(async (layerWizard: LayerWizard) => { return { ...layerWizard, - // @ts-ignore - isVisible: await layerWizard.checkVisibility(), + isVisible: await layerWizard.checkVisibility!(), + isDisabled: await layerWizard.getIsDisabled!(), }; }); return (await Promise.all(promises)).filter(({ isVisible }) => { diff --git a/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts b/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts index b0f09651968302..18591a3aa6d9b7 100644 --- a/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts +++ b/x-pack/plugins/maps/public/classes/layers/load_layer_wizards.ts @@ -37,8 +37,6 @@ export function registerLayerWizards() { // Registration order determines display order registerLayerWizard(uploadLayerWizardConfig); - registerLayerWizard(ObservabilityLayerWizardConfig); - registerLayerWizard(SecurityLayerWizardConfig); // @ts-ignore registerLayerWizard(esDocumentsLayerWizardConfig); // @ts-ignore @@ -62,5 +60,7 @@ export function registerLayerWizards() { registerLayerWizard(wmsLayerWizardConfig); registerLayerWizard(mvtVectorSourceWizardConfig); + registerLayerWizard(ObservabilityLayerWizardConfig); + registerLayerWizard(SecurityLayerWizardConfig); registered = true; } diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/observability_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/observability_layer_wizard.tsx index ddb07a9facee7b..9080b5b820a713 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/observability_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/layers/solution_layers/observability/observability_layer_wizard.tsx @@ -14,14 +14,18 @@ import { getIndexPatternService } from '../../../../kibana_services'; export const ObservabilityLayerWizardConfig: LayerWizard = { categories: [LAYER_WIZARD_CATEGORY.ELASTICSEARCH, LAYER_WIZARD_CATEGORY.SOLUTIONS], - checkVisibility: async () => { + getIsDisabled: async () => { try { await getIndexPatternService().get(APM_INDEX_PATTERN_ID); - return true; - } catch (e) { return false; + } catch (e) { + return true; } }, + disabledReason: i18n.translate('xpack.maps.observability.disabledDesc', { + defaultMessage: + 'Cannot find APM index pattern. To get started with Observably, go to Observability > Overview.', + }), description: i18n.translate('xpack.maps.observability.desc', { defaultMessage: 'APM layers', }), diff --git a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_layer_wizard.tsx b/x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_layer_wizard.tsx index f51aa5b40aa80b..5f9e71a507a93b 100644 --- a/x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_layer_wizard.tsx +++ b/x-pack/plugins/maps/public/classes/layers/solution_layers/security/security_layer_wizard.tsx @@ -13,10 +13,14 @@ import { SecurityLayerTemplate } from './security_layer_template'; export const SecurityLayerWizardConfig: LayerWizard = { categories: [LAYER_WIZARD_CATEGORY.ELASTICSEARCH, LAYER_WIZARD_CATEGORY.SOLUTIONS], - checkVisibility: async () => { + getIsDisabled: async () => { const indexPatterns = await getSecurityIndexPatterns(); - return indexPatterns.length > 0; + return indexPatterns.length === 0; }, + disabledReason: i18n.translate('xpack.maps.security.disabledDesc', { + defaultMessage: + 'Cannot find security index pattern. To get started with Security, go to Security > Overview.', + }), description: i18n.translate('xpack.maps.security.desc', { defaultMessage: 'Security layers', }), diff --git a/x-pack/plugins/maps/public/connected_components/_index.scss b/x-pack/plugins/maps/public/connected_components/_index.scss index 19c11d3fde6624..a1a65796dc94ac 100644 --- a/x-pack/plugins/maps/public/connected_components/_index.scss +++ b/x-pack/plugins/maps/public/connected_components/_index.scss @@ -3,3 +3,4 @@ @import 'widget_overlay/index'; @import 'toolbar_overlay/index'; @import 'mb_map/features_tooltip/index'; +@import 'mb_map/scale_control/index'; diff --git a/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.test.tsx b/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.test.tsx index d64e38cf49deac..9a54d3b9a58cef 100644 --- a/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.test.tsx +++ b/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.test.tsx @@ -23,6 +23,7 @@ describe('LayerWizardSelect', () => { { categories: [LAYER_WIZARD_CATEGORY.ELASTICSEARCH], description: 'mock wizard without icon', + isDisabled: false, renderWizard: () => { return
; }, @@ -31,6 +32,7 @@ describe('LayerWizardSelect', () => { { categories: [LAYER_WIZARD_CATEGORY.SOLUTIONS], description: 'mock wizard with icon', + isDisabled: false, icon: 'logoObservability', renderWizard: () => { return
; diff --git a/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.tsx b/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.tsx index 7870f11530634b..cf733b598a2e9c 100644 --- a/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.tsx +++ b/x-pack/plugins/maps/public/connected_components/add_layer_panel/flyout_body/layer_wizard_select.tsx @@ -19,7 +19,11 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { getLayerWizards, LayerWizard } from '../../../classes/layers/layer_wizard_registry'; +import { + getLayerWizards, + LayerWizard, + LayerWizardWithMeta, +} from '../../../classes/layers/layer_wizard_registry'; import { LAYER_WIZARD_CATEGORY } from '../../../../common/constants'; import './layer_wizard_select.scss'; @@ -30,7 +34,7 @@ interface Props { interface State { activeCategories: LAYER_WIZARD_CATEGORY[]; hasLoadedWizards: boolean; - layerWizards: LayerWizard[]; + layerWizards: LayerWizardWithMeta[]; selectedCategory: LAYER_WIZARD_CATEGORY | null; } @@ -140,19 +144,18 @@ export class LayerWizardSelect extends Component { } const wizardCards = this.state.layerWizards - .filter((layerWizard: LayerWizard) => { + .filter((layerWizard: LayerWizardWithMeta) => { return this.state.selectedCategory ? layerWizard.categories.includes(this.state.selectedCategory!) : true; }) - .map((layerWizard: LayerWizard) => { + .map((layerWizard: LayerWizardWithMeta) => { const icon = layerWizard.icon ? : undefined; const onClick = () => { this.props.onSelect(layerWizard); }; - const isDisabled = layerWizard.getIsDisabled ? layerWizard.getIsDisabled() : false; const card = ( { icon={icon} onClick={onClick} description={layerWizard.description} - isDisabled={isDisabled} + isDisabled={layerWizard.isDisabled} data-test-subj={_.camelCase(layerWizard.title)} /> ); return ( - {isDisabled && layerWizard.disabledReason ? ( + {layerWizard.isDisabled && layerWizard.disabledReason ? ( { + updateMapSetting('showScaleControl', event.target.checked); + }; + return ( @@ -43,6 +47,17 @@ export function DisplayPanel({ settings, updateMapSetting }: Props) { onChange={onBackgroundColorChange} /> + + + + ); } diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/index.ts b/x-pack/plugins/maps/public/connected_components/mb_map/index.ts index a624381781e54e..fd26abdc57f384 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/index.ts +++ b/x-pack/plugins/maps/public/connected_components/mb_map/index.ts @@ -26,6 +26,7 @@ import { getSpatialFiltersLayer, getMapSettings, } from '../../selectors/map_selectors'; +import { getIsFullScreen } from '../../selectors/ui_selectors'; import { getInspectorAdapters } from '../../reducers/non_serializable_instances'; import { MapStoreState } from '../../reducers/store'; @@ -38,6 +39,7 @@ function mapStateToProps(state: MapStoreState) { goto: getGoto(state), inspectorAdapters: getInspectorAdapters(state), scrollZoom: getScrollZoom(state), + isFullScreen: getIsFullScreen(state), }; } diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index 5f6c7369fd23e5..4dc765f1704a0b 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -18,6 +18,7 @@ import { Filter } from 'src/plugins/data/public'; import { ActionExecutionContext, Action } from 'src/plugins/ui_actions/public'; // @ts-expect-error import { DrawControl } from './draw_control'; +import { ScaleControl } from './scale_control'; // @ts-expect-error import { TooltipControl } from './tooltip_control'; import { clampToLatBounds, clampToLonBounds } from '../../../common/elasticsearch_util'; @@ -55,6 +56,7 @@ interface Props { spatialFiltersLayer: ILayer; goto?: Goto | null; inspectorAdapters: Adapters; + isFullScreen: boolean; scrollZoom: boolean; extentChanged: (mapExtentState: MapExtentState) => void; onMapReady: (mapExtentState: MapExtentState) => void; @@ -381,6 +383,7 @@ export class MBMap extends Component { render() { let drawControl; let tooltipControl; + let scaleControl; if (this.state.mbMap) { drawControl = ; tooltipControl = !this.props.settings.disableTooltipControl ? ( @@ -394,6 +397,9 @@ export class MBMap extends Component { renderTooltipContent={this.props.renderTooltipContent} /> ) : null; + scaleControl = this.props.settings.showScaleControl ? ( + + ) : null; } return (
{ data-test-subj="mapContainer" > {drawControl} + {scaleControl} {tooltipControl}
); diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/__snapshots__/scale_control.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/__snapshots__/scale_control.test.tsx.snap new file mode 100644 index 00000000000000..39d51b74bb7ca0 --- /dev/null +++ b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/__snapshots__/scale_control.test.tsx.snap @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`isFullScreen 1`] = ` +
+ ~50 km +
+`; + +exports[`render 1`] = ` +
+ ~50 km +
+`; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/_index.scss b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/_index.scss new file mode 100644 index 00000000000000..264dfe5e24843d --- /dev/null +++ b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/_index.scss @@ -0,0 +1,15 @@ +.mapScaleControl { + position: absolute; + z-index: $euiZLevel1; + left: $euiSizeM; + bottom: $euiSizeM; + pointer-events: none; + color: $euiTextColor; + border-left: 2px solid $euiTextColor; + border-bottom: 2px solid $euiTextColor; + text-align: right; +} + +.mapScaleControlFullScreen { + bottom: $euiSizeL * 2; +} diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/index.ts b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/index.ts new file mode 100644 index 00000000000000..c156421908b6cb --- /dev/null +++ b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/index.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { ScaleControl } from './scale_control'; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/scale_control.test.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/scale_control.test.tsx new file mode 100644 index 00000000000000..d1f1fed77aae1f --- /dev/null +++ b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/scale_control.test.tsx @@ -0,0 +1,67 @@ +/* + * 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 React from 'react'; +import { mount, shallow } from 'enzyme'; +import { ScaleControl } from './scale_control'; +import { LngLat, LngLatBounds, Map as MapboxMap, PointLike } from 'mapbox-gl'; + +const CLIENT_HEIGHT_PIXELS = 1200; +const DISTANCE_METERS = 87653; + +const mockMbMapHandlers: { [key: string]: () => void } = {}; +const mockMBMap = ({ + on: (eventName: string, callback: () => void) => { + mockMbMapHandlers[eventName] = callback; + }, + off: (eventName: string) => { + delete mockMbMapHandlers[eventName]; + }, + getContainer: () => { + return { + clientHeight: CLIENT_HEIGHT_PIXELS, + }; + }, + getZoom: () => { + return 4; + }, + getBounds: () => { + return ({ + getNorth: () => { + return 75; + }, + getSouth: () => { + return -60; + }, + } as unknown) as LngLatBounds; + }, + unproject: (point: PointLike) => { + return ({ + distanceTo: (lngLat: LngLat) => { + return DISTANCE_METERS; + }, + } as unknown) as LngLat; + }, +} as unknown) as MapboxMap; + +test('render', () => { + const component = shallow(); + expect(component).toMatchSnapshot(); +}); + +test('isFullScreen', () => { + const component = shallow(); + expect(component).toMatchSnapshot(); +}); + +test('should un-register all map callbacks on unmount', () => { + const component = mount(); + + expect(Object.keys(mockMbMapHandlers).length).toBe(1); + + component.unmount(); + expect(Object.keys(mockMbMapHandlers).length).toBe(0); +}); diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/scale_control.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/scale_control.tsx new file mode 100644 index 00000000000000..74270baa1ce6a1 --- /dev/null +++ b/x-pack/plugins/maps/public/connected_components/mb_map/scale_control/scale_control.tsx @@ -0,0 +1,121 @@ +/* + * 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 classNames from 'classnames'; +import React, { Component } from 'react'; +import { Map as MapboxMap } from 'mapbox-gl'; +const MAX_WIDTH = 110; + +interface Props { + isFullScreen: boolean; + mbMap: MapboxMap; +} + +interface State { + label: string; + width: number; +} + +function getScaleDistance(value: number) { + const orderOfMagnitude = Math.floor(Math.log10(value)); + const pow10 = Math.pow(10, orderOfMagnitude); + + // reduce value to single order of magnitude to making rounding simple regardless of order of magnitude + const distance = value / pow10; + + if (distance < 1) { + return pow10 * (Math.round(distance * 10) / 10); + } + + // provide easy to multiple round numbers for scale distance so its easy to measure distances longer then the scale + if (distance >= 10) { + return 10 * pow10; + } + + if (distance >= 5) { + return 5 * pow10; + } + + if (distance >= 3) { + return 3 * pow10; + } + + return Math.floor(distance) * pow10; +} + +export class ScaleControl extends Component { + private _isMounted: boolean = false; + + state: State = { label: '', width: 0 }; + + componentDidMount() { + this._isMounted = true; + this.props.mbMap.on('move', this._onUpdate); + this._onUpdate(); + } + + componentWillUnmount() { + this._isMounted = false; + this.props.mbMap.off('move', this._onUpdate); + } + + _onUpdate = () => { + if (!this._isMounted) { + return; + } + const centerHeight = this.props.mbMap.getContainer().clientHeight / 2; + const leftLatLon = this.props.mbMap.unproject([0, centerHeight]); + const rightLatLon = this.props.mbMap.unproject([MAX_WIDTH, centerHeight]); + const maxDistanceMeters = leftLatLon.distanceTo(rightLatLon); + if (maxDistanceMeters >= 1000) { + this._setScale( + maxDistanceMeters / 1000, + i18n.translate('xpack.maps.kilometersAbbr', { + defaultMessage: 'km', + }) + ); + } else { + this._setScale( + maxDistanceMeters, + i18n.translate('xpack.maps.metersAbbr', { + defaultMessage: 'm', + }) + ); + } + }; + + _setScale(maxDistance: number, unit: string) { + const scaleDistance = getScaleDistance(maxDistance); + const zoom = this.props.mbMap.getZoom(); + const bounds = this.props.mbMap.getBounds(); + let label = `${scaleDistance} ${unit}`; + if ( + zoom <= 4 || + (zoom <= 6 && (bounds.getNorth() > 23.5 || bounds.getSouth() < -23.5)) || + (zoom <= 8 && (bounds.getNorth() > 45 || bounds.getSouth() < -45)) + ) { + label = '~' + label; + } + this.setState({ + width: MAX_WIDTH * (scaleDistance / maxDistance), + label, + }); + } + + render() { + return ( +
+ {this.state.label} +
+ ); + } +} diff --git a/x-pack/plugins/maps/public/licensed_features.ts b/x-pack/plugins/maps/public/licensed_features.ts index f709dd529e3754..43a574b5a17c83 100644 --- a/x-pack/plugins/maps/public/licensed_features.ts +++ b/x-pack/plugins/maps/public/licensed_features.ts @@ -36,14 +36,40 @@ export const LICENCED_FEATURES_DETAILS: Record licenseId; export const getIsGoldPlus = () => isGoldPlus; - export const getIsEnterprisePlus = () => isEnterprisePlus; +let licensingPluginStart: LicensingPluginStart; +let initializeLicense: (value: unknown) => void; +const licenseInitialized = new Promise((resolve) => { + initializeLicense = resolve; +}); +export const whenLicenseInitialized = async (): Promise => { + await licenseInitialized; +}; + +export async function setLicensingPluginStart(licensingPlugin: LicensingPluginStart) { + const license = await licensingPlugin.refresh(); + updateLicenseState(license); + + licensingPluginStart = licensingPlugin; + licensingPluginStart.license$.subscribe(updateLicenseState); + + initializeLicense(undefined); +} + +function updateLicenseState(license: ILicense) { + const gold = license.check(APP_ID, 'gold'); + isGoldPlus = gold.state === 'valid'; + + const enterprise = license.check(APP_ID, 'enterprise'); + isEnterprisePlus = enterprise.state === 'valid'; + + licenseId = license.uid; +} + export function registerLicensedFeatures(licensingPlugin: LicensingPluginSetup) { for (const licensedFeature of Object.values(LICENSED_FEATURES)) { licensingPlugin.featureUsage.register( @@ -53,20 +79,6 @@ export function registerLicensedFeatures(licensingPlugin: LicensingPluginSetup) } } -let licensingPluginStart: LicensingPluginStart; -export function setLicensingPluginStart(licensingPlugin: LicensingPluginStart) { - licensingPluginStart = licensingPlugin; - licensingPluginStart.license$.subscribe((license: ILicense) => { - const gold = license.check(APP_ID, 'gold'); - isGoldPlus = gold.state === 'valid'; - - const enterprise = license.check(APP_ID, 'enterprise'); - isEnterprisePlus = enterprise.state === 'valid'; - - licenseId = license.uid; - }); -} - export function notifyLicensedFeatureUsage(licensedFeature: LICENSED_FEATURES) { if (!licensingPluginStart) { // eslint-disable-next-line no-console diff --git a/x-pack/plugins/maps/public/reducers/default_map_settings.ts b/x-pack/plugins/maps/public/reducers/default_map_settings.ts index 37fd19ea5a4776..5e508b37fddee6 100644 --- a/x-pack/plugins/maps/public/reducers/default_map_settings.ts +++ b/x-pack/plugins/maps/public/reducers/default_map_settings.ts @@ -22,6 +22,7 @@ export function getDefaultMapSettings(): MapSettings { browserLocation: { zoom: 2 }, maxZoom: MAX_ZOOM, minZoom: MIN_ZOOM, + showScaleControl: false, showSpatialFilters: true, spatialFiltersAlpa: 0.3, spatialFiltersFillColor: '#DA8B45', diff --git a/x-pack/plugins/maps/public/reducers/map.d.ts b/x-pack/plugins/maps/public/reducers/map.d.ts index da185a190e6dcb..273d1de6fddfe5 100644 --- a/x-pack/plugins/maps/public/reducers/map.d.ts +++ b/x-pack/plugins/maps/public/reducers/map.d.ts @@ -55,6 +55,7 @@ export type MapSettings = { }; maxZoom: number; minZoom: number; + showScaleControl: boolean; showSpatialFilters: boolean; spatialFiltersAlpa: number; spatialFiltersFillColor: string; diff --git a/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts b/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts index 88516aadc339a2..f3c3ec528c034f 100644 --- a/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts +++ b/x-pack/plugins/maps/public/routes/map_page/saved_map/saved_map.ts @@ -45,6 +45,7 @@ import { copyPersistentState } from '../../../reducers/util'; import { getBreadcrumbs } from './get_breadcrumbs'; import { DEFAULT_IS_LAYER_TOC_OPEN } from '../../../reducers/ui'; import { createBasemapLayerDescriptor } from '../../../classes/layers/create_basemap_layer_descriptor'; +import { whenLicenseInitialized } from '../../../licensed_features'; export class SavedMap { private _attributes: MapSavedObjectAttributes | null = null; @@ -87,6 +88,8 @@ export class SavedMap { } async whenReady() { + await whenLicenseInitialized(); + if (!this._mapEmbeddableInput) { this._attributes = { title: '', diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/constants.ts b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/constants.ts index 95ec298e2e3496..7fae1fc74d6575 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/constants.ts +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/constants.ts @@ -13,3 +13,6 @@ export const SIDEBAR_GROW_SIZE = 2; // Axis height // NOTE: This isn't a perfect solution - changes in font size etc within charts could change the ideal height here. export const FIXED_AXIS_HEIGHT = 32; + +// number of items to display in canvas, since canvas can only have limited size +export const CANVAS_MAX_ITEMS = 150; diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.tsx index 8479ee5cae195b..592e49740b5f0e 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/middle_truncated_text.tsx @@ -7,6 +7,7 @@ import React, { useMemo } from 'react'; import styled from 'styled-components'; import { EuiScreenReaderOnly, EuiToolTip } from '@elastic/eui'; +import { FIXED_AXIS_HEIGHT } from './constants'; const OuterContainer = styled.div` width: 100%; @@ -29,10 +30,12 @@ const FirstChunk = styled.span` text-overflow: ellipsis; white-space: nowrap; overflow: hidden; + line-height: ${FIXED_AXIS_HEIGHT}px; `; const LastChunk = styled.span` flex-shrink: 0; + line-height: ${FIXED_AXIS_HEIGHT}px; `; export const getChunks = (text: string) => { diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/sidebar.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/sidebar.tsx index c551561d5ad4f4..7493cfef8b70af 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/sidebar.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/sidebar.tsx @@ -6,7 +6,7 @@ import React from 'react'; import { EuiFlexItem } from '@elastic/eui'; -import { SIDEBAR_GROW_SIZE } from './constants'; +import { FIXED_AXIS_HEIGHT, SIDEBAR_GROW_SIZE } from './constants'; import { IWaterfallContext } from '../context/waterfall_chart'; import { WaterfallChartSidebarContainer, @@ -18,14 +18,13 @@ import { WaterfallChartProps } from './waterfall_chart'; interface SidebarProps { items: Required['sidebarItems']; - height: number; render: Required['renderSidebarItem']; } -export const Sidebar: React.FC = ({ items, height, render }) => { +export const Sidebar: React.FC = ({ items, render }) => { return ( - + props.theme.eui.euiZLevel4}; `; interface WaterfallChartSidebarContainer { @@ -54,7 +55,7 @@ interface WaterfallChartSidebarContainer { } export const WaterfallChartSidebarContainer = euiStyled.div` - height: ${(props) => `${props.height - FIXED_AXIS_HEIGHT}px`}; + height: ${(props) => `${props.height}px`}; overflow-y: hidden; `; @@ -76,12 +77,14 @@ export const WaterfallChartSidebarFlexItem = euiStyled(EuiFlexItem)` interface WaterfallChartChartContainer { height: number; + chartIndex: number; } export const WaterfallChartChartContainer = euiStyled.div` width: 100%; - height: ${(props) => `${props.height}px`}; - margin-top: -${FIXED_AXIS_HEIGHT}px; + height: ${(props) => `${props.height + FIXED_AXIS_HEIGHT - 4}px`}; + margin-top: -${FIXED_AXIS_HEIGHT - 4}px; + z-index: ${(props) => Math.round(props.theme.eui.euiZLevel3 / (props.chartIndex + 1))}; `; export const WaterfallChartLegendContainer = euiStyled.div` diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/use_bar_charts.test.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/use_bar_charts.test.tsx new file mode 100644 index 00000000000000..28b74c5affbdf1 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/use_bar_charts.test.tsx @@ -0,0 +1,69 @@ +/* + * 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 { useBarCharts } from './use_bar_charts'; +import { renderHook } from '@testing-library/react-hooks'; +import { IWaterfallContext } from '../context/waterfall_chart'; +import { CANVAS_MAX_ITEMS } from './constants'; + +const generateTestData = (): IWaterfallContext['data'] => { + const numberOfItems = 1000; + + const data: IWaterfallContext['data'] = []; + const testItem = { + x: 0, + y0: 0, + y: 4.345000023022294, + config: { + colour: '#b9a888', + showTooltip: true, + tooltipProps: { value: 'Queued / Blocked: 4.345ms', colour: '#b9a888' }, + }, + }; + + for (let i = 0; i < numberOfItems; i++) { + data.push( + { + ...testItem, + x: i, + }, + { + ...testItem, + x: i, + y0: 7, + y: 25, + } + ); + } + + return data; +}; + +describe('useBarChartsHooks', () => { + it('returns result as expected', () => { + const { result, rerender } = renderHook((props) => useBarCharts(props), { + initialProps: { data: [] as IWaterfallContext['data'] }, + }); + + expect(result.current).toHaveLength(0); + const newData = generateTestData(); + + rerender({ data: newData }); + + // Thousands items will result in 7 Canvas + expect(result.current.length).toBe(7); + + const firstChartItems = result.current[0]; + const lastChartItems = result.current[4]; + + // first chart items last item should be x 199, since we only display 150 items + expect(firstChartItems[firstChartItems.length - 1].x).toBe(CANVAS_MAX_ITEMS - 1); + + // since here are 5 charts, last chart first item should be x 800 + expect(lastChartItems[0].x).toBe(CANVAS_MAX_ITEMS * 4); + expect(lastChartItems[lastChartItems.length - 1].x).toBe(CANVAS_MAX_ITEMS * 5 - 1); + }); +}); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/use_bar_charts.ts b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/use_bar_charts.ts new file mode 100644 index 00000000000000..3345b30f5239f5 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/use_bar_charts.ts @@ -0,0 +1,40 @@ +/* + * 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 { useEffect, useState } from 'react'; +import { IWaterfallContext } from '../context/waterfall_chart'; +import { CANVAS_MAX_ITEMS } from './constants'; + +export interface UseBarHookProps { + data: IWaterfallContext['data']; +} + +export const useBarCharts = ({ data = [] }: UseBarHookProps) => { + const [charts, setCharts] = useState>([]); + + useEffect(() => { + if (data.length > 0) { + let chartIndex = 1; + + const firstCanvasItems = data.filter((item) => item.x <= CANVAS_MAX_ITEMS); + + const chartsN: Array = [firstCanvasItems]; + + data.forEach((item) => { + // Subtract 1 to account for x value starting from 0 + if (item.x === CANVAS_MAX_ITEMS * chartIndex && !chartsN[item.x / CANVAS_MAX_ITEMS]) { + chartsN.push([]); + chartIndex++; + } + chartsN[chartIndex - 1].push(item); + }); + + setCharts(chartsN); + } + }, [data]); + + return charts; +}; diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_chart.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_chart.tsx index 73aaacb6fab584..e937c3d35ec08d 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_chart.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_chart.tsx @@ -33,9 +33,10 @@ import { WaterfallChartTooltip, } from './styles'; import { WaterfallData } from '../types'; -import { BAR_HEIGHT, MAIN_GROW_SIZE, SIDEBAR_GROW_SIZE, FIXED_AXIS_HEIGHT } from './constants'; +import { BAR_HEIGHT, CANVAS_MAX_ITEMS, MAIN_GROW_SIZE, SIDEBAR_GROW_SIZE } from './constants'; import { Sidebar } from './sidebar'; import { Legend } from './legend'; +import { useBarCharts } from './use_bar_charts'; const Tooltip = (tooltipInfo: TooltipInfo) => { const { data, renderTooltipItem } = useWaterfallContext(); @@ -69,20 +70,11 @@ export interface WaterfallChartProps { fullHeight?: boolean; } -const getUniqueBars = (data: WaterfallData) => { - return (data ?? []).reduce>((acc, item) => { - if (!acc.has(item.x)) { - acc.add(item.x); - return acc; - } else { - return acc; - } - }, new Set()); +const getChartHeight = (data: WaterfallData, ind: number): number => { + // We get the last item x(number of bars) and adds 1 to cater for 0 index + return (data[data.length - 1]?.x + 1 - ind * CANVAS_MAX_ITEMS) * BAR_HEIGHT; }; -const getChartHeight = (data: WaterfallData): number => - getUniqueBars(data).size * BAR_HEIGHT + FIXED_AXIS_HEIGHT; - export const WaterfallChart = ({ tickFormat, domain, @@ -94,10 +86,6 @@ export const WaterfallChart = ({ }: WaterfallChartProps) => { const { data, sidebarItems, legendItems } = useWaterfallContext(); - const generatedHeight = useMemo(() => { - return getChartHeight(data); - }, [data]); - const [darkMode] = useUiSetting$('theme:darkMode'); const theme = useMemo(() => { @@ -108,10 +96,8 @@ export const WaterfallChart = ({ const [height, setHeight] = useState(maxHeight); - const shouldRenderSidebar = - sidebarItems && sidebarItems.length > 0 && renderSidebarItem ? true : false; - const shouldRenderLegend = - legendItems && legendItems.length > 0 && renderLegendItem ? true : false; + const shouldRenderSidebar = !!(sidebarItems && sidebarItems.length > 0 && renderSidebarItem); + const shouldRenderLegend = !!(legendItems && legendItems.length > 0 && renderLegendItem); useEffect(() => { if (fullHeight && chartWrapperDivRef.current) { @@ -120,6 +106,8 @@ export const WaterfallChart = ({ } }, [chartWrapperDivRef, fullHeight]); + const chartsToDisplay = useBarCharts({ data }); + return ( <> @@ -174,44 +162,48 @@ export const WaterfallChart = ({ style={{ paddingTop: '10px' }} ref={chartWrapperDivRef} > - {shouldRenderSidebar && ( - - )} + {shouldRenderSidebar && } - - - - - - - - - + {chartsToDisplay.map((chartData, ind) => ( + + + + + + + + + + ))} {shouldRenderLegend && } diff --git a/x-pack/scripts/functional_tests.js b/x-pack/scripts/functional_tests.js index eff3a24a0ff3aa..90c75cd62d6cc3 100644 --- a/x-pack/scripts/functional_tests.js +++ b/x-pack/scripts/functional_tests.js @@ -73,6 +73,7 @@ const onlyNotInCoverageTests = [ require.resolve('../test/saved_object_tagging/functional/config.ts'), require.resolve('../test/saved_object_tagging/api_integration/security_and_spaces/config.ts'), require.resolve('../test/saved_object_tagging/api_integration/tagging_api/config.ts'), + require.resolve('../test/usage_collection/config.ts'), ]; require('../../src/setup_node_env'); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts index 83ad17757f3a6f..24174acef98dc6 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts @@ -114,8 +114,7 @@ export default function slackTest({ getService }: FtrProviderContext) { expect(resp.body).to.eql({ statusCode: 400, error: 'Bad Request', - message: - 'error validating action type secrets: error configuring slack action: target hostname "slack.mynonexistent.com" is not added to the Kibana config xpack.actions.allowedHosts', + message: `error validating action type secrets: error configuring slack action: target url \"http://slack.mynonexistent.com/other/stuff/in/the/path\" is not added to the Kibana config xpack.actions.allowedHosts`, }); }); }); diff --git a/x-pack/test/usage_collection/config.ts b/x-pack/test/usage_collection/config.ts new file mode 100644 index 00000000000000..27b12a1ff298c1 --- /dev/null +++ b/x-pack/test/usage_collection/config.ts @@ -0,0 +1,44 @@ +/* + * 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 { resolve } from 'path'; +import fs from 'fs'; +import { FtrConfigProviderContext } from '@kbn/test/types/ftr'; +import { services } from './services'; +import { pageObjects } from './page_objects'; + +// the default export of config files must be a config provider +// that returns an object with the projects config values + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + + // Find all folders in ./plugins since we treat all them as plugin folder + const allFiles = fs.readdirSync(resolve(__dirname, 'plugins')); + const plugins = allFiles.filter((file) => + fs.statSync(resolve(__dirname, 'plugins', file)).isDirectory() + ); + + return { + ...xpackFunctionalConfig.getAll(), + // list paths to the files that contain your plugins tests + testFiles: [resolve(__dirname, './test_suites/application_usage')], + + services, + pageObjects, + + kbnTestServer: { + ...xpackFunctionalConfig.get('kbnTestServer'), + serverArgs: [ + ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), + ...plugins.map((pluginDir) => `--plugin-path=${resolve(__dirname, 'plugins', pluginDir)}`), + ], + }, + + junit: { + reportName: 'X-Pack Usage Collection Functional Tests', + }, + }; +} diff --git a/x-pack/test/usage_collection/ftr_provider_context.d.ts b/x-pack/test/usage_collection/ftr_provider_context.d.ts new file mode 100644 index 00000000000000..271f313d4bda90 --- /dev/null +++ b/x-pack/test/usage_collection/ftr_provider_context.d.ts @@ -0,0 +1,11 @@ +/* + * 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 { GenericFtrProviderContext } from '@kbn/test/types/ftr'; +import { services } from './services'; +import { pageObjects } from './page_objects'; + +export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test/usage_collection/page_objects.ts b/x-pack/test/usage_collection/page_objects.ts new file mode 100644 index 00000000000000..a216b0f2cd47a7 --- /dev/null +++ b/x-pack/test/usage_collection/page_objects.ts @@ -0,0 +1,6 @@ +/* + * 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. + */ +export { pageObjects } from '../functional/page_objects'; diff --git a/x-pack/test/usage_collection/plugins/application_usage_test/kibana.json b/x-pack/test/usage_collection/plugins/application_usage_test/kibana.json new file mode 100644 index 00000000000000..1bff6cb64be1c4 --- /dev/null +++ b/x-pack/test/usage_collection/plugins/application_usage_test/kibana.json @@ -0,0 +1,9 @@ +{ + "id": "applicationUsageTest", + "version": "1.0.0", + "kibanaVersion": "kibana", + "configPath": ["xpack", "applicationUsageTest"], + "requiredPlugins": [], + "server": false, + "ui": true +} diff --git a/x-pack/test/usage_collection/plugins/application_usage_test/public/index.ts b/x-pack/test/usage_collection/plugins/application_usage_test/public/index.ts new file mode 100644 index 00000000000000..83e72770884b17 --- /dev/null +++ b/x-pack/test/usage_collection/plugins/application_usage_test/public/index.ts @@ -0,0 +1,11 @@ +/* + * 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 { ApplicationUsageTest } from './plugin'; + +export function plugin() { + return new ApplicationUsageTest(); +} diff --git a/x-pack/test/usage_collection/plugins/application_usage_test/public/plugin.ts b/x-pack/test/usage_collection/plugins/application_usage_test/public/plugin.ts new file mode 100644 index 00000000000000..5df673d94da192 --- /dev/null +++ b/x-pack/test/usage_collection/plugins/application_usage_test/public/plugin.ts @@ -0,0 +1,18 @@ +/* + * 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 { Plugin, CoreSetup, CoreStart } from 'kibana/public'; +import { first } from 'rxjs/operators'; +import './types'; + +export class ApplicationUsageTest implements Plugin { + public setup(core: CoreSetup) {} + + public async start(core: CoreStart) { + const applications = await core.application.applications$.pipe(first()).toPromise(); + window.__applicationIds__ = [...applications.keys()]; + } +} diff --git a/x-pack/test/usage_collection/plugins/application_usage_test/public/types.ts b/x-pack/test/usage_collection/plugins/application_usage_test/public/types.ts new file mode 100644 index 00000000000000..5282b2fbdeb525 --- /dev/null +++ b/x-pack/test/usage_collection/plugins/application_usage_test/public/types.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export {}; // Hack to declare this file as a module so TS allows us to extend the Global Window interface + +declare global { + interface Window { + __applicationIds__: string[]; + } +} diff --git a/x-pack/test/usage_collection/plugins/application_usage_test/tsconfig.json b/x-pack/test/usage_collection/plugins/application_usage_test/tsconfig.json new file mode 100644 index 00000000000000..f1bf94a38de8fd --- /dev/null +++ b/x-pack/test/usage_collection/plugins/application_usage_test/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "./target", + "skipLibCheck": true + }, + "include": [ + "public/**/*.ts", + "public/**/*.tsx", + ], + "exclude": [] +} diff --git a/x-pack/test/usage_collection/services.ts b/x-pack/test/usage_collection/services.ts new file mode 100644 index 00000000000000..5c807720b2867c --- /dev/null +++ b/x-pack/test/usage_collection/services.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { services } from '../functional/services'; diff --git a/x-pack/test/usage_collection/test_suites/application_usage/index.ts b/x-pack/test/usage_collection/test_suites/application_usage/index.ts new file mode 100644 index 00000000000000..84a9dccc397ccb --- /dev/null +++ b/x-pack/test/usage_collection/test_suites/application_usage/index.ts @@ -0,0 +1,28 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; +import { applicationUsageSchema } from '../../../../../src/plugins/kibana_usage_collection/server/collectors/application_usage/schema'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + describe('Application Usage', function () { + this.tags('ciGroup1'); + const { common } = getPageObjects(['common']); + const browser = getService('browser'); + + it('keys in the schema match the registered application IDs', async () => { + await common.navigateToApp('home'); // Navigate to Home to make sure all the appIds are loaded + const appIds = await browser.execute(() => window.__applicationIds__); + try { + expect(Object.keys(applicationUsageSchema).sort()).to.eql(appIds.sort()); + } catch (err) { + err.message = `Application Usage's schema is not up-to-date with the actual registered apps. Please update it at src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts.\n${err.message}`; + throw err; + } + }); + }); +} diff --git a/yarn.lock b/yarn.lock index d8ea1d34b193ab..d1d39c0a37d249 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4528,10 +4528,10 @@ resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== -"@types/archiver@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@types/archiver/-/archiver-3.1.0.tgz#0d5bd922ba5cf06e137cd6793db7942439b1805e" - integrity sha512-nTvHwgWONL+iXG+9CX+gnQ/tTOV+qucAjwpXqeUn4OCRMxP42T29FFP/7XaOo0EqqO3TlENhObeZEe7RUJAriw== +"@types/archiver@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/archiver/-/archiver-5.1.0.tgz#869f4ce4028e49cf9a0243cf914415f4cc3d1f3d" + integrity sha512-baFOhanb/hxmcOd1Uey2TfFg43kTSmM6py1Eo7Rjbv/ivcl7PXLhY0QgXGf50Hx/eskGCFqPfhs/7IZLb15C5g== dependencies: "@types/glob" "*" @@ -7126,18 +7126,18 @@ archiver-utils@^2.1.0: normalize-path "^3.0.0" readable-stream "^2.0.0" -archiver@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-3.1.1.tgz#9db7819d4daf60aec10fe86b16cb9258ced66ea0" - integrity sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg== +archiver@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.2.0.tgz#25aa1b3d9febf7aec5b0f296e77e69960c26db94" + integrity sha512-QEAKlgQuAtUxKeZB9w5/ggKXh21bZS+dzzuQ0RPBC20qtDCbTyzqmisoeJP46MP39fg4B4IcyvR+yeyEBdblsQ== dependencies: archiver-utils "^2.1.0" - async "^2.6.3" + async "^3.2.0" buffer-crc32 "^0.2.1" - glob "^7.1.4" - readable-stream "^3.4.0" - tar-stream "^2.1.0" - zip-stream "^2.1.2" + readable-stream "^3.6.0" + readdir-glob "^1.0.0" + tar-stream "^2.1.4" + zip-stream "^4.0.4" archy@^1.0.0: version "1.0.0" @@ -7538,7 +7538,7 @@ async@^1.4.2, async@~1.5.2: resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= -async@^2.1.4, async@^2.6.1, async@^2.6.2, async@^2.6.3: +async@^2.1.4, async@^2.6.1, async@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== @@ -8812,7 +8812,7 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.0.2, buffer@^5.1.0, buffer@^5.2.0, buffer@^5.5.0: +buffer@^5.0.2, buffer@^5.2.0, buffer@^5.5.0: version "5.6.0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== @@ -9930,15 +9930,15 @@ component-emitter@^1.2.0, component-emitter@^1.2.1: resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= -compress-commons@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-2.1.1.tgz#9410d9a534cf8435e3fbbb7c6ce48de2dc2f0610" - integrity sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q== +compress-commons@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-4.0.2.tgz#d6896be386e52f37610cef9e6fa5defc58c31bd7" + integrity sha512-qhd32a9xgzmpfoga1VQEiLEwdKZ6Plnpx5UCgIsf89FSolyJ7WnifY4Gtjgv5WR6hWAyRaHxC5MiEhU/38U70A== dependencies: buffer-crc32 "^0.2.13" - crc32-stream "^3.0.1" + crc32-stream "^4.0.1" normalize-path "^3.0.0" - readable-stream "^2.3.6" + readable-stream "^3.6.0" compressible@~2.0.16: version "2.0.17" @@ -10331,20 +10331,21 @@ cpy@^8.1.1: p-filter "^2.1.0" p-map "^3.0.0" -crc32-stream@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-3.0.1.tgz#cae6eeed003b0e44d739d279de5ae63b171b4e85" - integrity sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w== +crc-32@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" + integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== dependencies: - crc "^3.4.4" - readable-stream "^3.4.0" + exit-on-epipe "~1.0.1" + printj "~1.1.0" -crc@^3.4.4: - version "3.8.0" - resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6" - integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ== +crc32-stream@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-4.0.1.tgz#0f047d74041737f8a55e86837a1b826bd8ab0067" + integrity sha512-FN5V+weeO/8JaXsamelVYO1PHyeCsuL3HcG4cqsj0ceARcocxalaShCsohZMSAF+db7UYFwBy1rARK/0oFItUw== dependencies: - buffer "^5.1.0" + crc-32 "^1.2.0" + readable-stream "^3.4.0" create-ecdh@^4.0.0: version "4.0.0" @@ -13165,6 +13166,11 @@ exit-hook@^2.2.0: resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-2.2.0.tgz#f5502f92179018e867f2d8ee4428392da7f3894e" integrity sha512-YFH+2oGdldRH5GqGpnaiKbBxWHMmuXHmKTMtUC58kWSOrnTf95rKITVSFTTtas14DWvWpih429+ffAvFetPwNA== +exit-on-epipe@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" + integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== + exit@^0.1.2, exit@~0.1.1, exit@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -22433,6 +22439,11 @@ pretty-ms@5.0.0: dependencies: parse-ms "^2.1.0" +printj@~1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" + integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== + prismjs@1.22.0, prismjs@^1.22.0, prismjs@~1.22.0: version "1.22.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.22.0.tgz#73c3400afc58a823dd7eed023f8e1ce9fd8977fa" @@ -23818,6 +23829,13 @@ readable-stream@~2.0.0: string_decoder "~0.10.x" util-deprecate "~1.0.1" +readdir-glob@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.1.tgz#f0e10bb7bf7bfa7e0add8baffdc54c3f7dbee6c4" + integrity sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA== + dependencies: + minimatch "^3.0.4" + readdir-scoped-modules@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747" @@ -26795,7 +26813,7 @@ tar-fs@^2.1.0: pump "^3.0.0" tar-stream "^2.0.0" -tar-stream@^2.0.0, tar-stream@^2.1.0: +tar-stream@^2.0.0: version "2.1.3" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.3.tgz#1e2022559221b7866161660f118255e20fa79e41" integrity sha512-Z9yri56Dih8IaK8gncVPx4Wqt86NDmQTSh49XLZgjWpGZL9GK9HKParS2scqHCC4w6X9Gh2jwaU45V47XTKwVA== @@ -30064,14 +30082,14 @@ zen-observable@^0.8.0: resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.8.tgz#1ea93995bf098754a58215a1e0a7309e5749ec42" integrity sha512-HnhhyNnwTFzS48nihkCZIJGsWGFcYUz+XPDlPK5W84Ifji8SksC6m7sQWOf8zdCGhzQ4tDYuMYGu5B0N1dXTtg== -zip-stream@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-2.1.2.tgz#841efd23214b602ff49c497cba1a85d8b5fbc39c" - integrity sha512-ykebHGa2+uzth/R4HZLkZh3XFJzivhVsjJt8bN3GvBzLaqqrUdRacu+c4QtnUgjkkQfsOuNE1JgLKMCPNmkKgg== +zip-stream@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.0.4.tgz#3a8f100b73afaa7d1ae9338d910b321dec77ff3a" + integrity sha512-a65wQ3h5gcQ/nQGWV1mSZCEzCML6EK/vyVPcrPNynySP1j3VBbQKh3nhC8CbORb+jfl2vXvh56Ul5odP1bAHqw== dependencies: archiver-utils "^2.1.0" - compress-commons "^2.1.1" - readable-stream "^3.4.0" + compress-commons "^4.0.2" + readable-stream "^3.6.0" zlib@^1.0.5: version "1.0.5"