diff --git a/.github/workflows/install-build-test.yaml b/.github/workflows/install-build-test.yaml index 2c75459..f651a35 100644 --- a/.github/workflows/install-build-test.yaml +++ b/.github/workflows/install-build-test.yaml @@ -8,6 +8,7 @@ on: env: GITHUB_TOKEN: ${{ secrets.DND_11_8_FRONTEND_TOKEN }} GITHUB_ACTIONS: true + VITE_API_URL: ${{ secrets.VITE_API_URL }} jobs: build: diff --git a/package.json b/package.json index a1e6dd3..a9a1522 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.4.8", "@testing-library/react": "^16.0.0", + "@testing-library/user-event": "^14.5.2", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.18.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b72990..5a8dc8e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -156,6 +156,9 @@ importers: '@testing-library/react': specifier: ^16.0.0 version: 16.0.0(@testing-library/dom@10.4.0)(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@testing-library/user-event': + specifier: ^14.5.2 + version: 14.5.2(@testing-library/dom@10.4.0) '@types/react': specifier: ^18.3.3 version: 18.3.3 @@ -8392,6 +8395,10 @@ snapshots: dependencies: '@testing-library/dom': 10.1.0 + '@testing-library/user-event@14.5.2(@testing-library/dom@10.4.0)': + dependencies: + '@testing-library/dom': 10.4.0 + '@toss/async-boundary@1.5.0(react@18.3.1)': dependencies: '@toss/error-boundary': 1.5.0(react@18.3.1) diff --git a/src/__test__/AddPlantPage.test.tsx b/src/__test__/AddPlantPage.test.tsx new file mode 100644 index 0000000..e1beb8e --- /dev/null +++ b/src/__test__/AddPlantPage.test.tsx @@ -0,0 +1,85 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { render, screen, waitFor } from '@testing-library/react'; +import AddPlantPage from '@/pages/AddPlantPage'; +import { Wrapper } from '@/__test__/helpers/wrapper.tsx'; +import userEvent from '@testing-library/user-event'; + +// Mock the ResizeObserver +const ResizeObserverMock = vi.fn(() => ({ + observe: vi.fn(), + unobserve: vi.fn(), + disconnect: vi.fn(), +})); + +// Stub the global ResizeObserver +vi.stubGlobal('ResizeObserver', ResizeObserverMock); + +describe('내 식물 등록 페이지 테스트', () => { + const user = userEvent.setup(); + beforeEach(() => { + render(, { wrapper: Wrapper }); + }); + it('식물 종류 입력 텍스트 필드를 클릭하면 식물 종류 검색 페이지가 나타난다.', async () => { + const plantTypeInput = screen.getByLabelText('식물 종류'); + + await user.click(plantTypeInput); + + const plantTypeSearchInput = screen.getByPlaceholderText('식물 종류 검색'); + expect(plantTypeSearchInput).toBeInTheDocument(); + }); + + it('식물 종류 검색시 검색 결과가 나타난다.', async () => { + const plantTypeInput = screen.getByLabelText('식물 종류'); + + await user.click(plantTypeInput); + + const plantTypeSearchInput = screen.getByPlaceholderText('식물 종류 검색') as HTMLInputElement; + + await waitFor( + async () => { + await user.type(plantTypeSearchInput, '몬스테라'); + expect(plantTypeSearchInput.value).toBe('몬스테라'); + }, + { timeout: 2000 }, + ); + + await waitFor( + async () => { + const plantTypeSearchResult = await screen.findByText(/몬스테라/); + expect(plantTypeSearchResult).toBeInTheDocument(); + }, + { timeout: 4000 }, + ); + }); + + it('검색 결과 클릭시 화면이 사라지고 선택한 식물의 값이 텍스트 필드에 표기된다', async () => { + const plantTypeInput = screen.getByLabelText('식물 종류') as HTMLInputElement; + + await user.click(plantTypeInput); + + const plantTypeSearchInput = screen.getByPlaceholderText('식물 종류 검색') as HTMLInputElement; + + await waitFor( + async () => { + await user.type(plantTypeSearchInput, '몬스테라'); + expect(plantTypeSearchInput.value).toBe('몬스테라'); + }, + { timeout: 2000 }, + ); + + await waitFor( + async () => { + const plantTypeAddButton = await screen.findByRole('button', { + name: /add-searched-result-button/, + }); + + await user.click(plantTypeAddButton); + }, + { timeout: 4000 }, + ); + + expect(plantTypeSearchInput).not.toBeInTheDocument(); + + expect(plantTypeInput.value).include('몬스테라'); + }); +}); diff --git a/src/__test__/helpers/wrapper.tsx b/src/__test__/helpers/wrapper.tsx new file mode 100644 index 0000000..e62fd36 --- /dev/null +++ b/src/__test__/helpers/wrapper.tsx @@ -0,0 +1,26 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { Provider as JotaiProvider } from 'jotai'; +import { GlobalPortal } from '@/providers/GlobalPortal.tsx'; +import { GlobalModalProvider } from '@/providers/GlobalModalProvider.tsx'; +import { PropsWithChildren } from 'react'; +import { MemoryRouter } from 'react-router-dom'; + +interface WrapperProps extends PropsWithChildren { + initialEntries?: string[]; +} + +export const Wrapper = ({ children, initialEntries }: WrapperProps) => { + const queryClient = new QueryClient({}); + return ( + + + + + {children} + + ; + + + + ); +}; diff --git a/src/__test__/setup.ts b/src/__test__/setup.ts index d13f63a..3a5ed4e 100644 --- a/src/__test__/setup.ts +++ b/src/__test__/setup.ts @@ -1,7 +1,15 @@ -import { afterEach } from 'vitest'; +import { afterEach, beforeEach } from 'vitest'; import { cleanup } from '@testing-library/react'; import '@testing-library/jest-dom'; +import { setupServer } from 'msw/node'; +import { handlers } from '@/mocks/handlers.ts'; + +const server = setupServer(...handlers); + +beforeEach(() => { + server.listen(); +}); afterEach(() => { cleanup(); diff --git a/src/components/searchPlant/SearchedPlantList.tsx b/src/components/searchPlant/SearchedPlantList.tsx index f031c8d..78f3059 100644 --- a/src/components/searchPlant/SearchedPlantList.tsx +++ b/src/components/searchPlant/SearchedPlantList.tsx @@ -103,7 +103,11 @@ const SearchedPlantList = ({ query, onClose }: SearchedPlantListProps) => { image={plant.imageUrl} key={`SearchedPlantList-${plant.plantId}`} trailingIcon={ - } @@ -112,7 +116,7 @@ const SearchedPlantList = ({ query, onClose }: SearchedPlantListProps) => { )); } - return ; + return ; }; export default SearchedPlantList; diff --git a/src/pages/SearchPlantPage.tsx b/src/pages/SearchPlantPage.tsx index 9f97a42..bd6cba5 100644 --- a/src/pages/SearchPlantPage.tsx +++ b/src/pages/SearchPlantPage.tsx @@ -27,7 +27,7 @@ const SearchPlantPage = ({ onClose }: SearchPlantPageProps) => { } /> - + diff --git a/vitest.config.ts b/vitest.config.ts index b4bf790..96c1bf5 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,8 +1,9 @@ import { defineConfig } from 'vitest/config'; import react from '@vitejs/plugin-react'; +import svgr from 'vite-plugin-svgr'; export default defineConfig({ - plugins: [react()], + plugins: [react(), svgr()], test: { globals: true, environment: 'jsdom',