SettingsController 리팩토링
요청 url을 상수로 변환 하였다.
package me.weekbelt.studyolle.settings;
@RequiredArgsConstructor
@Controller
@RequestMapping("/settings")
public class SettingsController {
// 추가
static final String ROOT = "/";
static final String SETTINGS = "settings";
static final String PROFILE = "/profile";
static final String PASSWORD = "/password";
static final String NOTIFICATIONS = "/notifications";
static final String ACCOUNT = "/account";
static final String TAGS = "/tags";
static final String ZONES = "/zones";
private final AccountService accountService;
private final ModelMapper modelMapper;
private final NicknameFormValidator nicknameFormValidator;
private final TagRepository tagRepository;
private final ObjectMapper objectMapper;
private final ZoneRepository zoneRepository;
@InitBinder("passwordForm")
public void passwordFormInitBinder(WebDataBinder webDataBinder) {
webDataBinder.addValidators(new PasswordFormValidator());
}
@InitBinder("nicknameForm")
public void nicknameFormInitBinder(WebDataBinder webDataBinder) {
webDataBinder.addValidators(nicknameFormValidator);
}
@GetMapping(PROFILE)
public String updateProfileForm(@CurrentAccount Account account, Model model) {
model.addAttribute(account);
model.addAttribute(modelMapper.map(account, Profile.class));
return SETTINGS + PROFILE;
}
@PostMapping(PROFILE)
public String updateProfile(@CurrentAccount Account account,
@Valid @ModelAttribute Profile profile,
Errors errors, Model model,
RedirectAttributes attributes) {
if (errors.hasErrors()) {
model.addAttribute(account);
return SETTINGS + PROFILE;
}
accountService.updateProfile(account, profile);
attributes.addFlashAttribute("message", "프로필을 수정했습니다.");
// return "redirect:" + "/settings/profile";
return "redirect:/" + SETTINGS + PROFILE;
}
// @GetMapping("/settings/password")
@GetMapping(PASSWORD)
public String updatePasswordForm(@CurrentAccount Account account, Model model) {
model.addAttribute(account);
model.addAttribute(new PasswordForm());
return SETTINGS + PASSWORD;
}
@PostMapping(PASSWORD)
public String updatePassword(@CurrentAccount Account account,
@Valid PasswordForm passwordForm,
Errors errors, Model model,
RedirectAttributes attributes) {
if (errors.hasErrors()) {
model.addAttribute(account);
return SETTINGS + PASSWORD;
}
accountService.updatePassword(account, passwordForm.getNewPassword());
attributes.addFlashAttribute("message", "패스워드를 변경했습니다.");
return "redirect:/" + SETTINGS + PASSWORD;
}
@GetMapping( NOTIFICATIONS)
public String updateNotificationsForm(@CurrentAccount Account account, Model model) {
model.addAttribute(account);
model.addAttribute(modelMapper.map(account, Notifications.class));
return SETTINGS + NOTIFICATIONS;
}
@PostMapping(NOTIFICATIONS)
public String updateNotifications(@CurrentAccount Account account, @Valid Notifications notifications,
Errors errors, Model model, RedirectAttributes attributes) {
if (errors.hasErrors()) {
model.addAttribute(account);
return SETTINGS + NOTIFICATIONS;
}
accountService.updateNotifications(account, notifications);
attributes.addFlashAttribute("message", "알림 설정을 변경했습니다.");
return "redirect:/" + SETTINGS + NOTIFICATIONS;
}
@GetMapping(ACCOUNT)
public String updateAccountForm(@CurrentAccount Account account, Model model) {
model.addAttribute(account);
model.addAttribute(modelMapper.map(account, NicknameForm.class));
return SETTINGS + ACCOUNT;
}
@PostMapping(ACCOUNT)
public String updateAccount(@CurrentAccount Account account, @Valid NicknameForm nicknameForm,
Errors errors, Model model, RedirectAttributes attributes) {
if (errors.hasErrors()) {
model.addAttribute(account);
return SETTINGS + ACCOUNT;
}
accountService.updateNickname(account, nicknameForm.getNickname());
attributes.addFlashAttribute("message", "닉네임을 수정했습니다.");
return "redirect:/" + SETTINGS + ACCOUNT;
}
@GetMapping(TAGS)
public String updateTags(@CurrentAccount Account account, Model model)
throws JsonProcessingException {
model.addAttribute(account);
Set<Tag> tags = accountService.getTags(account);
model.addAttribute("tags", tags.stream()
.map(Tag::getTitle).collect(Collectors.toList()));
List<String> allTags = tagRepository.findAll().stream()
.map(Tag::getTitle).collect(Collectors.toList());
model.addAttribute("whitelist", objectMapper.writeValueAsString(allTags));
return SETTINGS + TAGS;
}
@ResponseBody
@PostMapping(TAGS + "/add")
public ResponseEntity<?> addTag(@CurrentAccount Account account,
@RequestBody TagForm tagForm) {
String title = tagForm.getTagTitle();
Tag tag = tagRepository.findByTitle(title).orElseGet(
() -> tagRepository.save(Tag.builder().title(tagForm.getTagTitle())
.build()));
accountService.addTag(account, tag);
return ResponseEntity.ok().build();
}
@ResponseBody
@PostMapping(TAGS + "/remove")
public ResponseEntity<?> removeTag(@CurrentAccount Account account,
@RequestBody TagForm tagForm) {
String title = tagForm.getTagTitle();
Tag tag = tagRepository.findByTitle(title).get();
if (tag == null){
return ResponseEntity.badRequest().build();
}
accountService.removeTag(account, tag);
return ResponseEntity.ok().build();
}
@GetMapping(ZONES)
public String updateZonesForm(@CurrentAccount Account account, Model model)
throws JsonProcessingException {
model.addAttribute(account);
Set<Zone> zones = accountService.getZones(account);
model.addAttribute("zones", zones.stream().map(Zone::toString)
.collect(Collectors.toList()));
List<String> allZones = zoneRepository.findAll().stream().map(Zone::toString)
.collect(Collectors.toList());
model.addAttribute("whitelist", objectMapper.writeValueAsString(allZones));
return SETTINGS + ZONES;
}
@ResponseBody
@PostMapping(ZONES + "/add")
public ResponseEntity<?> addZone(@CurrentAccount Account account,
@RequestBody ZoneForm zoneForm) {
Zone zone = zoneRepository.findByCityAndProvince(zoneForm.getCityName(),
zoneForm.getProvinceName());
if (zone == null) {
return ResponseEntity.badRequest().build();
}
accountService.addZone(account, zone);
return ResponseEntity.ok().build();
}
@PostMapping(ZONES + "/remove")
public ResponseEntity<?> removeZone(@CurrentAccount Account account,
@RequestBody ZoneForm zoneForm) {
Zone zone = zoneRepository.findByCityAndProvince(zoneForm.getCityName(),
zoneForm.getProvinceName());
if(zone == null) {
return ResponseEntity.badRequest().build();
}
accountService.removeZone(account, zone);
return ResponseEntity.ok().build();
}
}
지역정보 관련 테스트 추가
package me.weekbelt.studyolle.settings;
@Transactional
@SpringBootTest
@AutoConfigureMockMvc
class SettingsControllerTest {
// ...........
@Autowired ZoneRepository zoneRepository;
private Zone testZone = Zone.builder()
.city("test").localNameOfCity("테스트시").province("테스트주")
.build();
@BeforeEach
void beforeEach() {
zoneRepository.save(testZone);
}
@AfterEach
public void afterEach() {
// ......
zoneRepository.deleteAll();
}
// ..............
@WithAccount("joohyuk")
@DisplayName("계정의 지역 정보 수정 폼")
@Test
public void updateZonesForm() throws Exception {
mockMvc.perform(get(ROOT + SETTINGS + ZONES))
.andExpect(view().name(SETTINGS + ZONES))
.andExpect(model().attributeExists("account"))
.andExpect(model().attributeExists("zones"))
.andExpect(model().attributeExists("whitelist"));
}
@WithAccount("joohyuk")
@DisplayName("계정의 지역 정보 추가")
@Test
public void addZone() throws Exception {
ZoneForm zoneForm = new ZoneForm();
zoneForm.setZoneName(testZone.toString());
mockMvc.perform(post(ROOT + SETTINGS + ZONES + "/add")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(zoneForm))
.with(csrf()))
.andExpect(status().isOk());
Account joohyuk = accountRepository.findByNickname("joohyuk");
Zone zone = zoneRepository.findByCityAndProvince(testZone.getCity(),
testZone.getProvince());
assertThat(joohyuk.getZones().contains(zone)).isTrue();
}
@WithAccount("joohyuk")
@DisplayName("계정의 지역 정보 삭제")
@Test
public void removeZone() throws Exception {
Account joohyuk = accountRepository.findByNickname("joohyuk");
Zone zone = zoneRepository.findByCityAndProvince(testZone.getCity(),
testZone.getProvince());
accountService.addZone(joohyuk, zone);
ZoneForm zoneForm = new ZoneForm();
zoneForm.setZoneName(testZone.toString());
mockMvc.perform(post(ROOT + SETTINGS + ZONES + "/remove")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(zoneForm))
.with(csrf()))
.andExpect(status().isOk());
assertThat(joohyuk.getZones().contains(zone)).isFalse();
}
}
참고: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-JPA-%EC%9B%B9%EC%95%B1#
'스프링과 JPA 기반 웹 어플리케이션 개발 > 2부(관심 주제와 지역 정보)' 카테고리의 다른 글
40. 지역 정보 추가 삭제 (0) | 2020.04.23 |
---|---|
39. 지역 도메인 (0) | 2020.04.23 |
38. 관심 주제 테스트 (0) | 2020.04.23 |
37. 관심 주제 자동완성 (0) | 2020.04.22 |
36. 관심 주제 삭제 (0) | 2020.04.22 |