Skip to content

Commit

Permalink
[Workspace] Add unit tests for inspect page url (#8834)
Browse files Browse the repository at this point in the history
* Add unit tests for inspect page url

Signed-off-by: yubonluo <[email protected]>

* Changeset file for PR #8834 created/updated

* optimize the code

Signed-off-by: yubonluo <[email protected]>

* optimize the code

Signed-off-by: yubonluo <[email protected]>

* optimize the code

Signed-off-by: yubonluo <[email protected]>

---------

Signed-off-by: yubonluo <[email protected]>
Co-authored-by: opensearch-changeset-bot[bot] <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com>
  • Loading branch information
yubonluo and opensearch-changeset-bot[bot] authored Nov 12, 2024
1 parent 0f899df commit 76cf823
Show file tree
Hide file tree
Showing 5 changed files with 287 additions and 24 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/8834.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
refactor:
- [Workspace] Add unit tests for inspect page url ([#8834](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8834))
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { render } from '@testing-library/react';
import { createOpenSearchDashboardsReactContext } from '../../../../../opensearch_dashboards_react/public';
import { coreMock, workspacesServiceMock } from '../../../../../../core/public/mocks';
import { BehaviorSubject } from 'rxjs';
import { WorkspaceObject } from 'opensearch-dashboards/public';
import { IntlProvider } from 'react-intl';
import { IndexHeader } from './index_header';

describe('IndexHeader at new home page', () => {
const indexPattern = { id: 'default-index', title: 'Test Index Pattern', fields: [] };
const mockCoreStart = coreMock.createStart();
const workspaceObject = {
id: 'foo_id',
name: 'foo',
};
const getIndexHeader = (props: any) => {
const mockHeaderControl =
(props?.header as Function) ||
(() => {
return null;
});

const setDefault = jest.fn();
const refreshFields = jest.fn();
const deleteIndexPatternClick = jest.fn();
const { Provider } = createOpenSearchDashboardsReactContext({
...mockCoreStart,
...{
application: {
...mockCoreStart.application,
capabilities: {
...mockCoreStart.application.capabilities,
workspaces: { enabled: props.workspaceEnabled },
},
},
uiSettings: { ...mockCoreStart.uiSettings, get: jest.fn().mockReturnValue(true) },
workspaces: {
...workspacesServiceMock.createStartContract(),
currentWorkspace$: new BehaviorSubject<WorkspaceObject | null>(props?.workspace),
},
navigationUI: {
HeaderControl: mockHeaderControl,
},
},
});

return (
<IntlProvider locale="en">
<Provider>
<IndexHeader
setDefault={setDefault}
refreshFields={refreshFields}
deleteIndexPatternClick={deleteIndexPatternClick}
indexPattern={indexPattern}
defaultIndex={props?.defaultIndex}
/>
</Provider>
</IntlProvider>
);
};

beforeEach(() => {
jest.clearAllMocks();
});

it('renders the set default button when index is not default and workspace is disabled', () => {
const mockHeaderControl = ({ controls }) => {
return controls?.[1]?.label ?? null;
};
const { getByText } = render(
getIndexHeader({
header: mockHeaderControl,
defaultIndex: 'no-default-index',
workspaceEnabled: false,
})
);

expect(getByText('Set as default index')).toBeInTheDocument();
});

it('does not render the set default button when index is default and workspace is disabled', () => {
const mockHeaderControl = ({ controls }) => {
return controls?.[1]?.label ?? null;
};
const { queryByText } = render(
getIndexHeader({
header: mockHeaderControl,
defaultIndex: 'default-index',
workspaceEnabled: false,
})
);

expect(queryByText('Set as default index')).toBeNull();
});

it('renders the set default button when index is not default and user is in workspace', () => {
const mockHeaderControl = ({ controls }) => {
return controls?.[1]?.label ?? null;
};
const { getByText } = render(
getIndexHeader({
header: mockHeaderControl,
defaultIndex: 'no-default-index',
workspace: workspaceObject,
workspaceEnabled: true,
})
);

expect(getByText('Set as default index')).toBeInTheDocument();
});

it('does not render the set default button when index is default and user is in workspace', () => {
const mockHeaderControl = ({ controls }) => {
return controls?.[1]?.label ?? null;
};
const { queryByText } = render(
getIndexHeader({
header: mockHeaderControl,
defaultIndex: 'default-index',
workspace: workspaceObject,
workspaceEnabled: true,
})
);

expect(queryByText('Set as default index')).toBeNull();
});

it('does not render the set default button when index is not default and user is not in workspace', () => {
const mockHeaderControl = ({ controls }) => {
return controls?.[1]?.label ?? null;
};
const { queryByText } = render(
getIndexHeader({
header: mockHeaderControl,
defaultIndex: 'no-default-index',
workspaceEnabled: true,
})
);

expect(queryByText('Set as default index')).toBeNull();
});

it('does not render the set default button when index is default and user is not in workspace', () => {
const mockHeaderControl = ({ controls }) => {
return controls?.[1]?.label ?? null;
};
const { queryByText } = render(
getIndexHeader({
header: mockHeaderControl,
defaultIndex: 'default-index',
workspaceEnabled: true,
})
);

expect(queryByText('Set as default index')).toBeNull();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import {
} from '../services';
import { SavedObjectsTable } from './objects_table';
import { NavigationPublicPluginStart } from '../../../navigation/public';
import { formatUrlWithWorkspaceId } from '../../../../core/public/utils';
import { formatInspectUrl } from '../utils';

const SavedObjectsTablePage = ({
coreStart,
Expand Down Expand Up @@ -76,8 +76,6 @@ const SavedObjectsTablePage = ({
const itemsPerPage = coreStart.uiSettings.get<number>('savedObjects:perPage', 50);
const dateFormat = coreStart.uiSettings.get<string>('dateFormat');
const currentWorkspace = useObservable(coreStart.workspaces.currentWorkspace$);
const basePath = coreStart.http.basePath;
const visibleWsIds = useObservable(coreStart.workspaces.workspaceList$)?.map((ws) => ws.id) || [];

useEffect(() => {
setBreadcrumbs([
Expand Down Expand Up @@ -119,26 +117,8 @@ const SavedObjectsTablePage = ({
workspaces={coreStart.workspaces}
perPageConfig={itemsPerPage}
goInspectObject={(savedObject) => {
const { editUrl } = savedObject.meta;
let finalEditUrl = editUrl;
if (useUpdatedUX && finalEditUrl) {
finalEditUrl = finalEditUrl.replace(/^\/management\/opensearch-dashboards/, '/app');
}
if (finalEditUrl) {
let inAppUrl = basePath.prepend(finalEditUrl);
if (savedObject.workspaces?.length) {
if (currentWorkspace) {
inAppUrl = formatUrlWithWorkspaceId(finalEditUrl, currentWorkspace.id, basePath);
} else {
// find first workspace user have permission
const workspaceId = savedObject.workspaces.find((wsId) =>
visibleWsIds.includes(wsId)
);
if (workspaceId) {
inAppUrl = formatUrlWithWorkspaceId(finalEditUrl, workspaceId, basePath);
}
}
}
const inAppUrl = formatInspectUrl(savedObject, coreStart);
if (inAppUrl) {
return coreStart.application.navigateToUrl(inAppUrl);
}
}}
Expand Down
84 changes: 83 additions & 1 deletion src/plugins/saved_objects_management/public/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { formatWorkspaceIdParams } from './utils';
import { coreMock } from '../../../core/public/mocks';
import { formatInspectUrl, formatWorkspaceIdParams } from './utils';
import { CoreStart } from 'opensearch-dashboards/public';

describe('Utils', () => {
it('formatWorkspaceIdParams with workspace null/undefined', async () => {
Expand Down Expand Up @@ -41,4 +43,84 @@ describe('Utils', () => {
});
expect(obj).toEqual({ foo: 'bar', availableWorkspaces: ['foo', 'bar'], workspaces: ['foo'] });
});

describe('formatInspectUrl', () => {
let mockCoreStart: CoreStart;
const savedObject = {
type: 'dashboard',
id: 'dashboard',
attributes: {},
references: [],
meta: {
editUrl: '/management/opensearch-dashboards/objects/savedDashboards/ID1',
},
};
const savedObjectWithWorkspaces = {
...savedObject,
workspaces: ['workspace1'],
};

beforeEach(() => {
jest.clearAllMocks();
mockCoreStart = coreMock.createStart();
mockCoreStart.application.capabilities = {
...mockCoreStart.application.capabilities,
workspaces: {
...mockCoreStart.application.capabilities.workspaces,
enabled: true,
},
};
mockCoreStart.uiSettings = {
...mockCoreStart.uiSettings,
get: jest.fn().mockReturnValue(true),
};
});

it('formats URL correctly when useUpdatedUX is false and workspace is disabled', () => {
mockCoreStart.application.capabilities = {
...mockCoreStart.application.capabilities,
workspaces: {
...mockCoreStart.application.capabilities.workspaces,
enabled: false,
},
};
mockCoreStart.uiSettings = {
...mockCoreStart.uiSettings,
get: jest.fn().mockReturnValue(false),
};
const result = formatInspectUrl(savedObject, mockCoreStart);
expect(result).toBe('/management/opensearch-dashboards/objects/savedDashboards/ID1');
});

it('formats URL correctly when useUpdatedUX is false, saved object does not belong to certain workspaces and not in current workspace', () => {
mockCoreStart.uiSettings = {
...mockCoreStart.uiSettings,
get: jest.fn().mockReturnValue(false),
};
const result = formatInspectUrl(savedObject, mockCoreStart);
expect(result).toBe('/management/opensearch-dashboards/objects/savedDashboards/ID1');
});

it('formats URL correctly when useUpdatedUX is true and in current workspace', () => {
const currentWorkspace = { id: 'workspace1', name: 'workspace1' };
mockCoreStart.workspaces.currentWorkspace$.next(currentWorkspace);
const result = formatInspectUrl(savedObjectWithWorkspaces, mockCoreStart);

expect(result).toBe('http://localhost/w/workspace1/app/objects/savedDashboards/ID1');
});

it('formats URL correctly when useUpdatedUX is true and saved object belongs to certain workspaces', () => {
mockCoreStart.workspaces.workspaceList$.next([{ id: 'workspace1', name: 'workspace1' }]);
const result = formatInspectUrl(savedObjectWithWorkspaces, mockCoreStart);

expect(result).toBe('http://localhost/w/workspace1/app/objects/savedDashboards/ID1');
});

it('formats URL correctly when useUpdatedUX is true and the object does not belong to any workspace', () => {
mockCoreStart.workspaces.workspaceList$.next([{ id: 'workspace2', name: 'workspace2' }]);
const result = formatInspectUrl(savedObjectWithWorkspaces, mockCoreStart);

expect(result).toBe('/app/objects/savedDashboards/ID1');
});
});
});
36 changes: 36 additions & 0 deletions src/plugins/saved_objects_management/public/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { CoreStart } from 'opensearch-dashboards/public';
import { formatUrlWithWorkspaceId } from '../../../core/public/utils';
import { SavedObjectWithMetadata } from './types';

export function formatWorkspaceIdParams<
T extends { workspaces?: string[] | null; availableWorkspaces?: string[] | null }
>(obj: T): T | Omit<T, 'workspaces' | 'availableWorkspaces'> {
Expand All @@ -12,3 +16,35 @@ export function formatWorkspaceIdParams<
}
return others;
}

export function formatInspectUrl(
savedObject: SavedObjectWithMetadata,
coreStart: CoreStart
): string | undefined {
const { editUrl } = savedObject.meta;
const useUpdatedUX = !!coreStart.uiSettings.get('home:useNewHomePage');
let finalEditUrl = editUrl;
if (useUpdatedUX && finalEditUrl) {
finalEditUrl = finalEditUrl.replace(/^\/management\/opensearch-dashboards/, '/app');
}
if (finalEditUrl) {
const basePath = coreStart.http.basePath;
let inAppUrl = basePath.prepend(finalEditUrl);
const workspaceEnabled = coreStart.application.capabilities.workspaces.enabled;
if (workspaceEnabled) {
const currentWorkspace = coreStart.workspaces.currentWorkspace$.value;
if (currentWorkspace) {
inAppUrl = formatUrlWithWorkspaceId(finalEditUrl, currentWorkspace.id, basePath);
} else {
const visibleWsIds = coreStart.workspaces.workspaceList$.value?.map((ws) => ws.id) || [];

// find first workspace user have permission
const workspaceId = savedObject?.workspaces?.find((wsId) => visibleWsIds.includes(wsId));
if (workspaceId) {
inAppUrl = formatUrlWithWorkspaceId(finalEditUrl, workspaceId, basePath);
}
}
}
return inAppUrl;
}
}

0 comments on commit 76cf823

Please sign in to comment.