From fe71c4696bf6cb23d02f010867573010e2f8a660 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tadeusz=20Miesi=C4=85c?= <tadeusz.miesiac@gmail.com>
Date: Wed, 20 Dec 2023 11:14:43 +0100
Subject: [PATCH] refactor(getoverlayfeatures): extraced helper functions to
 separate files, added tests

---
 .../createOverlayGeometryFeature.test.ts      | 49 +++++++++++++
 .../createOverlayGeometryFeature.ts           | 13 ++++
 .../getColorByAvailableProperties.test.ts     | 73 +++++++++++++++++++
 .../getColorByAvailableProperties.ts          | 18 +++++
 .../overlaysLayer/getOverlayFeatures.ts       | 32 +-------
 src/constants/backgrounds.ts                  |  1 +
 src/redux/backgrounds/background.selectors.ts |  3 +-
 7 files changed, 159 insertions(+), 30 deletions(-)
 create mode 100644 src/components/Map/MapViewer/utils/config/overlaysLayer/createOverlayGeometryFeature.test.ts
 create mode 100644 src/components/Map/MapViewer/utils/config/overlaysLayer/createOverlayGeometryFeature.ts
 create mode 100644 src/components/Map/MapViewer/utils/config/overlaysLayer/getColorByAvailableProperties.test.ts
 create mode 100644 src/components/Map/MapViewer/utils/config/overlaysLayer/getColorByAvailableProperties.ts
 create mode 100644 src/constants/backgrounds.ts

diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/createOverlayGeometryFeature.test.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/createOverlayGeometryFeature.test.ts
new file mode 100644
index 00000000..8ee12221
--- /dev/null
+++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/createOverlayGeometryFeature.test.ts
@@ -0,0 +1,49 @@
+import { createOverlayGeometryFeature } from './createOverlayGeometryFeature';
+
+describe('createOverlayGeometryFeature', () => {
+  it('should create a feature with the correct geometry and style', () => {
+    const xMin = 0;
+    const yMin = 0;
+    const xMax = 10;
+    const yMax = 10;
+    const colorHexString = '#FF0000';
+
+    const feature = createOverlayGeometryFeature([xMin, yMin, xMax, yMax], colorHexString);
+
+    expect(feature.getGeometry()!.getCoordinates()).toEqual([
+      [
+        [xMin, yMin],
+        [xMin, yMax],
+        [xMax, yMax],
+        [xMax, yMin],
+        [xMin, yMin],
+      ],
+    ]);
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-ignore - getStyle() is not typed
+    expect(feature.getStyle().getFill().getColor()).toEqual(colorHexString);
+  });
+
+  it('should create a feature with the correct geometry and style when using a different color', () => {
+    const xMin = -5;
+    const yMin = -5;
+    const xMax = 5;
+    const yMax = 5;
+    const colorHexString = '#00FF00';
+
+    const feature = createOverlayGeometryFeature([xMin, yMin, xMax, yMax], colorHexString);
+
+    expect(feature.getGeometry()!.getCoordinates()).toEqual([
+      [
+        [xMin, yMin],
+        [xMin, yMax],
+        [xMax, yMax],
+        [xMax, yMin],
+        [xMin, yMin],
+      ],
+    ]);
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-ignore - getStyle() is not typed
+    expect(feature.getStyle().getFill().getColor()).toEqual(colorHexString);
+  });
+});
diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/createOverlayGeometryFeature.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/createOverlayGeometryFeature.ts
new file mode 100644
index 00000000..90887721
--- /dev/null
+++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/createOverlayGeometryFeature.ts
@@ -0,0 +1,13 @@
+import { Fill, Style } from 'ol/style';
+import { fromExtent } from 'ol/geom/Polygon';
+import Feature from 'ol/Feature';
+import type Polygon from 'ol/geom/Polygon';
+
+export const createOverlayGeometryFeature = (
+  [xMin, yMin, xMax, yMax]: number[],
+  color: string,
+): Feature<Polygon> => {
+  const feature = new Feature({ geometry: fromExtent([xMin, yMin, xMax, yMax]) });
+  feature.setStyle(new Style({ fill: new Fill({ color }) }));
+  return feature;
+};
diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/getColorByAvailableProperties.test.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/getColorByAvailableProperties.test.ts
new file mode 100644
index 00000000..6b71e37e
--- /dev/null
+++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/getColorByAvailableProperties.test.ts
@@ -0,0 +1,73 @@
+import { OverlayBioEntityRender } from '@/types/OLrendering';
+import { getColorByAvailableProperties } from './getColorByAvailableProperties';
+
+describe('getColorByAvailableProperties', () => {
+  const ENTITY: OverlayBioEntityRender = {
+    id: 0,
+    modelId: 0,
+    x1: 0,
+    y1: 0,
+    x2: 0,
+    y2: 0,
+    width: 0,
+    height: 0,
+    value: null,
+    overlayId: 0,
+    color: null,
+  };
+
+  const getHexTricolorGradientColorWithAlpha = jest.fn().mockReturnValue('#FFFFFF');
+  const defaultColor = '#000000';
+
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
+
+  it('should return the result of getHexTricolorGradientColorWithAlpha if entity has a value equal to 0', () => {
+    const entity = { ...ENTITY, value: 0 };
+    const result = getColorByAvailableProperties(
+      entity,
+      getHexTricolorGradientColorWithAlpha,
+      defaultColor,
+    );
+
+    expect(result).toEqual('#FFFFFF');
+    expect(getHexTricolorGradientColorWithAlpha).toHaveBeenCalledWith(entity.value);
+  });
+
+  it('should return the result of getHexTricolorGradientColorWithAlpha if entity has a value', () => {
+    const entity = { ...ENTITY, value: -0.2137 };
+    const result = getColorByAvailableProperties(
+      entity,
+      getHexTricolorGradientColorWithAlpha,
+      defaultColor,
+    );
+
+    expect(result).toEqual('#FFFFFF');
+    expect(getHexTricolorGradientColorWithAlpha).toHaveBeenCalledWith(entity.value);
+  });
+
+  it('should return the result of convertDecimalToHex if entity has a color', () => {
+    const entity = { ...ENTITY, color: { rgb: -65536, alpha: 0 } }; // red  color
+
+    const result = getColorByAvailableProperties(
+      entity,
+      getHexTricolorGradientColorWithAlpha,
+      defaultColor,
+    );
+
+    expect(result).toEqual('#ff0000');
+    expect(getHexTricolorGradientColorWithAlpha).not.toHaveBeenCalled();
+  });
+
+  it('should return the default color if entity has neither a value nor a color', () => {
+    const result = getColorByAvailableProperties(
+      ENTITY,
+      getHexTricolorGradientColorWithAlpha,
+      defaultColor,
+    );
+
+    expect(result).toEqual('#000000');
+    expect(getHexTricolorGradientColorWithAlpha).not.toHaveBeenCalled();
+  });
+});
diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/getColorByAvailableProperties.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/getColorByAvailableProperties.ts
new file mode 100644
index 00000000..b7ac985f
--- /dev/null
+++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/getColorByAvailableProperties.ts
@@ -0,0 +1,18 @@
+import { ZERO } from '@/constants/common';
+import type { GetHex3ColorGradientColorWithAlpha } from '@/hooks/useTriColorLerp';
+import { OverlayBioEntityRender } from '@/types/OLrendering';
+import { convertDecimalToHex } from '@/utils/convert/convertDecimalToHex';
+
+export const getColorByAvailableProperties = (
+  entity: OverlayBioEntityRender,
+  getHexTricolorGradientColorWithAlpha: GetHex3ColorGradientColorWithAlpha,
+  defaultColor: string,
+): string => {
+  if (typeof entity.value === 'number') {
+    return getHexTricolorGradientColorWithAlpha(entity.value || ZERO);
+  }
+  if (entity.color) {
+    return convertDecimalToHex(entity.color.rgb);
+  }
+  return defaultColor;
+};
diff --git a/src/components/Map/MapViewer/utils/config/overlaysLayer/getOverlayFeatures.ts b/src/components/Map/MapViewer/utils/config/overlaysLayer/getOverlayFeatures.ts
index 1cb81f70..a2a7fb43 100644
--- a/src/components/Map/MapViewer/utils/config/overlaysLayer/getOverlayFeatures.ts
+++ b/src/components/Map/MapViewer/utils/config/overlaysLayer/getOverlayFeatures.ts
@@ -1,20 +1,10 @@
-import { ZERO } from '@/constants/common';
 import type { GetHex3ColorGradientColorWithAlpha } from '@/hooks/useTriColorLerp';
 import { OverlayBioEntityRender } from '@/types/OLrendering';
-import { convertDecimalToHex } from '@/utils/convert/convertDecimalToHex';
 import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
-import Feature from 'ol/Feature';
-import Polygon, { fromExtent } from 'ol/geom/Polygon';
-import { Fill, Style } from 'ol/style';
-
-export const createOverlayGeometryFeature = (
-  [xMin, yMin, xMax, yMax]: number[],
-  color: string,
-): Feature<Polygon> => {
-  const feature = new Feature({ geometry: fromExtent([xMin, yMin, xMax, yMax]) });
-  feature.setStyle(new Style({ fill: new Fill({ color }) }));
-  return feature;
-};
+import type Feature from 'ol/Feature';
+import type Polygon from 'ol/geom/Polygon';
+import { createOverlayGeometryFeature } from './createOverlayGeometryFeature';
+import { getColorByAvailableProperties } from './getColorByAvailableProperties';
 
 type GetOverlayFeaturesProps = {
   bioEntities: OverlayBioEntityRender[];
@@ -23,20 +13,6 @@ type GetOverlayFeaturesProps = {
   defaultColor: string;
 };
 
-export const getColorByAvailableProperties = (
-  entity: OverlayBioEntityRender,
-  getHexTricolorGradientColorWithAlpha: GetHex3ColorGradientColorWithAlpha,
-  defaultColor: string,
-): string => {
-  if (entity.value) {
-    return getHexTricolorGradientColorWithAlpha(entity.value || ZERO);
-  }
-  if (entity.color) {
-    return convertDecimalToHex(entity.color.rgb);
-  }
-  return defaultColor;
-};
-
 export const getOverlayFeatures = ({
   bioEntities,
   pointToProjection,
diff --git a/src/constants/backgrounds.ts b/src/constants/backgrounds.ts
new file mode 100644
index 00000000..1bfb4619
--- /dev/null
+++ b/src/constants/backgrounds.ts
@@ -0,0 +1 @@
+export const EMPTY_BACKGROUND_NAME = 'Empty';
diff --git a/src/redux/backgrounds/background.selectors.ts b/src/redux/backgrounds/background.selectors.ts
index 7c3d5924..b8443ab5 100644
--- a/src/redux/backgrounds/background.selectors.ts
+++ b/src/redux/backgrounds/background.selectors.ts
@@ -1,4 +1,5 @@
 import { createSelector } from '@reduxjs/toolkit';
+import { EMPTY_BACKGROUND_NAME } from '@/constants/backgrounds';
 import { mapDataSelector } from '../map/map.selectors';
 import { rootSelector } from '../root/root.selectors';
 
@@ -37,8 +38,6 @@ export const currentBackgroundImagePathSelector = createSelector(
   image => (image ? image.path : ''),
 );
 
-const EMPTY_BACKGROUND_NAME = 'Empty';
-
 export const emptyBackgroundIdSelector = createSelector(backgroundsDataSelector, backgrounds => {
   const emptyBackground = backgrounds?.find(
     background => background.name === EMPTY_BACKGROUND_NAME,
-- 
GitLab