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

[DDING-85] 동아리 지원폼지 생성 API 구현 #230

Merged
merged 2 commits into from
Jan 31, 2025
Merged
Changes from all 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
@@ -0,0 +1,29 @@
package ddingdong.ddingdongBE.domain.form.api;

import ddingdong.ddingdongBE.auth.PrincipalDetails;
import ddingdong.ddingdongBE.domain.form.controller.dto.request.CreateFormRequest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;

@Tag(name = "Form - Club", description = "Form API")
@RequestMapping("/server/central")
public interface CentralFormApi {

@Operation(summary = "동아리 지원 폼지 생성 API")
@ApiResponse(responseCode = "201", description = "동아리 지원 폼지 생성 성공")
@ResponseStatus(HttpStatus.CREATED)
@SecurityRequirement(name = "AccessToken")
@PostMapping("/my/forms")
void createForm(
@RequestBody CreateFormRequest createFormRequest,
@AuthenticationPrincipal PrincipalDetails principalDetails
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ddingdong.ddingdongBE.domain.form.controller;

import ddingdong.ddingdongBE.auth.PrincipalDetails;
import ddingdong.ddingdongBE.domain.form.api.CentralFormApi;
import ddingdong.ddingdongBE.domain.form.controller.dto.request.CreateFormRequest;
import ddingdong.ddingdongBE.domain.form.service.FacadeCentralFormService;
import ddingdong.ddingdongBE.domain.user.entity.User;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class CentralFormController implements CentralFormApi {

private final FacadeCentralFormService facadeCentralFormService;

@Override
public void createForm(
CreateFormRequest createFormRequest,
PrincipalDetails principalDetails
) {
User user = principalDetails.getUser();
facadeCentralFormService.createForm(createFormRequest.toCommand(user));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package ddingdong.ddingdongBE.domain.form.controller.dto.request;

import ddingdong.ddingdongBE.domain.form.entity.FieldType;
import ddingdong.ddingdongBE.domain.form.service.dto.command.CreateFormCommand;
import ddingdong.ddingdongBE.domain.form.service.dto.command.CreateFormCommand.CreateFormFieldCommand;
import ddingdong.ddingdongBE.domain.user.entity.User;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;
import java.util.List;


public record CreateFormRequest(
@Schema(description = "폼지 제목", example = "폼지제목입니다")
@NotNull(message = "폼지 제목은 null이 될 수 없습니다.")
String title,

@Schema(description = "폼지 설명", example = "우리 동아리는 띵동입니다.")
String description,

@Schema(description = "폼지 시작일자", example = "2001-01-01")
@NotNull(message = "폼지 시작일자는 null이 될 수 없습니다.")
LocalDate startDate,

@Schema(description = "폼지 종료일자", example = "2001-01-02")
@NotNull(message = "폼지 종료일자는 null이 될 수 없습니다.")
LocalDate endDate,

@Schema(description = "면접여부", example = "true")
@NotNull(message = "면접여부는 null이 될 수 없습니다.")
boolean hasInterview,

@ArraySchema(schema = @Schema(implementation = CreateFormFieldRequest.class))
List<CreateFormFieldRequest> formFields
) {
Comment on lines +14 to +36
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

추가적인 필드 유효성 검증이 필요합니다.

다음과 같은 추가 검증이 필요합니다:

  1. title의 최소/최대 길이 제한
  2. description의 최대 길이 제한
  3. formFields의 최소 개수 제한 (@SiZe 어노테이션 사용)

다음과 같이 검증을 추가하는 것을 제안드립니다:

 public record CreateFormRequest(
         @Schema(description = "폼지 제목", example = "폼지제목입니다")
         @NotNull(message = "폼지 제목은 null이 될 수 없습니다.")
+        @Size(min = 1, max = 100, message = "폼지 제목은 1자 이상 100자 이하여야 합니다.")
         String title,
 
         @Schema(description = "폼지 설명", example = "우리 동아리는 띵동입니다.")
+        @Size(max = 500, message = "폼지 설명은 500자 이하여야 합니다.")
         String description,
 
         @Schema(description = "폼지 시작일자", example = "2001-01-01")
         @NotNull(message = "폼지 시작일자는 null이 될 수 없습니다.")
         LocalDate startDate,
 
         @Schema(description = "폼지 종료일자", example = "2001-01-02")
         @NotNull(message = "폼지 종료일자는 null이 될 수 없습니다.")
         LocalDate endDate,
 
         @Schema(description = "면접여부", example = "true")
         @NotNull(message = "면접여부는 null이 될 수 없습니다.")
         boolean hasInterview,
 
         @ArraySchema(schema = @Schema(implementation = CreateFormFieldRequest.class))
+        @NotNull(message = "폼 필드 목록은 null이 될 수 없습니다.")
+        @Size(min = 1, message = "최소 하나 이상의 폼 필드가 필요합니다.")
         List<CreateFormFieldRequest> formFields
 )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public record CreateFormRequest(
@Schema(description = "폼지 제목", example = "폼지제목입니다")
@NotNull(message = "폼지 제목은 null이 될 수 없습니다.")
String title,
@Schema(description = "폼지 설명", example = "우리 동아리는 띵동입니다.")
String description,
@Schema(description = "폼지 시작일자", example = "2001-01-01")
@NotNull(message = "폼지 시작일자는 null이 될 수 없습니다.")
LocalDate startDate,
@Schema(description = "폼지 종료일자", example = "2001-01-02")
@NotNull(message = "폼지 종료일자는 null이 될 수 없습니다.")
LocalDate endDate,
@Schema(description = "면접여부", example = "true")
@NotNull(message = "면접여부는 null이 될 수 없습니다.")
boolean hasInterview,
@ArraySchema(schema = @Schema(implementation = CreateFormFieldRequest.class))
List<CreateFormFieldRequest> formFields
) {
public record CreateFormRequest(
@Schema(description = "폼지 제목", example = "폼지제목입니다")
@NotNull(message = "폼지 제목은 null이 될 수 없습니다.")
@Size(min = 1, max = 100, message = "폼지 제목은 1자 이상 100자 이하여야 합니다.")
String title,
@Schema(description = "폼지 설명", example = "우리 동아리는 띵동입니다.")
@Size(max = 500, message = "폼지 설명은 500자 이하여야 합니다.")
String description,
@Schema(description = "폼지 시작일자", example = "2001-01-01")
@NotNull(message = "폼지 시작일자는 null이 될 수 없습니다.")
LocalDate startDate,
@Schema(description = "폼지 종료일자", example = "2001-01-02")
@NotNull(message = "폼지 종료일자는 null이 될 수 없습니다.")
LocalDate endDate,
@Schema(description = "면접여부", example = "true")
@NotNull(message = "면접여부는 null이 될 수 없습니다.")
boolean hasInterview,
@ArraySchema(schema = @Schema(implementation = CreateFormFieldRequest.class))
@NotNull(message = "폼 필드 목록은 null이 될 수 없습니다.")
@Size(min = 1, message = "최소 하나 이상의 폼 필드가 필요합니다.")
List<CreateFormFieldRequest> formFields
)


record CreateFormFieldRequest(
@Schema(description = "폼지 질문", example = "우리 동아리 들어올겁니까?")
@NotNull(message = "질문는 null이 될 수 없습니다.")
String question,

@Schema(description = "질문 종류", example = "CHECK_BOX")
@NotNull(message = "질문 종류는 null이 될 수 없습니다.")
FieldType type,

@Schema(description = "질문의 선택리스트", example = "[지문1이다., 지문2이다., 지문3이다.]")
List<String> options,

@Schema(description = "필수여부", example = "true")
@NotNull(message = "필수여부는 null이 될 수 없습니다.")
boolean required,

@Schema(description = "질문 순서", example = "1")
@NotNull(message = "질문 순서는 null이 될 수 없습니다.")
int order,

@Schema(description = "질문 섹션 종류", example = "공통")
@NotNull(message = "질문 섹션종류는 null이 될 수 없습니다.")
String section
) {

public CreateFormFieldCommand toCommand() {
return CreateFormFieldCommand.builder()
.question(question)
.type(type)
.options(options)
.required(required)
.order(order)
.section(section)
.build();
}
}

public CreateFormCommand toCommand(User user) {
List<CreateFormFieldCommand> createFormFieldCommands = formFields.stream()
.map(CreateFormFieldRequest::toCommand)
.toList();
return CreateFormCommand.builder()
.user(user)
.title(title)
.description(description)
.startDate(startDate)
.endDate(endDate)
.hasInterview(hasInterview)
.formFieldCommands(createFormFieldCommands)
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ddingdong.ddingdongBE.domain.form.service;

import ddingdong.ddingdongBE.domain.form.service.dto.command.CreateFormCommand;

public interface FacadeCentralFormService {

void createForm(CreateFormCommand command);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package ddingdong.ddingdongBE.domain.form.service;

import ddingdong.ddingdongBE.domain.club.entity.Club;
import ddingdong.ddingdongBE.domain.club.service.ClubService;
import ddingdong.ddingdongBE.domain.form.entity.Form;
import ddingdong.ddingdongBE.domain.form.entity.FormField;
import ddingdong.ddingdongBE.domain.form.service.dto.command.CreateFormCommand;
import ddingdong.ddingdongBE.domain.form.service.dto.command.CreateFormCommand.CreateFormFieldCommand;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class FacadeCentralFormServiceImpl implements FacadeCentralFormService{

private final FormService formService;
private final FormFieldService formFieldService;
private final ClubService clubService;

@Transactional
@Override
public void createForm(CreateFormCommand createFormCommand) {
Club club = clubService.getByUserId(createFormCommand.user().getId());
Form form = createFormCommand.toEntity(club);
Form savedForm = formService.create(form);

List<FormField> formFields = toFormFields(savedForm, createFormCommand.formFieldCommands());
formFieldService.createAll(formFields);
}
Comment on lines +23 to +32
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

트랜잭션 내 검증 로직 추가가 필요합니다.

현재 구현에서는 엔티티 저장 전 비즈니스 규칙 검증이 누락되어 있습니다. 다음 사항들의 검증이 필요합니다:

  1. 클럽의 폼 생성 권한 확인
  2. 폼 필드의 유효성 검증

다음과 같이 수정을 제안드립니다:

     @Transactional
     @Override
     public void createForm(CreateFormCommand createFormCommand) {
         Club club = clubService.getByUserId(createFormCommand.user().getId());
+        validateFormCreationPermission(club);
+        validateFormFields(createFormCommand.formFieldCommands());
         
         Form form = createFormCommand.toEntity(club);
         Form savedForm = formService.create(form);

         List<FormField> formFields = toFormFields(savedForm, createFormCommand.formFieldCommands());
         formFieldService.createAll(formFields);
     }

Committable suggestion skipped: line range outside the PR's diff.


private List<FormField> toFormFields(Form savedForm, List<CreateFormFieldCommand> createFormFieldCommands) {
return createFormFieldCommands.stream()
.map(formFieldCommand -> formFieldCommand.toEntity(savedForm))
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ddingdong.ddingdongBE.domain.form.service;

import ddingdong.ddingdongBE.domain.form.entity.FormField;
import java.util.List;

public interface FormFieldService {

void createAll(List<FormField> formFields);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ddingdong.ddingdongBE.domain.form.service;

import ddingdong.ddingdongBE.domain.form.entity.Form;

public interface FormService {

Form create(Form form);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package ddingdong.ddingdongBE.domain.form.service;

import ddingdong.ddingdongBE.domain.form.entity.FormField;
import ddingdong.ddingdongBE.domain.form.repository.FormFieldRepository;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class GeneralFormFieldService implements FormFieldService {

private final FormFieldRepository formFieldRepository;

@Transactional
@Override
public void createAll(List<FormField> formFields) {
formFieldRepository.saveAll(formFields);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package ddingdong.ddingdongBE.domain.form.service;

import ddingdong.ddingdongBE.domain.form.entity.Form;
import ddingdong.ddingdongBE.domain.form.repository.FormRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class GeneralFormService implements FormService{

private final FormRepository formRepository;

@Transactional
@Override
public Form create(Form form) {
return formRepository.save(form);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package ddingdong.ddingdongBE.domain.form.service.dto.command;

import ddingdong.ddingdongBE.domain.club.entity.Club;
import ddingdong.ddingdongBE.domain.form.entity.FieldType;
import ddingdong.ddingdongBE.domain.form.entity.Form;
import ddingdong.ddingdongBE.domain.form.entity.FormField;
import ddingdong.ddingdongBE.domain.user.entity.User;
import java.time.LocalDate;
import java.util.List;
import lombok.Builder;

@Builder
public record CreateFormCommand(
User user,
String title,
String description,
LocalDate startDate,
LocalDate endDate,
boolean hasInterview,
List<CreateFormFieldCommand> formFieldCommands
) {

@Builder
public record CreateFormFieldCommand(
String question,
FieldType type,
List<String> options,
boolean required,
int order,
String section
) {

public FormField toEntity(Form savedForm) {
return FormField.builder()
.question(question)
.fieldType(type)
.options(options)
.required(required)
.fieldOrder(order)
.section(section)
.form(savedForm)
.build();
}
}

public Form toEntity(Club club) {
return Form.builder()
.title(title)
.description(description)
.startDate(startDate)
.endDate(endDate)
.hasInterview(hasInterview)
.club(club)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package ddingdong.ddingdongBE.domain.form.service;

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

import com.navercorp.fixturemonkey.FixtureMonkey;
import ddingdong.ddingdongBE.common.support.FixtureMonkeyFactory;
import ddingdong.ddingdongBE.common.support.TestContainerSupport;
import ddingdong.ddingdongBE.domain.club.entity.Club;
import ddingdong.ddingdongBE.domain.club.repository.ClubRepository;
import ddingdong.ddingdongBE.domain.form.entity.Form;
import ddingdong.ddingdongBE.domain.form.entity.FormField;
import ddingdong.ddingdongBE.domain.form.repository.FormFieldRepository;
import ddingdong.ddingdongBE.domain.form.repository.FormRepository;
import ddingdong.ddingdongBE.domain.form.service.dto.command.CreateFormCommand;
import ddingdong.ddingdongBE.domain.user.entity.Role;
import ddingdong.ddingdongBE.domain.user.entity.User;
import ddingdong.ddingdongBE.domain.user.repository.UserRepository;
import java.util.List;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class FacadeCentralFormServiceImplTest extends TestContainerSupport {

@Autowired
private FormService formService;

@Autowired
private FormRepository formRepository;

@Autowired
private FacadeCentralFormService facadeCentralFormService;

@Autowired
private ClubRepository clubRepository;

@Autowired
private UserRepository userRepository;

@Autowired
private FormFieldRepository formFieldRepository;

private static final FixtureMonkey fixtureMonkey = FixtureMonkeyFactory.getNotNullBuilderIntrospectorMonkey();

@DisplayName("폼지와 폼지 질문을 생성할 수 있다.")
@Test
void createForm() {
// given
User user = fixtureMonkey.giveMeBuilder(User.class)
.set("id", 1L)
.set("Role", Role.CLUB)
.set("deletedAt", null)
.sample();
User savedUser = userRepository.save(user);
Club club = fixtureMonkey.giveMeBuilder(Club.class)
.set("id", 1L)
.set("user", savedUser)
.set("score", null)
.set("clubMembers", null)
.set("deletedAt", null)
.sample();
clubRepository.save(club);
CreateFormCommand createFormCommand = fixtureMonkey.giveMeBuilder(CreateFormCommand.class)
.set("user", savedUser)
.sample();
// when
facadeCentralFormService.createForm(createFormCommand);
// then
List<Form> form = formRepository.findAll();
List<FormField> formFields = formFieldRepository.findAll();

assertThat(form).isNotEmpty();
assertThat(formFields).isNotEmpty();
}
Comment on lines +47 to +76
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

테스트 케이스와 검증 로직을 보강해주세요.

현재 테스트에서 개선이 필요한 부분들이 있습니다:

  1. 테스트 데이터 설정이 테스트 메소드 내에 직접 구현되어 있어 재사용이 어렵습니다.
  2. 단순히 리스트가 비어있지 않은지만 확인하고 있어, 실제 데이터의 정확성을 검증하지 않습니다.
  3. 실패 케이스에 대한 테스트가 없습니다.
  4. 엔티티 간의 관계가 올바르게 설정되었는지 검증하지 않습니다.

다음과 같이 개선해보세요:

+    private User createTestUser() {
+        User user = fixtureMonkey.giveMeBuilder(User.class)
+                .set("id", 1L)
+                .set("Role", Role.CLUB)
+                .set("deletedAt", null)
+                .sample();
+        return userRepository.save(user);
+    }
+
+    private Club createTestClub(User user) {
+        Club club = fixtureMonkey.giveMeBuilder(Club.class)
+                .set("id", 1L)
+                .set("user", user)
+                .set("score", null)
+                .set("clubMembers", null)
+                .set("deletedAt", null)
+                .sample();
+        return clubRepository.save(club);
+    }
+
     @DisplayName("폼지와 폼지 질문을 생성할 수 있다.")
     @Test
     void createForm() {
         // given
-        User user = fixtureMonkey.giveMeBuilder(User.class)
-                .set("id", 1L)
-                .set("Role", Role.CLUB)
-                .set("deletedAt", null)
-                .sample();
-        User savedUser = userRepository.save(user);
-        Club club = fixtureMonkey.giveMeBuilder(Club.class)
-                .set("id", 1L)
-                .set("user", savedUser)
-                .set("score", null)
-                .set("clubMembers", null)
-                .set("deletedAt", null)
-                .sample();
-        clubRepository.save(club);
+        User savedUser = createTestUser();
+        Club savedClub = createTestClub(savedUser);
         CreateFormCommand createFormCommand = fixtureMonkey.giveMeBuilder(CreateFormCommand.class)
                 .set("user", savedUser)
                 .sample();
+
         // when
         facadeCentralFormService.createForm(createFormCommand);
+
         // then
-        List<Form> form = formRepository.findAll();
+        List<Form> forms = formRepository.findAll();
         List<FormField> formFields = formFieldRepository.findAll();

-        assertThat(form).isNotEmpty();
-        assertThat(formFields).isNotEmpty();
+        assertThat(forms).hasSize(1);
+        Form createdForm = forms.get(0);
+        assertThat(createdForm.getClub()).isEqualTo(savedClub);
+        
+        assertThat(formFields)
+            .isNotEmpty()
+            .allSatisfy(field -> {
+                assertThat(field.getForm()).isEqualTo(createdForm);
+                assertThat(field.getQuestion()).isNotBlank();
+            });
     }
+
+    @DisplayName("권한이 없는 사용자는 폼지를 생성할 수 없다.")
+    @Test
+    void createForm_WithoutPermission() {
+        // given
+        User unauthorizedUser = fixtureMonkey.giveMeBuilder(User.class)
+                .set("id", 1L)
+                .set("Role", Role.USER)
+                .set("deletedAt", null)
+                .sample();
+        User savedUser = userRepository.save(unauthorizedUser);
+        CreateFormCommand createFormCommand = fixtureMonkey.giveMeBuilder(CreateFormCommand.class)
+                .set("user", savedUser)
+                .sample();
+
+        // when & then
+        assertThatThrownBy(() -> facadeCentralFormService.createForm(createFormCommand))
+                .isInstanceOf(UnauthorizedException.class);
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@DisplayName("폼지와 폼지 질문을 생성할 수 있다.")
@Test
void createForm() {
// given
User user = fixtureMonkey.giveMeBuilder(User.class)
.set("id", 1L)
.set("Role", Role.CLUB)
.set("deletedAt", null)
.sample();
User savedUser = userRepository.save(user);
Club club = fixtureMonkey.giveMeBuilder(Club.class)
.set("id", 1L)
.set("user", savedUser)
.set("score", null)
.set("clubMembers", null)
.set("deletedAt", null)
.sample();
clubRepository.save(club);
CreateFormCommand createFormCommand = fixtureMonkey.giveMeBuilder(CreateFormCommand.class)
.set("user", savedUser)
.sample();
// when
facadeCentralFormService.createForm(createFormCommand);
// then
List<Form> form = formRepository.findAll();
List<FormField> formFields = formFieldRepository.findAll();
assertThat(form).isNotEmpty();
assertThat(formFields).isNotEmpty();
}
private User createTestUser() {
User user = fixtureMonkey.giveMeBuilder(User.class)
.set("id", 1L)
.set("Role", Role.CLUB)
.set("deletedAt", null)
.sample();
return userRepository.save(user);
}
private Club createTestClub(User user) {
Club club = fixtureMonkey.giveMeBuilder(Club.class)
.set("id", 1L)
.set("user", user)
.set("score", null)
.set("clubMembers", null)
.set("deletedAt", null)
.sample();
return clubRepository.save(club);
}
@DisplayName("폼지와 폼지 질문을 생성할 수 있다.")
@Test
void createForm() {
// given
User savedUser = createTestUser();
Club savedClub = createTestClub(savedUser);
CreateFormCommand createFormCommand = fixtureMonkey.giveMeBuilder(CreateFormCommand.class)
.set("user", savedUser)
.sample();
// when
facadeCentralFormService.createForm(createFormCommand);
// then
List<Form> forms = formRepository.findAll();
List<FormField> formFields = formFieldRepository.findAll();
assertThat(forms).hasSize(1);
Form createdForm = forms.get(0);
assertThat(createdForm.getClub()).isEqualTo(savedClub);
assertThat(formFields)
.isNotEmpty()
.allSatisfy(field -> {
assertThat(field.getForm()).isEqualTo(createdForm);
assertThat(field.getQuestion()).isNotBlank();
});
}
@DisplayName("권한이 없는 사용자는 폼지를 생성할 수 없다.")
@Test
void createForm_WithoutPermission() {
// given
User unauthorizedUser = fixtureMonkey.giveMeBuilder(User.class)
.set("id", 1L)
.set("Role", Role.USER)
.set("deletedAt", null)
.sample();
User savedUser = userRepository.save(unauthorizedUser);
CreateFormCommand createFormCommand = fixtureMonkey.giveMeBuilder(CreateFormCommand.class)
.set("user", savedUser)
.sample();
// when & then
assertThatThrownBy(() -> facadeCentralFormService.createForm(createFormCommand))
.isInstanceOf(UnauthorizedException.class);
}

}