forked from opensearch-project/OpenSearch-Dashboards
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: workspace level ui settings (opensearch-project#328)
* feat: workspace level ui settings When getting ui settings within a workspace, it will combine the workspace ui settings with the global ui settings and workspace ui settings have higher priority if the same setting was defined in both places When updating ui settings within a workspace, it will update the workspace ui settings, the global ui settings will remain unchanged. Signed-off-by: Yulong Ruan <[email protected]> * fix WorkspaceAttribute type Signed-off-by: Yulong Ruan <[email protected]> * update based on PR comments Signed-off-by: Yulong Ruan <[email protected]> * add integration tests for workspace ui settings wrapper Signed-off-by: Yulong Ruan <[email protected]> * Update src/plugins/workspace/server/saved_objects/workspace_ui_settings_client_wrapper.ts Co-authored-by: SuZhou-Joe <[email protected]> * fix failed tests Signed-off-by: Yulong Ruan <[email protected]> --------- Signed-off-by: Yulong Ruan <[email protected]> Co-authored-by: SuZhou-Joe <[email protected]>
- Loading branch information
1 parent
1a353cc
commit 32fab61
Showing
8 changed files
with
381 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
...ns/workspace/server/saved_objects/integration_tests/workspace_ui_settings_wrapper.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { IUiSettingsClient, WorkspaceAttribute } from 'src/core/server'; | ||
|
||
import * as osdTestServer from '../../../../../core/test_helpers/osd_server'; | ||
import { httpServerMock } from '../../../../../core/server/http/http_server.mocks'; | ||
|
||
describe('workspace ui settings saved object client wrapper', () => { | ||
let opensearchServer: osdTestServer.TestOpenSearchUtils; | ||
let osd: osdTestServer.TestOpenSearchDashboardsUtils; | ||
let globalUiSettingsClient: IUiSettingsClient; | ||
let testWorkspace: WorkspaceAttribute = { | ||
id: '', | ||
name: '', | ||
}; | ||
|
||
beforeAll(async () => { | ||
const servers = osdTestServer.createTestServers({ | ||
adjustTimeout: (t: number) => jest.setTimeout(t), | ||
settings: { | ||
osd: { | ||
workspace: { | ||
enabled: true, | ||
}, | ||
savedObjects: { | ||
permission: { | ||
enabled: true, | ||
}, | ||
}, | ||
migrations: { | ||
skip: false, | ||
}, | ||
}, | ||
}, | ||
}); | ||
opensearchServer = await servers.startOpenSearch(); | ||
osd = await servers.startOpenSearchDashboards(); | ||
|
||
const savedObjectsClient = osd.coreStart.savedObjects.getScopedClient( | ||
httpServerMock.createOpenSearchDashboardsRequest() | ||
); | ||
globalUiSettingsClient = osd.coreStart.uiSettings.asScopedToClient(savedObjectsClient); | ||
|
||
const res = await osdTestServer.request.post(osd.root, '/api/workspaces').send({ | ||
attributes: { name: 'test workspace' }, | ||
}); | ||
testWorkspace = res.body.result; | ||
}, 30000); | ||
|
||
afterAll(async () => { | ||
await opensearchServer.stop(); | ||
await osd.stop(); | ||
}, 30000); | ||
|
||
beforeEach(async () => { | ||
await globalUiSettingsClient.set('defaultIndex', 'global-index'); | ||
}); | ||
|
||
it('should get and update workspace ui settings when currently in a workspace', async () => { | ||
const workspaceScopedSavedObjectsClient = osd.coreStart.savedObjects.getScopedClient( | ||
httpServerMock.createOpenSearchDashboardsRequest({ | ||
opensearchDashboardsRequestState: { requestWorkspaceId: testWorkspace.id }, | ||
}) | ||
); | ||
const workspaceScopedUiSettingsClient = osd.coreStart.uiSettings.asScopedToClient( | ||
workspaceScopedSavedObjectsClient | ||
); | ||
|
||
expect(await globalUiSettingsClient.get('defaultIndex')).toBe('global-index'); | ||
|
||
// workspace defaultIndex is not set, it will use the global value | ||
expect(await workspaceScopedUiSettingsClient.get('defaultIndex')).toBe('global-index'); | ||
|
||
// update ui settings in a workspace | ||
await workspaceScopedUiSettingsClient.set('defaultIndex', 'workspace-index'); | ||
|
||
// global ui settings remain unchanged | ||
expect(await globalUiSettingsClient.get('defaultIndex')).toBe('global-index'); | ||
|
||
// workspace ui settings updated to the new value | ||
expect(await workspaceScopedUiSettingsClient.get('defaultIndex')).toBe('workspace-index'); | ||
}); | ||
|
||
it('should get and update global ui settings when currently not in a workspace', async () => { | ||
expect(await globalUiSettingsClient.get('defaultIndex')).toBe('global-index'); | ||
|
||
await globalUiSettingsClient.set('defaultIndex', 'global-index-new'); | ||
expect(await globalUiSettingsClient.get('defaultIndex')).toBe('global-index-new'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
134 changes: 134 additions & 0 deletions
134
src/plugins/workspace/server/saved_objects/workspace_ui_settings_client_wrapper.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import { httpServerMock, savedObjectsClientMock, coreMock } from '../../../../core/server/mocks'; | ||
import { WorkspaceUiSettingsClientWrapper } from './workspace_ui_settings_client_wrapper'; | ||
import { WORKSPACE_TYPE } from '../../../../core/server'; | ||
|
||
import * as utils from '../../../../core/server/utils'; | ||
|
||
jest.mock('../../../../core/server/utils'); | ||
|
||
describe('WorkspaceUiSettingsClientWrapper', () => { | ||
const createWrappedClient = () => { | ||
const clientMock = savedObjectsClientMock.create(); | ||
const getClientMock = jest.fn().mockReturnValue(clientMock); | ||
const requestHandlerContext = coreMock.createRequestHandlerContext(); | ||
const requestMock = httpServerMock.createOpenSearchDashboardsRequest(); | ||
|
||
clientMock.get.mockImplementation(async (type, id) => { | ||
if (type === 'config') { | ||
return Promise.resolve({ | ||
id, | ||
references: [], | ||
type: 'config', | ||
attributes: { | ||
defaultIndex: 'default-index-global', | ||
}, | ||
}); | ||
} else if (type === WORKSPACE_TYPE) { | ||
return Promise.resolve({ | ||
id, | ||
references: [], | ||
type: WORKSPACE_TYPE, | ||
attributes: { | ||
uiSettings: { | ||
defaultIndex: 'default-index-workspace', | ||
}, | ||
}, | ||
}); | ||
} | ||
return Promise.reject(); | ||
}); | ||
|
||
const wrapper = new WorkspaceUiSettingsClientWrapper(); | ||
wrapper.setScopedClient(getClientMock); | ||
|
||
return { | ||
wrappedClient: wrapper.wrapperFactory({ | ||
client: clientMock, | ||
request: requestMock, | ||
typeRegistry: requestHandlerContext.savedObjects.typeRegistry, | ||
}), | ||
clientMock, | ||
}; | ||
}; | ||
|
||
it('should return workspace ui settings if in a workspace', async () => { | ||
// Currently in a workspace | ||
jest.spyOn(utils, 'getWorkspaceState').mockReturnValue({ requestWorkspaceId: 'workspace-id' }); | ||
|
||
const { wrappedClient } = createWrappedClient(); | ||
|
||
const result = await wrappedClient.get('config', '3.0.0'); | ||
expect(result).toEqual({ | ||
id: '3.0.0', | ||
references: [], | ||
type: 'config', | ||
attributes: { | ||
defaultIndex: 'default-index-workspace', | ||
}, | ||
}); | ||
}); | ||
|
||
it('should return global ui settings if NOT in a workspace', async () => { | ||
// Currently NOT in a workspace | ||
jest.spyOn(utils, 'getWorkspaceState').mockReturnValue({}); | ||
|
||
const { wrappedClient } = createWrappedClient(); | ||
|
||
const result = await wrappedClient.get('config', '3.0.0'); | ||
expect(result).toEqual({ | ||
id: '3.0.0', | ||
references: [], | ||
type: 'config', | ||
attributes: { | ||
defaultIndex: 'default-index-global', | ||
}, | ||
}); | ||
}); | ||
|
||
it('should update workspace ui settings', async () => { | ||
// Currently in a workspace | ||
jest.spyOn(utils, 'getWorkspaceState').mockReturnValue({ requestWorkspaceId: 'workspace-id' }); | ||
|
||
const { wrappedClient, clientMock } = createWrappedClient(); | ||
|
||
clientMock.update.mockResolvedValue({ | ||
id: 'workspace-id', | ||
references: [], | ||
type: WORKSPACE_TYPE, | ||
attributes: { | ||
uiSettings: { | ||
defaultIndex: 'new-index-id', | ||
}, | ||
}, | ||
}); | ||
|
||
await wrappedClient.update('config', '3.0.0', { defaultIndex: 'new-index-id' }); | ||
|
||
expect(clientMock.update).toHaveBeenCalledWith( | ||
WORKSPACE_TYPE, | ||
'workspace-id', | ||
{ | ||
uiSettings: { defaultIndex: 'new-index-id' }, | ||
}, | ||
{} | ||
); | ||
}); | ||
|
||
it('should update global ui settings', async () => { | ||
// Currently NOT in a workspace | ||
jest.spyOn(utils, 'getWorkspaceState').mockReturnValue({}); | ||
|
||
const { wrappedClient, clientMock } = createWrappedClient(); | ||
|
||
await wrappedClient.update('config', '3.0.0', { defaultIndex: 'new-index-id' }); | ||
|
||
expect(clientMock.update).toHaveBeenCalledWith( | ||
'config', | ||
'3.0.0', | ||
{ | ||
defaultIndex: 'new-index-id', | ||
}, | ||
{} | ||
); | ||
}); | ||
}); |
Oops, something went wrong.