From 1d9bf609b99a1b6f10d988c043616e89adb3358c Mon Sep 17 00:00:00 2001 From: Lin Wang Date: Wed, 28 Aug 2024 18:41:29 +0800 Subject: [PATCH] Add ut and fix integration tests Signed-off-by: Lin Wang --- .../server/integration_tests/routes.test.ts | 1 + .../workspace/server/routes/index.test.ts | 129 ++++++++++++++++++ ...apper_for_check_workspace_conflict.test.ts | 3 + .../workspace_id_consumer_wrapper.test.ts | 3 + .../workspace_ui_settings_wrapper.test.ts | 2 +- .../workspace/server/workspace_client.mock.ts | 16 +++ 6 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 src/plugins/workspace/server/routes/index.test.ts create mode 100644 src/plugins/workspace/server/workspace_client.mock.ts diff --git a/src/plugins/workspace/server/integration_tests/routes.test.ts b/src/plugins/workspace/server/integration_tests/routes.test.ts index e3de40309e72..589a4ccbe326 100644 --- a/src/plugins/workspace/server/integration_tests/routes.test.ts +++ b/src/plugins/workspace/server/integration_tests/routes.test.ts @@ -16,6 +16,7 @@ const testWorkspace: WorkspaceAttribute = { id: 'fake_id', name: 'test_workspace', description: 'test_workspace_description', + features: ['use-case-all'], }; describe('workspace service api integration test', () => { diff --git a/src/plugins/workspace/server/routes/index.test.ts b/src/plugins/workspace/server/routes/index.test.ts new file mode 100644 index 000000000000..cd9fafb2efc4 --- /dev/null +++ b/src/plugins/workspace/server/routes/index.test.ts @@ -0,0 +1,129 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import supertest from 'supertest'; +import { UnwrapPromise } from '@osd/utility-types'; + +import { setupServer } from '../../../../core/server/test_utils'; +import { loggingSystemMock } from '../../../../core/server/mocks'; +// eslint-disable-next-line @osd/eslint/no-restricted-paths +import { dynamicConfigServiceMock } from '../../../../core/server/config'; + +import { workspaceClientMock } from '../workspace_client.mock'; + +import { registerRoutes, WORKSPACES_API_BASE_URL } from './index'; + +type SetupServerReturn = UnwrapPromise>; +const mockDynamicConfigService = dynamicConfigServiceMock.createInternalStartContract(); + +describe(`Workspace routes`, () => { + let server: SetupServerReturn['server']; + let httpSetup: SetupServerReturn['httpSetup']; + + beforeEach(async () => { + ({ server, httpSetup } = await setupServer()); + + const router = httpSetup.createRouter(''); + + registerRoutes({ + router, + client: workspaceClientMock, + logger: loggingSystemMock.create().get(), + maxImportExportSize: Number.MAX_SAFE_INTEGER, + isPermissionControlEnabled: false, + }); + + await server.start({ dynamicConfigService: mockDynamicConfigService }); + }); + + afterEach(async () => { + await server.stop(); + }); + + it('creates a workspace successfully', async () => { + const result = await supertest(httpSetup.server.listener) + .post(WORKSPACES_API_BASE_URL) + .send({ + attributes: { + name: 'Observability', + features: ['use-case-observability'], + }, + }) + .expect(200); + expect(result.body).toEqual({ id: expect.any(String) }); + expect(workspaceClientMock.create).toHaveBeenCalledWith( + expect.any(Object), + expect.objectContaining({ + name: 'Observability', + features: ['use-case-observability'], + }) + ); + }); + + describe('feature validation', () => { + it('returns 400 when no features is provided during workspace creation', async () => { + await supertest(httpSetup.server.listener) + .post(WORKSPACES_API_BASE_URL) + .send({ + attributes: { + name: 'Observability', + }, + }) + .expect(400); + }); + it('returns 400 when no valid use case is provided during workspace creation', async () => { + const result = await supertest(httpSetup.server.listener) + .post(WORKSPACES_API_BASE_URL) + .send({ + attributes: { + name: 'Observability', + features: ['use-case-valid'], + }, + }) + .expect(400); + expect(result.body.message).toEqual( + '[request body.attributes.features]: At least one use case is required. Valid options: use-case-all, use-case-observability, use-case-security-analytics, use-case-analytics, use-case-search' + ); + }); + it('returns 400 when multiple use cases are provided during workspace creation', async () => { + const result = await supertest(httpSetup.server.listener) + .post(WORKSPACES_API_BASE_URL) + .send({ + attributes: { + name: 'Observability', + features: ['use-case-observability', 'use-case-all'], + }, + }) + .expect(400); + expect(result.body.message).toEqual( + '[request body.attributes.features]: Only one use case is allowed per workspace.' + ); + }); + it('returns 400 when no valid use case is provided during workspace update', async () => { + const result = await supertest(httpSetup.server.listener) + .put(`${WORKSPACES_API_BASE_URL}/mock-workspace-id`) + .send({ + attributes: { + name: 'Observability', + features: ['feature1', 'feature2'], + }, + }) + .expect(400); + expect(result.body.message).toEqual( + '[request body.attributes.features]: At least one use case is required. Valid options: use-case-all, use-case-observability, use-case-security-analytics, use-case-analytics, use-case-search' + ); + }); + it('updates workspace name successfully without modifying features', async () => { + await supertest(httpSetup.server.listener) + .put(`${WORKSPACES_API_BASE_URL}/mock-workspace-id`) + .send({ + attributes: { + name: 'Observability', + }, + }) + .expect(200); + }); + }); +}); diff --git a/src/plugins/workspace/server/saved_objects/integration_tests/saved_objects_wrapper_for_check_workspace_conflict.test.ts b/src/plugins/workspace/server/saved_objects/integration_tests/saved_objects_wrapper_for_check_workspace_conflict.test.ts index 9405c59a4796..58f7e1e7f525 100644 --- a/src/plugins/workspace/server/saved_objects/integration_tests/saved_objects_wrapper_for_check_workspace_conflict.test.ts +++ b/src/plugins/workspace/server/saved_objects/integration_tests/saved_objects_wrapper_for_check_workspace_conflict.test.ts @@ -38,6 +38,7 @@ const advancedSettings: Omit = { interface WorkspaceAttributes { id: string; name?: string; + features?: string[]; } describe('saved_objects_wrapper_for_check_workspace_conflict integration test', () => { @@ -76,9 +77,11 @@ describe('saved_objects_wrapper_for_check_workspace_conflict integration test', createdFooWorkspace = await createWorkspace({ name: 'foo', + features: ['use-case-all'], }).then((resp) => resp.body.result); createdBarWorkspace = await createWorkspace({ name: 'bar', + features: ['use-case-all'], }).then((resp) => resp.body.result); }, 30000); afterAll(async () => { diff --git a/src/plugins/workspace/server/saved_objects/integration_tests/workspace_id_consumer_wrapper.test.ts b/src/plugins/workspace/server/saved_objects/integration_tests/workspace_id_consumer_wrapper.test.ts index ac643d59e641..84d09af94362 100644 --- a/src/plugins/workspace/server/saved_objects/integration_tests/workspace_id_consumer_wrapper.test.ts +++ b/src/plugins/workspace/server/saved_objects/integration_tests/workspace_id_consumer_wrapper.test.ts @@ -16,6 +16,7 @@ const dashboard: Omit = { interface WorkspaceAttributes { id: string; name?: string; + features?: string[]; } describe('workspace_id_consumer integration test', () => { @@ -56,11 +57,13 @@ describe('workspace_id_consumer integration test', () => { createdFooWorkspace = await createWorkspace({ name: 'foo', + features: ['use-case-all'], }).then((resp) => { return resp.body.result; }); createdBarWorkspace = await createWorkspace({ name: 'bar', + features: ['use-case-all'], }).then((resp) => resp.body.result); }, 30000); afterAll(async () => { diff --git a/src/plugins/workspace/server/saved_objects/integration_tests/workspace_ui_settings_wrapper.test.ts b/src/plugins/workspace/server/saved_objects/integration_tests/workspace_ui_settings_wrapper.test.ts index 35e771780dc6..00a487989cf2 100644 --- a/src/plugins/workspace/server/saved_objects/integration_tests/workspace_ui_settings_wrapper.test.ts +++ b/src/plugins/workspace/server/saved_objects/integration_tests/workspace_ui_settings_wrapper.test.ts @@ -45,7 +45,7 @@ describe('workspace ui settings saved object client wrapper', () => { globalUiSettingsClient = osd.coreStart.uiSettings.asScopedToClient(savedObjectsClient); const res = await osdTestServer.request.post(osd.root, '/api/workspaces').send({ - attributes: { name: 'test workspace' }, + attributes: { name: 'test workspace', features: ['use-case-all'] }, }); testWorkspace = res.body.result; }, 30000); diff --git a/src/plugins/workspace/server/workspace_client.mock.ts b/src/plugins/workspace/server/workspace_client.mock.ts new file mode 100644 index 000000000000..b6dce61cedcf --- /dev/null +++ b/src/plugins/workspace/server/workspace_client.mock.ts @@ -0,0 +1,16 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +export const workspaceClientMock = { + setup: jest.fn(), + setSavedObjects: jest.fn(), + setUiSettings: jest.fn(), + create: jest.fn().mockResolvedValue({ id: 'mock-workspace-id' }), + list: jest.fn(), + get: jest.fn(), + update: jest.fn(), + delete: jest.fn(), + destroy: jest.fn(), +};