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

[FE][댓글모듈] 비로그인 유저 비밀번호 입력창을 수동으로 닫을 수 있게 만든다. (#257) #263

Merged
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
2 changes: 1 addition & 1 deletion frontend/manage/src/constants/api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const BASE_URL = "https://darass.o-r.kr";
const QUERY = {
LOGIN: "/api/v1/login/oauth?oauthAccessToken=",
LOGIN: "/api/v1/login/oauth?oauthProviderName=kakao&oauthAccessToken=",
USER: "/api/v1/users",
COMMENT: "/api/v1/comments",
PROJECT: "/api/v1/projects"
Expand Down
5 changes: 4 additions & 1 deletion frontend/reply-module/.babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@
],
"@babel/preset-typescript"
],
"plugins": [["@babel/transform-runtime"]]
"plugins": [
["@babel/transform-runtime"],
["babel-plugin-remove-react-jsx-attribute", { "attributes": ["data-testid"] }]
]
}
3 changes: 2 additions & 1 deletion frontend/reply-module/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "reply-module",
"version": "^0.1.1",
"version": "^0.1.2",
"description": "댓글 모듈",
"main": "index.js",
"author": "도비, 곤이",
Expand All @@ -26,6 +26,7 @@
"@types/styled-components": "^5.1.11",
"@types/testing-library__jest-dom": "^5.14.0",
"babel-loader": "^8.2.2",
"babel-plugin-remove-react-jsx-attribute": "^1.0.1",
"clean-webpack-plugin": "^4.0.0-alpha.0",
"eslint": "^7.29.0",
"eslint-config-prettier": "^8.3.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import "@testing-library/jest-dom/extend-expect";
import { fireEvent, render, waitFor } from "@testing-library/react";
import CommentInput from "../../components/organisms/CommentInput/index";
import CommentList from "../../components/organisms/CommentList";
import { useCreateComment, useDeleteComment, useEditComment } from "../../hooks";
import { useCreateComment, useDeleteComment, useEditComment, useConfirmGuestPassword } from "../../hooks";
import { Comment } from "../../types";
import { comments } from "../fixture/comments";

jest.mock("../../hooks/useEditComment");
jest.mock("../../hooks/useDeleteComment");
jest.mock("../../hooks/useCreateComment");
jest.mock("../../hooks/useConfirmGuestPassword");
jest.mock("../../utils/request");

window.alert = function (str) {
console.log(str);
Expand Down Expand Up @@ -36,6 +38,18 @@ describe("비로그인 유저 댓글 조회", () => {
error: false
};
});
(useConfirmGuestPassword as jest.Mock).mockImplementation(() => {
return {
isValid: true,
getPasswordConfirmResult: () => {
return {
data: {
isCorrectPassword: true
}
};
}
};
});
});
test("비로그인 유저인 경우, 비로그인 유저가 작성한 모든 댓글들에 수정/삭제 옵션이 노출된다.", () => {
const _comments: Comment[] = JSON.parse(JSON.stringify(comments));
Expand All @@ -45,8 +59,6 @@ describe("비로그인 유저 댓글 조회", () => {
$$comments.forEach(($comment, index) => {
if (_comments[index].user.type === "GuestUser") {
expect($comment.querySelectorAll("img")[1]).toBeVisible();
} else {
expect($comment.querySelectorAll("img")[1]).toBe(undefined);
}
});
});
Expand Down Expand Up @@ -119,6 +131,8 @@ describe("비로그인 유저 댓글 생성", () => {

describe("비로그인 유저 댓글 수정", () => {
beforeEach(() => {
// (request as jest.Mock).mockImplementation(() => {});

(useEditComment as jest.Mock).mockImplementation(() => {
return {
editComment: () => {},
Expand All @@ -134,18 +148,29 @@ describe("비로그인 유저 댓글 수정", () => {
error: false
};
});
(useConfirmGuestPassword as jest.Mock).mockImplementation(() => {
return {
isValid: true,
getPasswordConfirmResult: () => {
return {
data: {
isCorrectPassword: true
}
};
}
};
});
});
test("비로그인 유저는 댓글을 수정시, 비밀번호를 입력해야 수정내용 입력란이 활성화 된다.", async () => {
const _comments: Comment[] = JSON.parse(JSON.stringify(comments));
const guestUserComments = _comments.filter(comment => comment.user.type === "GuestUser");
const commentList = render(<CommentList comments={guestUserComments} project={undefined} />);
const commentList = render(<CommentList user={undefined} comments={guestUserComments} project={undefined} />);

const firstThreeDotButton = commentList.getAllByAltText("댓글 옵션")[0];

fireEvent.click(firstThreeDotButton);

const firstDeleteButton = commentList.getByText("수정");
fireEvent.click(firstDeleteButton);
const firstEditButton = commentList.getAllByTestId("comment-option-edit-button")[0];
fireEvent.click(firstEditButton);

const firstPasswordSubmitButton = commentList.getByText("입력");
fireEvent.click(firstPasswordSubmitButton);
Expand Down Expand Up @@ -174,14 +199,25 @@ describe("비로그인 유저 댓글 삭제", () => {
error: false
};
});
(useConfirmGuestPassword as jest.Mock).mockImplementation(() => {
return {
isValid: true,
getPasswordConfirmResult: () => {
return {
data: {
isCorrectPassword: true
}
};
}
};
});
});
test("비로그인 유저는 댓글을 수정시, 비밀번호를 입력해야 삭제를 할 수 있다.", async () => {
const _comments: Comment[] = JSON.parse(JSON.stringify(comments));
const guestUserComments = _comments.filter(comment => comment.user.type === "GuestUser");
const commentList = render(<CommentList comments={guestUserComments} project={undefined} />);

const firstThreeDotButton = commentList.getAllByAltText("댓글 옵션")[0];

fireEvent.click(firstThreeDotButton);

const firstEditButton = commentList.getByText("삭제");
Expand Down
35 changes: 12 additions & 23 deletions frontend/reply-module/src/__test__/intergration/login.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import "@testing-library/jest-dom/extend-expect";
import { render, waitFor } from "@testing-library/react";
import Avatar from "../../components/atoms/Avatar";
import UserAvatarOption from "../../components/molecules/UserAvatarOption";
import { useUser } from "../../hooks";
import { User } from "../../types/user";
Expand Down Expand Up @@ -30,21 +31,15 @@ describe("댓글모듈 Login 기능", () => {
로그아웃
</button>
) : (
<button type="button" onClick={() => {}}>
카카오로 로그인
</button>
<Avatar size="SM" alt="카카오톡 로그인 이미지" />
)}
</UserAvatarOption>
);

userAvatarOption.getByRole("img").click();
userAvatarOption.getByTestId("avatar-img").click();

await waitFor(() => {
expect(
userAvatarOption.getByRole("button", {
name: /카카오로 로그인/i
})
).toBeInTheDocument();
expect(userAvatarOption.getByAltText("카카오톡 로그인 이미지")).toBeInTheDocument();
});
});

Expand All @@ -70,25 +65,19 @@ describe("댓글모듈 Login 기능", () => {
로그아웃
</button>
) : (
<button type="button" onClick={() => {}}>
카카오로 로그인
</button>
<Avatar size="SM" alt="카카오톡 로그인 이미지" />
)}
</UserAvatarOption>
);

userAvatarOption.getByRole("img").click();

await waitFor(async () => {
userAvatarOption.getByRole("img").click();
userAvatarOption.getByTestId("avatar-img").click();

await waitFor(() => {
expect(
userAvatarOption.getByRole("button", {
name: /로그아웃/i
})
).toBeInTheDocument();
});
await waitFor(() => {
expect(
userAvatarOption.getByRole("button", {
name: /로그아웃/i
})
).toBeInTheDocument();
});
});
});
4 changes: 3 additions & 1 deletion frontend/reply-module/src/components/atoms/Avatar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ export interface Props {
}

const Avatar = ({ imageURL, size = "MD", onClick, alt }: Props) => {
return <Container src={imageURL || defaultUserImage} size={size} onClick={onClick} alt={alt} />;
return (
<Container src={imageURL || defaultUserImage} size={size} onClick={onClick} alt={alt} data-testid="avatar-img" />
);
};

export default Avatar;
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ const CommentOption = ({ className, startEditing, startDeleting }: Props) => {
{isShowOptionBox && (
<OptionContainer>
{startEditing && (
<EditButton type="button" onClick={onEdit}>
<EditButton type="button" onClick={onEdit} data-testid="comment-option-edit-button">
수정
</EditButton>
)}
{startDeleting && (
<DeleteButton type="button" onClick={onDelete}>
<DeleteButton type="button" onClick={onDelete} data-testid="comment-option-delete-button">
삭제
</DeleteButton>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const Text = styled.div`
const Button = styled.button`
width: 4rem;
height: 2.4rem;
background-color: ${PALETTE.PRIMARY};
background-color: ${PALETTE.SECONDARY};
color: ${PALETTE.WHITE};
font-size: 1.2rem;
font-weight: 500;
Expand Down
30 changes: 14 additions & 16 deletions frontend/reply-module/src/components/molecules/Comment/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FormEvent, useEffect, useState } from "react";
import { QUERY } from "../../../constants/api";
import { useDeleteComment, useEditComment, useInput } from "../../../hooks";
import { useConfirmGuestPassword, useDeleteComment, useEditComment, useInput } from "../../../hooks";
import { Comment as CommentType } from "../../../types";
import { DeleteCommentRequestParameter } from "../../../types/comment";
import { User } from "../../../types/user";
Expand All @@ -11,6 +11,7 @@ import Avatar from "../../atoms/Avatar";
import CommentTextBox from "../../atoms/CommentTextBox";
import {
Button,
CancelButton,
CommentOption,
CommentTextBoxWrapper,
CommentWrapper,
Expand Down Expand Up @@ -39,6 +40,10 @@ const Comment = ({ user, comment, align = "left", shouldShowOption, iAmAdmin, th
const { value: password, setValue: setPassword, onChange: onChangePassword } = useInput("");
const { editComment } = useEditComment();
const { deleteComment } = useDeleteComment();
const { getPasswordConfirmResult } = useConfirmGuestPassword({
guestUserId: comment.user.id,
guestUserPassword: password
});

const clear = () => {
setEditing(false);
Expand All @@ -50,24 +55,11 @@ const Comment = ({ user, comment, align = "left", shouldShowOption, iAmAdmin, th

const canIControl = (iAmAdmin && thisCommentIsMine) || !iAmAdmin;

const isEditable = (iAmAdmin && thisCommentIsMine) || !iAmAdmin;

const confirmGuestPassword = async () => {
try {
const response = await request.get(
QUERY.CHECK_GUEST_PASSWORD({
guestUserId: comment.user.id,
guestUserPassword: password
})
);

if (response.status >= 400) {
throw new Error(response.data.message);
}

const { isCorrectPassword } = response.data;
const { data } = await getPasswordConfirmResult();

return isCorrectPassword;
return !!data?.isCorrectPassword;
} catch (error) {
console.error(error.message);
setPasswordSubmitted(true);
Expand Down Expand Up @@ -110,6 +102,9 @@ const Comment = ({ user, comment, align = "left", shouldShowOption, iAmAdmin, th
event.preventDefault();

const isValidPassword = await confirmGuestPassword();

console.log(isValidPassword);

if (!isValidPassword) {
alert("비밀번호가 일치하지 않습니다.");
return;
Expand Down Expand Up @@ -180,6 +175,9 @@ const Comment = ({ user, comment, align = "left", shouldShowOption, iAmAdmin, th
placeholder="댓글 작성 시 입력한 비밀번호 입력"
isValidInput={!isPasswordSubmitted}
/>
<CancelButton type="button" onClick={() => clear()}>
취소
</CancelButton>
<Button>입력</Button>
</PasswordForm>
)}
Expand Down
19 changes: 17 additions & 2 deletions frontend/reply-module/src/components/molecules/Comment/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const PasswordInput = styled.input<{ isValidInput: Boolean }>`
const Button = styled.button`
width: 4rem;
height: 2.4rem;
background-color: ${PALETTE.PRIMARY};
background-color: ${PALETTE.SECONDARY};
color: ${PALETTE.WHITE};
font-size: 1.2rem;
font-weight: 500;
Expand All @@ -61,4 +61,19 @@ const Button = styled.button`
}
`;

export { Container, CommentWrapper, CommentTextBoxWrapper, Time, CommentOption, PasswordForm, PasswordInput, Button };
const CancelButton = styled(Button)`
background-color: ${PALETTE.RED_600};
margin-right: 0.5rem;
`;

export {
Container,
CommentWrapper,
CommentTextBoxWrapper,
Time,
CommentOption,
PasswordForm,
PasswordInput,
Button,
CancelButton
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ const UserAvatarOption = ({ user, children }: Props) => {
return (
<Container>
<UserNickName onClick={onShowOptionBox}>{user?.nickName ?? "로그인"}</UserNickName>
<Avatar imageURL={user?.profileImageUrl} onClick={onShowOptionBox} alt="유저 프로필 이미지" />
<Avatar
imageURL={user?.profileImageUrl}
onClick={onShowOptionBox}
alt="유저 프로필 이미지"
data-testid="avartar-option-img"
/>
{isShowOptionBox && <UserOption userName={user?.nickName || "Login With"}>{children}</UserOption>}
</Container>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const CommentList = ({ className, comments, user, project }: Props) => {
const authorId = comment.user.id;

const iAmGuestUser = !user;
const iAmAdmin = project?.userId === user?.id;
const iAmAdmin = user !== undefined && project?.userId === user.id;

const thisCommentIsMine = authorId === user?.id;
const thisCommentIsWrittenByGuest = comment.user.type === "GuestUser";
Expand Down
2 changes: 1 addition & 1 deletion frontend/reply-module/src/constants/api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { GuestUserInfo } from "../types/comment";
const BASE_URL = "https://darass.o-r.kr";
const QUERY = {
LOGIN: "/api/v1/login/oauth?oauthAccessToken=",
LOGIN: "/api/v1/login/oauth?oauthProviderName=kakao&oauthAccessToken=",
COMMENT: "/api/v1/comments",
GET_ALL_COMMENTS: (url: string, projectKey: string) => `/api/v1/comments?url=${url}&projectKey=${projectKey}`,
GET_PROJECT: (projectKey: string) => `/api/v1/projects/user-id?secretKey=${projectKey}`,
Expand Down
3 changes: 2 additions & 1 deletion frontend/reply-module/src/constants/reactQueryKey.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
const REACT_QUERY_KEY = {
USER: "user",
COMMENT: "comment",
PROJECT: "project"
PROJECT: "project",
GUEST_PASSWORD_CONFIRM: "guest-password-confirm"
};

export { REACT_QUERY_KEY };
Loading