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

사용자별 태그 목록 조회 기능 구현 #361

Merged
merged 4 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import codezap.global.swagger.error.ApiErrorResponse;
import codezap.global.swagger.error.ErrorCase;
import codezap.member.dto.MemberDto;
import codezap.template.dto.request.CreateTemplateRequest;
import codezap.template.dto.request.UpdateTemplateRequest;
import codezap.template.dto.response.ExploreTemplatesResponse;
import codezap.template.dto.response.FindAllTagsResponse;
import codezap.template.dto.response.FindAllTemplatesResponse;
import codezap.template.dto.response.FindTemplateResponse;
import io.swagger.v3.oas.annotations.Operation;
Expand Down Expand Up @@ -67,6 +70,13 @@ ResponseEntity<FindAllTemplatesResponse> getTemplates(
Pageable pageable
);

@Operation(summary = "태그 목록 조회", description = """
유저가 가지고 있는 태그 목록을 조회합니다.
""")
@ApiResponse(responseCode = "200", description = "태그 목록 조회 성공",
content = {@Content(schema = @Schema(implementation = FindAllTagsResponse.class))})
ResponseEntity<FindAllTagsResponse> getTags(Long memberId);

@Operation(summary = "템플릿 단건 조회", description = "해당하는 식별자의 템플릿을 조회합니다.")
@ApiResponse(responseCode = "200", description = "템플릿 단건 조회 성공",
content = {@Content(schema = @Schema(implementation = ExploreTemplatesResponse.class))})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import codezap.template.dto.request.CreateTemplateRequest;
import codezap.template.dto.request.UpdateTemplateRequest;
import codezap.template.dto.response.ExploreTemplatesResponse;
import codezap.template.dto.response.FindAllTagsResponse;
import codezap.template.dto.response.FindAllTemplatesResponse;
import codezap.template.dto.response.FindTemplateResponse;
import codezap.template.service.TemplateService;
Expand Down Expand Up @@ -60,6 +61,12 @@ public ResponseEntity<FindAllTemplatesResponse> getTemplates(
return ResponseEntity.ok(response);
}

@GetMapping("/tags")
public ResponseEntity<FindAllTagsResponse> getTags(@RequestParam Long memberId) {
FindAllTagsResponse response = templateService.findAllTagsByMemberId(memberId);
return ResponseEntity.ok(response);
}

@GetMapping("/explore")
public ResponseEntity<ExploreTemplatesResponse> explore() {
return ResponseEntity.ok(templateService.findAll());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package codezap.template.dto.response;

import java.util.List;

public record FindAllTagsResponse(
List<FindTagResponse> tags
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,5 @@ Page<Template> searchBy(
Pageable pageable
);

List<Template> findByMemberId(Long memberId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ public interface TemplateTagRepository extends JpaRepository<TemplateTag, Long>

void deleteAllByTemplateId(Long id);


List<TemplateTag> findByTagIn(List<Tag> tags);

List<TemplateTag> findByTemplateIn(List<Template> templates);

@Query("""
SELECT DISTINCT tt.id.templateId
FROM TemplateTag tt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
import codezap.template.dto.request.UpdateSnippetRequest;
import codezap.template.dto.request.UpdateTemplateRequest;
import codezap.template.dto.response.ExploreTemplatesResponse;
import codezap.template.dto.response.FindAllTagsResponse;
import codezap.template.dto.response.FindAllTemplatesResponse;
import codezap.template.dto.response.FindAllTemplatesResponse.ItemResponse;
import codezap.template.dto.response.FindTagResponse;
import codezap.template.dto.response.FindTemplateResponse;
import codezap.template.repository.SnippetRepository;
import codezap.template.repository.TagRepository;
Expand Down Expand Up @@ -278,4 +280,16 @@ private CodeZapException throwNotFoundTag() {
private CodeZapException throwNotFoundThumbnailSnippet() {
throw new CodeZapException(HttpStatus.NOT_FOUND, "해당하는 썸네일 스니펫이 존재하지 않습니다.");
}

public FindAllTagsResponse findAllTagsByMemberId(Long memberId) {
List<Template> byMemberId = templateRepository.findByMemberId(memberId);
List<TemplateTag> templateTags = templateTagRepository.findByTemplateIn(byMemberId);
return new FindAllTagsResponse(
templateTags.stream()
.map(TemplateTag::getTag)
.distinct()
.map(FindTagResponse::from)
.toList()
);
}
}
139 changes: 139 additions & 0 deletions backend/src/test/java/codezap/template/service/TagSearchTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package codezap.template.service;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;

import java.util.List;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;

import codezap.category.domain.Category;
import codezap.category.repository.CategoryRepository;
import codezap.fixture.MemberDtoFixture;
import codezap.member.domain.Member;
import codezap.member.repository.MemberRepository;
import codezap.template.domain.Snippet;
import codezap.template.domain.Tag;
import codezap.template.domain.Template;
import codezap.template.domain.TemplateTag;
import codezap.template.domain.ThumbnailSnippet;
import codezap.template.dto.request.CreateSnippetRequest;
import codezap.template.dto.request.CreateTemplateRequest;
import codezap.template.repository.SnippetRepository;
import codezap.template.repository.TagRepository;
import codezap.template.repository.TemplateRepository;
import codezap.template.repository.TemplateTagRepository;
import codezap.template.repository.ThumbnailSnippetRepository;
import io.restassured.RestAssured;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@Sql(value = "/clear.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(value = "/clear.sql", executionPhase = ExecutionPhase.AFTER_TEST_CLASS)
public class TagSearchTest {

@LocalServerPort
int port;

@Autowired
private TemplateService templateService;

@Autowired
private TemplateRepository templateRepository;

@Autowired
private SnippetRepository snippetRepository;

@Autowired
private ThumbnailSnippetRepository thumbnailSnippetRepository;

@Autowired
private CategoryRepository categoryRepository;

@Autowired
private TemplateTagRepository templateTagRepository;

@Autowired
private TagRepository tagRepository;

@Autowired
private MemberRepository memberRepository;

@BeforeEach
void setting() {
RestAssured.port = port;
}

private void saveDefault15Templates(Member member, Category category) {
saveTemplate(makeTemplateRequest("hello keyword 1"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 2"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 3"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 4"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 5"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 6"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 7"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 8"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 9"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 10"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 11"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 12"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 13"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 14"), member, category);
saveTemplate(makeTemplateRequest("hello keyword 15"), member, category);
}

private CreateTemplateRequest makeTemplateRequest(String title) {
return new CreateTemplateRequest(title, "description",
List.of(new CreateSnippetRequest("filename1", "content1", 1),
new CreateSnippetRequest("filename2", "content2", 2)),
1L,
List.of());
}

private Template saveTemplate(CreateTemplateRequest createTemplateRequest, Member member, Category category) {
Template savedTemplate = templateRepository.save(
new Template(member, createTemplateRequest.title(), createTemplateRequest.description(), category));
Snippet savedFirstSnippet = snippetRepository.save(new Snippet(savedTemplate, "filename1", "content1", 1));
snippetRepository.save(new Snippet(savedTemplate, "filename2", "content2", 2));
thumbnailSnippetRepository.save(new ThumbnailSnippet(savedTemplate, savedFirstSnippet));

return savedTemplate;
}

@Nested
@DisplayName("조건에 따른 페이지 조회 메서드 동작 확인")
class FilteringPageTest {

@Test
@DisplayName("사용자별 태그 목록 조회 성공")
void findBySingleTagPageSuccess() {
Member member1 = memberRepository.fetchById(MemberDtoFixture.getFirstMemberDto().id());
Member member2 = memberRepository.fetchById(MemberDtoFixture.getSecondMemberDto().id());
Category category1 = categoryRepository.save(new Category("category1", member1));
tagRepository.save(new Tag("tag1"));
tagRepository.save(new Tag("tag2"));
saveDefault15Templates(member1, category1);
saveDefault15Templates(member2, category1);

templateTagRepository.save(
new TemplateTag(templateRepository.fetchById(1L), tagRepository.fetchById(1L)));
templateTagRepository.save(
new TemplateTag(templateRepository.fetchById(2L), tagRepository.fetchById(2L)));
templateTagRepository.save(
new TemplateTag(templateRepository.fetchById(30L), tagRepository.fetchById(1L)));

assertAll(
() -> assertThat(templateService.findAllTagsByMemberId(member1.getId()).tags()).hasSize(2),
() -> assertThat(templateService.findAllTagsByMemberId(member2.getId()).tags()).hasSize(1)
);
}
}
}
Loading