Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release: v0.1.3 #38

Merged
merged 5 commits into from
Aug 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "p-travel-log",
"version": "0.1.2",
"version": "0.1.3",
"private": true,
"scripts": {
"dev": "next dev",
Expand Down
15 changes: 15 additions & 0 deletions public/camera.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/chevron-left.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
98 changes: 98 additions & 0 deletions src/__test__/NavigationBar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { render, fireEvent, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import { useRouter, usePathname } from 'next/navigation';

import { NavigationBar } from '@/components';

jest.mock('next/navigation', () => ({
useRouter: jest.fn(),
usePathname: jest.fn(),
}));

describe('내비게이션 바 스냅샷 테스트', () => {
let mockRouter: { replace: jest.Mock };
let mockUsePathname: jest.Mock;

beforeEach(() => {
mockRouter = {
replace: jest.fn(),
};
mockUsePathname = usePathname as jest.Mock;
(useRouter as jest.Mock).mockReturnValue(mockRouter);
});

afterEach(() => {
jest.clearAllMocks();
});

test('pathname이 /login 이거나 /my, /my/edit 인 경우에는 내비게이션 바가 렌더링되지 않아야 합니다.', () => {
const pathnames = ['/login', '/my', '/my/edit'];

pathnames.forEach((pathname) => {
mockUsePathname.mockReturnValue(pathname);

const { container } = render(<NavigationBar />);
expect(container.firstChild).toBeNull();
});
});

test('pathname이 /login 이나 /my가 아닌 경우 내비게이션 바가 렌더링 되어야 합니다.', () => {
mockUsePathname.mockReturnValue('/test');

const { getByText } = render(<NavigationBar />);
expect(getByText('여행하기')).toBeInTheDocument();
expect(getByText('홈')).toBeInTheDocument();
expect(getByText('기록하기')).toBeInTheDocument();
});

test('pathname이 /travel인 경우 여행하기 메뉴가 활성화 되어야 합니다.', () => {
mockUsePathname.mockReturnValue('/travel');
render(<NavigationBar />);

expect(screen.getByAltText('travel-active-menu')).toBeInTheDocument();
expect(screen.getByText('여행하기')).toHaveStyle('color: #605EFF');
});

test('pathname이 /인 경우 홈 메뉴가 활성화 되어야 합니다.', () => {
mockUsePathname.mockReturnValue('/');
render(<NavigationBar />);

expect(screen.getByAltText('home-active-menu')).toBeInTheDocument();
expect(screen.getByText('홈')).toHaveStyle('color: #605EFF');
});

test('pathname이 /record인 경우 기록하기 메뉴가 활성화 되어야 합니다.', () => {
mockUsePathname.mockReturnValue('/record');
render(<NavigationBar />);

expect(screen.getByAltText('record-active-menu')).toBeInTheDocument();
expect(screen.getByText('기록하기')).toHaveStyle('color: #605EFF');
});

test('여행하기 메뉴에 클릭 이벤트가 발생한 경우 router가 /travel 로 replace 되어야 합니다.', () => {
mockUsePathname.mockReturnValue('/travel');

const { getByText } = render(<NavigationBar />);
fireEvent.click(getByText('여행하기'));

expect(mockRouter.replace).toHaveBeenCalledWith('/travel');
});

test('홈 메뉴에 클릭 이벤트가 발생한 경우 router가 / 로 replace 되어야 합니다.', () => {
mockUsePathname.mockReturnValue('/');

const { getByText } = render(<NavigationBar />);
fireEvent.click(getByText('홈'));

expect(mockRouter.replace).toHaveBeenCalledWith('/');
});

test('기록하기 메뉴에 클릭 이벤트가 발생한 경우 router가 /record 로 replace 되어야 합니다.', () => {
mockUsePathname.mockReturnValue('/record');

const { getByText } = render(<NavigationBar />);
fireEvent.click(getByText('기록하기'));

expect(mockRouter.replace).toHaveBeenCalledWith('/record');
});
});
6 changes: 3 additions & 3 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

html,
body {
width: 100vw;
height: 100vh;
width: 100dvw;
height: 100dvh;
}

a {
Expand All @@ -20,7 +20,7 @@ a {

main {
width: 100%;
height: calc(100% - 96.7px);
height: 100%;
min-width: 375px;

display: flex;
Expand Down
7 changes: 7 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ export default function RootLayout({
}>) {
return (
<html lang='ko-kr'>
<head>
<meta name='theme-color' content='#605EFF' />
<meta
name='viewport'
content='width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no'
/>
</head>
<body className={inter.className}>
<TravelScheduleStoreProvider>
<main>
Expand Down
5 changes: 5 additions & 0 deletions src/app/my/edit/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { ProfileEditPage } from '@/app/pages';

export default function ProfilePage() {
return <ProfileEditPage />;
}
1 change: 1 addition & 0 deletions src/app/pages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './my-page';
export * from './travel-auto-page';
export * from './travel-traveler-page';
export * from './travel-page';
export * from './profile-edit-page';
18 changes: 15 additions & 3 deletions src/app/pages/my-page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import styled from '@emotion/styled';
import { useRouter } from 'next/navigation';
import { useState } from 'react';

interface Travel {
Expand Down Expand Up @@ -57,12 +58,20 @@
}
};

const router = useRouter();

return (
<styles.container>
<styles.top>
<styles.header>
<styles.xBtn src='/x.svg' alt='x' />
<span>프로필 편집</span>
<styles.xBtn
src='/x.svg'
alt='x'
onClick={() => router.replace('/')}
/>
<button type='button' onClick={() => router.replace('/my/edit')}>
프로필 편집
</button>
</styles.header>
<styles.profileSection>
<styles.profileImg />
Expand Down Expand Up @@ -100,7 +109,7 @@
return (
<styles.tabContents>
{Object.values(user.travel).map((travel, id) => (
<styles.list key={id}>

Check warning on line 112 in src/app/pages/my-page.tsx

View workflow job for this annotation

GitHub Actions / lint

Do not use Array index in keys
<styles.thumbnail />
<section>
<h3>{travel.name}</h3>
Expand All @@ -115,11 +124,11 @@
}

function RecordTab() {
return <></>;

Check warning on line 127 in src/app/pages/my-page.tsx

View workflow job for this annotation

GitHub Actions / lint

Fragments should contain more than one child - otherwise, there’s no need for a Fragment at all
}

function ScrapTab() {
return <></>;

Check warning on line 131 in src/app/pages/my-page.tsx

View workflow job for this annotation

GitHub Actions / lint

Fragments should contain more than one child - otherwise, there’s no need for a Fragment at all
}

const styles = {
Expand All @@ -146,7 +155,7 @@
align-items: center;
align-self: stretch;

span {
button {
color: #605eff;

text-align: center;
Expand All @@ -157,6 +166,9 @@
line-height: normal;
letter-spacing: -0.01625rem;
cursor: pointer;

border: none;
background-color: transparent;
}
`,

Expand Down
66 changes: 66 additions & 0 deletions src/app/pages/profile-edit-page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use client';

import styled from '@emotion/styled';
import { useRouter } from 'next/navigation';
import { useState } from 'react';

import {
Header,
EditProfileSection,
EditPasswordSection,
} from '@/components/profile';
import { type User } from '@/features/profile';

const dummyUser: User = {
tag: 123,
nickname: 'P의 여행자',
password: '123456',
email: '[email protected]',
profileImage: 'https://picsum.photos/50/50',
};

export function ProfileEditPage() {
const router = useRouter();
const [isEditPWD, setIsEditPWD] = useState(false);

const returnToEditPage = () => {
router.replace('/my/edit');
setIsEditPWD(false);
};

return (
<styles.container>
{!isEditPWD ? (
<>
<Header
h2='프로필 편집'
prevButtonHandler={() => router.replace('/my')}
/>
<EditProfileSection user={dummyUser} handlingEditPWD={setIsEditPWD} />
</>
) : (
<>
<Header
h2='비밀번호 변경하기'
prevButtonHandler={() => returnToEditPage()}
/>
<EditPasswordSection
currentPWD={dummyUser.password}
onClick={() => returnToEditPage()}
/>
</>
)}
</styles.container>
);
}

const styles = {
container: styled.div`
display: flex;
width: 100%;
height: 100%;
flex-direction: column;
align-items: center;
background-color: #fafaff;
`,
};
Loading
Loading