Skip to content
Snippets Groups Projects
Commit 3e14bed4 authored by Adrian Orłów's avatar Adrian Orłów
Browse files

test: add tests for the pin rendering module

parent 2e212854
No related branches found
No related tags found
2 merge requests!223reset the pin numbers before search results are fetch (so the results will be...,!58feat(map): display pins map interactive elements
Pipeline #81642 passed
Showing
with 302 additions and 54 deletions
......@@ -62,6 +62,7 @@
"eslint-plugin-testing-library": "^6.0.1",
"husky": "^8.0.0",
"jest": "^29.7.0",
"jest-canvas-mock": "^2.5.2",
"jest-environment-jsdom": "^29.7.0",
"jest-junit": "^16.0.0",
"jest-watch-typeahead": "^2.2.2",
......@@ -4024,6 +4025,12 @@
"node": ">=4"
}
},
"node_modules/cssfontparser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/cssfontparser/-/cssfontparser-1.2.1.tgz",
"integrity": "sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg==",
"dev": true
},
"node_modules/cssom": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz",
......@@ -7648,6 +7655,16 @@
}
}
},
"node_modules/jest-canvas-mock": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jest-canvas-mock/-/jest-canvas-mock-2.5.2.tgz",
"integrity": "sha512-vgnpPupjOL6+L5oJXzxTxFrlGEIbHdZqFU+LFNdtLxZ3lRDCl17FlTMM7IatoRQkrcyOTMlDinjUguqmQ6bR2A==",
"dev": true,
"dependencies": {
"cssfontparser": "^1.2.1",
"moo-color": "^1.0.2"
}
},
"node_modules/jest-changed-files": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
......@@ -9745,6 +9762,15 @@
"node": ">=10"
}
},
"node_modules/moo-color": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/moo-color/-/moo-color-1.0.3.tgz",
"integrity": "sha512-i/+ZKXMDf6aqYtBhuOcej71YSlbjT3wCO/4H1j8rPvxDJEifdwgg5MaFyu6iYAT8GBZJg2z0dkgK4YMzvURALQ==",
"dev": true,
"dependencies": {
"color-name": "^1.1.4"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
......
import '@testing-library/jest-dom';
import 'jest-canvas-mock';
// used by openlayers module
global.ResizeObserver = jest.fn().mockImplementation(() => ({
......
/* eslint-disable no-magic-numbers */
import { DEFAULT_FONT_FAMILY } from '@/constants/font';
import { getCanvas } from '@/utils/canvas/getCanvas';
import {
drawNumberOnCanvas,
drawPinOnCanvas,
getTextPosition,
getTextWidth,
} from './getCanvasIcon';
const getContext = (): CanvasRenderingContext2D => {
const canvas = getCanvas({ width: 100, height: 100 });
return canvas.getContext('2d') as CanvasRenderingContext2D;
};
const ONCE = 1;
describe('getCanvasIcon - util', () => {
beforeEach(() => {
jest.restoreAllMocks();
});
describe('getTextWidth - subUtil', () => {
const cases: [number, number][] = [
[1, 6.25],
[7, 8.333],
[43, 12.5],
[105, 16.666],
];
it.each(cases)('on value=%s should return %s', (input, output) => {
expect(getTextWidth(input)).toBeCloseTo(output);
});
});
describe('getTextPosition - subUtil', () => {
const cases: [number, number, number, number][] = [
[100, 100, -37.5, -27.2],
[532, 443, -253.5, -164.4],
[10, 0, 7.5, 12.8],
[0, 10, 12.5, 8.8],
[0, 0, 12.5, 12.8],
];
it.each(cases)(
'on textWidth=%s textHeight=%s should return x=%s y=%s',
(textWidth, textHeight, x, y) => {
expect(getTextPosition(textWidth, textHeight)).toMatchObject({
x,
y,
});
},
);
});
describe('drawPinOnCanvas - subUtil', () => {
const color = '#000000';
it('should run set fillStyle with color', () => {
const ctx = getContext();
drawPinOnCanvas({ color }, ctx);
expect(ctx.fillStyle).toBe(color);
});
it('should run fill method with valid arguments', () => {
const ctx = getContext();
const fillSpy = jest.spyOn(ctx, 'fill');
drawPinOnCanvas({ color }, ctx);
const call = fillSpy.mock.calls[0][0];
expect(call).toBeInstanceOf(Path2D);
expect(fillSpy).toBeCalledTimes(ONCE);
});
});
describe('drawNumberOnCanvas - subUtil', () => {
const ctx = getContext();
const fillTextSpy = jest.spyOn(ctx, 'fillText');
const value = 69;
beforeAll(() => {
drawNumberOnCanvas(
{
value,
},
ctx,
);
});
it('should set valid ctx fields', () => {
expect(ctx.fillStyle).toBe('#ffffff');
expect(ctx.textBaseline).toBe('top');
expect(ctx.font).toBe(`6.25px ${DEFAULT_FONT_FAMILY}`);
});
it('should run fillText once with valid args', () => {
expect(fillTextSpy).toBeCalledWith(`${value}`, 6.25, 12.8);
expect(fillTextSpy).toBeCalledTimes(ONCE);
});
});
});
......@@ -14,13 +14,16 @@ interface Args {
value: number;
}
const drawPinOnCanvas = ({ color }: Args, ctx: CanvasRenderingContext2D): void => {
export const drawPinOnCanvas = (
{ color }: Pick<Args, 'color'>,
ctx: CanvasRenderingContext2D,
): void => {
const path = new Path2D(PIN_PATH2D);
ctx.fillStyle = color;
ctx.fill(path);
};
const getTextWidth = (value: number): number => {
export const getTextWidth = (value: number): number => {
switch (true) {
case value === SMALL_TEXT_VALUE:
return PIN_SIZE.width / QUARTER;
......@@ -33,12 +36,15 @@ const getTextWidth = (value: number): number => {
}
};
const getTextPosition = (textWidth: number, textHeight: number): Point => ({
export const getTextPosition = (textWidth: number, textHeight: number): Point => ({
x: (PIN_SIZE.width - textWidth) / HALF,
y: (PIN_SIZE.height - textHeight) / TWO_AND_HALF,
});
const drawNumberOnCanvas = ({ value }: Args, ctx: CanvasRenderingContext2D): void => {
export const drawNumberOnCanvas = (
{ value }: Pick<Args, 'value'>,
ctx: CanvasRenderingContext2D,
): void => {
const text = `${value}`;
const textMetrics = ctx.measureText(text);
......
......@@ -5,7 +5,9 @@ import { getReduxWrapperUsingSliceReducer } from '@/utils/testing/getReduxWrappe
import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
import { renderHook, waitFor } from '@testing-library/react';
import { Map } from 'ol';
import BaseLayer from 'ol/layer/Base';
import TileLayer from 'ol/layer/Tile';
import VectorLayer from 'ol/layer/Vector';
import React from 'react';
import { useOlMap } from '../useOlMap';
import { useOlMapLayers } from './useOlMapLayers';
......@@ -46,7 +48,7 @@ describe('useOlMapLayers - util', () => {
await waitFor(() => expect(setLayersSpy).toBeCalledTimes(CALLED_ONCE));
});
it('should return valid View instance', async () => {
const getRenderedHookResults = (): BaseLayer[] => {
const { Wrapper } = getReduxWrapperWithStore({
map: {
data: {
......@@ -89,7 +91,20 @@ describe('useOlMapLayers - util', () => {
},
);
expect(result.current[0]).toBeInstanceOf(TileLayer);
expect(result.current[0].getSourceState()).toBe('ready');
return result.current;
};
it('should return valid TileLayer instance', () => {
const result = getRenderedHookResults();
expect(result[0]).toBeInstanceOf(TileLayer);
expect(result[0].getSourceState()).toBe('ready');
});
it('should return valid VectorLayer instance', () => {
const result = getRenderedHookResults();
expect(result[1]).toBeInstanceOf(VectorLayer);
expect(result[1].getSourceState()).toBe('ready');
});
});
......@@ -20,5 +20,5 @@ export const useOlMapLayers = ({ mapInstance }: UseOlMapLayersInput): MapConfig[
mapInstance.setLayers([tileLayer, pinsLayer]);
}, [tileLayer, pinsLayer, mapInstance]);
return [tileLayer];
return [tileLayer, pinsLayer];
};
/* eslint-disable no-magic-numbers */
import { MAP_DATA_INITIAL_STATE, OPENED_MAPS_INITIAL_STATE } from '@/redux/map/map.constants';
import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
import { renderHook } from '@testing-library/react';
import BaseLayer from 'ol/layer/Base';
import TileLayer from 'ol/layer/Tile';
import React from 'react';
import { useOlMapTileLayer } from './useOlMapTileLayer';
const useRefValue = {
current: null,
};
Object.defineProperty(useRefValue, 'current', {
get: jest.fn(() => ({
innerHTML: '',
appendChild: jest.fn(),
addEventListener: jest.fn(),
getRootNode: jest.fn(),
})),
set: jest.fn(() => ({
innerHTML: '',
appendChild: jest.fn(),
addEventListener: jest.fn(),
getRootNode: jest.fn(),
})),
});
jest.spyOn(React, 'useRef').mockReturnValue(useRefValue);
describe('useOlMapTileLayer - util', () => {
const getRenderedHookResults = (): BaseLayer => {
const { Wrapper } = getReduxWrapperWithStore({
map: {
data: {
...MAP_DATA_INITIAL_STATE,
size: {
width: 256,
height: 256,
tileSize: 256,
minZoom: 1,
maxZoom: 1,
},
position: {
initial: {
x: 256,
y: 256,
},
last: {
x: 256,
y: 256,
},
},
},
loading: 'idle',
error: {
name: '',
message: '',
},
openedMaps: OPENED_MAPS_INITIAL_STATE,
},
});
const { result } = renderHook(() => useOlMapTileLayer(), {
wrapper: Wrapper,
});
return result.current;
};
it('should return valid TileLayer instance', () => {
const result = getRenderedHookResults();
expect(result).toBeInstanceOf(TileLayer);
expect(result.getSourceState()).toBe('ready');
});
});
/* eslint-disable no-magic-numbers */
import { MAP_DATA_INITIAL_STATE, OPENED_MAPS_INITIAL_STATE } from '@/redux/map/map.constants';
import mapSlice, { setMapPosition } from '@/redux/map/map.slice';
import { getReduxWrapperUsingSliceReducer } from '@/utils/testing/getReduxWrapperUsingSliceReducer';
import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
import { renderHook, waitFor } from '@testing-library/react';
import { MAP_DATA_INITIAL_STATE, OPENED_MAPS_INITIAL_STATE } from '@/redux/map/map.constants';
import { View } from 'ol';
import Map from 'ol/Map';
import React from 'react';
......
/* eslint-disable no-magic-numbers */
import { getCanvas } from './getCanvas';
describe('getCanvas', () => {
it('should return HTMLCanvasElement with valid size on positive params', () => {
const result = getCanvas({
width: 800,
height: 600,
});
expect(result).toBeInstanceOf(HTMLCanvasElement);
expect(result.width).toEqual(800);
expect(result.height).toEqual(600);
});
});
/* eslint-disable no-magic-numbers */
import { getCanvas } from './getCanvas';
import { getFontSizeToFit } from './getFontSizeToFit';
const getContext = (): CanvasRenderingContext2D => {
const canvas = getCanvas({ width: 100, height: 100 });
return canvas.getContext('2d') as CanvasRenderingContext2D;
};
describe('getFontSizeToFit', () => {
const cases: [string, string, number, number][] = [
['Hello', 'Helvetica', 50, 10],
['123', 'Arial', 48, 16],
['1', '', 48, 48],
['Text', '', 0, 0],
['', '', 0, 0],
];
it.each(cases)(
'on text=%s, fontFace=%s, maxWidth=%s it should return value %s',
(text, fontFace, maxWidth, result) => {
const ctx = getContext();
expect(getFontSizeToFit(ctx, text, fontFace, maxWidth)).toBeCloseTo(result);
},
);
});
const DEFAULT_VALID_SIZE = 0;
export const getFontSizeToFit = (
ctx: CanvasRenderingContext2D,
text: string,
......@@ -5,5 +7,5 @@ export const getFontSizeToFit = (
maxWidth: number,
): number => {
ctx.font = `1px ${fontFace}`;
return maxWidth / ctx.measureText(text).width;
return maxWidth / ctx.measureText(text).width || DEFAULT_VALID_SIZE;
};
......@@ -847,49 +847,9 @@
"resolved" "https://registry.npmjs.org/@next/font/-/font-13.5.4.tgz"
"version" "13.5.4"
"@next/swc-darwin-x64@13.4.19":
"integrity" "sha512-jyzO6wwYhx6F+7gD8ddZfuqO4TtpJdw3wyOduR4fxTUCm3aLw7YmHGYNjS0xRSYGAkLpBkH1E0RcelyId6lNsw=="
"resolved" "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.19.tgz"
"version" "13.4.19"
"@next/swc-darwin-x64@13.4.19":
"integrity" "sha512-jyzO6wwYhx6F+7gD8ddZfuqO4TtpJdw3wyOduR4fxTUCm3aLw7YmHGYNjS0xRSYGAkLpBkH1E0RcelyId6lNsw=="
"resolved" "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.19.tgz"
"version" "13.4.19"
"@next/swc-linux-arm64-gnu@13.4.19":
"integrity" "sha512-vdlnIlaAEh6H+G6HrKZB9c2zJKnpPVKnA6LBwjwT2BTjxI7e0Hx30+FoWCgi50e+YO49p6oPOtesP9mXDRiiUg=="
"resolved" "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.19.tgz"
"version" "13.4.19"
"@next/swc-linux-arm64-musl@13.4.19":
"integrity" "sha512-aU0HkH2XPgxqrbNRBFb3si9Ahu/CpaR5RPmN2s9GiM9qJCiBBlZtRTiEca+DC+xRPyCThTtWYgxjWHgU7ZkyvA=="
"resolved" "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.19.tgz"
"version" "13.4.19"
"@next/swc-linux-x64-gnu@13.4.19":
"integrity" "sha512-htwOEagMa/CXNykFFeAHHvMJeqZfNQEoQvHfsA4wgg5QqGNqD5soeCer4oGlCol6NGUxknrQO6VEustcv+Md+g=="
"resolved" "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.19.tgz"
"version" "13.4.19"
"@next/swc-linux-x64-musl@13.4.19":
"integrity" "sha512-4Gj4vvtbK1JH8ApWTT214b3GwUh9EKKQjY41hH/t+u55Knxi/0wesMzwQRhppK6Ddalhu0TEttbiJ+wRcoEj5Q=="
"resolved" "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.19.tgz"
"version" "13.4.19"
"@next/swc-win32-arm64-msvc@13.4.19":
"integrity" "sha512-bUfDevQK4NsIAHXs3/JNgnvEY+LRyneDN788W2NYiRIIzmILjba7LaQTfihuFawZDhRtkYCv3JDC3B4TwnmRJw=="
"resolved" "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.19.tgz"
"version" "13.4.19"
"@next/swc-win32-ia32-msvc@13.4.19":
"integrity" "sha512-Y5kikILFAr81LYIFaw6j/NrOtmiM4Sf3GtOc0pn50ez2GCkr+oejYuKGcwAwq3jiTKuzF6OF4iT2INPoxRycEA=="
"resolved" "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.19.tgz"
"version" "13.4.19"
"@next/swc-win32-x64-msvc@13.4.19":
"integrity" "sha512-YzA78jBDXMYiINdPdJJwGgPNT3YqBNNGhsthsDoWHL9p24tEJn9ViQf/ZqTbwSpX/RrkPupLfuuTH2sf73JBAw=="
"resolved" "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.19.tgz"
"@next/swc-darwin-arm64@13.4.19":
"integrity" "sha512-vv1qrjXeGbuF2mOkhkdxMDtv9np7W4mcBtaDnHU+yJG+bBwa6rYsYSCI/9Xm5+TuF5SbZbrWO6G1NfTh1TMjvQ=="
"resolved" "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.19.tgz"
"version" "13.4.19"
"@nodelib/fs.scandir@2.1.5":
......@@ -2189,7 +2149,7 @@
dependencies:
"color-name" "~1.1.4"
"color-name@~1.1.4":
"color-name@^1.1.4", "color-name@~1.1.4":
"integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
"resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
"version" "1.1.4"
......@@ -2360,6 +2320,11 @@
"resolved" "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz"
"version" "3.0.0"
"cssfontparser@^1.2.1":
"integrity" "sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg=="
"resolved" "https://registry.npmjs.org/cssfontparser/-/cssfontparser-1.2.1.tgz"
"version" "1.2.1"
"cssom@^0.5.0":
"integrity" "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw=="
"resolved" "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz"
......@@ -4451,6 +4416,14 @@
"reflect.getprototypeof" "^1.0.4"
"set-function-name" "^2.0.1"
"jest-canvas-mock@^2.5.2":
"integrity" "sha512-vgnpPupjOL6+L5oJXzxTxFrlGEIbHdZqFU+LFNdtLxZ3lRDCl17FlTMM7IatoRQkrcyOTMlDinjUguqmQ6bR2A=="
"resolved" "https://registry.npmjs.org/jest-canvas-mock/-/jest-canvas-mock-2.5.2.tgz"
"version" "2.5.2"
dependencies:
"cssfontparser" "^1.2.1"
"moo-color" "^1.0.2"
"jest-changed-files@^29.7.0":
"integrity" "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w=="
"resolved" "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz"
......@@ -5377,6 +5350,13 @@
"resolved" "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz"
"version" "1.0.4"
"moo-color@^1.0.2":
"integrity" "sha512-i/+ZKXMDf6aqYtBhuOcej71YSlbjT3wCO/4H1j8rPvxDJEifdwgg5MaFyu6iYAT8GBZJg2z0dkgK4YMzvURALQ=="
"resolved" "https://registry.npmjs.org/moo-color/-/moo-color-1.0.3.tgz"
"version" "1.0.3"
dependencies:
"color-name" "^1.1.4"
"ms@^2.1.1", "ms@2.1.2":
"integrity" "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
"resolved" "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment