diff --git a/src/main/java/com/example/daobe/lounge/application/LoungeFacadeService.java b/src/main/java/com/example/daobe/lounge/application/LoungeFacadeService.java index bccc0dee..9ec46733 100644 --- a/src/main/java/com/example/daobe/lounge/application/LoungeFacadeService.java +++ b/src/main/java/com/example/daobe/lounge/application/LoungeFacadeService.java @@ -2,9 +2,9 @@ import com.example.daobe.lounge.application.dto.LoungeCreateRequestDto; import com.example.daobe.lounge.application.dto.LoungeCreateResponseDto; -import com.example.daobe.lounge.application.dto.LoungeDetailInfoDto; -import com.example.daobe.lounge.application.dto.LoungeInfoDto; -import com.example.daobe.lounge.application.dto.LoungeInviteDto; +import com.example.daobe.lounge.application.dto.LoungeDetailResponseDto; +import com.example.daobe.lounge.application.dto.LoungeInfoResponseDto; +import com.example.daobe.lounge.application.dto.LoungeInviteRequestDto; import com.example.daobe.lounge.application.dto.LoungeSharerInfoResponseDto; import com.example.daobe.lounge.application.dto.LoungeValidateRequestDto; import com.example.daobe.lounge.domain.Lounge; @@ -24,7 +24,6 @@ public class LoungeFacadeService { private final LoungeService loungeService; private final LoungeSharerService loungeSharerService; - // 라운지 생성 @Transactional public LoungeCreateResponseDto createLounge(LoungeCreateRequestDto request, Long userId) { User findUser = userService.getUserById(userId); @@ -33,35 +32,29 @@ public LoungeCreateResponseDto createLounge(LoungeCreateRequestDto request, Long return LoungeCreateResponseDto.of(createdLounge); } - // 라운지 목록 조회 - public List getAllLounges(Long userId) { + public List getAllLounges(Long userId) { return loungeService.getLoungeInfosByUserId(userId); } - // 라운지 상세 조회 - public LoungeDetailInfoDto getLoungeDetail(Long userId, Long loungeId) { + public LoungeDetailResponseDto getLoungeDetail(Long userId, Long loungeId) { Lounge findLounge = loungeService.getLoungeById(loungeId); loungeSharerService.validateLoungeSharer(userId, loungeId); return loungeService.getLoungeDetailInfo(findLounge); } - // 라운지 삭제 @Transactional public void deleteLounge(Long userId, Long loungeId) { - User findUser = userService.getUserById(userId); - Lounge findLounge = loungeService.getLoungeById(loungeId); - loungeService.deleteLoungeByUserId(findUser, findLounge); + Lounge lounge = loungeService.getLoungeById(loungeId); + loungeService.deleteLoungeByUserId(userId, lounge); } - // 라운지 초대 @Transactional - public void inviteUser(LoungeInviteDto request, Long inviterId) { + public void inviteUser(LoungeInviteRequestDto request, Long inviterId) { User findUser = userService.getUserById(request.userId()); Lounge findLounge = loungeService.getLoungeById(request.loungeId()); loungeSharerService.inviteUser(findUser, findLounge, inviterId); } - // 라운치 초대 수락/거절 @Transactional public void updateInvitedUserStatus(Long userId, Long loungeId) { User invitedUser = userService.getUserById(userId); @@ -69,13 +62,11 @@ public void updateInvitedUserStatus(Long userId, Long loungeId) { loungeSharerService.updateInvitedUserStatus(invitedUser.getId(), findLounge.getId()); } - // 라운지 내 유저 검색 public List searchLoungeSharer(Long userId, String nickname, Long loungeId) { Lounge findLounge = loungeService.getLoungeById(loungeId); return loungeSharerService.searchLoungeSharer(userId, nickname, findLounge); } - // 라운지 탈퇴 @Transactional public void withdraw(Long userId, Long loungeId) { User findUser = userService.getUserById(userId); @@ -83,7 +74,6 @@ public void withdraw(Long userId, Long loungeId) { loungeSharerService.withdraw(findUser, findLounge); } - // 라운지 공유자 검증 public void isLoungeSharer(Long userId, LoungeValidateRequestDto request) { loungeSharerService.validateLoungeSharer(userId, request.loungeId()); } diff --git a/src/main/java/com/example/daobe/lounge/application/LoungeService.java b/src/main/java/com/example/daobe/lounge/application/LoungeService.java index 89622644..8f076118 100644 --- a/src/main/java/com/example/daobe/lounge/application/LoungeService.java +++ b/src/main/java/com/example/daobe/lounge/application/LoungeService.java @@ -3,11 +3,9 @@ import static com.example.daobe.lounge.exception.LoungeExceptionType.INVALID_LOUNGE_ID_EXCEPTION; import com.example.daobe.lounge.application.dto.LoungeCreateRequestDto; -import com.example.daobe.lounge.application.dto.LoungeDetailInfoDto; -import com.example.daobe.lounge.application.dto.LoungeInfoDto; +import com.example.daobe.lounge.application.dto.LoungeDetailResponseDto; +import com.example.daobe.lounge.application.dto.LoungeInfoResponseDto; import com.example.daobe.lounge.domain.Lounge; -import com.example.daobe.lounge.domain.LoungeStatus; -import com.example.daobe.lounge.domain.LoungeType; import com.example.daobe.lounge.domain.event.LoungeDeletedEvent; import com.example.daobe.lounge.domain.repository.LoungeRepository; import com.example.daobe.lounge.exception.LoungeException; @@ -30,23 +28,22 @@ public Lounge createAndSaveLounge(LoungeCreateRequestDto request, User user) { Lounge lounge = Lounge.builder() .user(user) .name(request.name()) - .type(LoungeType.from(request.type())) - .status(LoungeStatus.ACTIVE) + .type(request.type()) .build(); loungeRepository.save(lounge); return lounge; } - public List getLoungeInfosByUserId(Long userId) { + public List getLoungeInfosByUserId(Long userId) { return loungeRepository.findLoungeByUserId(userId).stream() - .filter(lounge -> lounge.getStatus().isActive()) - .map(LoungeInfoDto::of) + .filter(Lounge::isActive) + .map(LoungeInfoResponseDto::of) .toList(); } - public LoungeDetailInfoDto getLoungeDetailInfo(Lounge lounge) { + public LoungeDetailResponseDto getLoungeDetailInfo(Lounge lounge) { lounge.isActiveOrThrow(); - return LoungeDetailInfoDto.of(lounge); + return LoungeDetailResponseDto.of(lounge); } public Lounge getLoungeById(Long loungeId) { @@ -54,8 +51,8 @@ public Lounge getLoungeById(Long loungeId) { .orElseThrow(() -> new LoungeException(INVALID_LOUNGE_ID_EXCEPTION)); } - public void deleteLoungeByUserId(User user, Lounge lounge) { - lounge.softDelete(user.getId()); + public void deleteLoungeByUserId(Long userId, Lounge lounge) { + lounge.softDelete(userId); eventPublisher.publishEvent(new LoungeDeletedEvent(lounge.getId())); } } diff --git a/src/main/java/com/example/daobe/lounge/application/LoungeSharerService.java b/src/main/java/com/example/daobe/lounge/application/LoungeSharerService.java index 8d8d3d84..4054f25a 100644 --- a/src/main/java/com/example/daobe/lounge/application/LoungeSharerService.java +++ b/src/main/java/com/example/daobe/lounge/application/LoungeSharerService.java @@ -73,7 +73,7 @@ public void updateInvitedUserStatus(Long invitedUserId, Long loungeId) { public List searchLoungeSharer(Long userId, String nickname, Lounge lounge) { validateLoungeSharer(userId, lounge.getId()); List byUserId = loungeSharerRepository - .findByLounge_IdAndUser_NicknameContaining(lounge.getId(), nickname); + .findActiveSharersByLoungeIdAndNickname(lounge.getId(), nickname); return LoungeSharerInfoResponseDto.of(byUserId); } diff --git a/src/main/java/com/example/daobe/lounge/application/dto/LoungeDetailInfoDto.java b/src/main/java/com/example/daobe/lounge/application/dto/LoungeDetailResponseDto.java similarity index 71% rename from src/main/java/com/example/daobe/lounge/application/dto/LoungeDetailInfoDto.java rename to src/main/java/com/example/daobe/lounge/application/dto/LoungeDetailResponseDto.java index 06abe148..0fec2558 100644 --- a/src/main/java/com/example/daobe/lounge/application/dto/LoungeDetailInfoDto.java +++ b/src/main/java/com/example/daobe/lounge/application/dto/LoungeDetailResponseDto.java @@ -2,15 +2,15 @@ import com.example.daobe.lounge.domain.Lounge; -public record LoungeDetailInfoDto( +public record LoungeDetailResponseDto( Long loungeId, String name, String type, Long userId ) { - public static LoungeDetailInfoDto of(Lounge lounge) { - return new LoungeDetailInfoDto( + public static LoungeDetailResponseDto of(Lounge lounge) { + return new LoungeDetailResponseDto( lounge.getId(), lounge.getName(), lounge.getType().getTypeName(), diff --git a/src/main/java/com/example/daobe/lounge/application/dto/LoungeInfoDto.java b/src/main/java/com/example/daobe/lounge/application/dto/LoungeInfoResponseDto.java similarity index 68% rename from src/main/java/com/example/daobe/lounge/application/dto/LoungeInfoDto.java rename to src/main/java/com/example/daobe/lounge/application/dto/LoungeInfoResponseDto.java index d1c77393..7a0ce325 100644 --- a/src/main/java/com/example/daobe/lounge/application/dto/LoungeInfoDto.java +++ b/src/main/java/com/example/daobe/lounge/application/dto/LoungeInfoResponseDto.java @@ -2,14 +2,14 @@ import com.example.daobe.lounge.domain.Lounge; -public record LoungeInfoDto( +public record LoungeInfoResponseDto( Long loungeId, String name, String type ) { - public static LoungeInfoDto of(Lounge lounge) { - return new LoungeInfoDto( + public static LoungeInfoResponseDto of(Lounge lounge) { + return new LoungeInfoResponseDto( lounge.getId(), lounge.getName(), lounge.getType().getTypeName() diff --git a/src/main/java/com/example/daobe/lounge/application/dto/LoungeInviteDto.java b/src/main/java/com/example/daobe/lounge/application/dto/LoungeInviteRequestDto.java similarity index 72% rename from src/main/java/com/example/daobe/lounge/application/dto/LoungeInviteDto.java rename to src/main/java/com/example/daobe/lounge/application/dto/LoungeInviteRequestDto.java index 983d32e6..949210f0 100644 --- a/src/main/java/com/example/daobe/lounge/application/dto/LoungeInviteDto.java +++ b/src/main/java/com/example/daobe/lounge/application/dto/LoungeInviteRequestDto.java @@ -1,6 +1,6 @@ package com.example.daobe.lounge.application.dto; -public record LoungeInviteDto( +public record LoungeInviteRequestDto( Long userId, Long loungeId ) { diff --git a/src/main/java/com/example/daobe/lounge/domain/Lounge.java b/src/main/java/com/example/daobe/lounge/domain/Lounge.java index 60543cf0..fe06f004 100644 --- a/src/main/java/com/example/daobe/lounge/domain/Lounge.java +++ b/src/main/java/com/example/daobe/lounge/domain/Lounge.java @@ -8,6 +8,7 @@ import com.example.daobe.lounge.exception.LoungeException; import com.example.daobe.user.domain.User; import jakarta.persistence.Column; +import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; @@ -38,8 +39,8 @@ public class Lounge extends BaseTimeEntity { @ManyToOne(fetch = FetchType.LAZY) private User user; - @Column(name = "name") - private String name; + @Embedded + private LoungeName name; @Enumerated(EnumType.STRING) private LoungeType type; @@ -54,18 +55,18 @@ public class Lounge extends BaseTimeEntity { private String reasonDetail; @Builder - public Lounge(User user, String name, LoungeType type, LoungeStatus status) { + public Lounge(User user, String name, String type) { this.user = user; - this.name = name; - this.type = type; - this.status = status; + this.name = new LoungeName(name); + this.type = LoungeType.from(type); + this.status = LoungeStatus.ACTIVE; } - public Lounge(Long id, User user, String name, LoungeType type, LoungeStatus status) { + public Lounge(Long id, User user, String name, String type, LoungeStatus status) { this.id = id; this.user = user; - this.name = name; - this.type = type; + this.name = new LoungeName(name); + this.type = LoungeType.from(type); this.status = status; } @@ -75,22 +76,30 @@ public void softDelete(Long userId) { this.status = LoungeStatus.DELETED; } + public boolean isActive() { + return status.isActive(); + } + public void isActiveOrThrow() { if (!status.isActive()) { throw new LoungeException(NOT_ACTIVE_LOUNGE_EXCEPTION); } } - public void isOwnerOrThrow(Long userId) { - if (userId != user.getId()) { - throw new LoungeException(INVALID_LOUNGE_OWNER_EXCEPTION); - } - } - public void isPossibleToWithdrawOrThrow(Long userId) { isActiveOrThrow(); if (userId == user.getId()) { throw new LoungeException(NOT_ALLOW_LOUNGE_WITHDRAW_EXCEPTION); } } + + public String getName() { + return name.getValue(); + } + + private void isOwnerOrThrow(Long userId) { + if (userId != user.getId()) { + throw new LoungeException(INVALID_LOUNGE_OWNER_EXCEPTION); + } + } } diff --git a/src/main/java/com/example/daobe/lounge/domain/LoungeName.java b/src/main/java/com/example/daobe/lounge/domain/LoungeName.java new file mode 100644 index 00000000..d53dec75 --- /dev/null +++ b/src/main/java/com/example/daobe/lounge/domain/LoungeName.java @@ -0,0 +1,42 @@ +package com.example.daobe.lounge.domain; + +import static com.example.daobe.lounge.exception.LoungeExceptionType.LOUNGE_NAME_LENGTH_EXCEPTION; +import static com.example.daobe.lounge.exception.LoungeExceptionType.LOUNGE_NAME_REGEX_EXCEPTION; + +import com.example.daobe.lounge.exception.LoungeException; +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Embeddable +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class LoungeName { + + private static final int MIN_LENGTH = 2; + private static final int MAX_LENGTH = 10; + private static final String NAME_REGEX = "^(?!.*[^가-힣a-zA-Z0-9\\s])(?!.*\\s{2,}).*$"; + + @Column(name = "name") + private String value; + + public LoungeName(String value) { + validateLength(value.length()); + validatePattern(value); + this.value = value.trim(); + } + + private void validateLength(int length) { + if (length < MIN_LENGTH || length > MAX_LENGTH) { + throw new LoungeException(LOUNGE_NAME_LENGTH_EXCEPTION); + } + } + + private void validatePattern(String value) { + if (!value.matches(NAME_REGEX)) { + throw new LoungeException(LOUNGE_NAME_REGEX_EXCEPTION); + } + } +} diff --git a/src/main/java/com/example/daobe/lounge/domain/repository/LoungeSharerRepository.java b/src/main/java/com/example/daobe/lounge/domain/repository/LoungeSharerRepository.java index 73843e30..12230227 100644 --- a/src/main/java/com/example/daobe/lounge/domain/repository/LoungeSharerRepository.java +++ b/src/main/java/com/example/daobe/lounge/domain/repository/LoungeSharerRepository.java @@ -30,7 +30,14 @@ SELECT CASE WHEN EXISTS ( """) boolean existsLoungeSharerByUserIdAndLoungeId(@Param("userId") Long userId, @Param("loungeId") Long loungeId); - List findByLounge_IdAndUser_NicknameContaining(Long loungeId, String nickname); + @Query(""" + SELECT ls FROM LoungeSharer ls + WHERE ls.lounge.id = :loungeId + AND ls.user.nickname LIKE %:nickname% + AND ls.status = 'ACTIVE' + """) + List findActiveSharersByLoungeIdAndNickname(@Param("loungeId") Long loungeId, + @Param("nickname") String nickname); @Query(""" SELECT COUNT(ls) FROM LoungeSharer ls diff --git a/src/main/java/com/example/daobe/lounge/exception/LoungeExceptionType.java b/src/main/java/com/example/daobe/lounge/exception/LoungeExceptionType.java index 4a8732b1..4fa63d47 100644 --- a/src/main/java/com/example/daobe/lounge/exception/LoungeExceptionType.java +++ b/src/main/java/com/example/daobe/lounge/exception/LoungeExceptionType.java @@ -4,6 +4,9 @@ import org.springframework.http.HttpStatus; public enum LoungeExceptionType implements BaseExceptionType { + + LOUNGE_NAME_LENGTH_EXCEPTION("라운지 이름은 2글자 이상 10글자 이하여야 합니다.", HttpStatus.BAD_REQUEST), + LOUNGE_NAME_REGEX_EXCEPTION("라운지 이름 형식이 올바르지 않습니다.", HttpStatus.BAD_REQUEST), INVALID_LOUNGE_ID_EXCEPTION("유효하지 않은 라운지 ID입니다.", HttpStatus.NOT_FOUND), INVALID_LOUNGE_TYPE_EXCEPTION("유효하지 않은 라운지 타입입니다.", HttpStatus.BAD_REQUEST), NOT_ACTIVE_LOUNGE_EXCEPTION("활성 상태가 아닌 라운지입니다.", HttpStatus.NOT_FOUND), diff --git a/src/main/java/com/example/daobe/lounge/presentation/LoungeController.java b/src/main/java/com/example/daobe/lounge/presentation/LoungeController.java index 122d69c1..e96c0542 100644 --- a/src/main/java/com/example/daobe/lounge/presentation/LoungeController.java +++ b/src/main/java/com/example/daobe/lounge/presentation/LoungeController.java @@ -13,9 +13,9 @@ import com.example.daobe.lounge.application.LoungeFacadeService; import com.example.daobe.lounge.application.dto.LoungeCreateRequestDto; import com.example.daobe.lounge.application.dto.LoungeCreateResponseDto; -import com.example.daobe.lounge.application.dto.LoungeDetailInfoDto; -import com.example.daobe.lounge.application.dto.LoungeInfoDto; -import com.example.daobe.lounge.application.dto.LoungeInviteDto; +import com.example.daobe.lounge.application.dto.LoungeDetailResponseDto; +import com.example.daobe.lounge.application.dto.LoungeInfoResponseDto; +import com.example.daobe.lounge.application.dto.LoungeInviteRequestDto; import com.example.daobe.lounge.application.dto.LoungeSharerInfoResponseDto; import com.example.daobe.lounge.application.dto.LoungeValidateRequestDto; import java.util.List; @@ -46,11 +46,14 @@ public ResponseEntity> createLounge( ) { LoungeCreateResponseDto response = loungeFacadeService.createLounge(request, userId); return ResponseEntity.status(LOUNGE_CREATED_SUCCESS.getHttpStatus()) - .body(new ApiResponse<>(LOUNGE_CREATED_SUCCESS.name(), response)); + .body(new ApiResponse<>( + LOUNGE_CREATED_SUCCESS.name(), + response) + ); } @GetMapping - public ResponseEntity>> getAllLounges( + public ResponseEntity>> getAllLounges( @AuthenticationPrincipal Long userId ) { return ResponseEntity.status(LOUNGE_LIST_LOADED_SUCCESS.getHttpStatus()) @@ -61,7 +64,7 @@ public ResponseEntity>> getAllLounges( } @GetMapping("/{loungeId}") - public ResponseEntity> getLoungeDetail( + public ResponseEntity> getLoungeDetail( @AuthenticationPrincipal Long userId, @PathVariable(name = "loungeId") Long loungeId ) { @@ -72,7 +75,6 @@ public ResponseEntity> getLoungeDetail( ); } - // TODO: 비활성화된 라운지 탈퇴 요청시 예외 발생하는지 확인하기 @DeleteMapping("/{loungeId}") public ResponseEntity> deleteLounge( @AuthenticationPrincipal Long userId, @@ -80,17 +82,23 @@ public ResponseEntity> deleteLounge( ) { loungeFacadeService.deleteLounge(userId, loungeId); return ResponseEntity.status(LOUNGE_DELETED_SUCCESS.getHttpStatus()) - .body(new ApiResponse<>(LOUNGE_DELETED_SUCCESS.name(), null)); + .body(new ApiResponse<>( + LOUNGE_DELETED_SUCCESS.name(), + null) + ); } @PostMapping("/invite") public ResponseEntity> inviteUser( @AuthenticationPrincipal Long userId, - @RequestBody LoungeInviteDto request + @RequestBody LoungeInviteRequestDto request ) { loungeFacadeService.inviteUser(request, userId); return ResponseEntity.status(LOUNGE_INVITE_SUCCESS.getHttpStatus()) - .body(new ApiResponse<>(LOUNGE_INVITE_SUCCESS.name(), null)); + .body(new ApiResponse<>( + LOUNGE_INVITE_SUCCESS.name(), + null) + ); } @PatchMapping("/{loungeId}/invite/accept") @@ -100,10 +108,12 @@ public ResponseEntity> updateInvitedUserStatus( ) { loungeFacadeService.updateInvitedUserStatus(userId, loungeId); return ResponseEntity.status(LOUNGE_INVITE_SUCCESS.getHttpStatus()) - .body(new ApiResponse<>(LOUNGE_INVITE_ACCEPTED_SUCCESS.name(), null)); + .body(new ApiResponse<>( + LOUNGE_INVITE_ACCEPTED_SUCCESS.name(), + null) + ); } - @GetMapping("/{loungeId}/search") public ResponseEntity>> searchLoungeSharer( @AuthenticationPrincipal Long userId, @@ -137,8 +147,8 @@ public ResponseEntity> validate( ) { loungeFacadeService.isLoungeSharer(userId, request); return ResponseEntity.ok(new ApiResponse<>( - "AUTHENTICATION_SUCCESS", null + "AUTHENTICATION_SUCCESS", + null )); - } } diff --git a/src/test/java/com/example/daobe/common/fixtures/LoungeFixtures.java b/src/test/java/com/example/daobe/common/fixtures/LoungeFixtures.java index 17a571b7..6f0e73b7 100644 --- a/src/test/java/com/example/daobe/common/fixtures/LoungeFixtures.java +++ b/src/test/java/com/example/daobe/common/fixtures/LoungeFixtures.java @@ -2,13 +2,12 @@ import com.example.daobe.lounge.domain.Lounge; import com.example.daobe.lounge.domain.LoungeStatus; -import com.example.daobe.lounge.domain.LoungeType; import com.example.daobe.user.domain.User; public class LoungeFixtures { - private static final String FAKE_LOUNGE_NAME = "Test Lounge"; - private static final LoungeType FAKE_LOUNGE_TYPE = LoungeType.L0001; + private static final String FAKE_LOUNGE_NAME = "TestLounge"; + private static final String FAKE_LOUNGE_TYPE = "L0001"; private static final LoungeStatus ACTIVE_STATUS = LoungeStatus.ACTIVE; private static final LoungeStatus DELETED_STATUS = LoungeStatus.DELETED; diff --git a/src/test/java/com/example/daobe/lounge/domain/LoungeNameTest.java b/src/test/java/com/example/daobe/lounge/domain/LoungeNameTest.java new file mode 100644 index 00000000..d2de83aa --- /dev/null +++ b/src/test/java/com/example/daobe/lounge/domain/LoungeNameTest.java @@ -0,0 +1,57 @@ +package com.example.daobe.lounge.domain; + +import static com.example.daobe.lounge.exception.LoungeExceptionType.LOUNGE_NAME_LENGTH_EXCEPTION; +import static com.example.daobe.lounge.exception.LoungeExceptionType.LOUNGE_NAME_REGEX_EXCEPTION; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatNoException; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +import com.example.daobe.lounge.exception.LoungeException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class LoungeNameTest { + + @ParameterizedTest + @ValueSource(strings = {"안녕하세요", "Lounge1", "한글 영어 1"}) + @DisplayName("올바른 라운지 이름인 경우 예외가 발생하지 않아야 한다.") + void testValidLoungeName(String validName) { + assertThatNoException().isThrownBy(() -> new LoungeName(validName)); + } + + @ParameterizedTest + @ValueSource(strings = {"안"}) + @DisplayName("라운지 이름이 2자 미만인 경우 예외가 발생해야 한다.") + void testTooShortLoungeName(String shortName) { + assertThatThrownBy(() -> new LoungeName(shortName)) + .isInstanceOf(LoungeException.class) + .hasMessage(LOUNGE_NAME_LENGTH_EXCEPTION.message()); + } + + @ParameterizedTest + @ValueSource(strings = {"안녕하세요 안녕하세요"}) + @DisplayName("라운지 이름이 10자를 초과하는 경우 예외가 발생해야 한다.") + void testTooLongLoungeName(String longName) { + assertThatThrownBy(() -> new LoungeName(longName)) + .isInstanceOf(LoungeException.class) + .hasMessage(LOUNGE_NAME_LENGTH_EXCEPTION.message()); + } + + @ParameterizedTest + @ValueSource(strings = {"new@Lounge", "Lounge!", "라운지#1"}) + @DisplayName("라운지 이름에 특수문자가 포함된 경우 예외가 발생해야 한다.") + void testLoungeNameWithSpecialCharacters(String invalidName) { + assertThatThrownBy(() -> new LoungeName(invalidName)) + .isInstanceOf(LoungeException.class) + .hasMessage(LOUNGE_NAME_REGEX_EXCEPTION.message()); + } + + @ParameterizedTest + @ValueSource(strings = {"Lou nge", "라운지 이름"}) + @DisplayName("라운지 이름에 연속된 공백이 포함된 경우 예외가 발생해야 한다.") + void testLoungeNameWithConsecutiveSpaces(String nameWithSpaces) { + assertThatThrownBy(() -> new LoungeName(nameWithSpaces)) + .isInstanceOf(LoungeException.class) + .hasMessage(LOUNGE_NAME_REGEX_EXCEPTION.message()); + } +}