728x90
반응형
AccountController
package com.demo.account;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class AccountController {
//sign-up 페이지에 연결된다면
@GetMapping("/sign-up")
public String signUpForm(Model model) {
//model.addAttribute(new SignUpForm()); 생략 가능
model.addAttribute("signUpForm", new SignUpForm());
return "account/sign-up";
}
//스프링부트 자동설정에 의해
//templates에 존재하는 view인 account/sign-up을 리턴한다.
}
SginUpForm
package com.demo.account;
import lombok.Data;
@Data
public class SignUpForm {
private String nickname;
private String email;
private String password;
}
AccountControllerTest
package com.demo.account;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
//테스트를 위한 어노테이션 -> 스프링부트테스트, 자동설정목업 MVC
@SpringBootTest @AutoConfigureMockMvc
//사용하면 서블릿이 뜨고, @AutoConfigureWebClient @AutoConfigureTestClient를 이용하면 테스트 가능
//@SpringBootTest (webEnvironment =WebEnvironment.DEFINED_PORT)
//@SpringBootTest (webEnvironment =WebEnvironment.NONE)
//@SpringBootTest (webEnvironment =WebEnvironment.RANDOM_PORT)
class AccountControllerTest {
//의존성 주입
@Autowired private MockMvc mockMvc;
@DisplayName("회원 가입 화면이 보이는지 테스트")
@Test
void signUpForm() throws Exception { //아래의 응답이 아닐경우 예외처리
mockMvc.perform(get("/sign-up")) //회원가입 요청에서
.andDo(print()) //실제 웹사이트 출력 -> 타임리프이기 때문에
.andExpect(status().isOk()) //보이는지 -> 즉, 상태가 정상일때 (200일때)
.andExpect(view().name("account/sign-up")) //뷰의 이름이 account/sign-up이 맞는지
.andExpect(model().attributeExists("signUpForm"));
}
}
sign-up.html
<!DOCTYPE html>
<!-- 회원가입 뷰 -> sign-up form을 만들어야 한다. 닉네임 이메일 비밀번호-->
<!-- 타임리프 네임스페이스 설정-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Demo</title>
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<style>
.container {
max-width: 100%;
}
</style>
</head>
<body class="bg-light">
<!-- 네비바 만들기-->
<nav class="navbar navbar-expand-sm navbar-dark bg-dark">
<!-- 배너-->
<a class="navbar-brand" href="/" th:href="@{/}">
<!--@는 경로설정인데 이 경우엔 root경로 -->
<img src="/images/logo_sm.png" width="30" height="30">
</a>
<!-- 네비게이션 아이템 검색 창-->
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent">
<span class="navbar-toggler-icon"> </span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<!-- 스터디 찾기 버튼 href="#" th:href="은 타임리프 동작 X와 동작시-->
<form th:action="@{/search/study}" class="form-inline" method="get" action="#">
<input class="form-control mr-sm-2" name="keyword" placeholder="스터디 찾기" type="search" />
</form>
</li>
</ul>
<!-- 로그인, 가입 버튼 href="#" th:href="은 타임리프 동작 X와 동작시-->
<ul class="navbar-nav justify-content-end">
<li class="nav-item">
<a class="nav-link" href="#" th:href="@{/login}">로그인</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" th:href="@{/signup}">가입</a>
</li>
</ul>
</div>
</nav>
<!-- 계정만들기 sign-up html-->
<div class="container">
<div class="py-5 text-center">
<h2>계정 만들기</h2>
</div>
<div class="row justify-content-center">
<!--th:object="${signUpForm}" 객체 이용해 form을 채운다 -> 객체의 프로퍼티를 *를 이용해 사용-->
<!--needs-validation 은 html로 검증 -->
<form class="needs-validation col-sm-6" action="#" th:action="@{/sign-up}" th:object="${signUpForm}"
method="post" novalidate>
<div class="form-group">
<label for="nickname">닉네임</label>
<!-- 필수 : 닉네임 이메일(이메일 형태 검증), 비밀번호 - > 검증이 안되면 invalid-feedback -->
<input id="nickname" type="text" th:field="*{nickname}" class="form-control" placeholder="whiteship"
aria-describedby="nicknameHelp" required minlength="3" maxlength="20">
<small id="nicknameHelp" class="form-text text-muted">
공백없이 문자와 숫자로만 3자 이상 20자 이내로 입력하세요. 가입후에 변경할 수 있습니다.
</small>
<small class="invalid-feedback">닉네임을 입력하세요.</small>
<small class="form-text text-danger" th:if="${#fields.hasErrors('nickname')}"
th:errors="*{nickname}">Nickname Error</small>
</div>
<div class="form-group">
<label for="email">이메일</label>
<input id="email" type="email" th:field="*{email}" class="form-control" placeholder="your@email.com"
aria-describedby="emailHelp" required>
<small id="emailHelp" class="form-text text-muted">
스터디올래는 사용자의 이메일을 공개하지 않습니다.
</small>
<small class="invalid-feedback">이메일을 입력하세요.</small>
<small class="form-text text-danger" th:if="${#fields.hasErrors('email')}"
th:errors="*{email}">Email Error</small>
</div>
<div class="form-group">
<label for="password">패스워드</label>
<input id="password" type="password" th:field="*{password}" class="form-control"
aria-describedby="passwordHelp" required minlength="8" maxlength="50">
<small id="passwordHelp" class="form-text text-muted">
8자 이상 50자 이내로 입력하세요. 영문자, 숫자, 특수기호를 사용할 수 있으며 공백은 사용할 수 없습니다.
</small>
<small class="invalid-feedback">패스워드를 입력하세요.</small>
<small class="form-text text-danger" th:if="${#fields.hasErrors('password')}"
th:errors="*{password}">Password Error</small>
</div>
<div class="form-group">
<button class="btn btn-primary btn-block" type="submit" aria-describedby="submitHelp">가입하기</button>
<small id="submitHelp" class="form-text text-muted">
<a href="#">약관</a>에 동의하시면 가입하기 버튼을 클릭하세요.
</small>
</div>
</form>
</div>
<footer th:fragment="footer">
<div class="row justify-content-center">
<img class="mb-2" src="/images/logo_long_kr.jpg" alt="" width="100">
<small class="d-block mb-3 text-muted">© 2020</small>
</div>
</footer>
</div>
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa"
crossorigin="anonymous"></script>
<!--needs-validation을 가지는 폼을 가져와 submit 이벤트 발생시 유효여부 검증, 유효하지 않으면, submit안되도록 처리 -->
<!--유효하면 was-validated에 추가 -> input의 required을 기반으로 처리-->
<script type="application/javascript" th:fragment="form-validation">
(function () {
'use strict';
window.addEventListener('load', function () {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
Array.prototype.filter.call(forms, function (form) {
form.addEventListener('submit', function (event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated')
}, false)
})
}, false)
}())
</script>
</body>
</html>
728x90
반응형
'Server Programming > Spring Boot Full-Stack Programming' 카테고리의 다른 글
[스프링 풀스택 클론 코딩 - 회원가입] (1-5) 회원가입 폼 서브밋 검증 (0) | 2022.08.26 |
---|---|
[스프링 풀스택 클론 코딩] @Valid @Length 어노테이션 의존성 추가 (0) | 2022.08.26 |
[스프링 풀스택 클론 코딩] 회원가입 페이지 만들기 (+ 부트스트랩, 자바스크립트, 롬복, 타임리프) (0) | 2022.08.26 |
[스프링 풀스택 클론 코딩] 의존성 주입 방법 (0) | 2022.08.25 |
[스프링 풀스택 클론 코딩 - 회원가입] (1-3) 회원가입 컨트롤러 (0) | 2022.08.25 |