Skip to content

Commit

Permalink
test: 补全单元测试
Browse files Browse the repository at this point in the history
  • Loading branch information
xyy94813 committed Sep 30, 2023
1 parent 967059d commit 49ffc12
Show file tree
Hide file tree
Showing 6 changed files with 384 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/helpers/__tests__/geoJSONHelper.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { isPosition, isLineCoords } from '../geoJSONHelper';

describe('isPosition', () => {
test('should return true for valid position', () => {
const validPosition: GeoJSON.Position = [1, 2];

const result = isPosition(validPosition);

expect(result).toBe(true);
});

test('should return false for invalid position', () => {
const invalidPosition = [1, '2'];

const result = isPosition(invalidPosition);

expect(result).toBe(false);
});
});

describe('isLineCoords', () => {
test('should return true for valid line coordinates', () => {
const validLineCoords: GeoJSON.Position[] = [[1, 2], [3, 4], [5, 6]];

const result = isLineCoords(validLineCoords);

expect(result).toBe(true);
});

test('should return false for invalid line coordinates', () => {
const invalidLineCoords = [[1, 2], [3, '4'], [5, 6]];

const result = isLineCoords(invalidLineCoords);

expect(result).toBe(false);
});
});
109 changes: 109 additions & 0 deletions src/hooks/__tests__/useAMapOverlayBinder.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import * as React from 'react';
import { renderHook } from '@testing-library/react-hooks';

import { AMapOverlayGroupContext } from '../../components/AMapOverlayGroup';

import useAMapOverlayBinder from '../useAMapOverlayBinder';
import createAMapContextWrapper from './createAMapContextWrapper';

describe('useAMapOverlayBinder', () => {
test('should add overlay to overlay group if overlay group context exists', () => {
// 创建一个 mock 的 overlay group 对象
const mockOverlayGroup: any = {
addOverlay: jest.fn(),
removeOverlay: jest.fn(),
};

// 创建一个 mock 的 overlay 对象
const mockOverlay = {};

const wrapper = (props: any) => createAMapContextWrapper({
__AMAP_UI__: null,
__AMAP__: null,
}, null)({
children: (
<AMapOverlayGroupContext.Provider value={mockOverlayGroup}>
{props.children}
</AMapOverlayGroupContext.Provider>
),
});

// 使用 renderHook 渲染一个包a含 useContext 的自定义 hook
const { unmount } = renderHook(() => useAMapOverlayBinder(mockOverlay), {
wrapper,
});

// // 断言 overlayGroup.addOverlay 被调用了一次,并且传入了 mockOverlay
expect(mockOverlayGroup.addOverlay).toHaveBeenCalledTimes(1);
expect(mockOverlayGroup.addOverlay).toHaveBeenCalledWith(mockOverlay);

// // 卸载 hook
unmount();

// // 断言 overlayGroup.removeOverlay 被调用了一次,并且传入了 mockOverlay
expect(mockOverlayGroup.removeOverlay).toHaveBeenCalledTimes(1);
expect(mockOverlayGroup.removeOverlay).toHaveBeenCalledWith(mockOverlay);
});

test('should add overlay to map if overlay group context does not exist', () => {
// 创建一个 mock 的 map 对象
const mockMap: any = {
add: jest.fn(),
remove: jest.fn(),
};

// 创建一个 mock 的 overlay 对象
const mockOverlay = {};

const wrapper = createAMapContextWrapper({
__AMAP_UI__: null,
__AMAP__: null,
}, mockMap);

// 使用 renderHook 渲染一个包a含 useContext 的自定义 hook
const { unmount } = renderHook(() => useAMapOverlayBinder(mockOverlay), {
wrapper,
});

// // 断言 overlayGroup.add 被调用了一次,并且传入了 mockOverlay
expect(mockMap.add).toHaveBeenCalledTimes(1);
expect(mockMap.add).toHaveBeenCalledWith(mockOverlay);

// // 卸载 hook
unmount();

// // 断言 overlayGroup.remove 被调用了一次,并且传入了 mockOverlay
expect(mockMap.remove).toHaveBeenCalledTimes(1);
expect(mockMap.remove).toHaveBeenCalledWith(mockOverlay);
});

test('undo anything if overlay dose not exist', () => {
// 创建一个 mock 的 map 对象
const mockMap: any = {
add: jest.fn(),
remove: jest.fn(),
};

// 创建一个 mock 的 overlay 对象
const mockOverlay = null;

const wrapper = createAMapContextWrapper({
__AMAP_UI__: null,
__AMAP__: null,
}, mockMap);

// 使用 renderHook 渲染一个包a含 useContext 的自定义 hook
const { unmount } = renderHook(() => useAMapOverlayBinder(mockOverlay), {
wrapper,
});

// // 断言 overlayGroup.add 被调用了一次,并且传入了 mockOverlay
expect(mockMap.add).not.toBeCalled();

// // 卸载 hook
unmount();

// // 断言 overlayGroup.remove 被调用了一次,并且传入了 mockOverlay
expect(mockMap.remove).not.toBeCalled();
});
});
108 changes: 108 additions & 0 deletions src/hooks/__tests__/useAMapPluginInstance.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/* eslint-disable no-underscore-dangle */
import { renderHook } from '@testing-library/react-hooks';

import useAMapPluginInstance from '../useAMapPluginInstance';
import createAMapContextWrapper from './createAMapContextWrapper';

describe('useAMapPluginInstance', () => {
test('sync init plugin', () => {
// mock AMap
const mockAMapAPICtx: any = {
__AMAP__: {
Polygon: jest.fn(),
plugin: jest.fn(),
},
__AMAP_UI__: {},
};

const mockMapInstance: any = {};

const mockInstance = {};
// mock init fn
const initFn = jest.fn(() => mockInstance);

const wrapper = createAMapContextWrapper(mockAMapAPICtx, mockMapInstance);

const { result } = renderHook(() => useAMapPluginInstance('Polygon', initFn), { wrapper });

// 断言异步加载函数没有执行
expect(mockAMapAPICtx.__AMAP__.plugin).not.toBeCalled();

// 初始化函数被成功调用
expect(initFn).toHaveBeenCalledTimes(1);
expect(initFn).toHaveBeenCalledWith(mockAMapAPICtx.__AMAP__, mockMapInstance);
// 返回初始化的实例
expect(result.current).toBe(mockInstance);
});

test('async init plugin', () => {
// mock AMap
const mockAMapAPICtx: any = {
__AMAP__: {
plugin: jest.fn((__, callback) => callback()),
},
__AMAP_UI__: {},
};

const mockMapInstance: any = {};

const mockInstance = {};
// mock init fn
const initFn = jest.fn(() => mockInstance);

const wrapper = createAMapContextWrapper(mockAMapAPICtx, mockMapInstance);

const { result } = renderHook(() => useAMapPluginInstance('Polygon', initFn), { wrapper });

// 执行了异步加载函数
expect(mockAMapAPICtx.__AMAP__.plugin).toHaveBeenCalledTimes(1);
// expect(mockAMapAPICtx.__AMAP__.plugin)
// .toHaveBeenCalledWith([`AMap.Polygon`], expect.any(Function));

// 初始化函数被成功调用
expect(initFn).toHaveBeenCalledTimes(1);
expect(initFn).toHaveBeenCalledWith(mockAMapAPICtx.__AMAP__, mockMapInstance);
// 返回初始化的实例
expect(result.current).toBe(mockInstance);
});

test('undo anything if AMap dose not exist', () => {
const mockAMapAPICtx: any = {
__AMAP__: null,
__AMAP_UI__: null,
};

const mockMapInstance: any = {};

// mock init fn
const initFn = jest.fn();

const wrapper = createAMapContextWrapper(mockAMapAPICtx, mockMapInstance);

const { result } = renderHook(() => useAMapPluginInstance('Polygon', initFn), { wrapper });

// 不会触发初始化函数,
expect(initFn).not.toBeCalled();
expect(result.current).toBe(null);
});

test('undo anything if map dose not exist', () => {
const mockAMapAPICtx: any = {
__AMAP__: {},
__AMAP_UI__: null,
};

const mockMapInstance = null;

// mock init fn
const initFn = jest.fn();

const wrapper = createAMapContextWrapper(mockAMapAPICtx, mockMapInstance);

const { result } = renderHook(() => useAMapPluginInstance('Polygon', initFn), { wrapper });

// 不会触发初始化函数,
expect(initFn).not.toBeCalled();
expect(result.current).toBe(null);
});
});
50 changes: 50 additions & 0 deletions src/hooks/__tests__/useControlContainerCSSText.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import useControlContainerCSSText from '../useControlContainerCSSText';

describe('useControlContainerCSSText', () => {
test('should return the correct CSS text for position "LT"', () => {
const cssText = useControlContainerCSSText('LT');
expect(cssText).toBe('left:10px;top:10px;');
});

test('should return the correct CSS text for position "RT"', () => {
const cssText = useControlContainerCSSText('RT');
expect(cssText).toBe('right:10px;top:10px;');
});

test('should return the correct CSS text for position "LB"', () => {
const cssText = useControlContainerCSSText('LB', [10, 10]);
expect(cssText).toBe('left:10px;bottom:10px;');
});

test('should return the correct CSS text for position "RB"', () => {
const cssText = useControlContainerCSSText('RB');
expect(cssText).toBe('right:10px;bottom:10px;');
});

test('should return the correct CSS text with custom offset', () => {
const cssText = useControlContainerCSSText('RB', [20, 20]);
expect(cssText).toBe('right:20px;bottom:20px;');
});

test('should return the correct CSS text for custom position object', () => {
const position = {
top: '10',
right: '20',
bottom: '30',
left: '40',
};
const cssText = useControlContainerCSSText(position, [10, 10]);
expect(cssText).toBe('top:10px;right:20px;bottom:30px;left:40px;');
});

test('should return an empty string for unknown position', () => {
const cssText = useControlContainerCSSText('unknown' as any, [10, 10]);
expect(cssText).toBe('');
});

test('should return an empty string for invalid position object', () => {
const position = {};
const cssText = useControlContainerCSSText(position, [10, 10]);
expect(cssText).toBe('');
});
});
53 changes: 53 additions & 0 deletions src/hooks/__tests__/useControlContainerUpdater.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* eslint-disable no-underscore-dangle */
import { renderHook } from '@testing-library/react-hooks';

import useControlContainerUpdater from '../useControlContainerUpdater';

describe('useControlContainerUpdater', () => {
test('should update container CSS text', () => {
const instance = {
_container: document.createElement('div'),
_config: {
position: 'LB',
offset: [],
},
};
const position = 'RT';
const offset = [20, 30];

renderHook(() => useControlContainerUpdater(instance, position, offset));

expect(instance._container.style.cssText).toBe('right: 20px; top: 30px;');

// 更新 _config
expect(instance._config.position).toBe(position);
expect(instance._config.offset).toBe(offset);
});

test('should update container CSS text when css text is empty', () => {
const instance = {
_container: document.createElement('div'),
_config: {
position: 'LB',
offset: [],
},
};
const position = {};

renderHook(() => useControlContainerUpdater(instance, position));

expect(instance._container.style.cssText).toBe('');
// 更新 _config
expect(instance._config.position).toEqual({});
expect(instance._config.offset).toEqual([10, 10]);
});

test('should update container CSS text when instance is Nil', () => {
const instance = null;
const position = 'LB';

expect(() => {
renderHook(() => useControlContainerUpdater(instance, position));
}).not.toThrow();
});
});
27 changes: 27 additions & 0 deletions src/hooks/__tests__/useSetter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { renderHook } from '@testing-library/react-hooks';

import useSetter from '../useSetter';

describe('useSetter', () => {
test('should call the instance method with provided arguments', () => {
const instance = {
methodName: jest.fn(),
};
const methodName = 'methodName';
const args = [1, 'test'];

renderHook(() => useSetter(instance, methodName, ...args));

expect(instance.methodName).toHaveBeenCalledWith(...args);
});

test('should not call the instance method if instance is null or undefined', () => {
const instance = null;
const methodName = 'methodName';
const args = [1, 'test'];

expect(() => {
renderHook(() => useSetter(instance, methodName, ...args));
}).not.toThrow();
});
});

0 comments on commit 49ffc12

Please sign in to comment.