From 9e047a9e751fef0cecff49224973b0ac720fddc0 Mon Sep 17 00:00:00 2001 From: abbyhu2000 Date: Fri, 24 Feb 2023 20:01:16 +0000 Subject: [PATCH 1/6] Add metric to metric, bucket to bucket aggregation persistance Signed-off-by: abbyhu2000 --- .../application/components/right_nav.tsx | 12 ++- .../utils/state_management/shared_actions.ts | 2 + .../state_management/visualization_slice.ts | 2 +- .../utils/use/use_persisted_agg_params.ts | 87 +++++++++++++++++++ 4 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.ts diff --git a/src/plugins/vis_builder/public/application/components/right_nav.tsx b/src/plugins/vis_builder/public/application/components/right_nav.tsx index d7e5586b3e94..015619ba1153 100644 --- a/src/plugins/vis_builder/public/application/components/right_nav.tsx +++ b/src/plugins/vis_builder/public/application/components/right_nav.tsx @@ -17,7 +17,12 @@ import { useVisualizationType } from '../utils/use'; import './side_nav.scss'; import { useOpenSearchDashboards } from '../../../../opensearch_dashboards_react/public'; import { VisBuilderServices } from '../../types'; -import { setActiveVisualization, useTypedDispatch } from '../utils/state_management'; +import { + setActiveVisualization, + useTypedDispatch, + useTypedSelector, +} from '../utils/state_management'; +import { usePersistedAggParams } from '../utils/use/use_persisted_agg_params'; export const RightNav = () => { const [newVisType, setNewVisType] = useState(); @@ -28,6 +33,10 @@ export const RightNav = () => { const dispatch = useTypedDispatch(); const StyleSection = ui.containerConfig.style.render; + const { activeVisualization } = useTypedSelector((state) => state.visualization); + const oldAggParams = activeVisualization?.aggConfigParams ?? []; + const persistedAggParams = usePersistedAggParams(types, oldAggParams, activeVisName, newVisType); + const options: Array> = types.all().map(({ name, icon, title }) => ({ value: name, inputDisplay: , @@ -68,6 +77,7 @@ export const RightNav = () => { setActiveVisualization({ name: newVisType, style: types.get(newVisType)?.ui.containerConfig.style.defaults, + aggParams: persistedAggParams, }) ); diff --git a/src/plugins/vis_builder/public/application/utils/state_management/shared_actions.ts b/src/plugins/vis_builder/public/application/utils/state_management/shared_actions.ts index f1dc6ee027b8..205b1aa2e4cc 100644 --- a/src/plugins/vis_builder/public/application/utils/state_management/shared_actions.ts +++ b/src/plugins/vis_builder/public/application/utils/state_management/shared_actions.ts @@ -4,11 +4,13 @@ */ import { createAction } from '@reduxjs/toolkit'; +import { CreateAggConfigParams } from '../../../../../data/common'; import { VisualizationType } from '../../../services/type_service/visualization_type'; interface ActiveVisPayload { name: VisualizationType['name']; style: VisualizationType['ui']['containerConfig']['style']['defaults']; + aggParams: CreateAggConfigParams[]; } export const setActiveVisualization = createAction('setActiveVisualzation'); diff --git a/src/plugins/vis_builder/public/application/utils/state_management/visualization_slice.ts b/src/plugins/vis_builder/public/application/utils/state_management/visualization_slice.ts index ece2618cbbe1..c132b91fc480 100644 --- a/src/plugins/vis_builder/public/application/utils/state_management/visualization_slice.ts +++ b/src/plugins/vis_builder/public/application/utils/state_management/visualization_slice.ts @@ -123,7 +123,7 @@ export const slice = createSlice({ builder.addCase(setActiveVisualization, (state, action) => { state.activeVisualization = { name: action.payload.name, - aggConfigParams: [], + aggConfigParams: action.payload.aggParams, }; }); }, diff --git a/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.ts b/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.ts new file mode 100644 index 000000000000..b6cf9fafe1f6 --- /dev/null +++ b/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.ts @@ -0,0 +1,87 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { integer } from '@opensearch-project/opensearch/api/types'; +import { AggGroupNames, CreateAggConfigParams } from '../../../../../data/common'; +import { Schema } from '../../../../../vis_default_editor/public'; + +export const usePersistedAggParams = ( + types, + oldAggParams: CreateAggConfigParams[], + oldVisType?: string, + newVisType?: string +): CreateAggConfigParams[] => { + if (oldVisType && newVisType) { + const oldVisualizationType = types.get(oldVisType)?.ui.containerConfig.data.schemas.all; + const newVisualizationType = types.get(newVisType)?.ui.containerConfig.data.schemas.all; + const aggMapping = getSchemaMapping(oldVisualizationType, newVisualizationType); + return oldAggParams.map((newAggParam: CreateAggConfigParams) => + updateAggParams(newAggParam, aggMapping) + ); + } + return []; +}; + +// may need to update the value to include a max count, currently all values are adding + +// Map metric fields to metric fields, bucket fields to bucket fields +export const getSchemaMapping = ( + oldVisualizationType: Schema[], + newVisualizationType: Schema[] +): Map => { + const aggMap = new Map(); + + // currently Metrics, Buckets, and None are the three groups. We simply drop the aggregations that belongs to the None group + mapAggParamsSchema(oldVisualizationType, newVisualizationType, AggGroupNames.Metrics, aggMap); + mapAggParamsSchema(oldVisualizationType, newVisualizationType, AggGroupNames.Buckets, aggMap); + + return aggMap; +}; + +export interface AggMapping { + name: string; + maxCount: integer; +} + +export const mapAggParamsSchema = ( + oldVisualizationType: Schema[], + newVisualizationType: Schema[], + aggGroup: string, + map: Map +) => { + const oldSchemas = oldVisualizationType.filter((type) => type.group === aggGroup); + const newSchemas = newVisualizationType.filter((type) => type.group === aggGroup); + + // console.log("newNames", newNames) + oldSchemas.forEach((oldSchema, index) => { + // what if first array is longer than the second one? + if (newSchemas[index]) { + const mappedNewSchema = { + name: newSchemas[index].name, + maxCount: newSchemas[index].max, + }; + map.set(oldSchema.name, mappedNewSchema); + } + }); +}; + +export const updateAggParams = ( + oldAggParam: CreateAggConfigParams, + aggMap: Map +) => { + const newAggParam = { + params: oldAggParam.params, + type: oldAggParam.type, + enabled: oldAggParam.enabled, + id: oldAggParam.id, + schema: oldAggParam.schema, + }; + if (oldAggParam.schema) { + newAggParam.schema = aggMap.has(oldAggParam.schema) + ? aggMap.get(oldAggParam.schema)?.name + : undefined; + } + return newAggParam; +}; From a70d9b8ddd5759e994740d1e2f50249cfa9fc46a Mon Sep 17 00:00:00 2001 From: abbyhu2000 Date: Tue, 28 Feb 2023 23:17:24 +0000 Subject: [PATCH 2/6] Add logics to avoid exceeding the max count for each schema field Signed-off-by: abbyhu2000 --- CHANGELOG.md | 1 + .../utils/use/use_persisted_agg_params.ts | 27 +++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9734f3d1de6..9879054c5ca8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Make build scripts find and use the latest version of Node.js that satisfies `engines.node` ([#3467](https://github.com/opensearch-project/OpenSearch-Dashboards/issues/3467)) - [Multiple DataSource] Refactor test connection to support SigV4 auth type ([#3456](https://github.com/opensearch-project/OpenSearch-Dashboards/issues/3456)) - [Darwin] Add support for Darwin for running OpenSearch snapshots with `yarn opensearch snapshot` ([#3537](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3537)) +- [Vis Builder] Add metric to metric, bucket to bucket aggregation persistence ([#3495](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3495)) ### 🐛 Bug Fixes diff --git a/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.ts b/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.ts index b6cf9fafe1f6..ea478f4a3dbc 100644 --- a/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.ts +++ b/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.ts @@ -17,15 +17,14 @@ export const usePersistedAggParams = ( const oldVisualizationType = types.get(oldVisType)?.ui.containerConfig.data.schemas.all; const newVisualizationType = types.get(newVisType)?.ui.containerConfig.data.schemas.all; const aggMapping = getSchemaMapping(oldVisualizationType, newVisualizationType); - return oldAggParams.map((newAggParam: CreateAggConfigParams) => + const newAggParams = oldAggParams.map((newAggParam: CreateAggConfigParams) => updateAggParams(newAggParam, aggMapping) ); + return newAggParams; } return []; }; -// may need to update the value to include a max count, currently all values are adding - // Map metric fields to metric fields, bucket fields to bucket fields export const getSchemaMapping = ( oldVisualizationType: Schema[], @@ -43,6 +42,7 @@ export const getSchemaMapping = ( export interface AggMapping { name: string; maxCount: integer; + currentCount: integer; } export const mapAggParamsSchema = ( @@ -54,13 +54,12 @@ export const mapAggParamsSchema = ( const oldSchemas = oldVisualizationType.filter((type) => type.group === aggGroup); const newSchemas = newVisualizationType.filter((type) => type.group === aggGroup); - // console.log("newNames", newNames) oldSchemas.forEach((oldSchema, index) => { - // what if first array is longer than the second one? if (newSchemas[index]) { const mappedNewSchema = { name: newSchemas[index].name, maxCount: newSchemas[index].max, + currentCount: 0, }; map.set(oldSchema.name, mappedNewSchema); } @@ -79,9 +78,21 @@ export const updateAggParams = ( schema: oldAggParam.schema, }; if (oldAggParam.schema) { - newAggParam.schema = aggMap.has(oldAggParam.schema) - ? aggMap.get(oldAggParam.schema)?.name - : undefined; + const newSchema = aggMap.get(oldAggParam.schema); + if (newSchema) { + if (newSchema.currentCount < newSchema.maxCount) { + newAggParam.schema = aggMap.get(oldAggParam.schema)?.name; + aggMap.set(oldAggParam.schema, { + name: newSchema.name, + maxCount: newSchema.maxCount, + currentCount: newSchema.currentCount + 1, + }); + } else { + newAggParam.schema = undefined; + } + } else { + newAggParam.schema = undefined; + } } return newAggParam; }; From 77ea970cb18a2455e1372ad016857e0b597493b8 Mon Sep 17 00:00:00 2001 From: abbyhu2000 Date: Tue, 28 Feb 2023 23:21:48 +0000 Subject: [PATCH 3/6] Add changelog entry Signed-off-by: abbyhu2000 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9879054c5ca8..2e595ef02cbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [Darwin] Add support for Darwin for running OpenSearch snapshots with `yarn opensearch snapshot` ([#3537](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3537)) - [Vis Builder] Add metric to metric, bucket to bucket aggregation persistence ([#3495](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3495)) + ### 🐛 Bug Fixes - [Vis Builder] Fixes auto bounds for timeseries bar chart visualization ([2401](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2401)) From 1fa0c1fd2434635965e7a5ecd7edca830c827c44 Mon Sep 17 00:00:00 2001 From: abbyhu2000 Date: Thu, 2 Mar 2023 19:46:40 +0000 Subject: [PATCH 4/6] addressing comments Signed-off-by: abbyhu2000 --- CHANGELOG.md | 1 - .../application/components/right_nav.tsx | 11 ++-- .../utils/state_management/shared_actions.ts | 2 +- .../state_management/visualization_slice.ts | 2 +- .../utils/use/use_persisted_agg_params.ts | 53 +++++++++---------- 5 files changed, 35 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e595ef02cbc..9879054c5ca8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,7 +68,6 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - [Darwin] Add support for Darwin for running OpenSearch snapshots with `yarn opensearch snapshot` ([#3537](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3537)) - [Vis Builder] Add metric to metric, bucket to bucket aggregation persistence ([#3495](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/3495)) - ### 🐛 Bug Fixes - [Vis Builder] Fixes auto bounds for timeseries bar chart visualization ([2401](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2401)) diff --git a/src/plugins/vis_builder/public/application/components/right_nav.tsx b/src/plugins/vis_builder/public/application/components/right_nav.tsx index 015619ba1153..c98638da28f1 100644 --- a/src/plugins/vis_builder/public/application/components/right_nav.tsx +++ b/src/plugins/vis_builder/public/application/components/right_nav.tsx @@ -34,8 +34,13 @@ export const RightNav = () => { const StyleSection = ui.containerConfig.style.render; const { activeVisualization } = useTypedSelector((state) => state.visualization); - const oldAggParams = activeVisualization?.aggConfigParams ?? []; - const persistedAggParams = usePersistedAggParams(types, oldAggParams, activeVisName, newVisType); + const aggConfigParams = activeVisualization?.aggConfigParams ?? []; + const persistedAggParams = usePersistedAggParams( + types, + aggConfigParams, + activeVisName, + newVisType + ); const options: Array> = types.all().map(({ name, icon, title }) => ({ value: name, @@ -77,7 +82,7 @@ export const RightNav = () => { setActiveVisualization({ name: newVisType, style: types.get(newVisType)?.ui.containerConfig.style.defaults, - aggParams: persistedAggParams, + aggConfigParams: persistedAggParams, }) ); diff --git a/src/plugins/vis_builder/public/application/utils/state_management/shared_actions.ts b/src/plugins/vis_builder/public/application/utils/state_management/shared_actions.ts index 205b1aa2e4cc..ebff4f91803c 100644 --- a/src/plugins/vis_builder/public/application/utils/state_management/shared_actions.ts +++ b/src/plugins/vis_builder/public/application/utils/state_management/shared_actions.ts @@ -10,7 +10,7 @@ import { VisualizationType } from '../../../services/type_service/visualization_ interface ActiveVisPayload { name: VisualizationType['name']; style: VisualizationType['ui']['containerConfig']['style']['defaults']; - aggParams: CreateAggConfigParams[]; + aggConfigParams: CreateAggConfigParams[]; } export const setActiveVisualization = createAction('setActiveVisualzation'); diff --git a/src/plugins/vis_builder/public/application/utils/state_management/visualization_slice.ts b/src/plugins/vis_builder/public/application/utils/state_management/visualization_slice.ts index c132b91fc480..6662f9f43d71 100644 --- a/src/plugins/vis_builder/public/application/utils/state_management/visualization_slice.ts +++ b/src/plugins/vis_builder/public/application/utils/state_management/visualization_slice.ts @@ -123,7 +123,7 @@ export const slice = createSlice({ builder.addCase(setActiveVisualization, (state, action) => { state.activeVisualization = { name: action.payload.name, - aggConfigParams: action.payload.aggParams, + aggConfigParams: action.payload.aggConfigParams, }; }); }, diff --git a/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.ts b/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.ts index ea478f4a3dbc..980c5f3e9f38 100644 --- a/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.ts +++ b/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.ts @@ -3,13 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { integer } from '@opensearch-project/opensearch/api/types'; import { AggGroupNames, CreateAggConfigParams } from '../../../../../data/common'; import { Schema } from '../../../../../vis_default_editor/public'; export const usePersistedAggParams = ( types, - oldAggParams: CreateAggConfigParams[], + aggConfigParams: CreateAggConfigParams[], oldVisType?: string, newVisType?: string ): CreateAggConfigParams[] => { @@ -17,10 +16,10 @@ export const usePersistedAggParams = ( const oldVisualizationType = types.get(oldVisType)?.ui.containerConfig.data.schemas.all; const newVisualizationType = types.get(newVisType)?.ui.containerConfig.data.schemas.all; const aggMapping = getSchemaMapping(oldVisualizationType, newVisualizationType); - const newAggParams = oldAggParams.map((newAggParam: CreateAggConfigParams) => - updateAggParams(newAggParam, aggMapping) + const updatedAggConfigParams = aggConfigParams.map((aggConfigParam: CreateAggConfigParams) => + updateAggParams(aggConfigParam, aggMapping) ); - return newAggParams; + return updatedAggConfigParams; } return []; }; @@ -41,8 +40,8 @@ export const getSchemaMapping = ( export interface AggMapping { name: string; - maxCount: integer; - currentCount: integer; + maxCount: number; + currentCount: number; } export const mapAggParamsSchema = ( @@ -70,29 +69,27 @@ export const updateAggParams = ( oldAggParam: CreateAggConfigParams, aggMap: Map ) => { - const newAggParam = { - params: oldAggParam.params, - type: oldAggParam.type, - enabled: oldAggParam.enabled, - id: oldAggParam.id, - schema: oldAggParam.schema, - }; + const newAggParam = { ...oldAggParam }; if (oldAggParam.schema) { const newSchema = aggMap.get(oldAggParam.schema); - if (newSchema) { - if (newSchema.currentCount < newSchema.maxCount) { - newAggParam.schema = aggMap.get(oldAggParam.schema)?.name; - aggMap.set(oldAggParam.schema, { - name: newSchema.name, - maxCount: newSchema.maxCount, - currentCount: newSchema.currentCount + 1, - }); - } else { - newAggParam.schema = undefined; - } - } else { - newAggParam.schema = undefined; - } + newAggParam.schema = newSchema + ? newSchema.currentCount < newSchema.maxCount + ? assignNewSchemaType(oldAggParam, aggMap, newSchema) + : undefined + : undefined; } return newAggParam; }; + +export const assignNewSchemaType = ( + oldAggParam: any, + aggMap: Map, + newSchema: AggMapping +) => { + aggMap.set(oldAggParam.schema, { + name: newSchema.name, + maxCount: newSchema.maxCount, + currentCount: newSchema.currentCount + 1, + }); + return aggMap.get(oldAggParam.schema)?.name; +}; From f4199e4df23894b5935295564f78cb0745af3c90 Mon Sep 17 00:00:00 2001 From: abbyhu2000 Date: Fri, 3 Mar 2023 16:55:02 +0000 Subject: [PATCH 5/6] Add unit tests for functions in use_persisted_agg_params Signed-off-by: abbyhu2000 --- .../public/application/utils/mocks.ts | 10 + .../use/use_persisted_agg_params.test.tsx | 201 ++++++++++++++++++ 2 files changed, 211 insertions(+) create mode 100644 src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.test.tsx diff --git a/src/plugins/vis_builder/public/application/utils/mocks.ts b/src/plugins/vis_builder/public/application/utils/mocks.ts index 6feb98aaa930..bbf9c3b1d446 100644 --- a/src/plugins/vis_builder/public/application/utils/mocks.ts +++ b/src/plugins/vis_builder/public/application/utils/mocks.ts @@ -54,6 +54,16 @@ export const createVisBuilderServicesMock = () => { }, }, }, + { + name: 'viz', + ui: { + containerConfig: { + style: { + defaults: 'style default states', + }, + }, + }, + }, ], }, }; diff --git a/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.test.tsx b/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.test.tsx new file mode 100644 index 000000000000..0c79e2e7f254 --- /dev/null +++ b/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.test.tsx @@ -0,0 +1,201 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { CreateAggConfigParams } from '../../../../../data/common'; +import { AggGroupNames } from '../../../../../data/common'; +import { Schema } from '../../../../../vis_default_editor/public'; +import { VisBuilderServices } from '../../../types'; +import { createVisBuilderServicesMock } from '../mocks'; +import { + AggMapping, + getSchemaMapping, + updateAggParams, + usePersistedAggParams, +} from './use_persisted_agg_params'; + +describe('new usePersistedAggParams', () => { + beforeEach(() => {}); + + test('return the correct metric to metric, bucket to bucket mapping', () => {}); + + test('drop the aggregations if it exceeds the max count', () => {}); + + test('drop the aggregation when there is no schema', () => {}); +}); + +describe('updateAggParams', () => { + let oldAggParam: CreateAggConfigParams; + let aggMap: Map; + let assignNewSchemaType: any; + + beforeEach(() => { + oldAggParam = { + type: '', + enabled: true, + schema: '', + }; + aggMap = new Map(); + aggMap.set('old metric', { + currentCount: 0, + maxCount: 1, + name: 'new metric', + }); + aggMap.set('old bucket', { + currentCount: 0, + maxCount: 1, + name: 'new bucket', + }); + assignNewSchemaType = jest.fn(); + }); + + test('return with the undefined schema if the old schema title does not get a mapping', () => { + const newAgg = updateAggParams(oldAggParam, aggMap); + expect(newAgg).toEqual(oldAggParam); + }); + + test('return the original aggregation with undefined schema', () => { + oldAggParam.schema = 'noMappingSchema'; + const newAgg = updateAggParams(oldAggParam, aggMap); + expect(newAgg).toEqual({ + type: '', + enabled: true, + schema: undefined, + }); + }); + + test('return with the updated schema for metric', () => { + oldAggParam.schema = 'old metric'; + const newAgg = updateAggParams(oldAggParam, aggMap); + expect(newAgg).toEqual({ + type: '', + enabled: true, + schema: 'new metric', + }); + expect(aggMap.get('old metric')).toEqual({ + currentCount: 1, + maxCount: 1, + name: 'new metric', + }); + }); + + test('return with the undefined schema if the mapped schema fields already reach max count', () => { + oldAggParam.schema = 'old metric'; + aggMap.set('old metric', { + currentCount: 1, + maxCount: 1, + name: 'new metric', + }); + const newAgg = updateAggParams(oldAggParam, aggMap); + expect(newAgg).toEqual({ + type: '', + enabled: true, + schema: undefined, + }); + }); +}); + +describe('getSchemaMapping', () => { + let oldVisualizationType: Schema[]; + let newVisualizationType: Schema[]; + let schemaMetricTemplate: Schema; + let schemaBucketTemplate: Schema; + + beforeEach(() => { + schemaMetricTemplate = { + aggFilter: [], + editor: '', + group: AggGroupNames.Metrics, + max: 1, + min: 1, + name: '', + params: [], + title: '', + defaults: '', + }; + schemaBucketTemplate = { + aggFilter: [], + editor: '', + group: AggGroupNames.Buckets, + max: 1, + min: 1, + name: '', + params: [], + title: '', + defaults: '', + }; + }); + + test('map metric schema to metric schema, bucket schema to bucket schema according to order', async () => { + oldVisualizationType = [ + { ...schemaMetricTemplate, name: 'old metric 1' }, + { ...schemaBucketTemplate, name: 'old bucket 1' }, + { ...schemaMetricTemplate, name: 'old metric 2' }, + { ...schemaBucketTemplate, name: 'old bucket 2' }, + { ...schemaBucketTemplate, name: 'old bucket 3' }, + { ...schemaBucketTemplate, name: 'old bucket 4' }, + { ...schemaBucketTemplate, group: AggGroupNames.None, name: 'none' }, + ]; + newVisualizationType = [ + { ...schemaMetricTemplate, name: 'new metric 1', max: 1 }, + { ...schemaMetricTemplate, name: 'new metric 2', max: 2 }, + { ...schemaMetricTemplate, name: 'new metric 3', max: 3 }, + { ...schemaBucketTemplate, name: 'new bucket 1', max: 4 }, + { ...schemaBucketTemplate, name: 'new bucket 2', max: 5 }, + { ...schemaBucketTemplate, name: 'new bucket 3', max: 6 }, + ]; + const mappingResult = getSchemaMapping(oldVisualizationType, newVisualizationType); + expect(mappingResult).toMatchInlineSnapshot(` + Map { + "old metric 1" => Object { + "currentCount": 0, + "maxCount": 1, + "name": "new metric 1", + }, + "old metric 2" => Object { + "currentCount": 0, + "maxCount": 2, + "name": "new metric 2", + }, + "old bucket 1" => Object { + "currentCount": 0, + "maxCount": 4, + "name": "new bucket 1", + }, + "old bucket 2" => Object { + "currentCount": 0, + "maxCount": 5, + "name": "new bucket 2", + }, + "old bucket 3" => Object { + "currentCount": 0, + "maxCount": 6, + "name": "new bucket 3", + }, + } + `); + }); +}); + +describe('usePersistedAggParams', () => { + let mockServices: jest.Mocked; + let types: any; + let aggConfigParams: CreateAggConfigParams[]; + let oldVisType: string | undefined; + let newVisType: string | undefined; + + beforeEach(() => { + mockServices = createVisBuilderServicesMock(); + types = mockServices.types; + aggConfigParams = []; + oldVisType = 'oldVisType'; + newVisType = 'newVisType'; + }); + + test('return an empty array when there is no old vis type or new vis type', async () => { + oldVisType = ''; + const persistResult = usePersistedAggParams(types, aggConfigParams, oldVisType, newVisType); + expect(persistResult).toEqual([]); + }); +}); From 1d32f584f6e5230134716d875b07b363ce0d577d Mon Sep 17 00:00:00 2001 From: abbyhu2000 Date: Wed, 8 Mar 2023 21:04:25 +0000 Subject: [PATCH 6/6] rewrite unit tests to test the entire functionality Signed-off-by: abbyhu2000 --- .../public/application/utils/mocks.ts | 11 +- .../use/use_persisted_agg_params.test.tsx | 357 +++++++++++++----- 2 files changed, 255 insertions(+), 113 deletions(-) diff --git a/src/plugins/vis_builder/public/application/utils/mocks.ts b/src/plugins/vis_builder/public/application/utils/mocks.ts index bbf9c3b1d446..25b9847986de 100644 --- a/src/plugins/vis_builder/public/application/utils/mocks.ts +++ b/src/plugins/vis_builder/public/application/utils/mocks.ts @@ -54,17 +54,8 @@ export const createVisBuilderServicesMock = () => { }, }, }, - { - name: 'viz', - ui: { - containerConfig: { - style: { - defaults: 'style default states', - }, - }, - }, - }, ], + get: jest.fn(), }, }; diff --git a/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.test.tsx b/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.test.tsx index 0c79e2e7f254..6011ac33f71f 100644 --- a/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.test.tsx +++ b/src/plugins/vis_builder/public/application/utils/use/use_persisted_agg_params.test.tsx @@ -16,91 +16,15 @@ import { } from './use_persisted_agg_params'; describe('new usePersistedAggParams', () => { - beforeEach(() => {}); - - test('return the correct metric to metric, bucket to bucket mapping', () => {}); - - test('drop the aggregations if it exceeds the max count', () => {}); - - test('drop the aggregation when there is no schema', () => {}); -}); - -describe('updateAggParams', () => { - let oldAggParam: CreateAggConfigParams; - let aggMap: Map; - let assignNewSchemaType: any; - - beforeEach(() => { - oldAggParam = { - type: '', - enabled: true, - schema: '', - }; - aggMap = new Map(); - aggMap.set('old metric', { - currentCount: 0, - maxCount: 1, - name: 'new metric', - }); - aggMap.set('old bucket', { - currentCount: 0, - maxCount: 1, - name: 'new bucket', - }); - assignNewSchemaType = jest.fn(); - }); - - test('return with the undefined schema if the old schema title does not get a mapping', () => { - const newAgg = updateAggParams(oldAggParam, aggMap); - expect(newAgg).toEqual(oldAggParam); - }); - - test('return the original aggregation with undefined schema', () => { - oldAggParam.schema = 'noMappingSchema'; - const newAgg = updateAggParams(oldAggParam, aggMap); - expect(newAgg).toEqual({ - type: '', - enabled: true, - schema: undefined, - }); - }); - - test('return with the updated schema for metric', () => { - oldAggParam.schema = 'old metric'; - const newAgg = updateAggParams(oldAggParam, aggMap); - expect(newAgg).toEqual({ - type: '', - enabled: true, - schema: 'new metric', - }); - expect(aggMap.get('old metric')).toEqual({ - currentCount: 1, - maxCount: 1, - name: 'new metric', - }); - }); - - test('return with the undefined schema if the mapped schema fields already reach max count', () => { - oldAggParam.schema = 'old metric'; - aggMap.set('old metric', { - currentCount: 1, - maxCount: 1, - name: 'new metric', - }); - const newAgg = updateAggParams(oldAggParam, aggMap); - expect(newAgg).toEqual({ - type: '', - enabled: true, - schema: undefined, - }); - }); -}); - -describe('getSchemaMapping', () => { - let oldVisualizationType: Schema[]; - let newVisualizationType: Schema[]; + const types = { + get: jest.fn(), + }; let schemaMetricTemplate: Schema; let schemaBucketTemplate: Schema; + let oldVisualizationType: Schema[]; + let newVisualizationType: Schema[]; + let aggConfigParam: CreateAggConfigParams; + let aggConfigParams: CreateAggConfigParams[]; beforeEach(() => { schemaMetricTemplate = { @@ -125,26 +49,59 @@ describe('getSchemaMapping', () => { title: '', defaults: '', }; + aggConfigParam = { + type: '', + schema: '', + }; }); - test('map metric schema to metric schema, bucket schema to bucket schema according to order', async () => { + test('return the correct metric-to-metric, bucket-to-bucket mapping and correct persisted aggregations', () => { oldVisualizationType = [ { ...schemaMetricTemplate, name: 'old metric 1' }, { ...schemaBucketTemplate, name: 'old bucket 1' }, { ...schemaMetricTemplate, name: 'old metric 2' }, { ...schemaBucketTemplate, name: 'old bucket 2' }, { ...schemaBucketTemplate, name: 'old bucket 3' }, - { ...schemaBucketTemplate, name: 'old bucket 4' }, - { ...schemaBucketTemplate, group: AggGroupNames.None, name: 'none' }, ]; newVisualizationType = [ { ...schemaMetricTemplate, name: 'new metric 1', max: 1 }, { ...schemaMetricTemplate, name: 'new metric 2', max: 2 }, - { ...schemaMetricTemplate, name: 'new metric 3', max: 3 }, { ...schemaBucketTemplate, name: 'new bucket 1', max: 4 }, { ...schemaBucketTemplate, name: 'new bucket 2', max: 5 }, { ...schemaBucketTemplate, name: 'new bucket 3', max: 6 }, ]; + types.get + .mockReturnValueOnce({ + ui: { + containerConfig: { + data: { + schemas: { + all: oldVisualizationType, + }, + }, + }, + }, + }) + .mockReturnValueOnce({ + ui: { + containerConfig: { + data: { + schemas: { + all: newVisualizationType, + }, + }, + }, + }, + }); + aggConfigParams = [ + { ...aggConfigParam, schema: 'old metric 1' }, + { ...aggConfigParam, schema: 'old bucket 1' }, + { ...aggConfigParam, schema: 'old metric 2' }, + { ...aggConfigParam, schema: 'old bucket 2' }, + { ...aggConfigParam, schema: 'old bucket 3' }, + { ...aggConfigParam, schema: 'old metric 2' }, + ]; + const mappingResult = getSchemaMapping(oldVisualizationType, newVisualizationType); expect(mappingResult).toMatchInlineSnapshot(` Map { @@ -175,27 +132,221 @@ describe('getSchemaMapping', () => { }, } `); + const persistResult = usePersistedAggParams( + types, + aggConfigParams, + 'old vis type', + 'new vis type' + ); + expect(persistResult).toMatchInlineSnapshot(` + Array [ + Object { + "schema": "new metric 1", + "type": "", + }, + Object { + "schema": "new bucket 1", + "type": "", + }, + Object { + "schema": "new metric 2", + "type": "", + }, + Object { + "schema": "new bucket 2", + "type": "", + }, + Object { + "schema": "new bucket 3", + "type": "", + }, + Object { + "schema": "new metric 2", + "type": "", + }, + ] + `); }); -}); -describe('usePersistedAggParams', () => { - let mockServices: jest.Mocked; - let types: any; - let aggConfigParams: CreateAggConfigParams[]; - let oldVisType: string | undefined; - let newVisType: string | undefined; + test('drop the schema fields when it can not be mapped or do not belong to either metric or bucket group', () => { + oldVisualizationType = [ + { ...schemaMetricTemplate, name: 'old metric 1' }, + { ...schemaMetricTemplate, name: 'old metric 2' }, + { ...schemaBucketTemplate, name: 'old bucket 1' }, + { ...schemaMetricTemplate, name: 'undefined group', group: AggGroupNames.None }, + ]; + newVisualizationType = [ + { ...schemaMetricTemplate, name: 'new metric 1', max: 1 }, + { ...schemaBucketTemplate, name: 'new bucket 2', max: 1 }, + ]; + types.get + .mockReturnValueOnce({ + ui: { + containerConfig: { + data: { + schemas: { + all: oldVisualizationType, + }, + }, + }, + }, + }) + .mockReturnValueOnce({ + ui: { + containerConfig: { + data: { + schemas: { + all: newVisualizationType, + }, + }, + }, + }, + }); + aggConfigParams = [ + { ...aggConfigParam, schema: 'old metric 1' }, + { ...aggConfigParam, schema: 'old bucket 1' }, + ]; + + const mappingResult = getSchemaMapping(oldVisualizationType, newVisualizationType); + expect(mappingResult).toMatchInlineSnapshot(` + Map { + "old metric 1" => Object { + "currentCount": 0, + "maxCount": 1, + "name": "new metric 1", + }, + "old bucket 1" => Object { + "currentCount": 0, + "maxCount": 1, + "name": "new bucket 2", + }, + } + `); + const persistResult = usePersistedAggParams( + types, + aggConfigParams, + 'old vis type', + 'new vis type' + ); + expect(persistResult).toMatchInlineSnapshot(` + Array [ + Object { + "schema": "new metric 1", + "type": "", + }, + Object { + "schema": "new bucket 2", + "type": "", + }, + ] + `); + }); + + test('aggregations with undefined schema remain undefined; schema will be set to undefined if aggregations that exceeds the max amount', () => { + oldVisualizationType = [{ ...schemaMetricTemplate, name: 'old metric 1' }]; + newVisualizationType = [{ ...schemaMetricTemplate, name: 'new metric 1', max: 1 }]; + types.get + .mockReturnValueOnce({ + ui: { + containerConfig: { + data: { + schemas: { + all: oldVisualizationType, + }, + }, + }, + }, + }) + .mockReturnValueOnce({ + ui: { + containerConfig: { + data: { + schemas: { + all: newVisualizationType, + }, + }, + }, + }, + }); + aggConfigParams = [ + { ...aggConfigParam, schema: undefined }, + { ...aggConfigParam, schema: 'old metric 1' }, + { ...aggConfigParam, schema: 'old metric 1' }, + ]; + + const mappingResult = getSchemaMapping(oldVisualizationType, newVisualizationType); + expect(mappingResult).toMatchInlineSnapshot(` + Map { + "old metric 1" => Object { + "currentCount": 0, + "maxCount": 1, + "name": "new metric 1", + }, + } + `); + const persistResult = usePersistedAggParams( + types, + aggConfigParams, + 'old vis type', + 'new vis type' + ); + expect(persistResult).toMatchInlineSnapshot(` + Array [ + Object { + "schema": undefined, + "type": "", + }, + Object { + "schema": "new metric 1", + "type": "", + }, + Object { + "schema": undefined, + "type": "", + }, + ] + `); + }); + + test('return an empty array when there are no aggregations for persistence', () => { + oldVisualizationType = [{ ...schemaMetricTemplate, name: 'old metric 1' }]; + newVisualizationType = [{ ...schemaMetricTemplate, name: 'new metric 1', max: 1 }]; + types.get + .mockReturnValueOnce({ + ui: { + containerConfig: { + data: { + schemas: { + all: oldVisualizationType, + }, + }, + }, + }, + }) + .mockReturnValueOnce({ + ui: { + containerConfig: { + data: { + schemas: { + all: newVisualizationType, + }, + }, + }, + }, + }); - beforeEach(() => { - mockServices = createVisBuilderServicesMock(); - types = mockServices.types; aggConfigParams = []; - oldVisType = 'oldVisType'; - newVisType = 'newVisType'; + const persistResult = usePersistedAggParams( + types, + aggConfigParams, + 'old vis type', + 'new vis type' + ); + expect(persistResult).toMatchInlineSnapshot(`Array []`); }); - test('return an empty array when there is no old vis type or new vis type', async () => { - oldVisType = ''; - const persistResult = usePersistedAggParams(types, aggConfigParams, oldVisType, newVisType); - expect(persistResult).toEqual([]); + test('return an empty array when there are no new vis type or old vis type', () => { + const persistResult = usePersistedAggParams(types, aggConfigParams); + expect(persistResult).toMatchInlineSnapshot(`Array []`); }); });