Skip to content

Commit

Permalink
Merge branch 'main' into getds-res-404
Browse files Browse the repository at this point in the history
  • Loading branch information
yujin-emma authored Jun 5, 2024
2 parents 5eeaa2f + b2ff7de commit aaa377e
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 1 deletion.
2 changes: 2 additions & 0 deletions changelogs/fragments/6780.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fix:
- [Discover][Bug] Migrate global state from legacy URL ([#6780](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6780))
2 changes: 2 additions & 0 deletions changelogs/fragments/6908.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fix:
- Fix not setting the default data source when creating data source bug ([#6908](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6908))
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,12 @@ describe('DataSourceManagement: Utils.ts', () => {
await handleSetDefaultDatasource(savedObjects.client, uiSettings);
expect(uiSettings.set).toHaveBeenCalled();
});
test('should set default datasource when returned default datasource id is empty string', async () => {
mockUiSettingsCalls(uiSettings, 'get', '');
mockResponseForSavedObjectsCalls(savedObjects.client, 'find', getDataSourcesResponse);
await handleSetDefaultDatasource(savedObjects.client, uiSettings);
expect(uiSettings.set).toHaveBeenCalled();
});
test('should not set default datasource when it has default datasouce', async () => {
mockUiSettingsCalls(uiSettings, 'get', 'test');
mockResponseForSavedObjectsCalls(savedObjects.client, 'find', getDataSourcesResponse);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export async function handleSetDefaultDatasource(
savedObjectsClient: SavedObjectsClientContract,
uiSettings: IUiSettingsClient
) {
if (getDefaultDataSourceId(uiSettings) === null) {
if (!getDefaultDataSourceId(uiSettings)) {
return await setFirstDataSourceAsDefault(savedObjectsClient, uiSettings, false);
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/discover/public/migrate_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ export function migrateUrlState(oldPath: string, newPath = '/'): string {
indexPattern: index,
},
};
const _g = getStateFromOsdUrl<any>('_g', oldPath);

path = setStateToOsdUrl('_g', _g, { useHash: false }, path);
path = setStateToOsdUrl('_a', _a, { useHash: false }, path);
path = setStateToOsdUrl('_q', _q, { useHash: false }, path);

Expand Down
196 changes: 196 additions & 0 deletions src/plugins/discover/public/migrate_states.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { migrateUrlState } from './migrate_state';
import { setStateToOsdUrl, getStateFromOsdUrl } from '../../opensearch_dashboards_utils/public';

jest.mock('../../opensearch_dashboards_utils/public', () => ({
setStateToOsdUrl: jest.fn(),
getStateFromOsdUrl: jest.fn(),
}));

describe('migrateUrlState', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('should return the new path if no matching pattern', () => {
const result = migrateUrlState('#/unknown', '/newPath');
expect(result).toBe('/newPath');
});

it('should migrate doc view', () => {
const result = migrateUrlState('#/doc/indexPattern/id', '/newPath');
expect(result).toBe('#/doc/indexPattern/id');
});

it('should migrate context view', () => {
const result = migrateUrlState('#/context/indexPattern/id', '/newPath');
expect(result).toBe('#/context/indexPattern/id');
});

it('should migrate discover view with saved search id and with global state', () => {
(getStateFromOsdUrl as jest.Mock).mockImplementation((key) => {
if (key === '_a') {
return {
columns: ['column1'],
filters: [],
index: 'indexPattern',
interval: 'auto',
query: { language: 'kuery', query: 'test' },
sort: [['field', 'desc']],
savedQuery: 'savedQueryId',
};
}
if (key === '_g') {
return {
time: { from: 'now-15m', to: 'now' },
filters: [],
refreshInterval: { pause: true, value: 0 },
};
}
return null;
});

(setStateToOsdUrl as jest.Mock).mockImplementation((key, state, options, rawUrl) => {
const query = new URLSearchParams(rawUrl.split('?')[1] || '');
query.set(key, JSON.stringify(state)); // Simplified encoding
return `${rawUrl.split('?')[0]}?${query.toString()}`;
});

const result = migrateUrlState('#/view/savedSearchId', '/newPath');
const decodedResult = decodeURIComponent(result);
const expectedPath =
'/newPath#/view/savedSearchId?_g={"time":{"from":"now-15m","to":"now"},"filters":[],"refreshInterval":{"pause":true,"value":0}}&_a={"discover":{"columns":["column1"],"interval":"auto","sort":[["field","desc"]],"savedQuery":"savedQueryId"},"metadata":{"indexPattern":"indexPattern"}}&_q={"query":{"language":"kuery","query":"test"},"filters":[]}';
expect(decodedResult).toBe(expectedPath);
});

it('should migrate discover view without saved search id and with global state', () => {
(getStateFromOsdUrl as jest.Mock).mockImplementation((key) => {
if (key === '_a') {
return {
columns: ['column1'],
filters: [],
index: 'indexPattern',
interval: 'auto',
query: { language: 'kuery', query: 'test' },
sort: [['field', 'desc']],
savedQuery: 'savedQueryId',
};
}
if (key === '_g') {
return {
time: { from: 'now-15m', to: 'now' },
filters: [],
refreshInterval: { pause: true, value: 0 },
};
}
return null;
});

const result = migrateUrlState('#/', '/newPath');
const decodedResult = decodeURIComponent(result);
const expectedPath =
'/newPath?_g={"time":{"from":"now-15m","to":"now"},"filters":[],"refreshInterval":{"pause":true,"value":0}}&_a={"discover":{"columns":["column1"],"interval":"auto","sort":[["field","desc"]],"savedQuery":"savedQueryId"},"metadata":{"indexPattern":"indexPattern"}}&_q={"query":{"language":"kuery","query":"test"},"filters":[]}';
expect(decodedResult).toBe(expectedPath);
});

it('should migrate discover view without saved search id and without global state', () => {
(getStateFromOsdUrl as jest.Mock).mockImplementation((key) => {
if (key === '_a') {
return {
columns: ['column1'],
filters: [],
index: 'indexPattern',
interval: 'auto',
query: { language: 'kuery', query: 'test' },
sort: [['field', 'desc']],
savedQuery: 'savedQueryId',
};
}
return null;
});

(setStateToOsdUrl as jest.Mock).mockImplementation((key, state, options, rawUrl) => {
const query = new URLSearchParams(rawUrl.split('?')[1] || '');
query.set(key, JSON.stringify(state)); // Simplified encoding
return `${rawUrl.split('?')[0]}?${query.toString()}`;
});

const result = migrateUrlState('#/', '/newPath');
const decodedResult = decodeURIComponent(result);
const expectedPath =
'/newPath?_g=null&_a={"discover":{"columns":["column1"],"interval":"auto","sort":[["field","desc"]],"savedQuery":"savedQueryId"},"metadata":{"indexPattern":"indexPattern"}}&_q={"query":{"language":"kuery","query":"test"},"filters":[]}';
expect(decodedResult).toBe(expectedPath);
});

it('should return the new path if appState is null', () => {
(getStateFromOsdUrl as jest.Mock).mockImplementation((key) => {
if (key === '_a') {
return null;
}
return null;
});

const result = migrateUrlState('#/view/savedSearchId', '/newPath');
expect(result).toBe('/newPath#/view/savedSearchId');
});

it('should handle missing global state to null', () => {
(getStateFromOsdUrl as jest.Mock).mockImplementation((key) => {
if (key === '_a') {
return {
columns: ['column1'],
filters: [],
index: 'indexPattern',
interval: 'auto',
query: { language: 'kuery', query: 'test' },
sort: [['field', 'desc']],
savedQuery: 'savedQueryId',
};
}
if (key === '_g') {
return null;
}
return null;
});

const result = migrateUrlState('#/view/savedSearchId', '/newPath');
const decodedResult = decodeURIComponent(result);
const expectedPath =
'/newPath#/view/savedSearchId?_g=null&_a={"discover":{"columns":["column1"],"interval":"auto","sort":[["field","desc"]],"savedQuery":"savedQueryId"},"metadata":{"indexPattern":"indexPattern"}}&_q={"query":{"language":"kuery","query":"test"},"filters":[]}';
expect(decodedResult).toBe(expectedPath);
});

it('should handle present global state', () => {
(getStateFromOsdUrl as jest.Mock).mockImplementation((key) => {
if (key === '_a') {
return {
columns: ['column1'],
filters: [],
index: 'indexPattern',
interval: 'auto',
query: { language: 'kuery', query: 'test' },
sort: [['field', 'desc']],
savedQuery: 'savedQueryId',
};
}
if (key === '_g') {
return {
time: { from: 'now-15m', to: 'now' },
filters: [],
refreshInterval: { pause: true, value: 0 },
};
}
return null;
});

const result = migrateUrlState('#/view/savedSearchId', '/newPath');
const decodedResult = decodeURIComponent(result);
const expectedPath =
'/newPath#/view/savedSearchId?_g={"time":{"from":"now-15m","to":"now"},"filters":[],"refreshInterval":{"pause":true,"value":0}}&_a={"discover":{"columns":["column1"],"interval":"auto","sort":[["field","desc"]],"savedQuery":"savedQueryId"},"metadata":{"indexPattern":"indexPattern"}}&_q={"query":{"language":"kuery","query":"test"},"filters":[]}';
expect(decodedResult).toBe(expectedPath);
});
});

0 comments on commit aaa377e

Please sign in to comment.