Skip to content

Commit

Permalink
add unit tests for workspace core service (opensearch-project#191)
Browse files Browse the repository at this point in the history
Signed-off-by: Yulong Ruan <ruanyl@amazon.com>
  • Loading branch information
ruanyl committed Sep 28, 2023
1 parent 8382b59 commit 4e0f906
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 6 deletions.
9 changes: 9 additions & 0 deletions src/core/public/core_system.test.mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { docLinksServiceMock } from './doc_links/doc_links_service.mock';
import { renderingServiceMock } from './rendering/rendering_service.mock';
import { contextServiceMock } from './context/context_service.mock';
import { integrationsServiceMock } from './integrations/integrations_service.mock';
import { workspacesServiceMock } from './workspace/workspaces_service.mock';
import { coreAppMock } from './core_app/core_app.mock';

export const MockInjectedMetadataService = injectedMetadataServiceMock.create();
Expand Down Expand Up @@ -145,3 +146,11 @@ export const CoreAppConstructor = jest.fn().mockImplementation(() => MockCoreApp
jest.doMock('./core_app', () => ({
CoreApp: CoreAppConstructor,
}));

export const MockWorkspacesService = workspacesServiceMock.create();
export const WorkspacesServiceConstructor = jest
.fn()
.mockImplementation(() => MockWorkspacesService);
jest.doMock('./workspace', () => ({
WorkspacesService: WorkspacesServiceConstructor,
}));
25 changes: 25 additions & 0 deletions src/core/public/core_system.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ import {
MockIntegrationsService,
CoreAppConstructor,
MockCoreApp,
WorkspacesServiceConstructor,
MockWorkspacesService,
} from './core_system.test.mocks';

import { CoreSystem } from './core_system';
Expand Down Expand Up @@ -99,6 +101,7 @@ describe('constructor', () => {
expect(RenderingServiceConstructor).toHaveBeenCalledTimes(1);
expect(IntegrationsServiceConstructor).toHaveBeenCalledTimes(1);
expect(CoreAppConstructor).toHaveBeenCalledTimes(1);
expect(WorkspacesServiceConstructor).toHaveBeenCalledTimes(1);
});

it('passes injectedMetadata param to InjectedMetadataService', () => {
Expand Down Expand Up @@ -223,6 +226,11 @@ describe('#setup()', () => {
expect(MockIntegrationsService.setup).toHaveBeenCalledTimes(1);
});

it('calls workspaces#setup()', async () => {
await setupCore();
expect(MockWorkspacesService.setup).toHaveBeenCalledTimes(1);
});

it('calls coreApp#setup()', async () => {
await setupCore();
expect(MockCoreApp.setup).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -310,6 +318,15 @@ describe('#start()', () => {
expect(MockIntegrationsService.start).toHaveBeenCalledTimes(1);
});

it('calls workspaces#start()', async () => {
await startCore();
expect(MockWorkspacesService.start).toHaveBeenCalledTimes(1);
expect(MockWorkspacesService.start).toHaveBeenCalledWith({
application: expect.any(Object),
http: expect.any(Object),
});
});

it('calls coreApp#start()', async () => {
await startCore();
expect(MockCoreApp.start).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -364,6 +381,14 @@ describe('#stop()', () => {
expect(MockIntegrationsService.stop).toHaveBeenCalled();
});

it('calls workspaces.stop()', () => {
const coreSystem = createCoreSystem();

expect(MockWorkspacesService.stop).not.toHaveBeenCalled();
coreSystem.stop();
expect(MockWorkspacesService.stop).toHaveBeenCalled();
});

it('calls coreApp.stop()', () => {
const coreSystem = createCoreSystem();

Expand Down
1 change: 1 addition & 0 deletions src/core/public/core_system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ export class CoreSystem {
this.chrome.stop();
this.i18n.stop();
this.application.stop();
this.workspaces.stop();
this.rootDomElement.textContent = '';
}
}
2 changes: 1 addition & 1 deletion src/core/public/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ function createCoreSetupMock({
getInjectedVar: injectedMetadataServiceMock.createSetupContract().getInjectedVar,
getBranding: injectedMetadataServiceMock.createSetupContract().getBranding,
},
workspaces: workspacesServiceMock.createSetupContractMock(),
workspaces: workspacesServiceMock.createSetupContract(),
};

return mock;
Expand Down
2 changes: 1 addition & 1 deletion src/core/public/plugins/plugins_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ describe('PluginsService', () => {
injectedMetadata: injectedMetadataServiceMock.createStartContract(),
notifications: notificationServiceMock.createSetupContract(),
uiSettings: uiSettingsServiceMock.createSetupContract(),
workspaces: workspacesServiceMock.createSetupContractMock(),
workspaces: workspacesServiceMock.createSetupContract(),
};
mockSetupContext = {
...mockSetupDeps,
Expand Down
13 changes: 12 additions & 1 deletion src/core/public/workspace/workspaces_service.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
*/

import { BehaviorSubject } from 'rxjs';
import type { PublicMethodsOf } from '@osd/utility-types';

import { WorkspacesService } from './workspaces_service';
import { WorkspaceAttribute } from '..';

const currentWorkspaceId$ = new BehaviorSubject<string>('');
Expand All @@ -30,7 +33,15 @@ const createWorkspacesStartContractMock = () => ({
renderWorkspaceMenu: jest.fn(),
});

export type WorkspacesServiceContract = PublicMethodsOf<WorkspacesService>;
const createMock = (): jest.Mocked<WorkspacesServiceContract> => ({
setup: jest.fn().mockReturnValue(createWorkspacesSetupContractMock()),
start: jest.fn().mockReturnValue(createWorkspacesStartContractMock()),
stop: jest.fn(),
});

export const workspacesServiceMock = {
createSetupContractMock: createWorkspacesSetupContractMock,
create: createMock,
createSetupContract: createWorkspacesSetupContractMock,
createStartContract: createWorkspacesStartContractMock,
};
94 changes: 94 additions & 0 deletions src/core/public/workspace/workspaces_service.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { httpServiceMock } from '../http/http_service.mock';
import { applicationServiceMock } from '../application/application_service.mock';
import { WorkspacesService, WorkspacesSetup, WorkspacesStart } from './workspaces_service';

describe('WorkspacesService', () => {
let workspaces: WorkspacesService;
let workspacesSetup: WorkspacesSetup;
let workspacesStart: WorkspacesStart;

beforeEach(() => {
workspaces = new WorkspacesService();
workspacesSetup = workspaces.setup();
workspacesStart = workspaces.start({
http: httpServiceMock.createStartContract(),
application: applicationServiceMock.createInternalStartContract(),
});
});

afterEach(() => {
workspaces.stop();
});

it('workspace initialized$ state is false by default', () => {
expect(workspacesStart.initialized$.value).toBe(false);
});

it('workspace is not enabled by default', () => {
expect(workspacesStart.workspaceEnabled$.value).toBe(false);
});

it('currentWorkspace is not set by default', () => {
expect(workspacesStart.currentWorkspace$.value).toBe(null);
expect(workspacesStart.currentWorkspaceId$.value).toBe('');
});

it('workspaceList$ is empty by default', () => {
expect(workspacesStart.workspaceList$.value.length).toBe(0);
});

it('should call menu render function', () => {
const renderFn = jest.fn();
workspacesSetup.registerWorkspaceMenuRender(renderFn);
workspacesStart.renderWorkspaceMenu();
expect(renderFn).toHaveBeenCalled();
});

it('should return null if NO menu render function was registered', () => {
expect(workspacesStart.renderWorkspaceMenu()).toBe(null);
});

it('the current workspace should also updated after changing current workspace id', () => {
expect(workspacesStart.currentWorkspace$.value).toBe(null);

workspacesStart.initialized$.next(true);
workspacesStart.workspaceList$.next([
{ id: 'workspace-1', name: 'workspace 1' },
{ id: 'workspace-2', name: 'workspace 2' },
]);
workspacesStart.currentWorkspaceId$.next('workspace-1');

expect(workspacesStart.currentWorkspace$.value).toEqual({
id: 'workspace-1',
name: 'workspace 1',
});

workspacesStart.currentWorkspaceId$.next('');
expect(workspacesStart.currentWorkspace$.value).toEqual(null);
});

it('should return error if the specified workspace id cannot be found', () => {
expect(workspacesStart.currentWorkspace$.hasError).toBe(false);
workspacesStart.initialized$.next(true);
workspacesStart.workspaceList$.next([
{ id: 'workspace-1', name: 'workspace 1' },
{ id: 'workspace-2', name: 'workspace 2' },
]);
workspacesStart.currentWorkspaceId$.next('workspace-3');
expect(workspacesStart.currentWorkspace$.hasError).toBe(true);
});

it('should stop all observables when workspace service stopped', () => {
workspaces.stop();
expect(workspacesStart.currentWorkspaceId$.isStopped).toBe(true);
expect(workspacesStart.currentWorkspace$.isStopped).toBe(true);
expect(workspacesStart.workspaceList$.isStopped).toBe(true);
expect(workspacesStart.workspaceEnabled$.isStopped).toBe(true);
expect(workspacesStart.initialized$.isStopped).toBe(true);
});
});
6 changes: 3 additions & 3 deletions src/core/public/workspace/workspaces_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import { isEqual } from 'lodash';

import { CoreService, WorkspaceAttribute } from '../../types';
import { InternalApplicationStart } from '../application';
import { HttpSetup } from '../http';
import { HttpStart } from '../http';

type WorkspaceMenuRenderFn = ({
basePath,
getUrlForApp,
observables,
}: {
getUrlForApp: InternalApplicationStart['getUrlForApp'];
basePath: HttpSetup['basePath'];
basePath: HttpStart['basePath'];
observables: WorkspaceObservables;
}) => JSX.Element | null;

Expand Down Expand Up @@ -99,7 +99,7 @@ export class WorkspacesService implements CoreService<WorkspacesSetup, Workspace
application,
}: {
application: InternalApplicationStart;
http: HttpSetup;
http: HttpStart;
}): WorkspacesStart {
const observables = {
currentWorkspaceId$: this.currentWorkspaceId$,
Expand Down

0 comments on commit 4e0f906

Please sign in to comment.