From 63cfffbe11c09388e600e67bafbd0aed3e893ece Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Wed, 19 Feb 2020 15:16:58 -0500 Subject: [PATCH] Embeddable add panel examples (#57319) * Embeddable add panel examples * add tests * Fix type error after merge * address code review comments Co-authored-by: Elastic Machine --- .../multi_task_todo_embeddable_factory.ts | 15 +- examples/embeddable_examples/public/plugin.ts | 29 +++- .../public/todo/todo_embeddable_factory.ts | 40 ----- .../public/todo/todo_embeddable_factory.tsx | 92 ++++++++++ examples/embeddable_explorer/kibana.json | 2 +- examples/embeddable_explorer/public/app.tsx | 69 +++++--- .../public/embeddable_panel_example.tsx | 164 ++++++++++++++++++ .../public/list_container_example.tsx | 11 +- .../embeddable_explorer/public/plugin.tsx | 27 ++- src/plugins/embeddable/public/api/types.ts | 5 +- test/examples/config.js | 7 + test/examples/embeddables/adding_children.ts | 43 +++++ test/examples/embeddables/index.ts | 1 + test/examples/embeddables/list_container.ts | 2 +- 14 files changed, 428 insertions(+), 79 deletions(-) delete mode 100644 examples/embeddable_examples/public/todo/todo_embeddable_factory.ts create mode 100644 examples/embeddable_examples/public/todo/todo_embeddable_factory.tsx create mode 100644 examples/embeddable_explorer/public/embeddable_panel_example.tsx create mode 100644 test/examples/embeddables/adding_children.ts diff --git a/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_embeddable_factory.ts b/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_embeddable_factory.ts index 37ac63e380f9..a54201b157a6 100644 --- a/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_embeddable_factory.ts +++ b/examples/embeddable_examples/public/multi_task_todo/multi_task_todo_embeddable_factory.ts @@ -23,9 +23,13 @@ import { MultiTaskTodoEmbeddable, MULTI_TASK_TODO_EMBEDDABLE, MultiTaskTodoInput, + MultiTaskTodoOutput, } from './multi_task_todo_embeddable'; -export class MultiTaskTodoEmbeddableFactory extends EmbeddableFactory { +export class MultiTaskTodoEmbeddableFactory extends EmbeddableFactory< + MultiTaskTodoInput, + MultiTaskTodoOutput +> { public readonly type = MULTI_TASK_TODO_EMBEDDABLE; public isEditable() { @@ -36,6 +40,15 @@ export class MultiTaskTodoEmbeddableFactory extends EmbeddableFactory { return new MultiTaskTodoEmbeddable(initialInput, parent); } + /** + * Check out todo_embeddable_factory for a better example that asks for data from + * the user. This just returns default data. That's okay too though, if you want to + * start with default data and expose an "edit" action to modify it. + */ + public async getExplicitInput() { + return { title: 'default title', tasks: ['Im default data'] }; + } + public getDisplayName() { return i18n.translate('embeddableExamples.multiTaskTodo.displayName', { defaultMessage: 'Multi-task todo item', diff --git a/examples/embeddable_examples/public/plugin.ts b/examples/embeddable_examples/public/plugin.ts index e75165bfbef1..b7a4f5c078d5 100644 --- a/examples/embeddable_examples/public/plugin.ts +++ b/examples/embeddable_examples/public/plugin.ts @@ -17,11 +17,20 @@ * under the License. */ -import { IEmbeddableSetup, IEmbeddableStart } from '../../../src/plugins/embeddable/public'; +import { + IEmbeddableSetup, + IEmbeddableStart, + EmbeddableFactory, +} from '../../../src/plugins/embeddable/public'; import { Plugin, CoreSetup, CoreStart } from '../../../src/core/public'; import { HelloWorldEmbeddableFactory, HELLO_WORLD_EMBEDDABLE } from './hello_world'; -import { TODO_EMBEDDABLE, TodoEmbeddableFactory } from './todo'; -import { MULTI_TASK_TODO_EMBEDDABLE, MultiTaskTodoEmbeddableFactory } from './multi_task_todo'; +import { TODO_EMBEDDABLE, TodoEmbeddableFactory, TodoInput, TodoOutput } from './todo'; +import { + MULTI_TASK_TODO_EMBEDDABLE, + MultiTaskTodoEmbeddableFactory, + MultiTaskTodoOutput, + MultiTaskTodoInput, +} from './multi_task_todo'; import { SEARCHABLE_LIST_CONTAINER, SearchableListContainerFactory, @@ -45,12 +54,9 @@ export class EmbeddableExamplesPlugin new HelloWorldEmbeddableFactory() ); - deps.embeddable.registerEmbeddableFactory(TODO_EMBEDDABLE, new TodoEmbeddableFactory()); - - deps.embeddable.registerEmbeddableFactory( - MULTI_TASK_TODO_EMBEDDABLE, - new MultiTaskTodoEmbeddableFactory() - ); + deps.embeddable.registerEmbeddableFactory< + EmbeddableFactory + >(MULTI_TASK_TODO_EMBEDDABLE, new MultiTaskTodoEmbeddableFactory()); } public start(core: CoreStart, deps: EmbeddableExamplesStartDependencies) { @@ -66,6 +72,11 @@ export class EmbeddableExamplesPlugin LIST_CONTAINER, new ListContainerFactory(deps.embeddable.getEmbeddableFactory) ); + + deps.embeddable.registerEmbeddableFactory>( + TODO_EMBEDDABLE, + new TodoEmbeddableFactory(core.overlays.openModal) + ); } public stop() {} diff --git a/examples/embeddable_examples/public/todo/todo_embeddable_factory.ts b/examples/embeddable_examples/public/todo/todo_embeddable_factory.ts deleted file mode 100644 index 386b3f296d99..000000000000 --- a/examples/embeddable_examples/public/todo/todo_embeddable_factory.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; -import { IContainer, EmbeddableFactory } from '../../../../src/plugins/embeddable/public'; -import { TodoEmbeddable, TODO_EMBEDDABLE, TodoInput } from './todo_embeddable'; - -export class TodoEmbeddableFactory extends EmbeddableFactory { - public readonly type = TODO_EMBEDDABLE; - - public isEditable() { - return true; - } - - public async create(initialInput: TodoInput, parent?: IContainer) { - return new TodoEmbeddable(initialInput, parent); - } - - public getDisplayName() { - return i18n.translate('embeddableExamples.todo.displayName', { - defaultMessage: 'Todo item', - }); - } -} diff --git a/examples/embeddable_examples/public/todo/todo_embeddable_factory.tsx b/examples/embeddable_examples/public/todo/todo_embeddable_factory.tsx new file mode 100644 index 000000000000..dd2168bb39ee --- /dev/null +++ b/examples/embeddable_examples/public/todo/todo_embeddable_factory.tsx @@ -0,0 +1,92 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import React, { useState } from 'react'; +import { EuiModalBody } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { OverlayStart } from 'kibana/public'; +import { EuiFieldText } from '@elastic/eui'; +import { EuiButton } from '@elastic/eui'; +import { toMountPoint } from '../../../../src/plugins/kibana_react/public'; +import { IContainer, EmbeddableFactory } from '../../../../src/plugins/embeddable/public'; +import { TodoEmbeddable, TODO_EMBEDDABLE, TodoInput, TodoOutput } from './todo_embeddable'; + +function TaskInput({ onSave }: { onSave: (task: string) => void }) { + const [task, setTask] = useState(''); + return ( + + setTask(e.target.value)} + /> + onSave(task)}> + Save + + + ); +} + +export class TodoEmbeddableFactory extends EmbeddableFactory< + TodoInput, + TodoOutput, + TodoEmbeddable +> { + public readonly type = TODO_EMBEDDABLE; + + constructor(private openModal: OverlayStart['openModal']) { + super(); + } + + public isEditable() { + return true; + } + + public async create(initialInput: TodoInput, parent?: IContainer) { + return new TodoEmbeddable(initialInput, parent); + } + + /** + * This function is used when dynamically creating a new embeddable to add to a + * container. Some input may be inherited from the container, but not all. This can be + * used to collect specific embeddable input that the container will not provide, like + * in this case, the task string. + */ + public async getExplicitInput() { + return new Promise<{ task: string }>(resolve => { + const onSave = (task: string) => resolve({ task }); + const overlay = this.openModal( + toMountPoint( + { + onSave(task); + overlay.close(); + }} + /> + ) + ); + }); + } + + public getDisplayName() { + return i18n.translate('embeddableExamples.todo.displayName', { + defaultMessage: 'Todo item', + }); + } +} diff --git a/examples/embeddable_explorer/kibana.json b/examples/embeddable_explorer/kibana.json index 4ca63e1a3624..6c27bcd39f12 100644 --- a/examples/embeddable_explorer/kibana.json +++ b/examples/embeddable_explorer/kibana.json @@ -5,6 +5,6 @@ "configPath": ["embeddable_explorer"], "server": false, "ui": true, - "requiredPlugins": ["embeddable", "embeddableExamples"], + "requiredPlugins": ["uiActions", "inspector", "embeddable", "embeddableExamples"], "optionalPlugins": [] } diff --git a/examples/embeddable_explorer/public/app.tsx b/examples/embeddable_explorer/public/app.tsx index be27fd04556e..da7e8cc188e3 100644 --- a/examples/embeddable_explorer/public/app.tsx +++ b/examples/embeddable_explorer/public/app.tsx @@ -23,11 +23,21 @@ import { BrowserRouter as Router, Route, withRouter, RouteComponentProps } from import { EuiPage, EuiPageSideBar, EuiSideNav } from '@elastic/eui'; -import { IEmbeddableStart } from 'src/plugins/embeddable/public'; -import { AppMountContext, AppMountParameters, CoreStart } from '../../../src/core/public'; +import { IEmbeddableStart } from '../../../src/plugins/embeddable/public'; +import { UiActionsStart } from '../../../src/plugins/ui_actions/public'; +import { Start as InspectorStartContract } from '../../../src/plugins/inspector/public'; +import { + AppMountContext, + AppMountParameters, + CoreStart, + SavedObjectsStart, + IUiSettingsClient, + OverlayStart, +} from '../../../src/core/public'; import { HelloWorldEmbeddableExample } from './hello_world_embeddable_example'; import { TodoEmbeddableExample } from './todo_embeddable_example'; import { ListContainerExample } from './list_container_example'; +import { EmbeddablePanelExample } from './embeddable_panel_example'; interface PageDef { title: string; @@ -61,15 +71,29 @@ const Nav = withRouter(({ history, navigateToApp, pages }: NavProps) => { ); }); +interface Props { + basename: string; + navigateToApp: CoreStart['application']['navigateToApp']; + embeddableApi: IEmbeddableStart; + uiActionsApi: UiActionsStart; + overlays: OverlayStart; + notifications: CoreStart['notifications']; + inspector: InspectorStartContract; + savedObject: SavedObjectsStart; + uiSettingsClient: IUiSettingsClient; +} + const EmbeddableExplorerApp = ({ basename, navigateToApp, embeddableApi, -}: { - basename: string; - navigateToApp: CoreStart['application']['navigateToApp']; - embeddableApi: IEmbeddableStart; -}) => { + inspector, + uiSettingsClient, + savedObject, + overlays, + uiActionsApi, + notifications, +}: Props) => { const pages: PageDef[] = [ { title: 'Hello world embeddable', @@ -90,6 +114,22 @@ const EmbeddableExplorerApp = ({ id: 'listContainerSection', component: , }, + { + title: 'Dynamically adding children to a container', + id: 'embeddablePanelExamplae', + component: ( + + ), + }, ]; const routes = pages.map((page, i) => ( @@ -108,19 +148,8 @@ const EmbeddableExplorerApp = ({ ); }; -export const renderApp = ( - core: CoreStart, - embeddableApi: IEmbeddableStart, - { appBasePath, element }: AppMountParameters -) => { - ReactDOM.render( - , - element - ); +export const renderApp = (props: Props, element: AppMountParameters['element']) => { + ReactDOM.render(, element); return () => ReactDOM.unmountComponentAtNode(element); }; diff --git a/examples/embeddable_explorer/public/embeddable_panel_example.tsx b/examples/embeddable_explorer/public/embeddable_panel_example.tsx new file mode 100644 index 000000000000..e6687d8563f5 --- /dev/null +++ b/examples/embeddable_explorer/public/embeddable_panel_example.tsx @@ -0,0 +1,164 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useState, useEffect, useRef } from 'react'; +import { + EuiPanel, + EuiPageBody, + EuiPageContent, + EuiPageContentBody, + EuiPageHeader, + EuiPageHeaderSection, + EuiTitle, + EuiText, +} from '@elastic/eui'; +import { EuiSpacer } from '@elastic/eui'; +import { OverlayStart, CoreStart, SavedObjectsStart, IUiSettingsClient } from 'kibana/public'; +import { + GetEmbeddableFactory, + EmbeddablePanel, + IEmbeddableStart, + IEmbeddable, +} from '../../../src/plugins/embeddable/public'; +import { + HELLO_WORLD_EMBEDDABLE, + TODO_EMBEDDABLE, + MULTI_TASK_TODO_EMBEDDABLE, + SEARCHABLE_LIST_CONTAINER, +} from '../../embeddable_examples/public'; +import { UiActionsStart } from '../../../src/plugins/ui_actions/public'; +import { Start as InspectorStartContract } from '../../../src/plugins/inspector/public'; +import { getSavedObjectFinder } from '../../../src/plugins/saved_objects/public'; + +interface Props { + getAllEmbeddableFactories: IEmbeddableStart['getEmbeddableFactories']; + getEmbeddableFactory: GetEmbeddableFactory; + uiActionsApi: UiActionsStart; + overlays: OverlayStart; + notifications: CoreStart['notifications']; + inspector: InspectorStartContract; + savedObject: SavedObjectsStart; + uiSettingsClient: IUiSettingsClient; +} + +export function EmbeddablePanelExample({ + inspector, + notifications, + overlays, + getAllEmbeddableFactories, + getEmbeddableFactory, + uiActionsApi, + savedObject, + uiSettingsClient, +}: Props) { + const searchableInput = { + id: '1', + title: 'My searchable todo list', + panels: { + '1': { + type: HELLO_WORLD_EMBEDDABLE, + explicitInput: { + id: '1', + title: 'Hello', + }, + }, + '2': { + type: TODO_EMBEDDABLE, + explicitInput: { + id: '2', + task: 'Goes out on Wednesdays!', + icon: 'broom', + title: 'Take out the trash', + }, + }, + '3': { + type: MULTI_TASK_TODO_EMBEDDABLE, + explicitInput: { + id: '3', + icon: 'searchProfilerApp', + title: 'Learn more', + tasks: ['Go to school', 'Watch planet earth', 'Read the encyclopedia'], + }, + }, + }, + }; + + const [embeddable, setEmbeddable] = useState(undefined); + + const ref = useRef(false); + + useEffect(() => { + ref.current = true; + if (!embeddable) { + const factory = getEmbeddableFactory(SEARCHABLE_LIST_CONTAINER); + const promise = factory?.create(searchableInput); + if (promise) { + promise.then(e => { + if (ref.current) { + setEmbeddable(e); + } + }); + } + } + return () => { + ref.current = false; + }; + }); + + return ( + + + + +

The embeddable panel component

+
+
+
+ + + + You can render your embeddable inside the EmbeddablePanel component. This adds some + extra rendering and offers a context menu with pluggable actions. Using EmbeddablePanel + to render your embeddable means you get access to the "e;Add panel flyout"e;. + Now you can see how to add embeddables to your container, and how + "e;getExplicitInput"e; is used to grab input not provided by the container. + + + {embeddable ? ( + + ) : ( + Loading... + )} + + + + + +
+ ); +} diff --git a/examples/embeddable_explorer/public/list_container_example.tsx b/examples/embeddable_explorer/public/list_container_example.tsx index 49cfae0d4e45..2c7b12a27d96 100644 --- a/examples/embeddable_explorer/public/list_container_example.tsx +++ b/examples/embeddable_explorer/public/list_container_example.tsx @@ -60,7 +60,7 @@ export function ListContainerExample({ getEmbeddableFactory }: Props) { type: TODO_EMBEDDABLE, explicitInput: { id: '2', - task: 'Goes out on Wenesdays!', + task: 'Goes out on Wednesdays!', icon: 'broom', title: 'Take out the trash', }, @@ -91,7 +91,7 @@ export function ListContainerExample({ getEmbeddableFactory }: Props) { type: TODO_EMBEDDABLE, explicitInput: { id: '2', - task: 'Goes out on Wenesdays!', + task: 'Goes out on Wednesdays!', icon: 'broom', title: 'Take out the trash', }, @@ -102,7 +102,7 @@ export function ListContainerExample({ getEmbeddableFactory }: Props) { id: '3', icon: 'searchProfilerApp', title: 'Learn more', - tasks: ['Go to school', 'Watch planet earth', 'Read the encylopedia'], + tasks: ['Go to school', 'Watch planet earth', 'Read the encyclopedia'], }, }, }, @@ -151,6 +151,11 @@ export function ListContainerExample({ getEmbeddableFactory }: Props) { The first HelloWorldEmbeddable does not emit the hasMatch output variable, so the container chooses to hide it.

+ +

+ Check out the "e;Dynamically adding children"e; section, to see how to add + children to this container, and see it rendered inside an `EmbeddablePanel` component. +

diff --git a/examples/embeddable_explorer/public/plugin.tsx b/examples/embeddable_explorer/public/plugin.tsx index 2576dea0cadb..1294e0c89c9e 100644 --- a/examples/embeddable_explorer/public/plugin.tsx +++ b/examples/embeddable_explorer/public/plugin.tsx @@ -18,17 +18,38 @@ */ import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public'; +import { UiActionsService } from '../../../src/plugins/ui_actions/public'; import { IEmbeddableStart } from '../../../src/plugins/embeddable/public'; +import { Start as InspectorStart } from '../../../src/plugins/inspector/public'; -export class EmbeddableExplorerPlugin implements Plugin { - public setup(core: CoreSetup<{ embeddable: IEmbeddableStart }>) { +interface StartDeps { + uiActions: UiActionsService; + embeddable: IEmbeddableStart; + inspector: InspectorStart; +} + +export class EmbeddableExplorerPlugin implements Plugin { + public setup(core: CoreSetup) { core.application.register({ id: 'embeddableExplorer', title: 'Embeddable explorer', async mount(params: AppMountParameters) { const [coreStart, depsStart] = await core.getStartServices(); const { renderApp } = await import('./app'); - return renderApp(coreStart, depsStart.embeddable, params); + return renderApp( + { + notifications: coreStart.notifications, + inspector: depsStart.inspector, + embeddableApi: depsStart.embeddable, + uiActionsApi: depsStart.uiActions, + basename: params.appBasePath, + uiSettingsClient: coreStart.uiSettings, + savedObject: coreStart.savedObjects, + overlays: coreStart.overlays, + navigateToApp: coreStart.application.navigateToApp, + }, + params.element + ); }, }); } diff --git a/src/plugins/embeddable/public/api/types.ts b/src/plugins/embeddable/public/api/types.ts index 30fa49578541..179d96a4aff8 100644 --- a/src/plugins/embeddable/public/api/types.ts +++ b/src/plugins/embeddable/public/api/types.ts @@ -24,7 +24,10 @@ export interface EmbeddableApi { getEmbeddableFactory: (embeddableFactoryId: string) => EmbeddableFactory; getEmbeddableFactories: GetEmbeddableFactories; // TODO: Make `registerEmbeddableFactory` receive only `factory` argument. - registerEmbeddableFactory: (id: string, factory: EmbeddableFactory) => void; + registerEmbeddableFactory: ( + id: string, + factory: TEmbeddableFactory + ) => void; } export interface EmbeddableDependencies { diff --git a/test/examples/config.js b/test/examples/config.js index d9411be26793..49d75da28607 100644 --- a/test/examples/config.js +++ b/test/examples/config.js @@ -33,6 +33,13 @@ export default async function({ readConfigFile }) { ...functionalConfig.get('services'), ...services, }, + uiSettings: { + defaults: { + 'accessibility:disableAnimations': true, + 'dateFormat:tz': 'UTC', + 'telemetry:optIn': false, + }, + }, pageObjects: functionalConfig.get('pageObjects'), servers: functionalConfig.get('servers'), esTestCluster: functionalConfig.get('esTestCluster'), diff --git a/test/examples/embeddables/adding_children.ts b/test/examples/embeddables/adding_children.ts new file mode 100644 index 000000000000..8f4951b0e22f --- /dev/null +++ b/test/examples/embeddables/adding_children.ts @@ -0,0 +1,43 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { PluginFunctionalProviderContext } from 'test/plugin_functional/services'; + +// eslint-disable-next-line import/no-default-export +export default function({ getService }: PluginFunctionalProviderContext) { + const testSubjects = getService('testSubjects'); + + describe('creating and adding children', () => { + before(async () => { + await testSubjects.click('embeddablePanelExamplae'); + }); + + it('Can create a new child', async () => { + await testSubjects.click('embeddablePanelToggleMenuIcon'); + await testSubjects.click('embeddablePanelAction-ADD_PANEL_ACTION_ID'); + await testSubjects.click('createNew'); + await testSubjects.click('createNew-TODO_EMBEDDABLE'); + await testSubjects.setValue('taskInputField', 'new task'); + await testSubjects.click('createTodoEmbeddable'); + const tasks = await testSubjects.getVisibleTextAll('todoEmbeddableTask'); + expect(tasks).to.eql(['Goes out on Wednesdays!', 'new task']); + }); + }); +} diff --git a/test/examples/embeddables/index.ts b/test/examples/embeddables/index.ts index ff7997b3b01d..8ad0961fcc3b 100644 --- a/test/examples/embeddables/index.ts +++ b/test/examples/embeddables/index.ts @@ -39,5 +39,6 @@ export default function({ loadTestFile(require.resolve('./hello_world_embeddable')); loadTestFile(require.resolve('./todo_embeddable')); loadTestFile(require.resolve('./list_container')); + loadTestFile(require.resolve('./adding_children')); }); } diff --git a/test/examples/embeddables/list_container.ts b/test/examples/embeddables/list_container.ts index 79e613164790..b1b91ad2c37f 100644 --- a/test/examples/embeddables/list_container.ts +++ b/test/examples/embeddables/list_container.ts @@ -45,7 +45,7 @@ export default function({ getService }: PluginFunctionalProviderContext) { expect(text).to.eql(['HELLO WORLD!', 'HELLO WORLD!']); const tasks = await testSubjects.getVisibleTextAll('multiTaskTodoTask'); - expect(tasks).to.eql(['Go to school', 'Watch planet earth', 'Read the encylopedia']); + expect(tasks).to.eql(['Go to school', 'Watch planet earth', 'Read the encyclopedia']); }); });