diff --git a/test/utils/getPrefix.test.js b/test/utils/getPrefix.test.js new file mode 100644 index 00000000..d4e3e1fb --- /dev/null +++ b/test/utils/getPrefix.test.js @@ -0,0 +1,121 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import { getPrefix, browserPrefixToKey, browserPrefixToStyle } from '../../lib/utils/getPrefix'; + +describe('getPrefix utilities', () => { + describe('browserPrefixToKey', () => { + it('should return prop unchanged when no prefix', () => { + expect(browserPrefixToKey('transform', '')).toBe('transform'); + }); + + it('should prefix and capitalize for Webkit', () => { + expect(browserPrefixToKey('transform', 'Webkit')).toBe('WebkitTransform'); + }); + + it('should prefix and capitalize for Moz', () => { + expect(browserPrefixToKey('transform', 'Moz')).toBe('MozTransform'); + }); + + it('should handle kebab-case properties', () => { + expect(browserPrefixToKey('user-select', 'Webkit')).toBe('WebkitUserSelect'); + }); + + it('should handle multi-hyphen properties', () => { + expect(browserPrefixToKey('border-top-left-radius', 'Webkit')).toBe('WebkitBorderTopLeftRadius'); + }); + }); + + describe('browserPrefixToStyle', () => { + it('should return prop unchanged when no prefix', () => { + expect(browserPrefixToStyle('transform', '')).toBe('transform'); + }); + + it('should add CSS prefix for Webkit', () => { + expect(browserPrefixToStyle('transform', 'Webkit')).toBe('-webkit-transform'); + }); + + it('should add CSS prefix for Moz', () => { + expect(browserPrefixToStyle('transform', 'Moz')).toBe('-moz-transform'); + }); + + it('should add CSS prefix for ms', () => { + expect(browserPrefixToStyle('transform', 'ms')).toBe('-ms-transform'); + }); + }); + + describe('getPrefix', () => { + let originalWindow; + + beforeEach(() => { + originalWindow = global.window; + }); + + afterEach(() => { + global.window = originalWindow; + }); + + it('should return empty string when window is undefined', () => { + global.window = undefined; + expect(getPrefix('transform')).toBe(''); + }); + + it('should return empty string when documentElement.style is unavailable', () => { + global.window = { document: {} }; + expect(getPrefix('transform')).toBe(''); + }); + + it('should return empty string when prop exists unprefixed', () => { + global.window = { + document: { + documentElement: { + style: { transform: '' } + } + } + }; + expect(getPrefix('transform')).toBe(''); + }); + + it('should return Webkit prefix when WebkitTransform exists', () => { + global.window = { + document: { + documentElement: { + style: { WebkitTransform: '' } + } + } + }; + expect(getPrefix('transform')).toBe('Webkit'); + }); + + it('should return Moz prefix when MozTransform exists', () => { + global.window = { + document: { + documentElement: { + style: { MozTransform: '' } + } + } + }; + expect(getPrefix('transform')).toBe('Moz'); + }); + + it('should return empty string when no prefix matches', () => { + global.window = { + document: { + documentElement: { + style: {} + } + } + }; + expect(getPrefix('someUnknownProperty')).toBe(''); + }); + + it('should use transform as default prop', () => { + global.window = { + document: { + documentElement: { + style: { transform: '' } + } + } + }; + expect(getPrefix()).toBe(''); + }); + }); +}); diff --git a/test/utils/positionFns.test.js b/test/utils/positionFns.test.js index b672c72d..9e8d8731 100644 --- a/test/utils/positionFns.test.js +++ b/test/utils/positionFns.test.js @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest'; -import { snapToGrid } from '../../lib/utils/positionFns'; +import { snapToGrid, canDragX, canDragY, createCoreData, createDraggableData } from '../../lib/utils/positionFns'; describe('positionFns utilities', () => { describe('snapToGrid', () => { @@ -36,4 +36,153 @@ describe('positionFns utilities', () => { expect(snapToGrid([10, 10], 4, 4)).toEqual([0, 0]); }); }); + + describe('canDragX', () => { + it('should return true for axis "both"', () => { + const draggable = { props: { axis: 'both' } }; + expect(canDragX(draggable)).toBe(true); + }); + + it('should return true for axis "x"', () => { + const draggable = { props: { axis: 'x' } }; + expect(canDragX(draggable)).toBe(true); + }); + + it('should return false for axis "y"', () => { + const draggable = { props: { axis: 'y' } }; + expect(canDragX(draggable)).toBe(false); + }); + + it('should return false for axis "none"', () => { + const draggable = { props: { axis: 'none' } }; + expect(canDragX(draggable)).toBe(false); + }); + }); + + describe('canDragY', () => { + it('should return true for axis "both"', () => { + const draggable = { props: { axis: 'both' } }; + expect(canDragY(draggable)).toBe(true); + }); + + it('should return true for axis "y"', () => { + const draggable = { props: { axis: 'y' } }; + expect(canDragY(draggable)).toBe(true); + }); + + it('should return false for axis "x"', () => { + const draggable = { props: { axis: 'x' } }; + expect(canDragY(draggable)).toBe(false); + }); + + it('should return false for axis "none"', () => { + const draggable = { props: { axis: 'none' } }; + expect(canDragY(draggable)).toBe(false); + }); + }); + + describe('createCoreData', () => { + const mockNode = document.createElement('div'); + + it('should create initial data when lastX/lastY are NaN', () => { + const draggableCore = { + lastX: NaN, + lastY: NaN, + findDOMNode: () => mockNode + }; + const data = createCoreData(draggableCore, 100, 200); + expect(data).toEqual({ + node: mockNode, + deltaX: 0, + deltaY: 0, + lastX: 100, + lastY: 200, + x: 100, + y: 200 + }); + }); + + it('should calculate deltas when lastX/lastY are set', () => { + const draggableCore = { + lastX: 50, + lastY: 100, + findDOMNode: () => mockNode + }; + const data = createCoreData(draggableCore, 150, 250); + expect(data).toEqual({ + node: mockNode, + deltaX: 100, + deltaY: 150, + lastX: 50, + lastY: 100, + x: 150, + y: 250 + }); + }); + + it('should throw when node is unmounted', () => { + const draggableCore = { + lastX: NaN, + lastY: NaN, + findDOMNode: () => null + }; + expect(() => createCoreData(draggableCore, 0, 0)).toThrow('Unmounted during event'); + }); + }); + + describe('createDraggableData', () => { + const mockNode = document.createElement('div'); + + it('should create data with scale of 1', () => { + const draggable = { + props: { scale: 1 }, + state: { x: 100, y: 200 } + }; + const coreData = { + node: mockNode, + deltaX: 10, + deltaY: 20, + lastX: 100, + lastY: 200, + x: 110, + y: 220 + }; + const data = createDraggableData(draggable, coreData); + expect(data).toEqual({ + node: mockNode, + x: 110, + y: 220, + deltaX: 10, + deltaY: 20, + lastX: 100, + lastY: 200 + }); + }); + + it('should apply scale to delta values', () => { + const draggable = { + props: { scale: 2 }, + state: { x: 100, y: 200 } + }; + const coreData = { + node: mockNode, + deltaX: 20, + deltaY: 40, + lastX: 100, + lastY: 200, + x: 120, + y: 240 + }; + const data = createDraggableData(draggable, coreData); + expect(data).toEqual({ + node: mockNode, + x: 110, // 100 + (20/2) + y: 220, // 200 + (40/2) + deltaX: 10, // 20/2 + deltaY: 20, // 40/2 + lastX: 100, + lastY: 200 + }); + }); + }); });