From dcac72a26e52b0a410521e17506bc6a09baa16e0 Mon Sep 17 00:00:00 2001 From: ukkodeveloper Date: Fri, 1 Sep 2023 09:07:54 +0900 Subject: [PATCH 1/6] =?UTF-8?q?test:=20formatOrdinals=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/shared/utils/formatOrdinals.test.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 frontend/src/shared/utils/formatOrdinals.test.ts diff --git a/frontend/src/shared/utils/formatOrdinals.test.ts b/frontend/src/shared/utils/formatOrdinals.test.ts new file mode 100644 index 000000000..b3a3641a9 --- /dev/null +++ b/frontend/src/shared/utils/formatOrdinals.test.ts @@ -0,0 +1,23 @@ +import formatOrdinals from '@/shared/utils/formatOrdinals'; + +describe('formatOrdinals', () => { + test('숫자 1은 1st를 반환한다.', () => { + expect(formatOrdinals(1)).toBe('1st'); + }); + + test('숫자 2은 1nd를 반환한다.', () => { + expect(formatOrdinals(2)).toBe('2nd'); + }); + + test('숫자 3은 1rd를 반환한다.', () => { + expect(formatOrdinals(3)).toBe('3rd'); + }); + + test('숫자 4은 4th를 반환한다.', () => { + expect(formatOrdinals(4)).toBe('4th'); + }); + + test('숫자 11은 11th를 반환한다.', () => { + expect(formatOrdinals(11)).toBe('11th'); + }); +}); From b7be15b8d82733287072fd5ce9c35df0f084e4bb Mon Sep 17 00:00:00 2001 From: ukkodeveloper Date: Fri, 1 Sep 2023 09:21:26 +0900 Subject: [PATCH 2/6] =?UTF-8?q?test:=20useDebounceEffect=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shared/hooks/useDebounceEffect.test.ts | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 frontend/src/shared/hooks/useDebounceEffect.test.ts diff --git a/frontend/src/shared/hooks/useDebounceEffect.test.ts b/frontend/src/shared/hooks/useDebounceEffect.test.ts new file mode 100644 index 000000000..77d5c4a7c --- /dev/null +++ b/frontend/src/shared/hooks/useDebounceEffect.test.ts @@ -0,0 +1,44 @@ +import { renderHook, act } from '@testing-library/react-hooks'; +import useDebounceEffect from './useDebounceEffect'; + +jest.useFakeTimers(); + +describe('useDebounceEffect 테스트. debounce 제한 딜레이를 0.5초로 둘 경우', () => { + test('0.499초 지났을 때, 한 번도 실행되지 않는다.', () => { + const fn = jest.fn(); + const { rerender } = renderHook(({ deps, delay }) => useDebounceEffect(fn, deps, delay), { + initialProps: { deps: 'dependency1', delay: 500 }, + }); + + expect(fn).not.toBeCalled(); + + rerender({ deps: 'dependency2', delay: 500 }); + rerender({ deps: 'dependency3', delay: 500 }); + rerender({ deps: 'dependency4', delay: 500 }); + + act(() => { + jest.advanceTimersByTime(499); + }); + + expect(fn).not.toBeCalled(); + }); + + test('0.5초 지났을 때, 한 번만 실행되지 않는다.', () => { + const fn = jest.fn(); + const { rerender } = renderHook(({ deps, delay }) => useDebounceEffect(fn, deps, delay), { + initialProps: { deps: 'dependency1', delay: 500 }, + }); + + expect(fn).not.toBeCalled(); + + rerender({ deps: 'dependency2', delay: 500 }); + rerender({ deps: 'dependency3', delay: 500 }); + rerender({ deps: 'dependency4', delay: 500 }); + + act(() => { + jest.advanceTimersByTime(500); + }); + + expect(fn).toBeCalledTimes(1); + }); +}); From 76781ecbe2ea0f80d183340c45b3cc1c72de9435 Mon Sep 17 00:00:00 2001 From: ukkodeveloper Date: Fri, 1 Sep 2023 09:32:09 +0900 Subject: [PATCH 3/6] =?UTF-8?q?test:=20useFetch=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/shared/hooks/useFetch.test.ts | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 frontend/src/shared/hooks/useFetch.test.ts diff --git a/frontend/src/shared/hooks/useFetch.test.ts b/frontend/src/shared/hooks/useFetch.test.ts new file mode 100644 index 000000000..5406b417a --- /dev/null +++ b/frontend/src/shared/hooks/useFetch.test.ts @@ -0,0 +1,38 @@ +import { renderHook } from '@testing-library/react-hooks'; +import useFetch from './useFetch'; + +describe('useFetch 테스트', () => { + let fetcher: jest.Mock; + + beforeEach(() => { + fetcher = jest.fn(); + }); + + test('fetch가 성공했을 경우, isLoading 은 false, data는 mockData, error은 null이다.', async () => { + const mockData = { key: 'value' }; + fetcher.mockResolvedValueOnce(mockData); + const { result, waitForNextUpdate } = renderHook(() => useFetch(fetcher, true)); + + expect(result.current.isLoading).toBe(true); + + await waitForNextUpdate(); + + expect(result.current.isLoading).toBe(false); + expect(result.current.data).toEqual(mockData); + expect(result.current.error).toBe(null); + }); + + test('fetch가 실패했을 경우, isLoading 은 false, datas는 null, error은 mockError다.', async () => { + const mockError = { message: 'An error occurred' }; + fetcher.mockRejectedValueOnce(mockError); + const { result, waitForNextUpdate } = renderHook(() => useFetch(fetcher, true)); + + expect(result.current.isLoading).toBe(true); + + await waitForNextUpdate(); + + expect(result.current.isLoading).toBe(false); + expect(result.current.data).toBe(null); + expect(result.current.error).toEqual(mockError); + }); +}); From c732e01af37901b5c431b440419b24e401ff1e04 Mon Sep 17 00:00:00 2001 From: ukkodeveloper Date: Fri, 1 Sep 2023 09:42:12 +0900 Subject: [PATCH 4/6] =?UTF-8?q?test:=20useMutation=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/shared/hooks/useMutation.test.ts | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 frontend/src/shared/hooks/useMutation.test.ts diff --git a/frontend/src/shared/hooks/useMutation.test.ts b/frontend/src/shared/hooks/useMutation.test.ts new file mode 100644 index 000000000..bdbf8dbe8 --- /dev/null +++ b/frontend/src/shared/hooks/useMutation.test.ts @@ -0,0 +1,45 @@ +import { renderHook, act } from '@testing-library/react-hooks'; +import { useMutation } from './useMutation'; + +describe('useMutation 테스트', () => { + let mutateFn: jest.Mock; + + beforeEach(() => { + mutateFn = jest.fn(); + }); + + test('fetch가 성공했을 경우, isLoading 은 false, data는 mockData, error은 null이다.', async () => { + const mockData = { key: 'value' }; + mutateFn.mockResolvedValueOnce(mockData); + const { result, waitForNextUpdate } = renderHook(() => useMutation(mutateFn)); + + act(() => { + result.current.mutateData(); + }); + expect(result.current.isLoading).toBe(true); + + await waitForNextUpdate(); + + expect(result.current.isLoading).toBe(false); + expect(result.current.data).toEqual(mockData); + expect(result.current.error).toBe(null); + }); + + test('fetch가 실패했을 경우, isLoading 은 false, datas는 null, error은 mockError다.', async () => { + const mockError = { message: 'An error occurred' }; + mutateFn.mockRejectedValueOnce(mockError); + const { result, waitForNextUpdate } = renderHook(() => useMutation(mutateFn)); + + act(() => { + result.current.mutateData(); + }); + + expect(result.current.isLoading).toBe(true); + + await waitForNextUpdate(); + + expect(result.current.isLoading).toBe(false); + expect(result.current.data).toBe(null); + expect(result.current.error).toEqual(mockError); + }); +}); From 3a8210757130d62faffe2ef29c0ede5bf7bd9e38 Mon Sep 17 00:00:00 2001 From: ukkodeveloper Date: Fri, 1 Sep 2023 14:45:24 +0900 Subject: [PATCH 5/6] =?UTF-8?q?test:=20useDebounceEFfect=20react=20hook=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/shared/hooks/useDebounceEffect.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/shared/hooks/useDebounceEffect.test.ts b/frontend/src/shared/hooks/useDebounceEffect.test.ts index 77d5c4a7c..2f8216867 100644 --- a/frontend/src/shared/hooks/useDebounceEffect.test.ts +++ b/frontend/src/shared/hooks/useDebounceEffect.test.ts @@ -1,4 +1,4 @@ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import useDebounceEffect from './useDebounceEffect'; jest.useFakeTimers(); @@ -23,7 +23,7 @@ describe('useDebounceEffect 테스트. debounce 제한 딜레이를 0.5초로 expect(fn).not.toBeCalled(); }); - test('0.5초 지났을 때, 한 번만 실행되지 않는다.', () => { + test('0.5초 지났을 때, 한 번만 실행된다.', () => { const fn = jest.fn(); const { rerender } = renderHook(({ deps, delay }) => useDebounceEffect(fn, deps, delay), { initialProps: { deps: 'dependency1', delay: 500 }, From 3031a5477258f1477318f5dba28f76e7547bedae Mon Sep 17 00:00:00 2001 From: ukkodeveloper Date: Fri, 1 Sep 2023 14:46:01 +0900 Subject: [PATCH 6/6] =?UTF-8?q?feat:=20useFetch,=20useMutation=20react-hoo?= =?UTF-8?q?k=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/shared/hooks/useFetch.test.ts | 26 +++++++++--------- frontend/src/shared/hooks/useMutation.test.ts | 27 ++++++++++--------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/frontend/src/shared/hooks/useFetch.test.ts b/frontend/src/shared/hooks/useFetch.test.ts index 5406b417a..6e7da8845 100644 --- a/frontend/src/shared/hooks/useFetch.test.ts +++ b/frontend/src/shared/hooks/useFetch.test.ts @@ -1,4 +1,4 @@ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import useFetch from './useFetch'; describe('useFetch 테스트', () => { @@ -11,28 +11,28 @@ describe('useFetch 테스트', () => { test('fetch가 성공했을 경우, isLoading 은 false, data는 mockData, error은 null이다.', async () => { const mockData = { key: 'value' }; fetcher.mockResolvedValueOnce(mockData); - const { result, waitForNextUpdate } = renderHook(() => useFetch(fetcher, true)); + const { result } = renderHook(() => useFetch(fetcher, true)); expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); - - expect(result.current.isLoading).toBe(false); - expect(result.current.data).toEqual(mockData); - expect(result.current.error).toBe(null); + waitFor(() => { + expect(result.current.isLoading).toBe(false); + expect(result.current.data).toEqual(mockData); + expect(result.current.error).toBe(null); + }); }); test('fetch가 실패했을 경우, isLoading 은 false, datas는 null, error은 mockError다.', async () => { const mockError = { message: 'An error occurred' }; fetcher.mockRejectedValueOnce(mockError); - const { result, waitForNextUpdate } = renderHook(() => useFetch(fetcher, true)); + const { result } = renderHook(() => useFetch(fetcher, true)); expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); - - expect(result.current.isLoading).toBe(false); - expect(result.current.data).toBe(null); - expect(result.current.error).toEqual(mockError); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + expect(result.current.data).toBe(null); + expect(result.current.error).toEqual(mockError); + }); }); }); diff --git a/frontend/src/shared/hooks/useMutation.test.ts b/frontend/src/shared/hooks/useMutation.test.ts index bdbf8dbe8..2a69bf23b 100644 --- a/frontend/src/shared/hooks/useMutation.test.ts +++ b/frontend/src/shared/hooks/useMutation.test.ts @@ -1,4 +1,4 @@ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act, waitFor } from '@testing-library/react'; import { useMutation } from './useMutation'; describe('useMutation 테스트', () => { @@ -11,24 +11,25 @@ describe('useMutation 테스트', () => { test('fetch가 성공했을 경우, isLoading 은 false, data는 mockData, error은 null이다.', async () => { const mockData = { key: 'value' }; mutateFn.mockResolvedValueOnce(mockData); - const { result, waitForNextUpdate } = renderHook(() => useMutation(mutateFn)); + const { result } = renderHook(() => useMutation(mutateFn)); act(() => { result.current.mutateData(); }); - expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); + expect(result.current.isLoading).toBe(true); - expect(result.current.isLoading).toBe(false); - expect(result.current.data).toEqual(mockData); - expect(result.current.error).toBe(null); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + expect(result.current.data).toEqual(mockData); + expect(result.current.error).toBe(null); + }); }); test('fetch가 실패했을 경우, isLoading 은 false, datas는 null, error은 mockError다.', async () => { const mockError = { message: 'An error occurred' }; mutateFn.mockRejectedValueOnce(mockError); - const { result, waitForNextUpdate } = renderHook(() => useMutation(mutateFn)); + const { result } = renderHook(() => useMutation(mutateFn)); act(() => { result.current.mutateData(); @@ -36,10 +37,10 @@ describe('useMutation 테스트', () => { expect(result.current.isLoading).toBe(true); - await waitForNextUpdate(); - - expect(result.current.isLoading).toBe(false); - expect(result.current.data).toBe(null); - expect(result.current.error).toEqual(mockError); + await waitFor(() => { + expect(result.current.isLoading).toBe(false); + expect(result.current.data).toBe(null); + expect(result.current.error).toEqual(mockError); + }); }); });