diff --git a/.npmignore b/.npmignore
index abce592..7c8b78a 100644
--- a/.npmignore
+++ b/.npmignore
@@ -12,4 +12,9 @@ build-storybook.log
storybook-static
.github
rollup.config.cjs.js
-rollup.config.js
\ No newline at end of file
+rollup.config.js
+coverage
+.husky
+.eslintrc.cjs
+.prettierrc
+.cache
\ No newline at end of file
diff --git a/package.json b/package.json
index 554e182..2262c96 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@rapiders/react-hooks",
- "version": "1.2.2",
+ "version": "1.2.5",
"description": "react hooks for fast development",
"main": "dist/esm/index.js",
"types": "dist/esm/index.d.ts",
@@ -12,7 +12,7 @@
"homepage": "https://github.com/rapiders/react-hooks",
"scripts": {
"test": "jest",
- "prepublish": "npm run build",
+ "prepublishOnly": "npm run build",
"build": "sh build.sh",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build",
diff --git a/src/index.ts b/src/index.ts
index 9dd1f15..ef0151c 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -6,5 +6,16 @@ import useCarousel from './useCarousel/useCarousel';
import useScrollRatio from './useScrollRatio';
import useInterval from './useInterval/useInterval';
import useAfterMountEffect from './useAfterMountEffect/useAfterMountEffect';
+import useRadio from './useRadio/useRadio';
-export { useInput, useAnimation, useFocusAnimation, useDragIndexCarousel, useCarousel, useScrollRatio, useInterval, useAfterMountEffect };
+export {
+ useInput,
+ useAnimation,
+ useFocusAnimation,
+ useDragIndexCarousel,
+ useCarousel,
+ useScrollRatio,
+ useInterval,
+ useAfterMountEffect,
+ useRadio,
+};
diff --git a/src/useCarousel/useCarousel.test.tsx b/src/useCarousel/useCarousel.test.tsx
index 150f906..4b4527c 100644
--- a/src/useCarousel/useCarousel.test.tsx
+++ b/src/useCarousel/useCarousel.test.tsx
@@ -1,35 +1,110 @@
-import { renderHook, act } from '@testing-library/react';
+import { render, screen, fireEvent } from '@testing-library/react';
import useCarousel from './useCarousel';
+import React from 'react';
+
+const DATA = [1, 2, 3, 4];
-const DATA_LENGTH = 3;
describe('useCarousel 기능 테스트', () => {
- it('next 함수를 통해 index를 1증가시킬 수 있다.', () => {
- const { result } = renderHook(() => useCarousel(DATA_LENGTH));
- expect(result.current.isStart).toBe(true);
- expect(result.current.index).toBe(0);
- act(() => result.current.next());
- expect(result.current.index).toBe(1);
- });
+ const TestComponent = () => {
+ const { CarouselWrapper, prev, next, index, ref } = useCarousel(DATA.length);
+ return (
+ <>
+
+ {DATA.map((num) => (
+
+ {num}
+
+ ))}
+
+
+
+
{index}
+ >
+ );
+ };
+
+ it('Carousel Wrapper컴포넌트를 통해 prev, next 기능을 수행할 수 있다.', async () => {
+ render();
+ const next = await screen.findByRole('next');
+ const prev = await screen.findByRole('prev');
- it('next 함수 실행시 dataLength와 index가 같아지는 경우 초기 index로 이동한다.', () => {
- const { result } = renderHook(() => useCarousel(DATA_LENGTH, { startIndex: DATA_LENGTH - 1, infinity: true }));
- expect(result.current.index).toBe(DATA_LENGTH - 1);
- expect(result.current.isEnd).toBe(true);
- act(() => result.current.next());
- expect(result.current.index).toBe(0);
+ fireEvent.click(next);
+ const indexElement = await screen.findByRole('index');
+ expect(indexElement.textContent).toBe('1');
+
+ fireEvent.click(prev);
+ expect(indexElement.textContent).toBe('0');
});
- it('prev 함수를 통해 index를 1감소시킬 수 있다.', () => {
- const { result } = renderHook(() => useCarousel(DATA_LENGTH, { startIndex: DATA_LENGTH - 1, infinity: true }));
- expect(result.current.index).toBe(DATA_LENGTH - 1);
- act(() => result.current.prev());
- expect(result.current.index).toBe(DATA_LENGTH - 2);
+ it('index 제한을 넘어가는 경우, prev와 next함수가 index를 변화시키지 않을 수 있다.', async () => {
+ render();
+ const next = await screen.findByRole('next');
+ const prev = await screen.findByRole('prev');
+
+ Array.from({ length: 10 }).forEach(() => fireEvent.click(next));
+
+ const indexElement = await screen.findByRole('index');
+ expect(indexElement.textContent).toBe('3');
+
+ Array.from({ length: 10 }).forEach(() => fireEvent.click(prev));
+ expect(indexElement.textContent).toBe('0');
});
+});
+
+describe('useCarousel(infinity) 기능 테스트', () => {
+ const TestComponent = () => {
+ const { CarouselWrapper, prev, next, index, ref } = useCarousel(DATA.length, { infinity: true });
+ return (
+ <>
+
+ {DATA.map((num) => (
+
+ {num}
+
+ ))}
+
+
+
+ {index}
+ >
+ );
+ };
+
+ it('index 제한을 넘어가는 경우, prev와 next함수가 index를 적절하게 변환할 수 있다.', async () => {
+ render();
+ const next = await screen.findByRole('next');
+ const prev = await screen.findByRole('prev');
+
+ Array.from({ length: 5 }).forEach(() => fireEvent.click(next));
+
+ const indexElement = await screen.findByRole('index');
+ expect(indexElement.textContent).toBe('1');
- it('prev 함수 실행시, index가 0인경우, 마지막 값으로 이동한다.', () => {
- const { result } = renderHook(() => useCarousel(DATA_LENGTH, { infinity: true }));
- expect(result.current.index).toBe(0);
- act(() => result.current.prev());
- expect(result.current.index).toBe(DATA_LENGTH - 1);
+ Array.from({ length: 2 }).forEach(() => fireEvent.click(prev));
+ expect(indexElement.textContent).toBe('3');
});
});
diff --git a/src/useCarousel/useCarousel.tsx b/src/useCarousel/useCarousel.tsx
index 467556d..c8b5f7b 100644
--- a/src/useCarousel/useCarousel.tsx
+++ b/src/useCarousel/useCarousel.tsx
@@ -36,10 +36,9 @@ export default function useCarousel(dataLength: number, options?: useCarouselOpt
}, [index]);
const getSliderWidth = () => {
- if (ref.current) {
- return ref.current.clientWidth;
- }
- return window.innerWidth;
+ // getSliderWidth는 상단의 useEffect에서 호출하는데, 여기서 ref.current를 확인하므로
+ // ref.current가 반드시 존재한다.
+ return ref!.current!.clientWidth;
};
const getNext = (index: number) => {