Skip to content

Commit

Permalink
Merge pull request #17 from Nexters/feature/theme
Browse files Browse the repository at this point in the history
[FEAT] Theme ν…ŒμŠ€νŠΈ μ½”λ“œ μž‘μ„± 및 API κ΅¬ν˜„ (#2)
  • Loading branch information
eunsol-an authored Jul 16, 2023
2 parents ecd19b6 + 8d01036 commit 7b63aec
Show file tree
Hide file tree
Showing 14 changed files with 443 additions and 17 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'
implementation 'com.google.code.gson:gson:2.10.1'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/nextroom/oescape/OEscapeApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ public static void main(String[] args) {
SpringApplication.run(com.nextroom.oescape.OEscapeApplication.class, args);
}

}
}
14 changes: 7 additions & 7 deletions src/main/java/com/nextroom/oescape/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ public class SwaggerConfig implements WebMvcConfigurer {
@Bean
public OpenAPI api() {
return new OpenAPI()
.info(this.apiInfo());
.info(this.apiInfo());
}

private Info apiInfo() {
return new Info()
.title("O Escape Api Server")
.description("Nexters 23th 였늘의 λ°©νƒˆμΆœ -NextRoom")
.version("1.0")
.contact(new Contact()
.name("O Escape Server Github Repository")
.url("https://github.com/Nexters/o-escape-be"));
.title("O Escape Api Server")
.description("Nexters 23th 였늘의 λ°©νƒˆμΆœ -NextRoom")
.version("1.0")
.contact(new Contact()
.name("O Escape Server Github Repository")
.url("https://github.com/Nexters/o-escape-be"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
public class TestController {

@Operation(
description = "Test endpoint",
summary = "Create Test",
responses = {
@ApiResponse(responseCode = "200", description = "Success"),
@ApiResponse(responseCode = "403", description = "Unauthorized / Invalid Token")
}
description = "Test endpoint",
summary = "Create Test",
responses = {
@ApiResponse(responseCode = "200", description = "Success"),
@ApiResponse(responseCode = "403", description = "Unauthorized / Invalid Token")
}
)
@PostMapping("/test")
public ResponseEntity<Void> exampleMethod() {
Expand Down
52 changes: 52 additions & 0 deletions src/main/java/com/nextroom/oescape/controller/ThemeController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.nextroom.oescape.controller;

import static com.nextroom.oescape.exceptions.StatusCode.*;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.nextroom.oescape.dto.BaseResponse;
import com.nextroom.oescape.dto.DataResponse;
import com.nextroom.oescape.dto.ThemeDto;
import com.nextroom.oescape.service.ThemeService;

import lombok.RequiredArgsConstructor;

@RestController
@RequestMapping("/api/v1/theme")
@RequiredArgsConstructor
public class ThemeController {
private final ThemeService themeService;

@PostMapping
public ResponseEntity<BaseResponse> addTheme(
@RequestBody ThemeDto.AddThemeRequest request) {
themeService.addTheme(request);
return ResponseEntity.ok(new BaseResponse(OK));
}

@GetMapping
public ResponseEntity<BaseResponse> getThemeList() {
return ResponseEntity.ok(new DataResponse<>(OK, themeService.getThemeList()));
}

@PutMapping
public ResponseEntity<BaseResponse> editTheme(
@RequestBody ThemeDto.EditThemeRequest request) {
themeService.editTheme(request);
return ResponseEntity.ok(new BaseResponse(OK));
}

@DeleteMapping
public ResponseEntity<BaseResponse> removeTheme(
@RequestBody ThemeDto.RemoveRequest request) {
themeService.removeTheme(request);
return ResponseEntity.ok(new BaseResponse(OK));
}
}
11 changes: 9 additions & 2 deletions src/main/java/com/nextroom/oescape/domain/Theme.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,16 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Theme {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand All @@ -22,8 +30,7 @@ public class Theme {
@JoinColumn(name = "shop_id")
private Shop shop;
private String title;
private Long timeLimit;
private Long hintCount;
private Integer timeLimit;
@OneToMany(mappedBy = "theme", cascade = CascadeType.ALL)
private List<Hint> hints = new ArrayList<>();
}
48 changes: 48 additions & 0 deletions src/main/java/com/nextroom/oescape/dto/ThemeDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.nextroom.oescape.dto;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;

public class ThemeDto {

@Getter
@Builder
@RequiredArgsConstructor
@NoArgsConstructor(force = true)
public static class AddThemeRequest {
private final String title;
private final Integer timeLimit;
}

@Getter
@Builder
public static class AddThemeResponse {
private final Long id;
private final String title;
private final Integer timeLimit;
}

@Getter
@Builder
public static class ThemeListResponse {
private final Long id;
private final String title;
private final Integer timeLimit;
}

@Getter
@RequiredArgsConstructor
public static class EditThemeRequest {
private final Long id;
private final String title;
private final Integer timeLimit;
}

@Getter
@RequiredArgsConstructor
public static class RemoveRequest {
private final Long id;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ public enum StatusCode {
/**
* 4xx Bad Request
*/
BAD_REQUEST(HttpStatus.BAD_REQUEST, "잘λͺ»λœ μš”μ²­μž…λ‹ˆλ‹€.");
BAD_REQUEST(HttpStatus.BAD_REQUEST, "잘λͺ»λœ μš”μ²­μž…λ‹ˆλ‹€."),

/**
* 2xx OK
*/
OK(HttpStatus.OK, "성곡");

private final HttpStatus code;
private final String message;
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/com/nextroom/oescape/repository/ThemeRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.nextroom.oescape.repository;

import java.util.List;
import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;

import com.nextroom.oescape.domain.Shop;
import com.nextroom.oescape.domain.Theme;

public interface ThemeRepository extends JpaRepository<Theme, Long> {
Optional<Theme> findByTitle(String title);

List<Theme> findAllByShop(Shop shop);
}
75 changes: 75 additions & 0 deletions src/main/java/com/nextroom/oescape/service/ThemeService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.nextroom.oescape.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Service;

import com.nextroom.oescape.domain.Shop;
import com.nextroom.oescape.domain.Theme;
import com.nextroom.oescape.dto.ThemeDto;
import com.nextroom.oescape.exceptions.CustomException;
import com.nextroom.oescape.exceptions.StatusCode;
import com.nextroom.oescape.repository.ThemeRepository;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class ThemeService {
private final ThemeRepository themeRepository;

public ThemeDto.AddThemeResponse addTheme(ThemeDto.AddThemeRequest request) {
Theme result = themeRepository.findByTitle(request.getTitle()).orElseThrow(
() -> new CustomException(StatusCode.BAD_REQUEST)
);

Theme theme = Theme.builder()
.title(request.getTitle())
.timeLimit(request.getTimeLimit())
.build();

Theme savedTheme = themeRepository.save(theme);

return ThemeDto.AddThemeResponse.builder()
.id(savedTheme.getId())
.title(savedTheme.getTitle())
.timeLimit(savedTheme.getTimeLimit())
.build();
}

public List<ThemeDto.ThemeListResponse> getThemeList() {
//TODO νšŒμ› 검증 둜직

List<Theme> themeList = themeRepository.findAllByShop(new Shop());
List<ThemeDto.ThemeListResponse> themeListResponses = new ArrayList<>();
for (Theme theme : themeList) {
themeListResponses.add(ThemeDto.ThemeListResponse
.builder()
.id(theme.getId())
.title(theme.getTitle())
.timeLimit(theme.getTimeLimit())
.build());
}
return themeListResponses;
}

public void editTheme(ThemeDto.EditThemeRequest request) {
//TODO ν…Œλ§ˆ μ‚¬μš©μž 쑰회

//TODO ν…Œλ§ˆ 쑰회
Theme theme = themeRepository.findById(request.getId()).orElseThrow(
() -> new CustomException(StatusCode.BAD_REQUEST)
);

//TODO ν…Œλ§ˆ μˆ˜μ •
}

public void removeTheme(ThemeDto.RemoveRequest request) {
//TODO ν…Œλ§ˆ μ‚¬μš©μž 쑰회

//TODO ν…Œλ§ˆ 쑰회

//TODO ν…Œλ§ˆ μ‚­μ œ
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.nextroom.oescape.controller;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import com.google.gson.Gson;
import com.nextroom.oescape.dto.ThemeDto;

@ExtendWith(MockitoExtension.class)
class ThemeControllerTest {

@InjectMocks
private ThemeController themeController;

private MockMvc mockMvc;
private Gson gson;

@BeforeEach
void init() {
gson = new Gson();
mockMvc = MockMvcBuilders.standaloneSetup(themeController).build();
}

@Test
@DisplayName("ν…Œλ§ˆ 등둝 μ‹€νŒ¨_μ‚¬μš©μž 식별값 헀더에 μ—†μŒ")
void failAddTheme() throws Exception {
//given
String url = "/api/v1/theme";

//when
ResultActions resultActions = mockMvc.perform(
MockMvcRequestBuilders.post(url)
.content(gson.toJson(addThemeRequest("ν…Œλ§ˆ 이름", 70)))
.contentType(MediaType.APPLICATION_JSON)
);

//then
resultActions.andExpect(status().isBadRequest());
}

private ThemeDto.AddThemeRequest addThemeRequest(String title, int timeLimit) {
return ThemeDto.AddThemeRequest.builder()
.title(title)
.timeLimit(timeLimit)
.build();
}
}
16 changes: 16 additions & 0 deletions src/test/java/com/nextroom/oescape/domain/ThemeTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.nextroom.oescape.domain;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class ThemeTest {

@Test
@DisplayName("ν…Œλ§ˆ 생성")
void createTheme() {
Theme theme = new Theme();
assertNotNull(theme);
}
}
Loading

0 comments on commit 7b63aec

Please sign in to comment.