From de8ee1e9ab7f6e92d0a927afa812d69e09f3b30e Mon Sep 17 00:00:00 2001 From: r-mulder Date: Mon, 13 May 2024 14:12:19 +0200 Subject: [PATCH] fix: add paginated story and add tests for utils --- .../src/components/Tabs/Tabs.stories.tsx | 1 + .../Tabs/utils/calculateScroll.test.tsx | 55 +++++++++++++++++++ .../components/Tabs/utils/calculateScroll.tsx | 28 ++++------ .../Tabs/utils/getMinimalChildWidth.test.tsx | 37 +++++++++++++ .../Tabs/utils/getMinimalChildWidth.tsx | 14 ++--- 5 files changed, 109 insertions(+), 26 deletions(-) create mode 100644 packages/libs/react-ui/src/components/Tabs/utils/calculateScroll.test.tsx create mode 100644 packages/libs/react-ui/src/components/Tabs/utils/getMinimalChildWidth.test.tsx diff --git a/packages/libs/react-ui/src/components/Tabs/Tabs.stories.tsx b/packages/libs/react-ui/src/components/Tabs/Tabs.stories.tsx index 65aa2288eca..5c5de0e2dbf 100644 --- a/packages/libs/react-ui/src/components/Tabs/Tabs.stories.tsx +++ b/packages/libs/react-ui/src/components/Tabs/Tabs.stories.tsx @@ -142,6 +142,7 @@ export const DefaultSelectedTabsStory: Story = { return ( {ExampleManyTabs.map((tab) => ( diff --git a/packages/libs/react-ui/src/components/Tabs/utils/calculateScroll.test.tsx b/packages/libs/react-ui/src/components/Tabs/utils/calculateScroll.test.tsx new file mode 100644 index 00000000000..0fcf7e1975b --- /dev/null +++ b/packages/libs/react-ui/src/components/Tabs/utils/calculateScroll.test.tsx @@ -0,0 +1,55 @@ +import { RefObject } from 'react'; +import { describe, expect, it } from 'vitest'; +import { calculateScroll } from './calculateScroll'; +import { mockChildElementsRef } from './getMinimalChildWidth.test'; + +const wrapperContainerRef = { + current: { + ...mockChildElementsRef.current, + scrollWidth: 1000, + offsetWidth: 100, + }, +} as RefObject; + +const currentValue = (scrollLeft: number) => + ({ + current: { + scrollLeft, + }, + }) as RefObject; + +describe('calculateScroll', () => { + it('should return 0 if direction is back and currentValue is less than offset', () => { + expect(calculateScroll('back', wrapperContainerRef, currentValue(0))).toBe( + 0, + ); + }); + + it('should return 700 if direction is back and currentValue is 750', () => { + expect( + calculateScroll('back', wrapperContainerRef, currentValue(750)), + ).toBe(700); + }); + + it('should return 50 if direction is forward and currentValue is 0', () => { + expect( + calculateScroll('forward', wrapperContainerRef, currentValue(0)), + ).toBe(50); + }); + + it('Should scroll to the end when the next value is more than the max width', () => { + expect( + calculateScroll('forward', wrapperContainerRef, currentValue(951)), + ).toBe(900); + }); + + it("Should return 0 if elements aren't present", () => { + expect( + calculateScroll( + 'forward', + {} as unknown as RefObject, + {} as unknown as RefObject, + ), + ).toBe(0); + }); +}); diff --git a/packages/libs/react-ui/src/components/Tabs/utils/calculateScroll.tsx b/packages/libs/react-ui/src/components/Tabs/utils/calculateScroll.tsx index b3bac34d540..8730967bda5 100644 --- a/packages/libs/react-ui/src/components/Tabs/utils/calculateScroll.tsx +++ b/packages/libs/react-ui/src/components/Tabs/utils/calculateScroll.tsx @@ -6,29 +6,25 @@ export const calculateScroll = ( wrapperContainerRef: RefObject, scrollContainerRef: RefObject, ) => { - const maxWidth = wrapperContainerRef.current?.scrollWidth || 0; - const viewWidth = wrapperContainerRef.current?.offsetWidth || 0; - const offset = getMinimalChildWidth(scrollContainerRef); - const currentValue = scrollContainerRef.current?.scrollLeft || 0; - - let nextValue = 0; + if (!wrapperContainerRef.current || !scrollContainerRef.current) return 0; + const maxWidth = wrapperContainerRef.current.scrollWidth; + const viewWidth = wrapperContainerRef.current.offsetWidth; + const offset = getMinimalChildWidth(wrapperContainerRef); + const currentValue = scrollContainerRef.current.scrollLeft; if (direction === 'forward') { - nextValue = Math.abs(currentValue + offset); - - if (nextValue > maxWidth - viewWidth) { - nextValue = maxWidth - viewWidth; - } + const nextValue = currentValue + offset; if (nextValue > maxWidth) { - return currentValue; + return maxWidth - viewWidth; } - } else { - nextValue = currentValue - offset; + return nextValue; + } else { if (Math.abs(currentValue) < offset) { - nextValue = 0; + return 0; } + + return currentValue - offset; } - return nextValue; }; diff --git a/packages/libs/react-ui/src/components/Tabs/utils/getMinimalChildWidth.test.tsx b/packages/libs/react-ui/src/components/Tabs/utils/getMinimalChildWidth.test.tsx new file mode 100644 index 00000000000..6b5e8c2caf2 --- /dev/null +++ b/packages/libs/react-ui/src/components/Tabs/utils/getMinimalChildWidth.test.tsx @@ -0,0 +1,37 @@ +import type { RefObject } from 'react'; +import { describe, expect, it } from 'vitest'; +import { getMinimalChildWidth } from './getMinimalChildWidth'; + +export const mockChildElementsRef = { + current: { + children: [ + { + offsetWidth: 59, + }, + { + offsetWidth: 50, + }, + { + offsetWidth: 55, + }, + { + offsetWidth: 60, + }, + ], + length: 3, + }, +} as unknown as RefObject; + +describe('getMinimalChildWidth', () => { + it('should return the lowest value', async () => { + expect(getMinimalChildWidth(mockChildElementsRef)).toBe(50); + }); + + it('should return 0 if no children are present', async () => { + expect( + getMinimalChildWidth({ + current: { length: 0 }, + } as unknown as RefObject), + ).toBe(0); + }); +}); diff --git a/packages/libs/react-ui/src/components/Tabs/utils/getMinimalChildWidth.tsx b/packages/libs/react-ui/src/components/Tabs/utils/getMinimalChildWidth.tsx index 0dbe95875fe..2a0051ce0af 100644 --- a/packages/libs/react-ui/src/components/Tabs/utils/getMinimalChildWidth.tsx +++ b/packages/libs/react-ui/src/components/Tabs/utils/getMinimalChildWidth.tsx @@ -7,15 +7,9 @@ export const getMinimalChildWidth = (ref: RefObject) => { return 0; } - let minimalWidth = 0; + const widths = Array.from(children).map( + (child) => (child as HTMLElement)?.offsetWidth || 0, + ); - for (let i = 0; i < children.length; i++) { - const child = children[i] as HTMLElement; - - if (child.offsetWidth > minimalWidth) { - minimalWidth = child.offsetWidth; - } - } - - return minimalWidth; + return Math.min(...widths.filter((width) => width === 0)); };