diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json
index 34509e33bf137..7e86d2f1dc435 100644
--- a/x-pack/.i18nrc.json
+++ b/x-pack/.i18nrc.json
@@ -9,6 +9,7 @@
"xpack.canvas": "legacy/plugins/canvas",
"xpack.crossClusterReplication": "legacy/plugins/cross_cluster_replication",
"xpack.dashboardMode": "legacy/plugins/dashboard_mode",
+ "xpack.endpoint": "plugins/endpoint",
"xpack.features": "plugins/features",
"xpack.fileUpload": "legacy/plugins/file_upload",
"xpack.graph": ["legacy/plugins/graph", "plugins/graph"],
@@ -18,20 +19,20 @@
"xpack.infra": "legacy/plugins/infra",
"xpack.kueryAutocomplete": "legacy/plugins/kuery_autocomplete",
"xpack.lens": "legacy/plugins/lens",
- "xpack.licensing": "plugins/licensing",
"xpack.licenseMgmt": "legacy/plugins/license_management",
- "xpack.maps": "legacy/plugins/maps",
- "xpack.ml": "legacy/plugins/ml",
+ "xpack.licensing": "plugins/licensing",
"xpack.logstash": "legacy/plugins/logstash",
"xpack.main": "legacy/plugins/xpack_main",
+ "xpack.maps": "legacy/plugins/maps",
+ "xpack.ml": "legacy/plugins/ml",
"xpack.monitoring": "legacy/plugins/monitoring",
"xpack.remoteClusters": "legacy/plugins/remote_clusters",
"xpack.reporting": [ "plugins/reporting", "legacy/plugins/reporting" ],
"xpack.rollupJobs": "legacy/plugins/rollup",
"xpack.searchProfiler": "legacy/plugins/searchprofiler",
- "xpack.siem": "legacy/plugins/siem",
"xpack.security": ["legacy/plugins/security", "plugins/security"],
"xpack.server": "legacy/server",
+ "xpack.siem": "legacy/plugins/siem",
"xpack.snapshotRestore": "legacy/plugins/snapshot_restore",
"xpack.spaces": ["legacy/plugins/spaces", "plugins/spaces"],
"xpack.taskManager": "legacy/plugins/task_manager",
diff --git a/x-pack/plugins/endpoint/kibana.json b/x-pack/plugins/endpoint/kibana.json
new file mode 100644
index 0000000000000..a7fd20b93f62d
--- /dev/null
+++ b/x-pack/plugins/endpoint/kibana.json
@@ -0,0 +1,9 @@
+{
+ "id": "endpoint",
+ "version": "1.0.0",
+ "kibanaVersion": "kibana",
+ "configPath": ["xpack", "endpoint"],
+ "requiredPlugins": ["embeddable"],
+ "server": true,
+ "ui": true
+}
diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/embeddable.tsx b/x-pack/plugins/endpoint/public/embeddables/resolver/embeddable.tsx
new file mode 100644
index 0000000000000..55f9fd52f4662
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/embeddables/resolver/embeddable.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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 {
+ EmbeddableInput,
+ IContainer,
+ Embeddable,
+} from '../../../../../../src/plugins/embeddable/public';
+
+export class ResolverEmbeddable extends Embeddable {
+ public readonly type = 'resolver';
+ constructor(initialInput: EmbeddableInput, parent?: IContainer) {
+ super(
+ // Input state is irrelevant to this embeddable, just pass it along.
+ initialInput,
+ // Initial output state - this embeddable does not do anything with output, so just
+ // pass along an empty object.
+ {},
+ // Optional parent component, this embeddable can optionally be rendered inside a container.
+ parent
+ );
+ }
+
+ public render(node: HTMLElement) {
+ node.innerHTML = '
Welcome from Resolver
';
+ }
+
+ public reload(): void {
+ throw new Error('Method not implemented.');
+ }
+}
diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/factory.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/factory.ts
new file mode 100644
index 0000000000000..aef2e309254ef
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/embeddables/resolver/factory.ts
@@ -0,0 +1,31 @@
+/*
+ * 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 { ResolverEmbeddable } from './';
+import {
+ EmbeddableFactory,
+ EmbeddableInput,
+ IContainer,
+} from '../../../../../../src/plugins/embeddable/public';
+
+export class ResolverEmbeddableFactory extends EmbeddableFactory {
+ public readonly type = 'resolver';
+
+ public isEditable() {
+ return true;
+ }
+
+ public async create(initialInput: EmbeddableInput, parent?: IContainer) {
+ return new ResolverEmbeddable(initialInput, parent);
+ }
+
+ public getDisplayName() {
+ return i18n.translate('xpack.endpoint.resolver.displayNameTitle', {
+ defaultMessage: 'Resolver',
+ });
+ }
+}
diff --git a/x-pack/plugins/endpoint/public/embeddables/resolver/index.ts b/x-pack/plugins/endpoint/public/embeddables/resolver/index.ts
new file mode 100644
index 0000000000000..e4f3cc90ae30a
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/embeddables/resolver/index.ts
@@ -0,0 +1,8 @@
+/*
+ * 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 { ResolverEmbeddableFactory } from './factory';
+export { ResolverEmbeddable } from './embeddable';
diff --git a/x-pack/plugins/endpoint/public/index.ts b/x-pack/plugins/endpoint/public/index.ts
new file mode 100644
index 0000000000000..e6a7683efd9a3
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/index.ts
@@ -0,0 +1,21 @@
+/*
+ * 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 { PluginInitializer } from 'kibana/public';
+import {
+ EndpointPlugin,
+ EndpointPluginStart,
+ EndpointPluginSetup,
+ EndpointPluginStartDependencies,
+ EndpointPluginSetupDependencies,
+} from './plugin';
+
+export const plugin: PluginInitializer<
+ EndpointPluginSetup,
+ EndpointPluginStart,
+ EndpointPluginSetupDependencies,
+ EndpointPluginStartDependencies
+> = () => new EndpointPlugin();
diff --git a/x-pack/plugins/endpoint/public/plugin.ts b/x-pack/plugins/endpoint/public/plugin.ts
new file mode 100644
index 0000000000000..21bf1b3cdea12
--- /dev/null
+++ b/x-pack/plugins/endpoint/public/plugin.ts
@@ -0,0 +1,38 @@
+/*
+ * 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 } from 'kibana/public';
+import { IEmbeddableSetup } from 'src/plugins/embeddable/public';
+import { ResolverEmbeddableFactory } from './embeddables/resolver';
+
+export type EndpointPluginStart = void;
+export type EndpointPluginSetup = void;
+export interface EndpointPluginSetupDependencies {
+ embeddable: IEmbeddableSetup;
+}
+
+export interface EndpointPluginStartDependencies {} // eslint-disable-line @typescript-eslint/no-empty-interface
+
+export class EndpointPlugin
+ implements
+ Plugin<
+ EndpointPluginSetup,
+ EndpointPluginStart,
+ EndpointPluginSetupDependencies,
+ EndpointPluginStartDependencies
+ > {
+ public setup(_core: CoreSetup, plugins: EndpointPluginSetupDependencies) {
+ const resolverEmbeddableFactory = new ResolverEmbeddableFactory();
+ plugins.embeddable.registerEmbeddableFactory(
+ resolverEmbeddableFactory.type,
+ resolverEmbeddableFactory
+ );
+ }
+
+ public start() {}
+
+ public stop() {}
+}
diff --git a/x-pack/plugins/endpoint/server/index.ts b/x-pack/plugins/endpoint/server/index.ts
new file mode 100644
index 0000000000000..f10bc7ee51b2c
--- /dev/null
+++ b/x-pack/plugins/endpoint/server/index.ts
@@ -0,0 +1,26 @@
+/*
+ * 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 { schema } from '@kbn/config-schema';
+import { PluginInitializer } from 'src/core/server';
+import {
+ EndpointPlugin,
+ EndpointPluginStart,
+ EndpointPluginSetup,
+ EndpointPluginStartDependencies,
+ EndpointPluginSetupDependencies,
+} from './plugin';
+
+export const config = {
+ schema: schema.object({ enabled: schema.boolean({ defaultValue: false }) }),
+};
+
+export const plugin: PluginInitializer<
+ EndpointPluginStart,
+ EndpointPluginSetup,
+ EndpointPluginStartDependencies,
+ EndpointPluginSetupDependencies
+> = () => new EndpointPlugin();
diff --git a/x-pack/plugins/endpoint/server/plugin.ts b/x-pack/plugins/endpoint/server/plugin.ts
new file mode 100644
index 0000000000000..400b906c5230e
--- /dev/null
+++ b/x-pack/plugins/endpoint/server/plugin.ts
@@ -0,0 +1,30 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { Plugin, CoreSetup } from 'kibana/server';
+import { addRoutes } from './routes';
+
+export type EndpointPluginStart = void;
+export type EndpointPluginSetup = void;
+export interface EndpointPluginSetupDependencies {} // eslint-disable-line @typescript-eslint/no-empty-interface
+
+export interface EndpointPluginStartDependencies {} // eslint-disable-line @typescript-eslint/no-empty-interface
+
+export class EndpointPlugin
+ implements
+ Plugin<
+ EndpointPluginStart,
+ EndpointPluginSetup,
+ EndpointPluginStartDependencies,
+ EndpointPluginSetupDependencies
+ > {
+ public setup(core: CoreSetup) {
+ const router = core.http.createRouter();
+ addRoutes(router);
+ }
+
+ public start() {}
+}
diff --git a/x-pack/plugins/endpoint/server/routes/index.ts b/x-pack/plugins/endpoint/server/routes/index.ts
new file mode 100644
index 0000000000000..517ee2a853660
--- /dev/null
+++ b/x-pack/plugins/endpoint/server/routes/index.ts
@@ -0,0 +1,24 @@
+/*
+ * 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 { IRouter } from 'kibana/server';
+
+export function addRoutes(router: IRouter) {
+ router.get(
+ {
+ path: '/api/endpoint/hello-world',
+ validate: false,
+ },
+ async function greetingIndex(_context, _request, response) {
+ return response.ok({
+ body: { hello: 'world' },
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ }
+ );
+}
diff --git a/x-pack/scripts/functional_tests.js b/x-pack/scripts/functional_tests.js
index e984c23385508..2c21ec4a95ef4 100644
--- a/x-pack/scripts/functional_tests.js
+++ b/x-pack/scripts/functional_tests.js
@@ -16,6 +16,7 @@ require('@kbn/test').runTestsCli([
require.resolve('../test/alerting_api_integration/spaces_only/config.ts'),
require.resolve('../test/alerting_api_integration/security_and_spaces/config.ts'),
require.resolve('../test/plugin_api_integration/config.js'),
+ require.resolve('../test/plugin_functional/config'),
require.resolve('../test/kerberos_api_integration/config'),
require.resolve('../test/kerberos_api_integration/anonymous_access.config'),
require.resolve('../test/saml_api_integration/config'),
diff --git a/x-pack/test/api_integration/apis/endpoint/index.ts b/x-pack/test/api_integration/apis/endpoint/index.ts
new file mode 100644
index 0000000000000..e0ffbb13e5978
--- /dev/null
+++ b/x-pack/test/api_integration/apis/endpoint/index.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.
+ */
+
+import { FtrProviderContext } from '../../ftr_provider_context';
+
+export default function endpointAPIIntegrationTests({ loadTestFile }: FtrProviderContext) {
+ describe('Endpoint plugin', function() {
+ loadTestFile(require.resolve('./resolver'));
+ });
+}
diff --git a/x-pack/test/api_integration/apis/endpoint/resolver.ts b/x-pack/test/api_integration/apis/endpoint/resolver.ts
new file mode 100644
index 0000000000000..96d16e0d76e40
--- /dev/null
+++ b/x-pack/test/api_integration/apis/endpoint/resolver.ts
@@ -0,0 +1,29 @@
+/*
+ * 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';
+
+const commonHeaders = {
+ Accept: 'application/json',
+ 'kbn-xsrf': 'some-xsrf-token',
+};
+
+// eslint-disable-next-line import/no-default-export
+export default function resolverAPIIntegrationTests({ getService }: FtrProviderContext) {
+ const supertest = getService('supertest');
+ describe('Resolver api', function() {
+ it('should respond to hello-world', async function() {
+ const { body } = await supertest
+ .get('/api/endpoint/hello-world')
+ .set(commonHeaders)
+ .expect('Content-Type', /application\/json/)
+ .expect(200);
+
+ expect(body).to.eql({ hello: 'world' });
+ });
+ });
+}
diff --git a/x-pack/test/api_integration/apis/index.js b/x-pack/test/api_integration/apis/index.js
index 0e96a04343b64..5af941dde525f 100644
--- a/x-pack/test/api_integration/apis/index.js
+++ b/x-pack/test/api_integration/apis/index.js
@@ -27,6 +27,7 @@ export default function({ loadTestFile }) {
loadTestFile(require.resolve('./siem'));
loadTestFile(require.resolve('./short_urls'));
loadTestFile(require.resolve('./lens'));
+ loadTestFile(require.resolve('./endpoint'));
loadTestFile(require.resolve('./ml'));
});
}
diff --git a/x-pack/test/api_integration/config.js b/x-pack/test/api_integration/config.js
index 4794a7bee5dfb..6e35a6f31d79b 100644
--- a/x-pack/test/api_integration/config.js
+++ b/x-pack/test/api_integration/config.js
@@ -25,6 +25,7 @@ export async function getApiIntegrationConfig({ readConfigFile }) {
...xPackFunctionalTestsConfig.get('kbnTestServer.serverArgs'),
'--xpack.security.session.idleTimeout=3600000', // 1 hour
'--optimize.enabled=false',
+ '--xpack.endpoint.enabled=true',
],
},
esTestCluster: {
diff --git a/x-pack/test/plugin_functional/config.ts b/x-pack/test/plugin_functional/config.ts
new file mode 100644
index 0000000000000..6c3c496da71f6
--- /dev/null
+++ b/x-pack/test/plugin_functional/config.ts
@@ -0,0 +1,72 @@
+/*
+ * 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
+
+/* eslint-disable import/no-default-export */
+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 {
+ // list paths to the files that contain your plugins tests
+ testFiles: [resolve(__dirname, './test_suites/resolver')],
+
+ services,
+ pageObjects,
+
+ servers: xpackFunctionalConfig.get('servers'),
+
+ esTestCluster: xpackFunctionalConfig.get('esTestCluster'),
+
+ kbnTestServer: {
+ ...xpackFunctionalConfig.get('kbnTestServer'),
+ serverArgs: [
+ ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'),
+ ...plugins.map(pluginDir => `--plugin-path=${resolve(__dirname, 'plugins', pluginDir)}`),
+ // Required to load new platform plugins via `--plugin-path` flag.
+ '--env.name=development',
+ '--xpack.endpoint.enabled=true',
+ ],
+ },
+ uiSettings: xpackFunctionalConfig.get('uiSettings'),
+ // the apps section defines the urls that
+ // `PageObjects.common.navigateTo(appKey)` will use.
+ // Merge urls for your plugin with the urls defined in
+ // Kibana's config in order to use this helper
+ apps: {
+ ...xpackFunctionalConfig.get('apps'),
+ resolverTest: {
+ pathname: '/app/resolver_test',
+ },
+ },
+
+ // choose where esArchiver should load archives from
+ esArchiver: {
+ directory: resolve(__dirname, 'es_archives'),
+ },
+
+ // choose where screenshots should be saved
+ screenshots: {
+ directory: resolve(__dirname, 'screenshots'),
+ },
+
+ junit: {
+ reportName: 'Chrome X-Pack UI Plugin Functional Tests',
+ },
+ };
+}
diff --git a/x-pack/test/plugin_functional/ftr_provider_context.d.ts b/x-pack/test/plugin_functional/ftr_provider_context.d.ts
new file mode 100644
index 0000000000000..271f313d4bda9
--- /dev/null
+++ b/x-pack/test/plugin_functional/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/plugin_functional/page_objects.ts b/x-pack/test/plugin_functional/page_objects.ts
new file mode 100644
index 0000000000000..a216b0f2cd47a
--- /dev/null
+++ b/x-pack/test/plugin_functional/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/plugin_functional/plugins/resolver_test/kibana.json b/x-pack/test/plugin_functional/plugins/resolver_test/kibana.json
new file mode 100644
index 0000000000000..c715a0aaa3b20
--- /dev/null
+++ b/x-pack/test/plugin_functional/plugins/resolver_test/kibana.json
@@ -0,0 +1,9 @@
+{
+ "id": "resolver_test",
+ "version": "1.0.0",
+ "kibanaVersion": "kibana",
+ "configPath": ["xpack", "resolver_test"],
+ "requiredPlugins": ["embeddable"],
+ "server": false,
+ "ui": true
+}
diff --git a/x-pack/test/plugin_functional/plugins/resolver_test/public/applications/resolver_test/index.tsx b/x-pack/test/plugin_functional/plugins/resolver_test/public/applications/resolver_test/index.tsx
new file mode 100644
index 0000000000000..98baad6a18411
--- /dev/null
+++ b/x-pack/test/plugin_functional/plugins/resolver_test/public/applications/resolver_test/index.tsx
@@ -0,0 +1,63 @@
+/*
+ * 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 * as React from 'react';
+import ReactDOM from 'react-dom';
+import { AppMountParameters } from 'kibana/public';
+import { I18nProvider } from '@kbn/i18n/react';
+import { IEmbeddable } from 'src/plugins/embeddable/public';
+import { useEffect } from 'react';
+
+/**
+ * This module will be loaded asynchronously to reduce the bundle size of your plugin's main bundle.
+ */
+export function renderApp(
+ { element }: AppMountParameters,
+ embeddable: Promise
+) {
+ ReactDOM.render(
+
+
+ ,
+ element
+ );
+
+ return () => {
+ ReactDOM.unmountComponentAtNode(element);
+ };
+}
+
+const AppRoot = React.memo(
+ ({ embeddable: embeddablePromise }: { embeddable: Promise }) => {
+ const [embeddable, setEmbeddable] = React.useState(undefined);
+ const [renderTarget, setRenderTarget] = React.useState(null);
+
+ useEffect(() => {
+ let cleanUp;
+ Promise.race([
+ new Promise((_resolve, reject) => {
+ cleanUp = reject;
+ }),
+ embeddablePromise,
+ ]).then(value => {
+ setEmbeddable(value);
+ });
+
+ return cleanUp;
+ }, [embeddablePromise]);
+
+ useEffect(() => {
+ if (embeddable && renderTarget) {
+ embeddable.render(renderTarget);
+ return () => {
+ embeddable.destroy();
+ };
+ }
+ }, [embeddable, renderTarget]);
+
+ return ;
+ }
+);
diff --git a/x-pack/test/plugin_functional/plugins/resolver_test/public/index.ts b/x-pack/test/plugin_functional/plugins/resolver_test/public/index.ts
new file mode 100644
index 0000000000000..c5f3c0e19138f
--- /dev/null
+++ b/x-pack/test/plugin_functional/plugins/resolver_test/public/index.ts
@@ -0,0 +1,10 @@
+/*
+ * 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 { PluginInitializer } from 'kibana/public';
+import { ResolverTestPlugin } from './plugin';
+
+export const plugin: PluginInitializer = () => new ResolverTestPlugin();
diff --git a/x-pack/test/plugin_functional/plugins/resolver_test/public/plugin.ts b/x-pack/test/plugin_functional/plugins/resolver_test/public/plugin.ts
new file mode 100644
index 0000000000000..f063271f4b5dd
--- /dev/null
+++ b/x-pack/test/plugin_functional/plugins/resolver_test/public/plugin.ts
@@ -0,0 +1,53 @@
+/*
+ * 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 } from 'kibana/public';
+import { i18n } from '@kbn/i18n';
+import { IEmbeddable, IEmbeddableStart } from '../../../../../../src/plugins/embeddable/public';
+
+export type ResolverTestPluginSetup = void;
+export type ResolverTestPluginStart = void;
+export interface ResolverTestPluginSetupDependencies {} // eslint-disable-line @typescript-eslint/no-empty-interface
+export interface ResolverTestPluginStartDependencies {
+ embeddable: IEmbeddableStart;
+}
+
+export class ResolverTestPlugin
+ implements
+ Plugin<
+ ResolverTestPluginSetup,
+ ResolverTestPluginStart,
+ ResolverTestPluginSetupDependencies,
+ ResolverTestPluginStartDependencies
+ > {
+ private resolveEmbeddable!: (
+ value: IEmbeddable | undefined | PromiseLike | undefined
+ ) => void;
+ private embeddablePromise: Promise = new Promise<
+ IEmbeddable | undefined
+ >(resolve => {
+ this.resolveEmbeddable = resolve;
+ });
+ public setup(core: CoreSetup) {
+ core.application.register({
+ id: 'resolver_test',
+ title: i18n.translate('xpack.resolver_test.pluginTitle', {
+ defaultMessage: 'Resolver Test',
+ }),
+ mount: async (_context, params) => {
+ const { renderApp } = await import('./applications/resolver_test');
+ return renderApp(params, this.embeddablePromise);
+ },
+ });
+ }
+
+ public start(...args: [unknown, { embeddable: IEmbeddableStart }]) {
+ const [, plugins] = args;
+ const factory = plugins.embeddable.getEmbeddableFactory('resolver');
+ this.resolveEmbeddable(factory.create({ id: 'test basic render' }));
+ }
+ public stop() {}
+}
diff --git a/x-pack/test/plugin_functional/services.ts b/x-pack/test/plugin_functional/services.ts
new file mode 100644
index 0000000000000..5c807720b2867
--- /dev/null
+++ b/x-pack/test/plugin_functional/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/plugin_functional/test_suites/resolver/index.ts b/x-pack/test/plugin_functional/test_suites/resolver/index.ts
new file mode 100644
index 0000000000000..a0735f216e309
--- /dev/null
+++ b/x-pack/test/plugin_functional/test_suites/resolver/index.ts
@@ -0,0 +1,27 @@
+/*
+ * 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 { FtrProviderContext } from '../../ftr_provider_context';
+
+export default function({ getPageObjects, getService }: FtrProviderContext) {
+ const pageObjects = getPageObjects(['common']);
+ const testSubjects = getService('testSubjects');
+
+ describe('Resolver embeddable test app', function() {
+ this.tags('ciGroup7');
+
+ beforeEach(async function() {
+ await pageObjects.common.navigateToApp('resolverTest');
+ });
+
+ it('renders a container div for the embeddable', async function() {
+ await testSubjects.existOrFail('resolverEmbeddableContainer');
+ });
+ it('renders resolver', async function() {
+ await testSubjects.existOrFail('resolverEmbeddable');
+ });
+ });
+}