Skip to content

Commit

Permalink
[OING-40] feat: Feed부분 API 설계하기 (#23)
Browse files Browse the repository at this point in the history
* feat: add Pagination Response and DTO

* test: add dto, response test code

* feat: add PostFeedController

* fix: change package issue

* feat: implement mock logic

* test: fix test

* test: add test to PostFeedResponse

* feat: add Member API
  • Loading branch information
CChuYong authored Dec 9, 2023
1 parent dc6fbb1 commit a52b47d
Show file tree
Hide file tree
Showing 12 changed files with 394 additions and 0 deletions.
20 changes: 20 additions & 0 deletions common/src/main/java/com/oing/domain/PaginationDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.oing.domain;

import org.springframework.data.domain.Page;

import java.util.Collection;

/**
* no5ing-server
* User: CChuYong
* Date: 2023/12/05
* Time: 12:37 PM
*/
public record PaginationDTO<T>(
int totalPage,
Collection<T> results
) {
public static <T> PaginationDTO<T> of(Page<T> page) {
return new PaginationDTO<>(page.getTotalPages(), page.getContent());
}
}
21 changes: 21 additions & 0 deletions common/src/main/java/com/oing/dto/response/ArrayResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.oing.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;

import java.util.Collection;

/**
* no5ing-server
* User: CChuYong
* Date: 2023/12/05
* Time: 12:30 PM
*/
@Schema(description = "배열(복수) 응답")
public record ArrayResponse<T>(
@Schema(description = "실제 데이터 컬렉션", example = "[\"data\"]")
Collection<T> results
) {
public static <T> ArrayResponse<T> of(Collection<T> results) {
return new ArrayResponse<>(results);
}
}
37 changes: 37 additions & 0 deletions common/src/main/java/com/oing/dto/response/PaginationResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.oing.dto.response;

import com.oing.domain.PaginationDTO;
import io.swagger.v3.oas.annotations.media.Schema;

import java.util.Collection;
import java.util.function.Function;

/**
* no5ing-server
* User: CChuYong
* Date: 2023/12/05
* Time: 12:30 PM
*/
@Schema(description = "페이지네이션 응답")
public record PaginationResponse<T>(
@Schema(description = "현재 페이지", example = "1")
int currentPage,

@Schema(description = "전체 페이지 수", example = "30")
int totalPage,

@Schema(description = "페이지당 데이터 수", example = "10")
int itemPerPage,

@Schema(description = "실제 데이터 컬렉션", example = "[\"data\"]")
Collection<T> results
) {
public static <T> PaginationResponse<T> of(PaginationDTO<T> dto, int currentPage, int itemPerPage) {
return new PaginationResponse<>(currentPage, dto.totalPage(), itemPerPage, dto.results());
}

public <R> PaginationResponse<R> map(Function<T, R> mappingFunction) {
Collection<R> mappedResults = results.stream().map(mappingFunction).toList();
return new PaginationResponse<>(currentPage, totalPage, itemPerPage, mappedResults);
}
}
32 changes: 32 additions & 0 deletions common/src/test/java/com/oing/domain/PaginationDTOTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.oing.domain;

import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;

import java.util.Arrays;
import java.util.List;

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

/**
* no5ing-server
* User: CChuYong
* Date: 2023/12/05
* Time: 12:45 PM
*/
public class PaginationDTOTest {
@Test
void testPaginationDTOCreation() {
// Given
List<String> testData = Arrays.asList("Item1", "Item2", "Item3");
Page<String> page = new PageImpl<>(testData, PageRequest.of(0, testData.size()), testData.size());

// When
PaginationDTO<String> paginationDTO = PaginationDTO.of(page);

// Then
assertEquals(testData, paginationDTO.results());
}
}
28 changes: 28 additions & 0 deletions common/src/test/java/com/oing/dto/response/ArrayResponseTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.oing.dto.response;

import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;

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

/**
* no5ing-server
* User: CChuYong
* Date: 2023/12/05
* Time: 12:46 PM
*/
public class ArrayResponseTest {
@Test
public void testArrayResponseCreation() {
// Given
List<String> testData = Arrays.asList("data1", "data2", "data3");

// When
ArrayResponse<String> arrayResponse = ArrayResponse.of(testData);

// Then
assertEquals(testData, arrayResponse.results());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.oing.dto.response;

import com.oing.domain.PaginationDTO;
import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;

import java.util.Arrays;
import java.util.List;

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

/**
* no5ing-server
* User: CChuYong
* Date: 2023/12/05
* Time: 12:46 PM
*/
public class PaginationResponseTest {
@Test
void testPaginationResponseCreation() {
// Given
List<String> testData = Arrays.asList("data1", "data2", "data3");
Page<String> page = new PageImpl<>(testData, PageRequest.of(0, testData.size()), testData.size());

// When
PaginationDTO<String> paginationDTO = PaginationDTO.of(page);
PaginationResponse<String> paginationResponse = PaginationResponse.of(paginationDTO, 1, testData.size());

// Then
assertEquals(1, paginationResponse.currentPage());
assertEquals(paginationDTO.totalPage(), paginationResponse.totalPage());
assertEquals(testData, paginationResponse.results());
}

@Test
void testPaginationResponseMapping() {
// Given
List<String> testData = Arrays.asList("data1", "data2", "data3");
Page<String> page = new PageImpl<>(testData, PageRequest.of(0, testData.size()), testData.size());

// When
PaginationDTO<String> paginationDTO = PaginationDTO.of(page);
PaginationResponse<String> paginationResponse = PaginationResponse.of(paginationDTO, 1, testData.size());
PaginationResponse<Integer> mappedResponse = paginationResponse.map(String::length);

// Then
assertEquals(paginationResponse.currentPage(), mappedResponse.currentPage());
assertEquals(paginationResponse.totalPage(), mappedResponse.totalPage());
assertEquals(paginationResponse.itemPerPage(), mappedResponse.itemPerPage());
assertEquals(Arrays.asList(5, 5, 5), mappedResponse.results());
}
}
12 changes: 12 additions & 0 deletions member/src/main/java/com/oing/dto/response/MemberResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.oing.dto.response;

/**
* no5ing-server
* User: CChuYong
* Date: 12/7/23
* Time: 6:03 PM
*/
public record MemberResponse(

) {
}
22 changes: 22 additions & 0 deletions member/src/main/java/com/oing/restapi/MemberApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.oing.restapi;

import com.oing.dto.response.MemberResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* no5ing-server
* User: CChuYong
* Date: 12/7/23
* Time: 6:01 PM
*/
@Tag(name = "멤버 API", description = "멤버(사용자) 관련 API")
@RestController
@RequestMapping("/v1/members")
public interface MemberApi {
@GetMapping("/{memberId}")
MemberResponse getMember(@PathVariable String memberId);
}
50 changes: 50 additions & 0 deletions post/src/main/java/com/oing/controller/PostFeedController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.oing.controller;


import com.oing.dto.response.PaginationResponse;
import com.oing.dto.response.PostFeedResponse;
import com.oing.restapi.PostFeedApi;
import org.springframework.stereotype.Controller;

import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

/**
* no5ing-server
* User: CChuYong
* Date: 2023/12/05
* Time: 12:24 PM
*/
@Controller
public class PostFeedController implements PostFeedApi {
@Override
public PaginationResponse<PostFeedResponse> fetchDailyFeeds(Integer page, Integer size, LocalDate date) {
if (page > 5) return new PaginationResponse<>(page, 5, size, List.of());

String postIdBase = "01HGW2N7EHJVJ4CJ999RRS2E";
String writerIdBase = "01HGW2N7EHJVJ4CJ888RRS2E";

List<PostFeedResponse> mockResponses = new ArrayList<>();
Random random = new Random();
for(int i = 0; i < size; i++) {
int currentIndex = i + ((page - 1) * size);
String suffix = String.format("%02d", currentIndex);
mockResponses.add(
new PostFeedResponse(
postIdBase + suffix,
writerIdBase + suffix,
random.nextInt(5),
random.nextInt(5),
"https://picsum.photos/200/300?random=" + currentIndex,
ZonedDateTime.now().minusSeconds(currentIndex * 30L)
)
);
}

return new PaginationResponse<>(page, 5, size, mockResponses);
}
}
33 changes: 33 additions & 0 deletions post/src/main/java/com/oing/dto/response/PostFeedResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.oing.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;

import java.time.ZonedDateTime;

/**
* no5ing-server
* User: CChuYong
* Date: 2023/12/05
* Time: 12:30 PM
*/
@Schema(description = "피드 게시물 응답")
public record PostFeedResponse(
@Schema(description = "피드 게시물 ID", example = "01HGW2N7EHJVJ4CJ999RRS2E97")
String postId,

@Schema(description = "피드 게시물 작성자 ID", example = "01HGW2N7EHJVJ4CJ999RRS2E97")
String authorId,

@Schema(description = "피드 게시물 댓글 수", example = "3")
Integer commentCount,

@Schema(description = "피드 게시물 반응 수", example = "2")
Integer emojiCount,

@Schema(description = "피드 게시물 사진 주소", example = "https://asset.no5ing.kr/post/01HGW2N7EHJVJ4CJ999RRS2E97")
String imageUrl,

@Schema(description = "피드 작성 시간", example = "2021-12-05T12:30:00.000+09:00")
ZonedDateTime createdAt
) {
}
47 changes: 47 additions & 0 deletions post/src/main/java/com/oing/restapi/PostFeedApi.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.oing.restapi;

import com.oing.dto.response.PaginationResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import com.oing.dto.response.PostFeedResponse;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;

/**
* no5ing-server
* User: CChuYong
* Date: 2023/12/05
* Time: 12:23 PM
*/
@Tag(name = "피드 API", description = "게시물 피드 관련 API")
@RestController
@Valid
@RequestMapping("/v1/feeds")
public interface PostFeedApi {
@Operation(summary = "데일리 피드 조회", description = "데일리 피드를 조회합니다.")
@GetMapping(params = {"type=DAILY"})
PaginationResponse<PostFeedResponse> fetchDailyFeeds(
@RequestParam(required = false, defaultValue = "1")
@Parameter(description = "가져올 현재 페이지", example = "1")
@Min(value = 1)
Integer page,

@RequestParam(required = false, defaultValue = "10")
@Parameter(description = "가져올 페이지당 크기", example = "10")
@Min(value = 1)
Integer size,

@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
@RequestParam(required = false)
@Parameter(description = "오늘의 날짜", example = "2023-12-05")
LocalDate date
);
}
Loading

0 comments on commit a52b47d

Please sign in to comment.