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

feature/196 사용자 닉네임 설정에 제한사항을 건다. #209

Merged
merged 14 commits into from
Oct 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
211e76b
feature/196 feat: 백엔드 코드에 Member 닉네임 글자 수 제한 사항(최대 15자) 설정
YejiAhn Sep 11, 2020
bbe858f
feature/196 feat: 프론트엔드 코드에 Member 닉네임 글자 수 제한 사항(최대 15자) 설정
YejiAhn Sep 11, 2020
c3e7260
feature/196 feat: 프론트엔드 닉네임 관련 css들 리팩토링
YejiAhn Sep 11, 2020
198eb58
feature/196 feat: 닉네임에 한글/숫자/영어만 쓰게 하는 제한사항 설정
YejiAhn Sep 11, 2020
3118da3
feature/196 refactor: 포매터 적용
YejiAhn Sep 11, 2020
9e865f9
feature/196 refactor: css 관련 수정
YejiAhn Sep 20, 2020
b1b0ab7
feature/196 refactor: 닉네임 길이제한 관련 코드 리팩토링
YejiAhn Sep 20, 2020
864a1e9
feature/196 refactor: 닉네임 관련 제한사항 규칙들을 한꺼번에 묶어서 관리하게 리팩토링
YejiAhn Sep 20, 2020
a6f04a7
feature/196 refactor: 변경한 닉네임이 기존 닉네임과 같을 때 메세지 없이 저장버튼만 비활성화되게 리팩토링
YejiAhn Sep 20, 2020
7565973
feature/196 refactor: 닉네임 제한사항 관련 Test를 ParameterizedTest로 묶어서 관리
YejiAhn Sep 20, 2020
40f9c36
feature/196 feat: Member 닉네임 정규표현식 관련 제한사항 설정
YejiAhn Sep 20, 2020
6ebd65b
feature/196 refactor: 저장 버튼을 비활성화시켜주는 작업을 methods에서 computed로 이동
YejiAhn Sep 20, 2020
d862d2c
feature/196 refactor: 재사용되는 메서드 분리
YejiAhn Sep 21, 2020
4b9100f
feature/196 feat: 상수로 쓰이던 함수 위치를 methods로 변경
YejiAhn Oct 5, 2020
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
25 changes: 21 additions & 4 deletions front/src/components/member/MemberSidebar.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<template>
<div>
<v-navigation-drawer v-model="drawer" absolute temporary class="drawer">
<v-icon @click="hideSidebar" class="float-right ma-4">
<v-icon @click="hideSidebar" class="modal-close-btn">
mdi-window-close
</v-icon>

<div class="ma-5 mt-10 mb-5" @click="login">
<div class="mx-3 mt-10 mb-4" @click="login">
<v-avatar>
<v-icon size="36">mdi-account-circle</v-icon>
</v-avatar>
<span class="mx-3 font-weight-bold">
{{ member.nickname }}
<span class="font-weight-bold">
{{ shortenedNickname }} {{ nicknameTail }}
</span>
</div>

Expand Down Expand Up @@ -53,6 +53,7 @@ const LOGOUT_SUCCESS_MESSAGE = "성공적으로 로그아웃 되었습니다.";
const FAILED_TO_DELETE_MEMBER_MESSAGE =
"탈퇴에 실패했습니다. 다시 요청해주세요.";
const DELETE_MEMBER_SUCCESS = "성공적으로 탈퇴를 완료했습니다.";
const MAX_NICKNAME_LENGTH = 11;

export default {
name: "MemberSidebar",
Expand Down Expand Up @@ -83,6 +84,15 @@ export default {
isGuest() {
return this.$store.getters["member/isGuest"];
},
shortenedNickname() {
return Array.from(this.member.nickname)
.slice(0, MAX_NICKNAME_LENGTH)
.join("")
.trim();
},
nicknameTail() {
return this.member.nickname.length > MAX_NICKNAME_LENGTH ? "..." : "";
},
drawer: {
get() {
return this.$store.getters["memberSidebar/visible"];
Expand Down Expand Up @@ -149,4 +159,11 @@ export default {
.drawer {
z-index: 9999;
}

.modal-close-btn {
position: absolute;
top: 12px;
right: 12px;
z-index: 1;
}
</style>
29 changes: 24 additions & 5 deletions front/src/components/member/MemberUpdateModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
<VTextField
label="새 닉네임을 입력하세요."
color="grey darken-2"
maxlength="15"
:counter="15"
v-model="newNickname"
:rules="Object.values(rules)"
@keypress.enter="updateMember"
/>
<div class="button-box">
Expand All @@ -19,7 +22,7 @@
</v-btn>
<v-btn
text
:disabled="nicknameNotChanged()"
:disabled="isUpdateDisabled"
class="mb-2 text-subtitle-1 font-weight-bold amber--text text--accent-4"
@click="updateMember"
>
Expand All @@ -35,18 +38,31 @@
<script>
import api from "@/api/member";

const NICKNAME_REGEX = "^[a-zA-Zㄱ-ㅎㅏ-ㅣ가-힣0-9]+$";

export default {
name: "PostCreateModal",
name: "MemberUpdateModal",
data() {
return {
rendered: false,
newNickname: "",
rules: {
YejiAhn marked this conversation as resolved.
Show resolved Hide resolved
regexViolation: (newVal) =>
!this.violateRegex(newVal) ||
"닉네임은 숫자/한글/영어로 이루어져야 합니다.",
},
};
},
computed: {
member() {
return this.$store.getters["member/getMember"];
},
isUpdateDisabled() {
return (
this.isValueSame(this.member.nickname, this.newNickname) ||
this.violateRegex(this.newNickname)
);
},
},
mounted() {
this.rendered = true;
Expand All @@ -66,12 +82,15 @@ export default {
closeModal() {
this.$emit("close");
},
nicknameNotChanged() {
return this.member.nickname === this.newNickname;
},
bounceOut() {
this.rendered = false;
},
isValueSame(oldVal, newVal) {
return oldVal === newVal;
},
violateRegex(val) {
return !val.match(NICKNAME_REGEX);
},
},
};
</script>
Expand Down
7 changes: 2 additions & 5 deletions front/src/components/post/PostModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<DoranAppBar />
<div v-if="existMember" class="pa-4">
<div class="mb-3">
<v-icon x-large class="mr-3">mdi-account-circle</v-icon>
<v-icon x-large class="mr-2">mdi-account-circle</v-icon>
<span class="font-weight-bold">{{ post.author.nickname }}</span>
<div class="float-right mt-2">
{{ postDate }}
Expand Down Expand Up @@ -85,10 +85,7 @@ export default {
return localStorage.getItem("accessToken");
},
isMine() {
return (
this.post.author.id ===
this.$store.getters["member/getMember"].id
);
return this.post.author.id === this.$store.getters["member/getMember"].id;
},
post: {
get() {
Expand Down
2 changes: 1 addition & 1 deletion front/src/components/timeline/PostItem.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="mx-4 my-3" @click="openPostModal">
<div class="my-2">
<v-icon large class="mr-3">mdi-account-circle</v-icon>
<v-icon large class="mr-2">mdi-account-circle</v-icon>
<span class="font-weight-bold">{{ post.author.nickname }}</span>
<div class="float-right mt-1">{{ postDate }}</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
Expand All @@ -34,6 +36,8 @@ public class Member {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Length(max = 15, message = "닉네임은 15자를 초과할 수 없습니다.")
YejiAhn marked this conversation as resolved.
Show resolved Hide resolved
@Pattern(regexp = "^[a-zA-Zㄱ-ㅎㅏ-ㅣ가-힣0-9]+$", message = "닉네임은 한글/영어/숫자로만 이루어져야 합니다.")
YejiAhn marked this conversation as resolved.
Show resolved Hide resolved
@NotBlank(message = "닉네임은 비어 있을 수 없습니다.")
@Column(unique = true, nullable = false)
private String nickname;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.grasshouse.dorandoran.member.repository;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import com.grasshouse.dorandoran.member.domain.Member;
import javax.validation.ConstraintViolationException;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class MemberRepositoryTest {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

엔티티 validation에 관한 테스트는 어떻게 하나 궁금했는데
repository test를 하는 방법이 있군요 👍


@Autowired
private MemberRepository memberRepository;

@DisplayName("가능한 닉네임들로 Member를 생성한다.")
@ParameterizedTest
@ValueSource(strings = {"일이삼사오육칠팔구십일이삼사오", "ottffssentottff", "123456789012345"})
void possibleNicknameTest(String nickname) {
Member member = Member.builder().nickname(nickname).oAuthId("oauthId").build();
assertThat(memberRepository.save(member)).isNotNull();
}

@DisplayName("[예외] 가능하지 않은 닉네임들로 Member를 생성한다.")
@ParameterizedTest
@ValueSource(strings = {"일이삼사오육칠팔구십일이삼사오육", "ottffssentottffs", "1234567890123456", "d;", "-"})
void impossibleNicknameTest(String nickname) {
Member member = Member.builder().nickname(nickname).oAuthId("oauthId").build();
assertThatThrownBy(() -> {
memberRepository.save(member);
}).isInstanceOf(ConstraintViolationException.class);
}

@AfterEach
void tearDown() {
memberRepository.deleteAll();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,4 @@ void deleteMemberWithComments() {
void tearDown() {
memberRepository.deleteAll();
}
}
}