├── .gitignore ├── .travis.yml ├── README.md ├── backend ├── .gitignore ├── build.gradle └── src │ ├── main │ ├── java │ │ └── io │ │ │ └── codechobostudy │ │ │ └── common │ │ │ └── RequireJSController.java │ ├── resources │ │ ├── application.yml │ │ ├── static │ │ │ ├── js │ │ │ │ ├── app.js │ │ │ │ └── views │ │ │ │ │ └── app.view.js │ │ │ └── styles │ │ │ │ └── .gitkeep │ │ └── templates │ │ │ └── index.html │ └── scala │ │ └── io │ │ └── codechobostudy │ │ ├── Application.scala │ │ ├── config │ │ ├── SimpleCORSFilter.scala │ │ └── WebConfig.scala │ │ ├── home │ │ └── controller │ │ │ └── HomeController.scala │ │ └── sample │ │ ├── controller │ │ └── SampleController.scala │ │ ├── domain │ │ ├── BaseEntity.scala │ │ └── SampleDomain.scala │ │ ├── repository │ │ └── SampleRepository.scala │ │ └── service │ │ └── SampleService.scala │ └── test │ └── scala │ └── io │ └── codechobostudy │ └── sample │ ├── controller │ └── SampleControllerTest.java │ ├── domain │ └── SampleDomainDomainTest.java │ ├── fixture │ └── SampleBuilder.java │ ├── repository │ └── SampleRepositoryTest.java │ └── service │ └── SampleServiceTest.java ├── build.gradle └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | build 4 | gradle 5 | out 6 | gradlew 7 | gradlew.bat 8 | *.iml 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | script: "gradle build" 5 | branches: 6 | only: 7 | - develop 8 | env: 9 | - TERM=dumb 10 | after_success: 11 | - gradle cobertura coveralls 12 | notifications: 13 | slack: codechobostudy:7xxE3u0mOPli3DRz6cKiIz51 14 | email: 15 | - changhwaoh.co@gmail.com -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # code-chobo-study 2 | [![Build Status](https://travis-ci.org/codechobostudy/code-chobo-study.svg?branch=develop)](https://travis-ci.org/codechobostudy/code-chobo-study)[![Coverage Status](https://coveralls.io/repos/codechobostudy/code-chobo-study/badge.svg?branch=develop)](https://coveralls.io/r/codechobostudy/code-chobo-study?branch=develop) 3 | 코드초보스터디 사이트 개편 프로젝트 4 | 5 | #### Requirement 6 | 1. JDK 1.8 7 | 2. scala 2.11.x 8 | 3. gradle 2.x 9 | 10 | #### 실행방법 11 | ``` 12 | # 프로젝트 루트 폴더에서 해당 명령어 실행 13 | gradle bootRun 또는 gradle backend:bootRun 14 | ``` 15 | 16 | #### Git 브랜치 전략 및 참여방법 17 | ---- 18 | ##### Branch 19 | 1. master는 태그처럼 관리하며 사이클(주기) 별로 배포된다. 20 | 2. develop 브랜치는 개발서버로 배포되는 브랜치이다. 21 | 3. feature 브랜치는 각 기능이 개발되는 브랜치이다. 22 | 4. bugfix 브랜치는 develop, master 브랜치에서 생성될 수 있고 버그 수정이다. 23 | 5. release 브랜치는 사용유무는 회의를 통해 결정한다. 24 | 25 | ##### 참여방법 26 | 1. develop 브랜치를 기준으로 각 feature 브랜치를 생성한다. 27 | 2. 또는 develop 브랜치로 Fork를 한다. 28 | 3. github이슈에 자신을 등록하고 ing 라벨을 붙인다. 29 | 4. 개발이 완료 되면 develop 브랜치로 Pull Request를 보낸다. 30 | 5. 반드시 최소 2인 이상의 TF,명예팀 코드리뷰를 통과해야한다 31 | 만약 TF, 명예팀이 보낸 Pull Request는 본인을 제외한 2인이다. 32 | 6. 브랜치를 병합하고 삭제한다. 33 | 7. develop 브랜치에 병합되면 정상적으로 동작하는지 확인한다. 34 | 8. 완류 후 이슈를 close 하고 ing 라벨을 제거한다. 35 | 9. 가능한 pull 을 받는 경우는 --rebase 옵션을 활용한다. 36 | 10. 그외 방법은 [angularjs Contribute Guide](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#submitting-a-pull-request) 를 참고한다. 37 | 38 | ##### 커밋로그작성방법 39 | 1. 기본형태 40 | ``` 41 | commit type (관련 기능, 이슈번호등) : 요약메세지 (짧을 경우 전체기입가능) 42 | 1. 자세한 메세지 내용 43 | 2. 자세한 메세지 내용 44 | 3. 자세한 메세지 내용 45 | 46 | ex) 회원기능의 CRUD 개발 후 메세지 47 | feature(user) : 회원 CRUD 개발 48 | 1. 회원가입,수정,탈퇴 49 | 2. 스프링 시큐리티 설정 50 | ``` 51 | 2. 가능한 커밋은 해당 메세지에 해당하는 항목만 커밋되도록한다. (커밋합치기, 쪼개기 활용) 52 | 3. 경우에 따라 리뷰시 커밋관련 메세지나 잘못끼어든 파일등으로 반려될 수 있다. 53 | 4. 커밋타입은 다음과 같다. (필요에 따라 추가될 수 있다.) 54 | - feature : 기능 55 | - bugfix : 버그 패치 56 | - doc : 문서가 변경된 경우 57 | - style : 코드 영향을 주지 않는 공백, 코드스타일 등을 수정한 경우 58 | - refactor : 코드 리팩토링 59 | - test : 테스트코드를 추가할때 (가능한 커밋시 테스트코드는 따로 하지말고 같이보낸다) 60 | - enhancement : 개발완료된 기능을 개선하는 경우 (성능등) 61 | - framework : 프레임워크 관련 수정 또는 프로젝트 설정 수정등 62 | -------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | build 3 | out 4 | .DS_Store 5 | **/.DS_Store -------------------------------------------------------------------------------- /backend/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenLocal() 4 | mavenCentral() 5 | } 6 | dependencies { 7 | classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.3.RELEASE") 8 | classpath 'net.saliman:gradle-cobertura-plugin:2.2.8' 9 | classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.3.1' 10 | } 11 | } 12 | 13 | apply plugin: 'spring-boot' 14 | apply plugin: 'war' 15 | apply plugin: 'scala' 16 | 17 | apply plugin: 'net.saliman.cobertura' 18 | apply plugin: 'com.github.kt3k.coveralls' 19 | 20 | dependencies { 21 | compile 'org.scala-lang:scala-library:2.11.6' 22 | compile 'org.springframework.boot:spring-boot-starter-web' 23 | compile 'org.springframework.boot:spring-boot-starter-jdbc' 24 | compile 'org.springframework.boot:spring-boot-starter-data-jpa' 25 | compile 'org.springframework.boot:spring-boot-starter-thymeleaf' 26 | compile 'com.h2database:h2' 27 | compile 'com.zaxxer:HikariCP' 28 | compile 'mysql:mysql-connector-java' 29 | compile 'org.projectlombok:lombok:1.16.4' 30 | 31 | testCompile 'org.springframework.boot:spring-boot-starter-test' 32 | compile 'com.jayway.restassured:rest-assured:2.4.1' 33 | runtime 'net.sourceforge.nekohtml:nekohtml:1.9.21' 34 | compile 'org.codehaus.groovy:groovy-all:2.4.3' 35 | 36 | 37 | //webjars 38 | compile 'org.webjars:jquery:1.11.3' 39 | compile 'org.webjars:underscorejs:1.8.3' 40 | compile 'org.webjars:backbonejs:1.1.2-4' 41 | compile 'org.webjars:bootstrap:3.3.4' 42 | compile 'org.webjars:requirejs:2.1.17' 43 | compile 'org.webjars:webjars-locator:0.21' 44 | 45 | } 46 | 47 | sourceSets { 48 | main { 49 | scala { 50 | srcDirs = ['src/main/scala'] 51 | } 52 | } 53 | test { 54 | scala { 55 | srcDirs = ['src/test/scala'] 56 | } 57 | } 58 | } 59 | 60 | cobertura { 61 | coverageFormats = ['html', 'xml'] // coveralls plugin depends on xml format report 62 | coverageExcludes = ['.*common\\.RequireJSController.*' 63 | ,'.*config\\.SimpleCORSFilter.*' 64 | ,'.*config\\.WebConfig.*' 65 | ,'.*home\\.*controller\\.HomeController.*' 66 | ,'.*codechobostudy\\.Application.*'] 67 | } 68 | 69 | 70 | war{ 71 | baseName = 'sample' 72 | version = '1.0' 73 | } 74 | 75 | springBoot { 76 | mainClass = 'io.codechobostudy.Application' 77 | } -------------------------------------------------------------------------------- /backend/src/main/java/io/codechobostudy/common/RequireJSController.java: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.common; 2 | 3 | import org.springframework.core.io.ClassPathResource; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.stereotype.Controller; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.ResponseBody; 10 | import org.springframework.web.servlet.HandlerMapping; 11 | import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; 12 | import org.webjars.RequireJS; 13 | import org.webjars.WebJarAssetLocator; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | 17 | @Controller 18 | public class RequireJSController extends ResourceHttpRequestHandler { 19 | 20 | private WebJarAssetLocator assetLocator = new WebJarAssetLocator(); 21 | 22 | @ResponseBody 23 | @RequestMapping(value = "/webjarsjs", produces = "application/javascript") 24 | public String webjarjs() { 25 | return RequireJS.getSetupJavaScript("/webjars/"); 26 | } 27 | 28 | @ResponseBody 29 | @RequestMapping("/webjarslocator/{webjar}/**") 30 | public ResponseEntity locateWebjarAsset(@PathVariable String webjar, HttpServletRequest request) { 31 | try { 32 | String mvcPrefix = "/webjarslocator/" + webjar + "/"; // This prefix must match the mapping path! 33 | String mvcPath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); 34 | String fullPath = assetLocator.getFullPath(webjar, mvcPath.substring(mvcPrefix.length())); 35 | return new ResponseEntity(new ClassPathResource(fullPath), HttpStatus.OK); 36 | } catch (Exception e) { 37 | return new ResponseEntity<>(HttpStatus.NOT_FOUND); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /backend/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring.thymeleaf.cache: false 2 | spring.template.cache: false 3 | spring.thymeleaf.mode: LEGACYHTML5 4 | 5 | webjars.requirejs.newModules: 6 | 7 | app: 8 | version: de4db33f -------------------------------------------------------------------------------- /backend/src/main/resources/static/js/app.js: -------------------------------------------------------------------------------- 1 | require([ 2 | 'backbone', 3 | 'views/app.view' 4 | ], function (Backbone, AppView) { 5 | /*jshint nonew:false*/ 6 | Backbone.history.start(); 7 | new AppView(); 8 | }); 9 | -------------------------------------------------------------------------------- /backend/src/main/resources/static/js/views/app.view.js: -------------------------------------------------------------------------------- 1 | /*global define*/ 2 | define([ 3 | 'jquery', 4 | 'underscore', 5 | 'backbone' 6 | ], function ($, _, Backbone) { 7 | 'use strict'; 8 | 9 | var AppView = Backbone.View.extend({ 10 | 11 | el: '#content', 12 | 13 | initialize: function(){ 14 | this.render(); 15 | }, 16 | 17 | render: function(){ 18 | this.$el.html($("#message").val()); 19 | } 20 | }); 21 | 22 | return AppView; 23 | }); 24 | -------------------------------------------------------------------------------- /backend/src/main/resources/static/styles/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codechobostudy/code-chobo-study/07a1a52203ef6e077089729e2a232d7039472127/backend/src/main/resources/static/styles/.gitkeep -------------------------------------------------------------------------------- /backend/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Getting Started: Spring Boot CLI + Javascript 5 | 6 | 7 | 8 | 9 | 10 | 11 | Gooooood! 12 |
13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /backend/src/main/scala/io/codechobostudy/Application.scala: -------------------------------------------------------------------------------- 1 | package io.codechobostudy 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper 4 | import org.springframework.boot.SpringApplication 5 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration 6 | import org.springframework.boot.builder.SpringApplicationBuilder 7 | import org.springframework.boot.context.web.SpringBootServletInitializer 8 | import org.springframework.context.annotation.{Bean, ComponentScan, Configuration} 9 | import org.springframework.web.WebApplicationInitializer 10 | 11 | object Application extends App { 12 | SpringApplication.run(classOf[Application]) 13 | } 14 | 15 | @Configuration 16 | @EnableAutoConfiguration 17 | @ComponentScan 18 | class Application extends SpringBootServletInitializer with WebApplicationInitializer { 19 | 20 | protected override def configure(application: SpringApplicationBuilder): SpringApplicationBuilder = { 21 | application.sources(classOf[Application]) 22 | } 23 | 24 | @Bean 25 | def objectMapper() : ObjectMapper = { 26 | return new ObjectMapper() 27 | } 28 | } -------------------------------------------------------------------------------- /backend/src/main/scala/io/codechobostudy/config/SimpleCORSFilter.scala: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.config 2 | 3 | import javax.servlet.http.HttpServletResponse 4 | import javax.servlet._ 5 | 6 | import org.springframework.context.annotation.Profile 7 | import org.springframework.stereotype.Component 8 | 9 | @Component 10 | @Profile(Array("dev")) 11 | class SimpleCORSFilter extends Filter { 12 | 13 | def doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain) { 14 | val response = res.asInstanceOf[HttpServletResponse] 15 | response.setHeader("Access-Control-Allow-Origin", "*") 16 | response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE") 17 | response.setHeader("Access-Control-Max-Age", "3600") 18 | response.setHeader("Access-Control-Allow-Headers", "origin, x-requested-with, content-type, accept") 19 | chain.doFilter(req, res) 20 | } 21 | 22 | def init(filterConfig: FilterConfig) { 23 | } 24 | 25 | def destroy() { 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /backend/src/main/scala/io/codechobostudy/config/WebConfig.scala: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.config 2 | 3 | import org.springframework.beans.factory.annotation.{Autowired, Value} 4 | import org.springframework.context.annotation.{Bean, ComponentScan, Configuration} 5 | import org.springframework.core.env.Environment 6 | import org.springframework.web.servlet.config.annotation.{ResourceHandlerRegistry, ViewControllerRegistry, WebMvcConfigurerAdapter} 7 | import org.springframework.web.servlet.resource.{AppCacheManifestTransformer, ResourceUrlEncodingFilter, VersionResourceResolver} 8 | 9 | @Configuration 10 | @ComponentScan 11 | class WebConfig extends WebMvcConfigurerAdapter { 12 | 13 | private var environment: Environment = _ 14 | 15 | @Value("${app.version:}") 16 | private var appVersion: String = _ 17 | 18 | 19 | override def addViewControllers(registry: ViewControllerRegistry) { 20 | registry.addViewController("/").setViewName("index") 21 | } 22 | 23 | @Bean 24 | def resourceUrlEncodingFilter: ResourceUrlEncodingFilter = { 25 | new ResourceUrlEncodingFilter 26 | } 27 | 28 | override def addResourceHandlers(registry: ResourceHandlerRegistry ) { 29 | 30 | val isDevMode = environment.acceptsProfiles("dev") 31 | val pathPatterns = "/**" 32 | var cachePeriod: java.lang.Integer = null 33 | var useResourceCache = false 34 | 35 | val locations = "classpath:static/" 36 | 37 | if (isDevMode) { 38 | cachePeriod = 0 39 | useResourceCache = true 40 | } 41 | 42 | val appCacheTransformer = new AppCacheManifestTransformer 43 | val versionResolver = new VersionResourceResolver() 44 | //.addFixedVersionStrategy(getApplicationVersion, "/**/*.js", "/**/*.map") 45 | .addContentVersionStrategy("/**") 46 | 47 | registry.addResourceHandler(pathPatterns) 48 | .addResourceLocations(locations) 49 | .setCachePeriod(cachePeriod) 50 | .resourceChain(useResourceCache) 51 | .addResolver(versionResolver) 52 | .addTransformer(appCacheTransformer) 53 | } 54 | 55 | def getApplicationVersion : String = { 56 | return if (environment.acceptsProfiles("dev")) "dev" else appVersion 57 | } 58 | 59 | @Autowired 60 | def setEnvironment(environment: Environment) { 61 | this.environment = environment 62 | } 63 | } -------------------------------------------------------------------------------- /backend/src/main/scala/io/codechobostudy/home/controller/HomeController.scala: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.home.controller 2 | 3 | import org.springframework.ui.Model 4 | import org.springframework.web.bind.annotation.{RequestMapping, RestController} 5 | 6 | @RestController 7 | class HomeController { 8 | 9 | @RequestMapping(Array("/index")) 10 | def home (model: Model) = { 11 | model.addAttribute("message", "Hello World") 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /backend/src/main/scala/io/codechobostudy/sample/controller/SampleController.scala: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.sample.controller 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper 4 | import io.codechobostudy.sample.domain.SampleDomain 5 | import io.codechobostudy.sample.service.SampleService 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.web.bind.annotation.{RequestMethod, RequestBody, RequestMapping, RestController} 8 | 9 | @RestController 10 | @RequestMapping(Array("/api/sample")) 11 | class SampleController { 12 | 13 | @Autowired 14 | private var objectMapper: ObjectMapper = _ 15 | 16 | @Autowired 17 | private var categoryService: SampleService = _ 18 | 19 | @RequestMapping(value = Array( "/create"), method = Array(RequestMethod.POST)) 20 | def create(@RequestBody category: SampleDomain): String = { 21 | objectMapper.writeValueAsString(categoryService.create(category)) 22 | } 23 | 24 | @RequestMapping(value = Array("/update"), method = Array(RequestMethod.PUT)) 25 | def update(@RequestBody category: SampleDomain): String = { 26 | val updateCategory = categoryService.update(category) 27 | objectMapper.writeValueAsString(updateCategory) 28 | } 29 | 30 | @RequestMapping(Array("/")) 31 | def getAllCategory: String = { 32 | objectMapper.writeValueAsString(categoryService.getAllCategory) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /backend/src/main/scala/io/codechobostudy/sample/domain/BaseEntity.scala: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.sample.domain 2 | 3 | import java.util.Date 4 | import javax.persistence._ 5 | 6 | import com.fasterxml.jackson.annotation.JsonFormat 7 | 8 | import scala.beans.BeanProperty 9 | 10 | @MappedSuperclass 11 | class BaseEntity { 12 | 13 | @Id 14 | @GeneratedValue(strategy = GenerationType.AUTO) 15 | @BeanProperty 16 | var id: Long = _ 17 | 18 | @Column(name = "created_at") 19 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") 20 | @BeanProperty 21 | var createdAt: Date = _ 22 | 23 | @Column(name = "updated_at") 24 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") 25 | @BeanProperty 26 | var updatedAt: Date = _ 27 | 28 | @PrePersist 29 | def created = { 30 | this.updatedAt = new Date() 31 | this.createdAt = this.updatedAt 32 | } 33 | 34 | @PreUpdate 35 | def updated = { 36 | this.updatedAt = new Date() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /backend/src/main/scala/io/codechobostudy/sample/domain/SampleDomain.scala: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.sample.domain 2 | 3 | import javax.persistence.Entity 4 | import scala.beans.BeanProperty 5 | 6 | 7 | @Entity 8 | class SampleDomain extends BaseEntity{ 9 | 10 | @BeanProperty 11 | var categoryName: String = _ 12 | 13 | @BeanProperty 14 | var categoryDesc: String = _ 15 | } 16 | -------------------------------------------------------------------------------- /backend/src/main/scala/io/codechobostudy/sample/repository/SampleRepository.scala: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.sample.repository 2 | 3 | import io.codechobostudy.sample.domain.SampleDomain 4 | import org.springframework.data.jpa.repository.JpaRepository 5 | import java.lang.Long 6 | import java.util.List 7 | 8 | trait SampleRepository extends JpaRepository[SampleDomain, Long]{ 9 | 10 | def findByCategoryName(categoryName: String) : List[SampleDomain] 11 | 12 | } 13 | -------------------------------------------------------------------------------- /backend/src/main/scala/io/codechobostudy/sample/service/SampleService.scala: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.sample.service 2 | 3 | import io.codechobostudy.sample.domain.SampleDomain 4 | import io.codechobostudy.sample.repository.SampleRepository 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.stereotype.Service 7 | import org.springframework.transaction.annotation.Transactional 8 | 9 | @Service 10 | @Transactional 11 | class SampleService { 12 | 13 | @Autowired 14 | private var categoryRepository: SampleRepository = _ 15 | 16 | def create(category: SampleDomain): SampleDomain = { 17 | categoryRepository.save(category) 18 | } 19 | 20 | def update(category: SampleDomain): SampleDomain = { 21 | val updateCategory = categoryRepository.findOne(category.getId) 22 | updateCategory.setCategoryName(category.categoryName) 23 | updateCategory.setCategoryDesc(category.categoryDesc) 24 | 25 | categoryRepository.save(updateCategory) 26 | } 27 | 28 | def getAllCategory: java.util.List[SampleDomain] = { 29 | categoryRepository.findAll() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /backend/src/test/scala/io/codechobostudy/sample/controller/SampleControllerTest.java: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.sample.controller; 2 | 3 | import io.codechobostudy.sample.domain.SampleDomain; 4 | import io.codechobostudy.sample.repository.SampleRepository; 5 | import io.codechobostudy.sample.fixture.SampleBuilder; 6 | import io.codechobostudy.Application; 7 | 8 | import org.apache.http.HttpStatus; 9 | import org.junit.Before; 10 | import org.junit.Test; 11 | import org.junit.runner.RunWith; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.beans.factory.annotation.Value; 14 | import org.springframework.boot.test.IntegrationTest; 15 | import org.springframework.boot.test.SpringApplicationConfiguration; 16 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 17 | import org.springframework.test.context.web.WebAppConfiguration; 18 | 19 | import com.jayway.restassured.RestAssured; 20 | 21 | import static com.jayway.restassured.RestAssured.given; 22 | import static org.hamcrest.CoreMatchers.containsString; 23 | 24 | @RunWith(SpringJUnit4ClassRunner.class) 25 | @SpringApplicationConfiguration(classes = Application.class) 26 | @WebAppConfiguration 27 | @IntegrationTest("server.port:0") 28 | public class SampleControllerTest { 29 | 30 | @Autowired 31 | private SampleRepository sampleRepository; 32 | 33 | private static final String apiPrefixUrl = "/api/sample"; 34 | private static final String contentType = "application/json"; 35 | 36 | @Value("${local.server.port}") 37 | private int port; 38 | 39 | private SampleDomain paramSampleDomain; 40 | 41 | @Before 42 | public void setup(){ 43 | RestAssured.port = port; 44 | 45 | paramSampleDomain = SampleBuilder.anCategory() 46 | .withCategoryName("Test Category") 47 | .withCategoryDesc("Test Category Desc") 48 | .build(); 49 | } 50 | 51 | @Test 52 | public void test_sample_create(){ 53 | 54 | given() 55 | .contentType(contentType) 56 | .body(paramSampleDomain) 57 | .when() 58 | .post(apiPrefixUrl + "/create") 59 | .then() 60 | .statusCode(HttpStatus.SC_OK) 61 | .body(containsString(paramSampleDomain.getCategoryName())); 62 | } 63 | 64 | @Test 65 | public void test_sample_update(){ 66 | 67 | SampleDomain sampleDomain = sampleRepository.save(paramSampleDomain); 68 | sampleDomain.setCategoryName("Update Category"); 69 | 70 | given() 71 | .contentType(contentType) 72 | .body(sampleDomain) 73 | .when() 74 | .put(apiPrefixUrl + "/update") 75 | .then() 76 | .statusCode(HttpStatus.SC_OK) 77 | .body(containsString("Update Category")); 78 | } 79 | 80 | @Test 81 | public void test_sample_get_all(){ 82 | 83 | sampleRepository.save(paramSampleDomain); 84 | 85 | given() 86 | .when() 87 | .get(apiPrefixUrl+"/") 88 | .then() 89 | .statusCode(HttpStatus.SC_OK); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /backend/src/test/scala/io/codechobostudy/sample/domain/SampleDomainDomainTest.java: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.sample.domain; 2 | 3 | import io.codechobostudy.sample.domain.SampleDomain; 4 | import org.junit.Test; 5 | import static org.hamcrest.CoreMatchers.is; 6 | import static org.junit.Assert.*; 7 | 8 | public class SampleDomainDomainTest { 9 | 10 | @Test 11 | public void test_get_set_domain(){ 12 | 13 | SampleDomain sampleDomain = new SampleDomain(); 14 | sampleDomain.setId(1L); 15 | sampleDomain.setCategoryName("TEST"); 16 | 17 | assertThat(sampleDomain.getId(), is(1L)); 18 | assertThat(sampleDomain.getCategoryName(), is("TEST")); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /backend/src/test/scala/io/codechobostudy/sample/fixture/SampleBuilder.java: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.sample.fixture; 2 | 3 | import io.codechobostudy.sample.domain.SampleDomain; 4 | 5 | public class SampleBuilder { 6 | 7 | private String categoryName; 8 | private String categoryDesc; 9 | 10 | public static SampleBuilder anCategory(){ 11 | return new SampleBuilder(); 12 | } 13 | 14 | public SampleBuilder withCategoryName(String categoryName){ 15 | this.categoryName = categoryName; 16 | return this; 17 | } 18 | 19 | public SampleBuilder withCategoryDesc(String categoryDesc){ 20 | this.categoryDesc = categoryDesc; 21 | return this; 22 | } 23 | 24 | public SampleDomain build(){ 25 | SampleDomain sampleDomain = new SampleDomain(); 26 | sampleDomain.setCategoryName(this.categoryName); 27 | sampleDomain.setCategoryDesc(this.categoryDesc); 28 | return sampleDomain; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /backend/src/test/scala/io/codechobostudy/sample/repository/SampleRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.sample.repository; 2 | 3 | import io.codechobostudy.Application; 4 | import io.codechobostudy.sample.domain.SampleDomain; 5 | import io.codechobostudy.sample.fixture.SampleBuilder; 6 | import io.codechobostudy.sample.repository.SampleRepository; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.test.SpringApplicationConfiguration; 12 | import org.springframework.test.annotation.Rollback; 13 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 14 | import org.springframework.transaction.annotation.Transactional; 15 | 16 | import java.util.List; 17 | 18 | import static org.hamcrest.CoreMatchers.is; 19 | import static org.junit.Assert.*; 20 | 21 | @RunWith(SpringJUnit4ClassRunner.class) 22 | @SpringApplicationConfiguration(classes = Application.class) 23 | @Transactional 24 | public class SampleRepositoryTest { 25 | 26 | @Autowired 27 | private SampleRepository sampleRepository; 28 | 29 | SampleDomain sampleDomain1; 30 | SampleDomain sampleDomain2; 31 | 32 | @Before 33 | public void setup(){ 34 | 35 | sampleDomain1 = SampleBuilder 36 | .anCategory() 37 | .withCategoryName("Test") 38 | .withCategoryDesc("Test sample") 39 | .build(); 40 | 41 | sampleDomain2 = SampleBuilder 42 | .anCategory() 43 | .withCategoryName("Test2") 44 | .withCategoryDesc("Test sample") 45 | .build(); 46 | } 47 | 48 | @Test 49 | @Rollback 50 | public void test_sample_save(){ 51 | 52 | //when 53 | SampleDomain resultSampleDomain = sampleRepository.save(sampleDomain1); 54 | 55 | //then 56 | assertNotNull(resultSampleDomain.getId()); 57 | assertNotNull(resultSampleDomain.getCreatedAt()); 58 | assertThat(resultSampleDomain.getCategoryName(), is(sampleDomain1.getCategoryName())); 59 | } 60 | 61 | @Test 62 | @Rollback 63 | public void test_sample_update(){ 64 | 65 | //given 66 | SampleDomain sampleDomain = sampleRepository.save(sampleDomain1); 67 | Long categoryId = sampleDomain.getId(); 68 | 69 | //when 70 | sampleDomain.setCategoryName("UpdateName"); 71 | sampleRepository.save(sampleDomain1); 72 | 73 | //then 74 | assertThat(sampleDomain.getId(), is(categoryId)); 75 | assertThat(sampleDomain.getCategoryName(), is("UpdateName")); 76 | } 77 | 78 | @Test 79 | @Rollback 80 | public void test_find_by_name_one(){ 81 | 82 | //given 83 | sampleRepository.save(sampleDomain1); 84 | 85 | //when 86 | List categories = sampleRepository.findByCategoryName(sampleDomain1.getCategoryName()); 87 | 88 | //then 89 | assertThat(categories.size(), is(1)); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /backend/src/test/scala/io/codechobostudy/sample/service/SampleServiceTest.java: -------------------------------------------------------------------------------- 1 | package io.codechobostudy.sample.service; 2 | 3 | import io.codechobostudy.Application; 4 | import io.codechobostudy.sample.domain.SampleDomain; 5 | import io.codechobostudy.sample.repository.SampleRepository; 6 | import io.codechobostudy.sample.fixture.SampleBuilder; 7 | import io.codechobostudy.sample.service.SampleService; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.boot.test.SpringApplicationConfiguration; 13 | import org.springframework.test.annotation.Rollback; 14 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 15 | import org.springframework.transaction.annotation.Transactional; 16 | 17 | import java.util.List; 18 | 19 | import static org.hamcrest.CoreMatchers.is; 20 | import static org.junit.Assert.assertNotNull; 21 | import static org.junit.Assert.assertThat; 22 | 23 | @RunWith(SpringJUnit4ClassRunner.class) 24 | @SpringApplicationConfiguration(classes = Application.class) 25 | @Transactional 26 | public class SampleServiceTest { 27 | 28 | @Autowired 29 | private SampleService sampleService; 30 | 31 | @Autowired 32 | private SampleRepository sampleRepository; 33 | 34 | private SampleDomain sampleDomain1; 35 | 36 | @Before 37 | public void setup(){ 38 | 39 | sampleDomain1 = SampleBuilder 40 | .anCategory() 41 | .withCategoryName("Test") 42 | .withCategoryDesc("Test Category") 43 | .build(); 44 | } 45 | 46 | @Test 47 | @Rollback 48 | public void test_sample_save(){ 49 | 50 | //when 51 | SampleDomain resultSampleDomain = sampleService.create(sampleDomain1); 52 | 53 | //then 54 | assertNotNull(resultSampleDomain.getId()); 55 | assertNotNull(resultSampleDomain.getCreatedAt()); 56 | assertThat(resultSampleDomain.getCategoryName(), is(sampleDomain1.getCategoryName())); 57 | } 58 | 59 | @Test 60 | @Rollback 61 | public void test_sample_update(){ 62 | 63 | //given 64 | SampleDomain saveSampleDomain = sampleRepository.save(sampleDomain1); 65 | saveSampleDomain.setCategoryName("Update Category"); 66 | 67 | //when 68 | SampleDomain resultSampleDomain = sampleService.update(saveSampleDomain); 69 | 70 | //then 71 | assertThat(resultSampleDomain.getCategoryName(), is(saveSampleDomain.getCategoryName())); 72 | } 73 | 74 | @Test 75 | public void test_get_all_sample(){ 76 | 77 | //given 78 | sampleRepository.save(sampleDomain1); 79 | 80 | //when 81 | List categories = sampleService.getAllCategory(); 82 | 83 | //then 84 | assertThat(categories.size(), is(1)); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | 2 | 3 | buildscript { 4 | repositories { 5 | mavenLocal() 6 | mavenCentral() 7 | } 8 | dependencies { 9 | classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.3.RELEASE") 10 | } 11 | } 12 | 13 | configurations { 14 | providedRuntime 15 | } 16 | 17 | configure(allprojects) { project -> 18 | 19 | apply plugin: 'java' 20 | apply plugin: 'idea' 21 | apply plugin: 'eclipse-wtp' 22 | 23 | sourceCompatibility = 1.8 24 | compileJava.options.encoding = 'UTF-8' 25 | 26 | configurations { 27 | all*.exclude module: 'commons-logging' 28 | } 29 | repositories { 30 | mavenLocal() 31 | mavenCentral() 32 | } 33 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'codechobostudy' 2 | 3 | include 'backend' 4 | --------------------------------------------------------------------------------