From 6810da84e7b1c777f63988a54f295d0c588e0798 Mon Sep 17 00:00:00 2001 From: Suren Date: Mon, 18 Dec 2023 19:08:59 +0530 Subject: [PATCH] #9739: Fix - Incorrect connection of the parent table with the map and other widget (#9804) --- .../widgets/builder/wizard/ChartWizard.jsx | 1 + .../widgets/builder/wizard/map/MapCatalog.jsx | 2 +- .../__tests__/dependenciesToWidget-test.jsx | 139 ++++++++++++++++++ .../widgets/enhancers/dependenciesToWidget.js | 11 +- web/client/epics/widgets.js | 12 +- web/client/plugins/Dashboard.jsx | 3 +- .../plugins/widgetbuilder/ChartBuilder.jsx | 4 +- .../enhancers/chartLayerSelector.js | 2 +- .../enhancers/connection/withConnectButton.js | 40 ++--- web/client/selectors/widgets.js | 4 +- web/client/utils/WidgetsUtils.js | 12 ++ .../utils/__tests__/WidgetsUtils-test.js | 11 +- 12 files changed, 205 insertions(+), 36 deletions(-) diff --git a/web/client/components/widgets/builder/wizard/ChartWizard.jsx b/web/client/components/widgets/builder/wizard/ChartWizard.jsx index 914a456eba..29743133ef 100644 --- a/web/client/components/widgets/builder/wizard/ChartWizard.jsx +++ b/web/client/components/widgets/builder/wizard/ChartWizard.jsx @@ -75,6 +75,7 @@ const renderPreview = ({ data = {}, layer, dependencies = {}, setValid = () => { setValid(false); setErrors({...errors, [layer.name]: true}); }} + id={data.id} isAnimationActive={false} dependencies={dependencies} dependenciesMap={data.dependenciesMap} diff --git a/web/client/components/widgets/builder/wizard/map/MapCatalog.jsx b/web/client/components/widgets/builder/wizard/map/MapCatalog.jsx index e991a8b0a0..432d550db6 100644 --- a/web/client/components/widgets/builder/wizard/map/MapCatalog.jsx +++ b/web/client/components/widgets/builder/wizard/map/MapCatalog.jsx @@ -80,7 +80,7 @@ const MapCatalog = ({ : i)} loading={loading} onItemClick={({ map } = {}, props, event) => { - if (event.ctrlKey) { + if (event.ctrlKey || event.metaKey) { return onSelected(isEmpty(selected) ? castArray(map) : castArray(selected).concat(map)); diff --git a/web/client/components/widgets/enhancers/__tests__/dependenciesToWidget-test.jsx b/web/client/components/widgets/enhancers/__tests__/dependenciesToWidget-test.jsx index 836f7f4d06..052d09f097 100644 --- a/web/client/components/widgets/enhancers/__tests__/dependenciesToWidget-test.jsx +++ b/web/client/components/widgets/enhancers/__tests__/dependenciesToWidget-test.jsx @@ -262,4 +262,143 @@ describe('dependenciesToWidget enhancer', () => { const response = buildDependencies(null, deps, originalWidgetId); expect(response).toBe(deps); }); + it('Return dependencies if there is a parent table', () => { + const dependencyMap = { + "viewport": "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].maps[3800a3a0-9030-11ee-b036-b16bb8d06c94].viewport", + "layers": "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].maps[3800a3a0-9030-11ee-b036-b16bb8d06c94].layers", + "filter": "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].maps[3800a3a0-9030-11ee-b036-b16bb8d06c94].filter", + "quickFilters": "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].maps[3800a3a0-9030-11ee-b036-b16bb8d06c94].quickFilters", + "layer": "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].maps[3800a3a0-9030-11ee-b036-b16bb8d06c94].layer", + "options": "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].maps[3800a3a0-9030-11ee-b036-b16bb8d06c94].options", + "mapSync": "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].mapSync", + "dependenciesMap": "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].dependenciesMap" + }; + const deps = { + "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].dependenciesMap": { + "filter": "widgets[34792a90-9030-11ee-b036-b16bb8d06c94].filter", + "quickFilters": "widgets[34792a90-9030-11ee-b036-b16bb8d06c94].quickFilters", + "layer": "widgets[34792a90-9030-11ee-b036-b16bb8d06c94].layer", + "options": "widgets[34792a90-9030-11ee-b036-b16bb8d06c94].options", + "dependenciesMap": "widgets[34792a90-9030-11ee-b036-b16bb8d06c94].dependenciesMap", + "mapSync": "widgets[34792a90-9030-11ee-b036-b16bb8d06c94].mapSync" + }, + "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].mapSync": true, + "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].maps[3800a3a0-9030-11ee-b036-b16bb8d06c94].viewport": { + "bounds": { + "minx": -10428653.241920743, + "miny": 2596212.3657196583, + "maxx": -8237050.76692817, + "maxy": 3907260.274867002 + }, + "crs": "EPSG:3857", + "rotation": 0 + }, + "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].maps[3800a3a0-9030-11ee-b036-b16bb8d06c94].center": { + "x": -83.83843600000002, + "y": 28.021909206829974, + "crs": "EPSG:4326" + }, + "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].maps[3800a3a0-9030-11ee-b036-b16bb8d06c94].zoom": 5, + "widgets[3d418c80-9030-11ee-b036-b16bb8d06c94].maps[3800a3a0-9030-11ee-b036-b16bb8d06c94].layers": [ + { + "type": "osm", + "title": "Open Street Map", + "name": "mapnik", + "source": "osm", + "group": "background", + "visibility": true, + "id": "mapnik__0" + }, + { + "type": "wms", + "featureInfo": null, + "url": "https://gs-stable.geosolutionsgroup.com/geoserver/wms", + "visibility": true, + "dimensions": [ + + ], + "name": "gs:us_states", + "title": "States of US", + "description": "", + "bbox": { + "crs": "EPSG:4326", + "bounds": { + "minx": -124.73142200000001, + "miny": 24.955967, + "maxx": -66.969849, + "maxy": 49.371735 + } + }, + "links": [], + "params": {}, + "allowedSRS": {}, + "imageFormats": [], + "infoFormats": [], + "search": { + "type": "wfs", + "url": "https://gs-stable.geosolutionsgroup.com/geoserver/wfs" + }, + "id": "gs:us_states__3bb39980-9030-11ee-b036-b16bb8d06c94" + } + ], + "layers": [], + "widgets[34792a90-9030-11ee-b036-b16bb8d06c94].quickFilters": { + "STATE_NAME": { + "rawValue": "florida", + "value": "florida", + "operator": "ilike", + "type": "string", + "attribute": "STATE_NAME" + } + }, + "widgets[34792a90-9030-11ee-b036-b16bb8d06c94].mapSync": false, + "widgets[34792a90-9030-11ee-b036-b16bb8d06c94].layer": { + "type": "wms", + "featureInfo": null, + "url": "https://gs-stable.geosolutionsgroup.com/geoserver/wms", + "visibility": true, + "dimensions": [ + + ], + "name": "gs:us_states", + "title": "States of US", + "description": "", + "bbox": { + "crs": "EPSG:4326", + "bounds": { + "minx": -124.73142200000001, + "miny": 24.955967, + "maxx": -66.969849, + "maxy": 49.371735 + } + }, + "links": [], + "params": {}, + "allowedSRS": {}, + "imageFormats": [], + "infoFormats": [], + "search": { + "type": "wfs", + "url": "https://gs-stable.geosolutionsgroup.com/geoserver/wfs" + } + }, + "widgets[34792a90-9030-11ee-b036-b16bb8d06c94].options": { + "propertyName": [{"name": "STATE_NAME"}, {"name": "STATE_FIPS"}, {"name": "SUB_REGION"}, {"name": "STATE_ABBR"}, {"name": "LAND_KM"}, {"name": "WATER_KM"}, {"name": "PERSONS"}, {"name": "FAMILIES"}, {"name": "HOUSHOLD"}, {"name": "MALE"}, {"name": "FEMALE"}, {"name": "WORKERS"}, {"name": "DRVALONE"}, {"name": "CARPOOL"}, {"name": "PUBTRANS"}, {"name": "EMPLOYED"}, {"name": "UNEMPLOY"}, {"name": "SERVICE"}, {"name": "MANUAL"}, {"name": "P_MALE"}, {"name": "P_FEMALE"}, {"name": "SAMP_POP"}] + } + }; + const response = buildDependencies(dependencyMap, deps, "e81849f0-9404-11ee-b8a8-2f8d898ee742"); + expect(response).toEqual({ + viewport: {bounds: {minx: -10428653.241920743, miny: 2596212.3657196583, maxx: -8237050.76692817, maxy: 3907260.274867002}, crs: 'EPSG:3857', rotation: 0}, + layers: [ + {type: 'osm', title: 'Open Street Map', name: 'mapnik', source: 'osm', group: 'background', visibility: true, id: 'mapnik__0'}, + {type: 'wms', featureInfo: null, url: 'https://gs-stable.geosolutionsgroup.com/geoserver/wms', visibility: true, dimensions: [], name: 'gs:us_states', title: 'States of US', description: '', bbox: {crs: 'EPSG:4326', bounds: {minx: -124.73142200000001, miny: 24.955967, maxx: -66.969849, maxy: 49.371735}}, links: [], params: {}, allowedSRS: {}, imageFormats: [], infoFormats: [], search: {type: 'wfs', url: 'https://gs-stable.geosolutionsgroup.com/geoserver/wfs'}, id: 'gs:us_states__3bb39980-9030-11ee-b036-b16bb8d06c94'} + ], + filter: undefined, + quickFilters: {STATE_NAME: {rawValue: 'florida', value: 'florida', operator: 'ilike', type: 'string', attribute: 'STATE_NAME'}}, + layer: {type: 'wms', featureInfo: null, url: 'https://gs-stable.geosolutionsgroup.com/geoserver/wms', visibility: true, dimensions: [], name: 'gs:us_states', title: 'States of US', description: '', bbox: {crs: 'EPSG:4326', bounds: {minx: -124.73142200000001, miny: 24.955967, maxx: -66.969849, maxy: 49.371735}}, links: [], params: {}, allowedSRS: {}, imageFormats: [], infoFormats: [], search: {type: 'wfs', url: 'https://gs-stable.geosolutionsgroup.com/geoserver/wfs'}}, + options: {propertyName: [{name: 'STATE_NAME'}, {name: 'STATE_FIPS'}, {name: 'SUB_REGION'}, {name: 'STATE_ABBR'}, {name: 'LAND_KM'}, {name: 'WATER_KM'}, {name: 'PERSONS'}, {name: 'FAMILIES'}, {name: 'HOUSHOLD'}, {name: 'MALE'}, {name: 'FEMALE'}, {name: 'WORKERS'}, {name: 'DRVALONE'}, {name: 'CARPOOL'}, {name: 'PUBTRANS'}, {name: 'EMPLOYED'}, {name: 'UNEMPLOY'}, {name: 'SERVICE'}, {name: 'MANUAL'}, {name: 'P_MALE'}, {name: 'P_FEMALE'}, {name: 'SAMP_POP'}]}, + mapSync: true, + dependenciesMap: undefined + }); + }); }); diff --git a/web/client/components/widgets/enhancers/dependenciesToWidget.js b/web/client/components/widgets/enhancers/dependenciesToWidget.js index 21359ca417..db5549b469 100644 --- a/web/client/components/widgets/enhancers/dependenciesToWidget.js +++ b/web/client/components/widgets/enhancers/dependenciesToWidget.js @@ -64,17 +64,18 @@ import { pick } from 'lodash'; * // the enhancer will pass to the component of dependencies={counterDependencies} */ -export const buildDependencies = (map, deps, originalWidgetId) => { +export const buildDependencies = (map, deps, originalWidgetId, updatedDependencyMap = []) => { if (map) { const dependenciesGenerated = Object.keys(map).reduce((ret, k) => { - if (k === "dependenciesMap" && deps[map[k]] && deps[map.mapSync] && - deps[map[k]][k] && deps[map[k]][k].indexOf(originalWidgetId) === -1 // avoiding loop - && !ret.mapSync + if (k === "dependenciesMap" && deps[map[k]] && deps[map.mapSync] && deps[map[k]][k] + && originalWidgetId && deps[map[k]][k].indexOf(originalWidgetId) === -1 + && updatedDependencyMap.every(dep => deps[map[k]][k] !== dep) ) { + const _updatedDependencyMap = updatedDependencyMap.concat(deps[map[k]][k]); // go recursively until we get the dependencies from table ancestors return { ...ret, - ...pick(buildDependencies(deps[map[k]], deps, originalWidgetId), ["options", "layer", "quickFilters", "filter", "dependenciesMap"]) + ...pick(buildDependencies(deps[map[k]], deps, originalWidgetId, _updatedDependencyMap), ["options", "layer", "quickFilters", "filter", "dependenciesMap"]) }; } return { diff --git a/web/client/epics/widgets.js b/web/client/epics/widgets.js index 4b6887d8b7..edcece197d 100644 --- a/web/client/epics/widgets.js +++ b/web/client/epics/widgets.js @@ -49,7 +49,7 @@ const updateDependencyMap = (active, targetId, { dependenciesMap, mappings}) => const id = (WIDGETS_REGEX.exec(targetId) || [])[1]; const cleanDependenciesMap = omitBy(dependenciesMap, i => i.indexOf(id) === -1); - + const depToTheWidget = targetId.split(".maps")[0]; const overrides = Object.keys(mappings).filter(k => mappings[k] !== undefined).reduce( (ov, k) => { if (!endsWith(targetId, "map") && includes(tableDependencies, k)) { return { @@ -66,12 +66,12 @@ const updateDependencyMap = (active, targetId, { dependenciesMap, mappings}) => } return { ...ov, - [k]: `${targetId.replace(/.map$/, "")}.${mappings[k]}` + [k]: `${depToTheWidget}.${mappings[k]}` }; } return ov; }, {}); - const depToTheWidget = targetId.split(".maps")[0]; + return active ? { ...cleanDependenciesMap, ...overrides, ["dependenciesMap"]: `${depToTheWidget}.dependenciesMap`, ["mapSync"]: `${depToTheWidget}.mapSync`} : omit(cleanDependenciesMap, [Object.keys(mappings)]); @@ -106,11 +106,11 @@ const getValidLocationChange = action$ => * @param {string} dependency the dependency element id to add * @param {object} options dependency mapping options. Must contain `mappings` object */ -const configureDependency = (active, dependency, options, targetDependenciesMap) => +const configureDependency = (active, dependency, options) => Rx.Observable.of( onEditorChange("mapSync", active), onEditorChange('dependenciesMap', - updateDependencyMap(active, dependency, options, targetDependenciesMap) + updateDependencyMap(active, dependency, options) ) ); @@ -184,7 +184,7 @@ export const toggleWidgetConnectFlow = (action$, {getState = () => {}} = {}) => if (widget.widgetType === 'map') { deps = deps.filter(d => (WIDGETS_MAPS_REGEX.exec(d) || [])[2] === widget.selectedMapId); } - return configureDependency(active, deps[0], options, widget.dependeciesMap).concat(Rx.Observable.of(toggleDependencySelector(false, {}))); + return configureDependency(active, deps[0], options).concat(Rx.Observable.of(toggleDependencySelector(false, {}))); }).takeUntil( action$.ofType(LOCATION_CHANGE) .merge(action$.filter(({ type, key } = {}) => type === EDITOR_SETTING_CHANGE && key === DEPENDENCY_SELECTOR_KEY)) diff --git a/web/client/plugins/Dashboard.jsx b/web/client/plugins/Dashboard.jsx index 6af04b1949..4c8cf71eea 100644 --- a/web/client/plugins/Dashboard.jsx +++ b/web/client/plugins/Dashboard.jsx @@ -46,6 +46,7 @@ import { import dashboardReducers from '../reducers/dashboard'; import dashboardEpics from '../epics/dashboard'; import widgetsEpics from '../epics/widgets'; +import { isChartCompatibleWithTableWidget } from '../utils/WidgetsUtils'; const WidgetsView = compose( connect( @@ -112,7 +113,7 @@ const WidgetsView = compose( target.widgetType === "table" && (editingWidget.widgetType !== "map" && editingWidget.widgetType === "chart" - ? (target.layer && editingWidget && editingWidget?.charts?.map(c => c?.layer?.name)?.includes(target.layer.name)) + ? (target.layer && editingWidget && editingWidget?.charts?.map(c => c?.layer?.name)?.includes(target.layer.name) && isChartCompatibleWithTableWidget(editingWidget, target)) : (target.layer && editingWidget.layer && target.layer.name === editingWidget.layer.name) || editingWidget.widgetType === "map") && !target.mapSync ) && target.id !== editingWidget.id diff --git a/web/client/plugins/widgetbuilder/ChartBuilder.jsx b/web/client/plugins/widgetbuilder/ChartBuilder.jsx index 1145785a91..03436825f4 100644 --- a/web/client/plugins/widgetbuilder/ChartBuilder.jsx +++ b/web/client/plugins/widgetbuilder/ChartBuilder.jsx @@ -31,7 +31,7 @@ import LayerSelector from './ChartLayerSelector'; import BuilderHeader from './BuilderHeader'; import Toolbar from '../../components/widgets/builder/wizard/chart/Toolbar'; import { catalogEditorEnhancer } from './enhancers/catalogEditorEnhancer'; -import { getDependantWidget } from "../../utils/WidgetsUtils"; +import { getDependantWidget, isChartCompatibleWithTableWidget } from "../../utils/WidgetsUtils"; const setMultiDependencySupport = ({editorData = {}, disableMultiDependencySupport: disableSupport, widgets = []} = {}) => { @@ -40,7 +40,7 @@ const setMultiDependencySupport = ({editorData = {}, disableMultiDependencySuppo if (dependantWidget?.widgetType === 'table') { // Disable dependency support when some layers in multi chart // doesn't match dependant table widget - disableMultiDependencySupport = disableMultiDependencySupport || editorData?.charts?.some(c => c.layer.name !== dependantWidget?.layer?.name); + disableMultiDependencySupport = disableMultiDependencySupport || !isChartCompatibleWithTableWidget(editorData, dependantWidget); } return { disableMultiDependencySupport }; }; diff --git a/web/client/plugins/widgetbuilder/enhancers/chartLayerSelector.js b/web/client/plugins/widgetbuilder/enhancers/chartLayerSelector.js index 9e0bd9745a..e4fd347fe8 100644 --- a/web/client/plugins/widgetbuilder/enhancers/chartLayerSelector.js +++ b/web/client/plugins/widgetbuilder/enhancers/chartLayerSelector.js @@ -66,7 +66,7 @@ const layerSelector = compose( : i ), onItemClick: ({record} = {}, props, event) => { - if (event.ctrlKey) { + if (event.ctrlKey || event.metaKey) { const selectedArray = castArray(selected); if (isEmpty(selected)) { return setSelected(castArray(record)); diff --git a/web/client/plugins/widgetbuilder/enhancers/connection/withConnectButton.js b/web/client/plugins/widgetbuilder/enhancers/connection/withConnectButton.js index 9d86127b29..f824a27eb9 100644 --- a/web/client/plugins/widgetbuilder/enhancers/connection/withConnectButton.js +++ b/web/client/plugins/widgetbuilder/enhancers/connection/withConnectButton.js @@ -6,6 +6,7 @@ * LICENSE file in the root directory of this source tree. */ import { withProps, compose } from 'recompose'; +import isNil from 'lodash/isNil'; /** * Returns an enhancer that add `stepButtons` for viewport connection to a wizard toolbar @@ -20,21 +21,26 @@ export default (showCondition = () => true) => compose( canConnect, connected, ...props - }) => ({ - stepButtons: [...stepButtons, { - onClick: () => toggleConnection(availableDependencies, props.widgets), - disabled: disableMultiDependencySupport, - visible: !!showCondition(props) && availableDependencies.length > 0, - bsStyle: (!disableMultiDependencySupport && connected) ? "success" : "primary", - glyph: connected ? "plug" : "unplug", - tooltipId: (disableMultiDependencySupport || !canConnect) - ? "widgets.builder.wizard.disableConnectToMap" - : connected - ? "widgets.builder.wizard.clearConnection" - : availableDependencies.length === 1 - ? "widgets.builder.wizard.connectToTheMap" - : "widgets.builder.wizard.connectToAMap" - } - ] - })) + }) => { + const disableConnect = !isNil(disableMultiDependencySupport) ? disableMultiDependencySupport : !canConnect; + return { + stepButtons: [ + ...stepButtons, + { + onClick: () => toggleConnection(availableDependencies, props.widgets), + disabled: disableConnect, + visible: !!showCondition(props) && availableDependencies.length > 0, + bsStyle: (!disableMultiDependencySupport && connected) ? "success" : "primary", + glyph: connected ? "plug" : "unplug", + tooltipId: disableConnect + ? "widgets.builder.wizard.disableConnectToMap" + : connected + ? "widgets.builder.wizard.clearConnection" + : availableDependencies.length === 1 + ? "widgets.builder.wizard.connectToTheMap" + : "widgets.builder.wizard.connectToAMap" + } + ] + }; + }) ); diff --git a/web/client/selectors/widgets.js b/web/client/selectors/widgets.js index d4bba4b428..40359d27d0 100644 --- a/web/client/selectors/widgets.js +++ b/web/client/selectors/widgets.js @@ -12,7 +12,7 @@ import { mapSelector } from './map'; import { getSelectedLayer } from './layers'; import { pathnameSelector } from './router'; import { DEFAULT_TARGET, DEPENDENCY_SELECTOR_KEY, WIDGETS_REGEX } from '../actions/widgets'; -import { getWidgetsGroups, getWidgetDependency, getSelectedWidgetData } from '../utils/WidgetsUtils'; +import { getWidgetsGroups, getWidgetDependency, getSelectedWidgetData, isChartCompatibleWithTableWidget } from '../utils/WidgetsUtils'; import { dashboardServicesSelector, isDashboardAvailable, isDashboardEditing } from './dashboard'; import { createSelector, createStructuredSelector } from 'reselect'; import { createShallowSelector } from '../utils/ReselectUtils'; @@ -109,7 +109,7 @@ export const availableDependenciesForEditingWidgetSelector = createSelector( .concat( castArray(tableWidgets) .filter(() => pathname.indexOf("viewer") === -1) - .filter((w) => (!isChart && isArray(editingLayer)) || (isChart ? editingLayer.includes(w.layer.name) : editingLayer.name === w.layer.name)) + .filter((w) => (!isChart && isArray(editingLayer)) || (isChart ? isChartCompatibleWithTableWidget(editingWidget, w) : editingLayer.name === w.layer.name)) .filter((w) => editingWidget && editingWidget.id !== w.id) .map(({id}) => `widgets[${id}]`) ) diff --git a/web/client/utils/WidgetsUtils.js b/web/client/utils/WidgetsUtils.js index 53242cd8d7..013e04e3b4 100644 --- a/web/client/utils/WidgetsUtils.js +++ b/web/client/utils/WidgetsUtils.js @@ -331,3 +331,15 @@ export const getSelectedWidgetData = (widget = {}) => { } return widget; }; + +/** + * Check if chart widget layers are compatible with table widget layer + * @param {object} widget current widget object + * @param {object} tableWidget depedant table widget object + * @returns {boolean} flag determines if compatible + */ +export const isChartCompatibleWithTableWidget = (widget, tableWidget) => { + const tableLayerName = tableWidget?.layer?.name; + return tableLayerName && get(widget, 'charts', []) + .every(({ layer = {} } = {}) => layer.name === tableLayerName); +}; diff --git a/web/client/utils/__tests__/WidgetsUtils-test.js b/web/client/utils/__tests__/WidgetsUtils-test.js index 93ccbf77cc..49406a8285 100644 --- a/web/client/utils/__tests__/WidgetsUtils-test.js +++ b/web/client/utils/__tests__/WidgetsUtils-test.js @@ -13,7 +13,8 @@ import { getConnectionList, getDependantWidget, getMapDependencyPath, getSelectedWidgetData, getWidgetDependency, getWidgetsGroups, - shortenLabel, updateDependenciesMapOfMapList + shortenLabel, updateDependenciesMapOfMapList, + isChartCompatibleWithTableWidget } from '../WidgetsUtils'; import SAMPLE_1 from '../../test-resources/widgets/widgets1.json'; const widgets = SAMPLE_1.widgets; @@ -319,4 +320,12 @@ describe('Test WidgetsUtils', () => { expect(widget).toBeTruthy(); expect(widget.layer.name).toBe("test"); }); + it("isChartCompatibleWithTableWidget", () => { + expect(isChartCompatibleWithTableWidget()).toBeFalsy(); + expect(isChartCompatibleWithTableWidget({charts: []})).toBeFalsy(); + expect(isChartCompatibleWithTableWidget({charts: [{layer: {name: "test"}}]})).toBeFalsy(); + expect(isChartCompatibleWithTableWidget({charts: [{layer: {name: "test"}}]}, {layer: {name: "test"}})).toBeTruthy(); + expect(isChartCompatibleWithTableWidget({charts: [{layer: {name: "test"}}, {layer: {name: "test1"}}]}, {layer: {name: "test"}})).toBeFalsy(); + expect(isChartCompatibleWithTableWidget({charts: [{layer: {name: "test"}}, {layer: {name: "test"}}]}, {layer: {name: "test"}})).toBeTruthy(); + }); });