From c479637f1857044649aa741b01fcbe24c2cc4f27 Mon Sep 17 00:00:00 2001 From: Kristen Tian Date: Tue, 13 Jun 2023 21:27:11 -0700 Subject: [PATCH] add ut --- .../sample_data/data_sets/ecommerce/index.ts | 8 +- .../sample_data/data_sets/flights/index.ts | 8 +- .../sample_data/data_sets/logs/index.ts | 8 +- .../services/sample_data/data_sets/util.ts | 4 + .../lib/sample_dataset_registry_types.ts | 2 +- .../sample_data/routes/install.test.ts | 160 ++++++++++++++++++ .../services/sample_data/routes/install.ts | 8 +- .../services/sample_data/routes/list.test.ts | 122 +++++++++++++ .../services/sample_data/routes/list.ts | 5 +- .../sample_data/routes/uninstall.test.ts | 101 +++++++++++ .../sample_data/sample_data_registry.ts | 4 +- 11 files changed, 409 insertions(+), 21 deletions(-) create mode 100644 src/plugins/home/server/services/sample_data/routes/install.test.ts create mode 100644 src/plugins/home/server/services/sample_data/routes/list.test.ts create mode 100644 src/plugins/home/server/services/sample_data/routes/uninstall.test.ts diff --git a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/index.ts b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/index.ts index 898e4f7f5cba..0321c428cf68 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/index.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/index.ts @@ -33,7 +33,7 @@ import { i18n } from '@osd/i18n'; import { getSavedObjects } from './saved_objects'; import { fieldMappings } from './field_mappings'; import { SampleDatasetSchema, AppLinkSchema } from '../../lib/sample_dataset_registry_types'; -import { getSavedObjectsWithDataSource } from '../util'; +import { getSavedObjectsWithDataSource, appendDataSourceId } from '../util'; const ecommerceName = i18n.translate('home.sampleData.ecommerceSpecTitle', { defaultMessage: 'Sample eCommerce orders', @@ -44,6 +44,7 @@ const ecommerceDescription = i18n.translate('home.sampleData.ecommerceSpecDescri const initialAppLinks = [] as AppLinkSchema[]; const DEFAULT_INDEX = 'ff959d40-b880-11e8-a6d9-e546fe2bba5f'; +const DASHBOARD_ID = '722b74f0-b882-11e8-a6d9-e546fe2bba5f'; export const ecommerceSpecProvider = function (): SampleDatasetSchema { return { @@ -52,10 +53,9 @@ export const ecommerceSpecProvider = function (): SampleDatasetSchema { description: ecommerceDescription, previewImagePath: '/plugins/home/assets/sample_data_resources/ecommerce/dashboard.png', darkPreviewImagePath: '/plugins/home/assets/sample_data_resources/ecommerce/dashboard_dark.png', - overviewDashboard: '722b74f0-b882-11e8-a6d9-e546fe2bba5f', + overviewDashboard: appendDataSourceId(DASHBOARD_ID), appLinks: initialAppLinks, - defaultIndex: (dataSourceId?: string) => - dataSourceId ? `${dataSourceId}_` + DEFAULT_INDEX : DEFAULT_INDEX, + defaultIndex: appendDataSourceId(DEFAULT_INDEX), savedObjects: (dataSourceId?: string, dataSourceTitle?: string) => getSavedObjectsWithDataSource(getSavedObjects(), dataSourceId, dataSourceTitle), dataIndices: [ diff --git a/src/plugins/home/server/services/sample_data/data_sets/flights/index.ts b/src/plugins/home/server/services/sample_data/data_sets/flights/index.ts index e60654107683..038744419f3e 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/flights/index.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/flights/index.ts @@ -33,7 +33,7 @@ import { i18n } from '@osd/i18n'; import { getSavedObjects } from './saved_objects'; import { fieldMappings } from './field_mappings'; import { SampleDatasetSchema, AppLinkSchema } from '../../lib/sample_dataset_registry_types'; -import { getSavedObjectsWithDataSource } from '../util'; +import { getSavedObjectsWithDataSource, appendDataSourceId } from '../util'; const flightsName = i18n.translate('home.sampleData.flightsSpecTitle', { defaultMessage: 'Sample flight data', @@ -44,6 +44,7 @@ const flightsDescription = i18n.translate('home.sampleData.flightsSpecDescriptio const initialAppLinks = [] as AppLinkSchema[]; const DEFAULT_INDEX = 'd3d7af60-4c81-11e8-b3d7-01146121b73d'; +const DASHBOARD_ID = '7adfa750-4c81-11e8-b3d7-01146121b73d'; export const flightsSpecProvider = function (): SampleDatasetSchema { return { @@ -52,10 +53,9 @@ export const flightsSpecProvider = function (): SampleDatasetSchema { description: flightsDescription, previewImagePath: '/plugins/home/assets/sample_data_resources/flights/dashboard.png', darkPreviewImagePath: '/plugins/home/assets/sample_data_resources/flights/dashboard_dark.png', - overviewDashboard: '7adfa750-4c81-11e8-b3d7-01146121b73d', + overviewDashboard: appendDataSourceId(DASHBOARD_ID), appLinks: initialAppLinks, - defaultIndex: (dataSourceId?: string) => - dataSourceId ? `${dataSourceId}_` + DEFAULT_INDEX : DEFAULT_INDEX, + defaultIndex: appendDataSourceId(DEFAULT_INDEX), savedObjects: (dataSourceId?: string, dataSourceTitle?: string) => getSavedObjectsWithDataSource(getSavedObjects(), dataSourceId, dataSourceTitle), dataIndices: [ diff --git a/src/plugins/home/server/services/sample_data/data_sets/logs/index.ts b/src/plugins/home/server/services/sample_data/data_sets/logs/index.ts index c61aeb059b21..e4afabcdd212 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/logs/index.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/logs/index.ts @@ -33,7 +33,7 @@ import { i18n } from '@osd/i18n'; import { getSavedObjects } from './saved_objects'; import { fieldMappings } from './field_mappings'; import { SampleDatasetSchema, AppLinkSchema } from '../../lib/sample_dataset_registry_types'; -import { getSavedObjectsWithDataSource } from '../util'; +import { appendDataSourceId, getSavedObjectsWithDataSource } from '../util'; const logsName = i18n.translate('home.sampleData.logsSpecTitle', { defaultMessage: 'Sample web logs', @@ -44,6 +44,7 @@ const logsDescription = i18n.translate('home.sampleData.logsSpecDescription', { const initialAppLinks = [] as AppLinkSchema[]; const DEFAULT_INDEX = '90943e30-9a47-11e8-b64d-95841ca0b247'; +const DASHBOARD_ID = 'edf84fe0-e1a0-11e7-b6d5-4dc382ef7f5b'; export const logsSpecProvider = function (): SampleDatasetSchema { return { @@ -52,10 +53,9 @@ export const logsSpecProvider = function (): SampleDatasetSchema { description: logsDescription, previewImagePath: '/plugins/home/assets/sample_data_resources/logs/dashboard.png', darkPreviewImagePath: '/plugins/home/assets/sample_data_resources/logs/dashboard_dark.png', - overviewDashboard: 'edf84fe0-e1a0-11e7-b6d5-4dc382ef7f5b', + overviewDashboard: appendDataSourceId(DASHBOARD_ID), appLinks: initialAppLinks, - defaultIndex: (dataSourceId?: string) => - dataSourceId ? `${dataSourceId}_` + DEFAULT_INDEX : DEFAULT_INDEX, + defaultIndex: appendDataSourceId(DEFAULT_INDEX), savedObjects: (dataSourceId?: string, dataSourceTitle?: string) => getSavedObjectsWithDataSource(getSavedObjects(), dataSourceId, dataSourceTitle), dataIndices: [ diff --git a/src/plugins/home/server/services/sample_data/data_sets/util.ts b/src/plugins/home/server/services/sample_data/data_sets/util.ts index 3d3c97308528..46022f1c22d3 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/util.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/util.ts @@ -5,6 +5,10 @@ import { SavedObject } from 'opensearch-dashboards/server'; +export const appendDataSourceId = (id: string) => { + return (dataSourceId?: string) => (dataSourceId ? `${dataSourceId}_` + id : id); +}; + export const getSavedObjectsWithDataSource = ( saveObjectList: SavedObject[], dataSourceId?: string, diff --git a/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts b/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts index 66670b72e8d0..76632ee4489d 100644 --- a/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts +++ b/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts @@ -87,7 +87,7 @@ export interface SampleDatasetSchema { darkPreviewImagePath: string; // saved object id of main dashboard for sample data set - overviewDashboard: string; + overviewDashboard: (dataSourceId?: string) => string; appLinks: AppLinkSchema[]; // saved object id of default index-pattern for sample data set diff --git a/src/plugins/home/server/services/sample_data/routes/install.test.ts b/src/plugins/home/server/services/sample_data/routes/install.test.ts new file mode 100644 index 000000000000..ad7b421c23d5 --- /dev/null +++ b/src/plugins/home/server/services/sample_data/routes/install.test.ts @@ -0,0 +1,160 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { CoreSetup, RequestHandlerContext } from 'src/core/server'; +import { coreMock, httpServerMock } from '../../../../../../core/server/mocks'; +import { flightsSpecProvider } from '../data_sets'; +import { SampleDatasetSchema } from '../lib/sample_dataset_registry_types'; +import { createInstallRoute } from './install'; + +const flightsSampleDataset = flightsSpecProvider(); + +const sampleDatasets: SampleDatasetSchema[] = [flightsSampleDataset]; + +describe('sample data install route', () => { + let mockCoreSetup: MockedKeys; + let mockLogger; + let mockUsageTracker; + + beforeEach(() => { + mockCoreSetup = coreMock.createSetup(); + mockLogger = { + warn: jest.fn(), + }; + + mockUsageTracker = { + addInstall: jest.fn(), + addUninstall: jest.fn(), + }; + }); + + it('handler calls expected api with the given request', async () => { + const mockClient = jest.fn().mockResolvedValue(true); + + const mockSOClientGetResponse = { + saved_objects: [ + { + type: 'dashboard', + id: '12345', + namespaces: ['default'], + attributes: { title: 'dashboard' }, + }, + ], + }; + const mockSOClient = { bulkCreate: jest.fn().mockResolvedValue(mockSOClientGetResponse) }; + + const mockContext = { + core: { + opensearch: { + legacy: { + client: { callAsCurrentUser: mockClient }, + }, + }, + savedObjects: { client: mockSOClient }, + }, + }; + const mockBody = { id: 'flights' }; + const mockQuery = {}; + const mockRequest = httpServerMock.createOpenSearchDashboardsRequest({ + params: mockBody, + query: mockQuery, + }); + const mockResponse = httpServerMock.createResponseFactory(); + + createInstallRoute( + mockCoreSetup.http.createRouter(), + sampleDatasets, + mockLogger, + mockUsageTracker + ); + + const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; + const handler = mockRouter.post.mock.calls[0][1]; + + await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse); + + expect(mockClient.mock.calls[1][1].body.settings).toMatchObject({ + index: { number_of_shards: 1, auto_expand_replicas: '0-1' }, + }); + + // expect(mockClient).toBeCalledTimes(2); + expect(mockResponse.ok).toBeCalled(); + expect(mockResponse.ok.mock.calls[0][0]).toMatchObject({ + body: { + opensearchIndicesCreated: { opensearch_dashboards_sample_data_flights: 13059 }, + opensearchDashboardsSavedObjectsLoaded: 20, + }, + }); + }); + + it('handler calls expected api with the given request with data source', async () => { + const mockDataSourceId = 'dataSource'; + + const mockClient = jest.fn().mockResolvedValue(true); + + const mockSOClientGetResponse = { + saved_objects: [ + { + type: 'dashboard', + id: '12345', + namespaces: ['default'], + attributes: { title: 'dashboard' }, + }, + ], + }; + const mockSOClient = { + bulkCreate: jest.fn().mockResolvedValue(mockSOClientGetResponse), + get: jest.fn().mockResolvedValue(mockSOClientGetResponse), + }; + + const mockContext = { + dataSource: { + opensearch: { + legacy: { + getClient: (id) => { + return { + callAPI: mockClient, + }; + }, + }, + }, + }, + core: { + savedObjects: { client: mockSOClient }, + }, + }; + const mockBody = { id: 'flights' }; + const mockQuery = { data_source_id: mockDataSourceId }; + const mockRequest = httpServerMock.createOpenSearchDashboardsRequest({ + params: mockBody, + query: mockQuery, + }); + const mockResponse = httpServerMock.createResponseFactory(); + + createInstallRoute( + mockCoreSetup.http.createRouter(), + sampleDatasets, + mockLogger, + mockUsageTracker + ); + + const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; + const handler = mockRouter.post.mock.calls[0][1]; + + await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse); + + expect(mockClient.mock.calls[1][1].body.settings).toMatchObject({ + index: { number_of_shards: 1 }, + }); + + expect(mockResponse.ok).toBeCalled(); + expect(mockResponse.ok.mock.calls[0][0]).toMatchObject({ + body: { + opensearchIndicesCreated: { opensearch_dashboards_sample_data_flights: 13059 }, + opensearchDashboardsSavedObjectsLoaded: 20, + }, + }); + }); +}); diff --git a/src/plugins/home/server/services/sample_data/routes/install.ts b/src/plugins/home/server/services/sample_data/routes/install.ts index 596231d75e73..3a321c3bdf0a 100644 --- a/src/plugins/home/server/services/sample_data/routes/install.ts +++ b/src/plugins/home/server/services/sample_data/routes/install.ts @@ -29,7 +29,7 @@ */ import { schema } from '@osd/config-schema'; -import { IRouter, Logger } from 'src/core/server'; +import { IRouter, LegacyCallAPIOptions, Logger } from 'src/core/server'; import { SampleDatasetSchema } from '../lib/sample_dataset_registry_types'; import { createIndexName } from '../lib/create_index_name'; import { @@ -44,7 +44,11 @@ const insertDataIntoIndex = ( dataIndexConfig: any, index: string, nowReference: string, - caller: (endpoint: string, clientParams?: Record, options?: any) => Promise, + caller: ( + endpoint: string, + clientParams?: Record, + options?: LegacyCallAPIOptions + ) => Promise, logger: Logger ) => { function updateTimestamps(doc: any) { diff --git a/src/plugins/home/server/services/sample_data/routes/list.test.ts b/src/plugins/home/server/services/sample_data/routes/list.test.ts new file mode 100644 index 000000000000..0f0aa4b09d15 --- /dev/null +++ b/src/plugins/home/server/services/sample_data/routes/list.test.ts @@ -0,0 +1,122 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { CoreSetup, RequestHandlerContext } from 'src/core/server'; +import { coreMock, httpServerMock } from '../../../../../../core/server/mocks'; +import { createListRoute } from './list'; +import { flightsSpecProvider } from '../data_sets'; +import { SampleDatasetSchema } from '../lib/sample_dataset_registry_types'; + +const flightsSampleDataset = flightsSpecProvider(); + +const sampleDatasets: SampleDatasetSchema[] = [flightsSampleDataset]; + +describe('sample data list route', () => { + let mockCoreSetup: MockedKeys; + + beforeEach(() => { + mockCoreSetup = coreMock.createSetup(); + }); + + it('handler calls expected api with the given request', async () => { + const mockClient = jest.fn().mockResolvedValueOnce(true).mockResolvedValueOnce({ count: 1 }); + + const mockSOClientGetResponse = { + saved_objects: [ + { + type: 'dashboard', + id: '12345', + namespaces: ['default'], + attributes: { title: 'dashboard' }, + }, + ], + }; + const mockSOClient = { get: jest.fn().mockResolvedValue(mockSOClientGetResponse) }; + + const mockContext = { + core: { + opensearch: { + legacy: { + client: { callAsCurrentUser: mockClient }, + }, + }, + savedObjects: { client: mockSOClient }, + }, + }; + const mockBody = {}; + const mockQuery = {}; + const mockRequest = httpServerMock.createOpenSearchDashboardsRequest({ + body: mockBody, + query: mockQuery, + }); + const mockResponse = httpServerMock.createResponseFactory(); + + createListRoute(mockCoreSetup.http.createRouter(), sampleDatasets); + + const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; + const handler = mockRouter.get.mock.calls[0][1]; + + await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse); + + expect(mockClient).toBeCalledTimes(2); + expect(mockResponse.ok).toBeCalled(); + expect(mockSOClient.get.mock.calls[0][1]).toMatch('7adfa750-4c81-11e8-b3d7-01146121b73d'); + }); + + it('handler calls expected api with the given request with data source', async () => { + const mockDataSourceId = 'dataSource'; + const mockClient = jest.fn().mockResolvedValueOnce(true).mockResolvedValueOnce({ count: 1 }); + + const mockSOClientGetResponse = { + saved_objects: [ + { + type: 'dashboard', + id: '12345', + namespaces: ['default'], + attributes: { title: 'dashboard' }, + }, + ], + }; + const mockSOClient = { get: jest.fn().mockResolvedValue(mockSOClientGetResponse) }; + + const mockContext = { + dataSource: { + opensearch: { + legacy: { + getClient: (id) => { + return { + callAPI: mockClient, + }; + }, + }, + }, + }, + core: { + savedObjects: { client: mockSOClient }, + }, + }; + + const mockBody = {}; + const mockQuery = { data_source_id: mockDataSourceId }; + const mockRequest = httpServerMock.createOpenSearchDashboardsRequest({ + body: mockBody, + query: mockQuery, + }); + const mockResponse = httpServerMock.createResponseFactory(); + + createListRoute(mockCoreSetup.http.createRouter(), sampleDatasets); + + const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; + const handler = mockRouter.get.mock.calls[0][1]; + + await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse); + + expect(mockClient).toBeCalledTimes(2); + expect(mockResponse.ok).toBeCalled(); + expect(mockSOClient.get.mock.calls[0][1]).toMatch( + `${mockDataSourceId}_7adfa750-4c81-11e8-b3d7-01146121b73d` + ); + }); +}); diff --git a/src/plugins/home/server/services/sample_data/routes/list.ts b/src/plugins/home/server/services/sample_data/routes/list.ts index 43c167943b65..3ec765b3a239 100644 --- a/src/plugins/home/server/services/sample_data/routes/list.ts +++ b/src/plugins/home/server/services/sample_data/routes/list.ts @@ -94,10 +94,7 @@ export const createListRoute = (router: IRouter, sampleDatasets: SampleDatasetSc } } try { - // todo: change to function provider accept dataSourceId - const dashboardId = dataSourceId - ? `${dataSourceId}_${sampleDataset.overviewDashboard}` - : sampleDataset.overviewDashboard; + const dashboardId = sampleDataset.overviewDashboard(dataSourceId); await context.core.savedObjects.client.get('dashboard', dashboardId); } catch (err) { diff --git a/src/plugins/home/server/services/sample_data/routes/uninstall.test.ts b/src/plugins/home/server/services/sample_data/routes/uninstall.test.ts new file mode 100644 index 000000000000..7d9797d752cb --- /dev/null +++ b/src/plugins/home/server/services/sample_data/routes/uninstall.test.ts @@ -0,0 +1,101 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { CoreSetup, RequestHandlerContext } from 'src/core/server'; +import { coreMock, httpServerMock } from '../../../../../../core/server/mocks'; +import { flightsSpecProvider } from '../data_sets'; +import { SampleDatasetSchema } from '../lib/sample_dataset_registry_types'; +import { createUninstallRoute } from './uninstall'; + +const flightsSampleDataset = flightsSpecProvider(); + +const sampleDatasets: SampleDatasetSchema[] = [flightsSampleDataset]; + +describe('sample data uninstall route', () => { + let mockCoreSetup: MockedKeys; + let mockUsageTracker; + let mockClient; + let mockSOClient; + + beforeEach(() => { + mockCoreSetup = coreMock.createSetup(); + + mockUsageTracker = { + addInstall: jest.fn(), + addUninstall: jest.fn(), + }; + + mockClient = jest.fn(); + mockSOClient = { delete: jest.fn().mockResolvedValue(true) }; + }); + + it('handler calls expected api with the given request', async () => { + const mockContext = { + core: { + opensearch: { + legacy: { + client: { callAsCurrentUser: mockClient }, + }, + }, + savedObjects: { client: mockSOClient }, + }, + }; + const mockBody = { id: 'flights' }; + const mockQuery = {}; + const mockRequest = httpServerMock.createOpenSearchDashboardsRequest({ + params: mockBody, + query: mockQuery, + }); + const mockResponse = httpServerMock.createResponseFactory(); + + createUninstallRoute(mockCoreSetup.http.createRouter(), sampleDatasets, mockUsageTracker); + + const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; + const handler = mockRouter.delete.mock.calls[0][1]; + + await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse); + + expect(mockClient).toBeCalled(); + expect(mockSOClient.delete).toBeCalled(); + }); + + it('handler calls expected api with the given request with data source', async () => { + const mockDataSourceId = 'dataSource'; + + const mockContext = { + dataSource: { + opensearch: { + legacy: { + getClient: (id) => { + return { + callAPI: mockClient, + }; + }, + }, + }, + }, + core: { + savedObjects: { client: mockSOClient }, + }, + }; + const mockBody = { id: 'flights' }; + const mockQuery = { data_source_id: mockDataSourceId }; + const mockRequest = httpServerMock.createOpenSearchDashboardsRequest({ + params: mockBody, + query: mockQuery, + }); + const mockResponse = httpServerMock.createResponseFactory(); + + createUninstallRoute(mockCoreSetup.http.createRouter(), sampleDatasets, mockUsageTracker); + + const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; + const handler = mockRouter.delete.mock.calls[0][1]; + + await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse); + + expect(mockClient).toBeCalled(); + expect(mockSOClient.delete).toBeCalled(); + }); +}); diff --git a/src/plugins/home/server/services/sample_data/sample_data_registry.ts b/src/plugins/home/server/services/sample_data/sample_data_registry.ts index 7ab4db4681c5..5f298fd86ef3 100644 --- a/src/plugins/home/server/services/sample_data/sample_data_registry.ts +++ b/src/plugins/home/server/services/sample_data/sample_data_registry.ts @@ -95,12 +95,12 @@ export class SampleDataRegistry { const dashboardSavedObjectJson = value.savedObjects.find((savedObjectJson: any) => { return ( - savedObjectJson.type === 'dashboard' && savedObjectJson.id === value.overviewDashboard + savedObjectJson.type === 'dashboard' && savedObjectJson.id === value.overviewDashboard() ); }); if (!dashboardSavedObjectJson) { throw new Error( - `Unable to register sample dataset spec, overviewDashboard: "${value.overviewDashboard}" does not exist in savedObject list.` + `Unable to register sample dataset spec, overviewDashboard: "${value.overviewDashboard()}" does not exist in savedObject list.` ); } this.sampleDatasets.push(value);