diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..631767f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "pandora"] + path = pandora + url = https://github.com/hex-g/pandora.git diff --git a/README.md b/README.md index 9d4bc68..00d7329 100644 --- a/README.md +++ b/README.md @@ -1 +1,56 @@ # player +--- +**The profile data API** + +*"A person in its life is as a player."* + +### First steps +(Configuring the environment): + +1. git clone https://github.com/hex-g/player.git + 1. cd player +2. git checkout [branch] +3. git submodule init +4. git submodule update +5. Run the project in your IDE +--- +### Usage +> URL: `http://localhost:9600/` + +#### ![#c5f015](https://placehold.it/15/c5f015/000000?text=+) `GET` +If an request profile data does not exist then a new one be created. +* `header` + * *key*: `authenticated-user-id` + * *value*: [string] + +#### ![#1589F0](https://placehold.it/15/1589F0/000000?text=+) `POST` +Inserts a new profile data or updates an existent. +* `header` + * *key*: `authenticated-user-id` + * *value*: [string] +* `body JSON` + * *value*: + ``` + { + "loginAlias": string, + "email": string, + "telnumber": string, + "flavorText": string, + "birthday": string, + "options": { + "laurel_wreath": string, + "honorific": string, + "darkmode": string["on"/"off"], + "notify_hiveshare": string["on"/"off"], + "notify_hivecentral": string["on"/"off"], + "notify_disciplines": string["on"/"off"] + }, + "social": { + "github": string, + "linkedIn": string, + "twitter": string + } + } + ``` + + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..80dc266 --- /dev/null +++ b/build.gradle @@ -0,0 +1,69 @@ +buildscript { + ext { + springBootVersion = '2.1.3.RELEASE' + springCloudVersion = 'Greenwich.SR1' + } + repositories { + mavenCentral() + maven { url 'https://repo.spring.io/milestone' } + } + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}" as Object + classpath "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" as Object + } +} + +plugins { + id "io.spring.dependency-management" version "1.0.5.RELEASE" + id 'java' + id 'org.springframework.boot' version '2.1.3.RELEASE' +} + +apply plugin: 'groovy' +apply plugin: 'io.spring.dependency-management' + +group = 'hive' +version = '0.0.1-SNAPSHOT' +sourceCompatibility = '11' + +repositories { + mavenCentral() + maven { url 'https://repo.spring.io/milestone' } +} + +dependencies { + implementation project(':pandora') + + implementation 'javax.xml.bind:jaxb-api:2.3.1' + implementation 'javax.activation:activation:1.1.1' + implementation 'org.glassfish.jaxb:jaxb-runtime:2.3.2' + //production db: + //implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.16' + //development db: + implementation 'com.h2database:h2' + + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' + implementation 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.1' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + + compile 'io.springfox:springfox-swagger2:2.9.2' + compile 'io.springfox:springfox-swagger-ui:2.9.2' + + testCompile( + 'org.hamcrest:hamcrest-core:1.3',//if not using delete this + 'org.spockframework:spock-core:1.3-groovy-2.5', + 'org.spockframework:spock-spring:1.3-groovy-2.5' + ) +} + +dependencyManagement { + imports { + mavenBom "org.springframework.boot:spring-boot-dependencies:${springBootVersion}" + mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" + } +} +bootJar(){ + launchScript() +} diff --git a/pandora b/pandora new file mode 160000 index 0000000..1d677c4 --- /dev/null +++ b/pandora @@ -0,0 +1 @@ +Subproject commit 1d677c43f5dc204545eb66de763f9ea4c84382de diff --git a/settings.gradle b/settings.gradle index 1b12350..7683048 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,10 +1,3 @@ -/* - * This file was generated by the Gradle 'init' task. - * - * The settings file is used to specify which projects to include in your build. - * - * Detailed information about configuring a multi-project build in Gradle can be found - * in the user manual at https://docs.gradle.org/5.2.1/userguide/multi_project_builds.html - */ - rootProject.name = 'player' +include 'pandora' +include 'ishigami' diff --git a/src/main/java/hive/player/PlayerApplication.java b/src/main/java/hive/player/PlayerApplication.java new file mode 100644 index 0000000..f34049a --- /dev/null +++ b/src/main/java/hive/player/PlayerApplication.java @@ -0,0 +1,14 @@ +package hive.player; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.context.annotation.PropertySource; + +@SpringBootApplication +@EnableEurekaClient +public class PlayerApplication { + public static void main(String[] args) { + SpringApplication.run(PlayerApplication.class, args); + } +} diff --git a/src/main/java/hive/player/controller/PlayerController.java b/src/main/java/hive/player/controller/PlayerController.java new file mode 100644 index 0000000..240d5c4 --- /dev/null +++ b/src/main/java/hive/player/controller/PlayerController.java @@ -0,0 +1,62 @@ +package hive.player.controller; + +import static hive.pandora.constant.HiveInternalHeaders.*; + +import hive.player.entity.Player; +import hive.player.exception.PlayerIdShouldNotBeInJsonException; +import hive.player.repository.PlayerRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/") +public class PlayerController { + private final PlayerRepository playerRepository; + + @Autowired + public PlayerController(final PlayerRepository playerRepository) { + this.playerRepository = playerRepository; + } + + @GetMapping + public Player retrieveProfileData( + @RequestHeader(name = AUTHENTICATED_USER_ID) final String authenticatedUserId + ) { + return createAnPlayerInDatabaseIfNotExists(authenticatedUserId); + } + + @PostMapping + public void insertProfileData( + @RequestHeader(name = AUTHENTICATED_USER_ID) final String authenticatedUserId, + @RequestBody final Player player + ) { + if(player.getPlayerId() != null){ + throw new PlayerIdShouldNotBeInJsonException(); + } + updatePlayerCorrelatedWithTheAuthenticatedId(player, authenticatedUserId); + player.setAuthenticatedUserId(authenticatedUserId); + playerRepository.save(player); + } + + private Player createAnPlayerInDatabaseIfNotExists(final String authenticatedUserId) { + var player = playerRepository.findByAuthenticatedUserId(authenticatedUserId); + if (player == null) { + player = new Player(authenticatedUserId); + playerRepository.save(player); + } + return player; + } + + private void updatePlayerCorrelatedWithTheAuthenticatedId( + final Player player, + final String authenticatedUserId + ) { + final var playerFound=playerRepository.findByAuthenticatedUserId(authenticatedUserId); + if(playerFound != null) { + final var autogeneratedPlayerId = playerFound.getPlayerId(); + if (autogeneratedPlayerId != null) { + player.setPlayerId(autogeneratedPlayerId); + } + } + } +} diff --git a/src/main/java/hive/player/entity/Player.java b/src/main/java/hive/player/entity/Player.java new file mode 100644 index 0000000..642af4e --- /dev/null +++ b/src/main/java/hive/player/entity/Player.java @@ -0,0 +1,86 @@ +package hive.player.entity; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +@Entity +@Table(name = "tb_user_profile") +public class Player { + @Id + @JsonProperty + @GeneratedValue(strategy = GenerationType.IDENTITY) + //is some DBMS like Oracle you should change the strategy + private Integer playerId; + @JsonIgnore + private String authenticatedUserId; + + @JsonProperty + @Column(name = "login_alias", unique = true) + private String loginAlias; + @JsonProperty + @Column(name = "email") + private String email; + @JsonProperty + @Column(name = "telnumber") + private String telnumber; + @JsonProperty + @Column(name = "flavor_text") + private String flavorText; + @JsonProperty + @Column(name = "birthday") + private String birthday; + + @Embedded + @JsonProperty + @Column(name = "options") + private PlayerOptions options; + @Embedded + @JsonProperty + @Column(name = "social") + private PlayerSocial social; + + public Integer getPlayerId() { + return playerId; + } + + public void setPlayerId(final Integer playerId) { + this.playerId = playerId; + } + + public String getAuthenticatedUserId() { + return authenticatedUserId; + } + + public void setAuthenticatedUserId(@NotNull final String authenticatedUserId) { + this.authenticatedUserId = authenticatedUserId; + } + + private Player() { + } + + public Player( + @NotNull final String authenticatedUserId, + final String loginAlias, + final String email, + final String telNumber, + final String flavorText, + final String birthday, + final PlayerOptions options, + final PlayerSocial social + ) { + setAuthenticatedUserId(authenticatedUserId); + this.loginAlias = loginAlias; + this.email = email; + this.telnumber = telNumber; + this.flavorText = flavorText; + this.birthday = birthday; + this.options = options; + this.social = social; + } + public Player(@NotNull final String authenticatedUserId){ + setAuthenticatedUserId(authenticatedUserId); + } +} diff --git a/src/main/java/hive/player/entity/PlayerOptions.java b/src/main/java/hive/player/entity/PlayerOptions.java new file mode 100644 index 0000000..2a68f29 --- /dev/null +++ b/src/main/java/hive/player/entity/PlayerOptions.java @@ -0,0 +1,30 @@ +package hive.player.entity; + +import javax.persistence.Embeddable; + +@Embeddable +public class PlayerOptions { + public String laurel_wreath; + public String honorific; + public Boolean darkmode; + public Boolean notify_hiveshare; + public Boolean notify_hivecentral; + public Boolean notify_disciplines; + + public PlayerOptions( + final String laurel_wreath, + final String honorific, + final Boolean darkmode, + final Boolean notify_hiveshare, + final Boolean notify_hivecentral, + final Boolean notify_disciplines + ) { + this.laurel_wreath = laurel_wreath; + this.honorific = honorific; + this.darkmode = darkmode; + this.notify_hiveshare = notify_hiveshare; + this.notify_hivecentral = notify_hivecentral; + this.notify_disciplines = notify_disciplines; + } + public PlayerOptions(){} +} diff --git a/src/main/java/hive/player/entity/PlayerSocial.java b/src/main/java/hive/player/entity/PlayerSocial.java new file mode 100644 index 0000000..0639b67 --- /dev/null +++ b/src/main/java/hive/player/entity/PlayerSocial.java @@ -0,0 +1,17 @@ +package hive.player.entity; + +import javax.persistence.Embeddable; + +@Embeddable +public class PlayerSocial { + public String github; + public String linkedIn; + public String twitter; + + public PlayerSocial(final String github, final String linkedIn, final String twitter) { + this.github = github; + this.linkedIn = linkedIn; + this.twitter = twitter; + } + public PlayerSocial() {} +} diff --git a/src/main/java/hive/player/exception/BlankIdException.java b/src/main/java/hive/player/exception/BlankIdException.java new file mode 100644 index 0000000..93abe73 --- /dev/null +++ b/src/main/java/hive/player/exception/BlankIdException.java @@ -0,0 +1,8 @@ +package hive.player.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "The Authenticated user id can not be blank") +public class BlankIdException extends RuntimeException{ +} diff --git a/src/main/java/hive/player/exception/PlayerIdShouldNotBeInJsonException.java b/src/main/java/hive/player/exception/PlayerIdShouldNotBeInJsonException.java new file mode 100644 index 0000000..dfa1a1a --- /dev/null +++ b/src/main/java/hive/player/exception/PlayerIdShouldNotBeInJsonException.java @@ -0,0 +1,8 @@ +package hive.player.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "The autogenerated playerId should not be in JSON") +public class PlayerIdShouldNotBeInJsonException extends RuntimeException{ +} diff --git a/src/main/java/hive/player/repository/PlayerRepository.java b/src/main/java/hive/player/repository/PlayerRepository.java new file mode 100644 index 0000000..b17568a --- /dev/null +++ b/src/main/java/hive/player/repository/PlayerRepository.java @@ -0,0 +1,13 @@ +package hive.player.repository; + +import hive.player.entity.Player; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +@Repository +public interface PlayerRepository extends JpaRepository { + + Player findByAuthenticatedUserId(final String authenticatedUserId); + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..72c5d08 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,16 @@ +spring.application.name=player-service +server.port=9600 +eureka.client.service-url.default-zone=http://localhost:8761/eureka +# H2 +spring.h2.console.enabled=true +spring.h2.console.path=/h2 +# Datasource +spring.datasource.url=jdbc:h2:file:./db/projeto-pw;AUTO_SERVER=TRUE +spring.datasource.username=sa +spring.datasource.password= +spring.datasource.driver-class-name=org.h2.Driver +spring.jpa.hibernate.ddl-auto=create-drop +#spring.jpa.hibernate.ddl-auto=create +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.format_sql=true +logging.level.org.hibernate.type=trace diff --git a/src/test/groovy/hive/player/PlayerApplicationSpec.groovy b/src/test/groovy/hive/player/PlayerApplicationSpec.groovy new file mode 100644 index 0000000..42f3071 --- /dev/null +++ b/src/test/groovy/hive/player/PlayerApplicationSpec.groovy @@ -0,0 +1,4 @@ +package hive.player + +class PlayerApplicationSpec{ +} diff --git a/src/test/groovy/hive/player/controller/PlayerControllerIntegrationTest.groovy b/src/test/groovy/hive/player/controller/PlayerControllerIntegrationTest.groovy new file mode 100644 index 0000000..a674a93 --- /dev/null +++ b/src/test/groovy/hive/player/controller/PlayerControllerIntegrationTest.groovy @@ -0,0 +1,123 @@ +package hive.player.controller + +import hive.player.repository.PlayerRepository +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import spock.lang.Shared +import spock.lang.Specification +import groovyx.net.http.ContentType +import groovyx.net.http.RESTClient + +import static hive.pandora.constant.HiveInternalHeaders.* + +class PlayerControllerIntegrationTest extends Specification { + + @Shared + def integrationTestHeaderValue="INTEGRATION" + @Shared + RESTClient client + + def setup(){ + client = new RESTClient("${urlBase}", ContentType.JSON) + client.handler.failure = { resp, data -> resp.setData(data); return resp } + } + + def urlBase = 'http://localhost:9600/' + + def validProfileDataJson = $/ + { + "loginAlias": "Integration_Test", + "email": "integration@test.com", + "telnumber": "11987654321", + "flavorText": "Large string Lorem Ipsum dolor aquicumsitum amet", + "birthday": "21/04/1998", + "options": { + "laurel_wreath": "CHALLENGER", + "honorific": "Coffee Titan", + "darkmode": "true", + "notify_hiveshare": "true", + "notify_hivecentral": "true", + "notify_disciplines": "true" + }, + "social": { + "github": "git", + "linkedIn": "linkedin", + "twitter": "@twitter" + } + } + /$ + + def cleanupSpec(){ + //should have some delete method in the original application + } + + def 'Perform GET with correct header and expect HttpStatus OK'() { + + given: + def response = client.get( + headers: ["$AUTHENTICATED_USER_ID": "${integrationTestHeaderValue}"]) + + expect: + response.status == 200 + } + + def 'Perform POST with valid Json and expect HttpStatus OK'() { + + given: + def response = client.post( + headers: ["$AUTHENTICATED_USER_ID": "${integrationTestHeaderValue}"], + body: "$validProfileDataJson") + + expect: + response.status == 200 + } + + def 'Perform GET with wrong Header key and expect HttpStatus BAD REQUEST'() { + + given: + def response = client.get( + headers: ['wrong_key': "${integrationTestHeaderValue}"]) + + expect: + response.status == 400 + } + + def 'Perform POST with wrong Header key and expect HttpStatus BAD REQUEST'() { + + given: + def response = client.post( + headers: ["wrong_key": '1']) + + expect: + response.status == 400 + } + + def 'Perform POST with empty body request and expect HttpStatus BAD REQUEST'() { + + given: + def response = client.post( + headers: ["$AUTHENTICATED_USER_ID": "${integrationTestHeaderValue}"]) + + expect: + response.status == 400 + } + + def ''' + Given Json containing playerId, + when user profile data is inserted, + then HttpStatus BAD REQUEST + '''() { + + given: + def invalidProfileDataJson='{"playerId": 10}' + + when: + def response = client.post( + headers: ["$AUTHENTICATED_USER_ID": "${integrationTestHeaderValue}"], + body: ["$invalidProfileDataJson"]) + + then: + response.status == 400 + } + +} diff --git a/src/test/groovy/hive/player/controller/PlayerControllerUnitTest.groovy b/src/test/groovy/hive/player/controller/PlayerControllerUnitTest.groovy new file mode 100644 index 0000000..92aebc2 --- /dev/null +++ b/src/test/groovy/hive/player/controller/PlayerControllerUnitTest.groovy @@ -0,0 +1,211 @@ +package hive.player.controller + + +import hive.player.entity.Player +import hive.player.entity.PlayerOptions +import hive.player.repository.PlayerRepository +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import spock.lang.Shared +import spock.lang.Specification + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.* +import static hive.pandora.constant.HiveInternalHeaders.AUTHENTICATED_USER_ID + +class PlayerControllerUnitTest extends Specification { + + def urlBase = 'http://localhost:9600/' + @Shared Player player + MockMvc mockMvc + PlayerRepository playerRepository = Mock() + + def validProfileDataJson = ''' + { + "loginAlias": "custom2", + "email": "email", + "telnumber": "11985055502", + "flavorText": "String grande Lorem Ipsum dolor aquicumsitum amet", + "birthday": "21/04/1998", + "options": { + "laurel_wreath": "ouro", + "honorific": "titan do café", + "darkmode": "true", + "notify_hiveshare": "true", + "notify_hivecentral": "true", + "notify_disciplines": "true" + }, + "social": { + "github": "git", + "linkedIn": "linkedin", + "twitter": "@twitter" + } + } + ''' + def setup(){ + createAnPlayer() + mockMvc = MockMvcBuilders.standaloneSetup(new PlayerController(playerRepository)).build() + } + + def createAnPlayer(){ + def options = new PlayerOptions( + "gold", + "Coffee Titan", + true, + true, + true, + true) + player = new Player( + "CompletePlayer", + "alias", + "email", + "11985054202", + "Some flavor text", + "21/04/1998", + options, + null) + } + + def "Should return BAD REQUEST when POST a Json with playerId"(){ + + given:"a JSON containing playerId" + def invalidProfileDataJson='{"playerId":10}' + + when:"perform POST" + def response = + mockMvc.perform(post("$urlBase") + .header(AUTHENTICATED_USER_ID,1) + .contentType('application/json') + .content(invalidProfileDataJson)) + .andReturn() + .getResponse() + + then:"HttpResponse as BAD REQUEST" + response.getStatus()==400 + response.getErrorMessage()=="The autogenerated playerId should not be in JSON" + + } + + def ''' + Given profile options with valid values in boolean fields, + when perform POST, + then HttpResponse as BAD REQUEST. + '''(){ + + given: + def validProfileOptionsJson= $/ + { + "options": { + "laurel_wreath": "ouro", + "honorific": "titan do café", + "darkmode": $validBooleanValues, + "notify_hiveshare": $validBooleanValues, + "notify_hivecentral": $validBooleanValues, + "notify_disciplines": $validBooleanValues + } + } + /$ + + when: + def response = + mockMvc.perform(post("$urlBase") + .header(AUTHENTICATED_USER_ID,1) + .contentType('application/json') + .content(validProfileOptionsJson)) + .andReturn() + .getResponse() + + then: + response.getStatus()==200 + + where: + validBooleanValues << ['\"True\"', '\"true\"', true, 1, '\"False\"', '\"false\"', false, 0] + } + + def ''' + Given profile options with string values in boolean fields, + when perform POST, + then HttpResponse as BAD REQUEST. + '''(){ + + given: + def invalidProfileOptionsJson= $/ + { + "options": { + "laurel_wreath": "ouro", + "honorific": "titan do café", + "darkmode": $testedStringValues, + "notify_hiveshare": $testedStringValues, + "notify_hivecentral": $testedStringValues, + "notify_disciplines": $testedStringValues + } + } + /$ + + when: + def response = + mockMvc.perform(post("$urlBase") + .header(AUTHENTICATED_USER_ID,1) + .contentType('application/json') + .content(invalidProfileOptionsJson)) + .andReturn() + .getResponse() + then: + response.getStatus() == 400 + + where: + testedStringValues << ['\"TrUe\"', '\"FALSE\"', '\"Something\"'] + } + + def ''' + Given correct header key, + when perform GET, + then HttpResponse as OK. + Where header value accepts numbers or string to query. + '''(){ + + given: + def headerKey=AUTHENTICATED_USER_ID + + when: + def response=mockMvc.perform(get("$urlBase") + .header(headerKey,val)) + .andReturn() + .getResponse() + + then: + response.getStatus()==200 + + where: + val | _ + 1 | _ + "2" | _ + + } + + def ''' + Given correct header key, + when perform POST with valid json, + then HttpResponse as OK. + Where header value accepts numbers or string to query. + '''(){ + + given: + def headerKey=AUTHENTICATED_USER_ID + + when: + def response=mockMvc.perform(post("$urlBase") + .header(headerKey,val) + .contentType('application/json') + .content(validProfileDataJson)) + .andReturn().getResponse() + + then: + response.getStatus()==200 + + where: + val | _ + 1 | _ + "2" | _ + + } +} diff --git a/src/test/groovy/hive/player/entity/PlayerSpec.groovy b/src/test/groovy/hive/player/entity/PlayerSpec.groovy new file mode 100644 index 0000000..ddb3342 --- /dev/null +++ b/src/test/groovy/hive/player/entity/PlayerSpec.groovy @@ -0,0 +1,32 @@ +package hive.player.entity + +import hive.player.exception.BlankIdException +import spock.lang.Specification + +class PlayerSpec extends Specification{ + + def "Should not accept blank value as authenticated user id in constructor"(){ + when: + new Player(blankValues) + + then: + thrown BlankIdException + + where: + blankValues<<[""," "] + } + + def "Should not set blank value into authenticated user Id"(){ + + when: + def player = new Player() + player.setAuthenticatedUserId(blankValues) + + then: + thrown BlankIdException + + where: + blankValues<<[""," "] + } + +} diff --git a/src/test/groovy/hive/player/repository/PlayerRepositorySpec.groovy b/src/test/groovy/hive/player/repository/PlayerRepositorySpec.groovy new file mode 100644 index 0000000..d73a80f --- /dev/null +++ b/src/test/groovy/hive/player/repository/PlayerRepositorySpec.groovy @@ -0,0 +1,139 @@ +package hive.player.repository + +import hive.player.entity.Player +import hive.player.entity.PlayerOptions +import hive.player.entity.PlayerSocial + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest + +import spock.lang.Shared +import spock.lang.Specification + +@DataJpaTest +class PlayerRepositorySpec extends Specification { + + @Shared + Player player + @Shared + def existentAuthIdList = [] + @Shared + private PlayerRepository playerRepository + + def createACompletePlayer(){ + def social = new PlayerSocial() + def options = new PlayerOptions( + "gold", + "Coffee Titan", + true, + true, + true, + true) + player = new Player( + "CompletePlayer", + "alias", + "email", + "11985054202", + "Some flavor text", + "21/04/1998", + options, + social) + return player + } + + def createEmptyPlayers(int quantity){ + quantity.times { + playerRepository.save new Player(it.toString()) + existentAuthIdList+=it.toString() + } + } + @Autowired(required = true) + def initRepo(PlayerRepository playerRepository){ + this.playerRepository=playerRepository + } + + def setupSpec(){ + initRepo(playerRepository) + } + + def setup() { + createEmptyPlayers 1 + } + + def cleanup() { + playerRepository.deleteAll() + } + + def ''' + Given an player with complete data, + when create this player, + then all player information should have persisted. + '''() { + + given: + def playerToPersist = createACompletePlayer() + def authenticatedId = playerToPersist.getAuthenticatedUserId() + + when: + playerRepository.save playerToPersist + def persistedPlayer = playerRepository.findByAuthenticatedUserId authenticatedId + + then: + player == persistedPlayer + } + + def ''' + Given existent authenticatedUserId, + when search in database, + then the player exists. + '''() { + + given: + def authenticatedId = existentAuthenticatedId + + when: + def persistedPlayer = playerRepository.findByAuthenticatedUserId authenticatedId + + then: + persistedPlayer != null + + where: + existentAuthenticatedId << existentAuthIdList + } + + def ''' + Given not existent authenticatedUserId, + when search in database, + then the player not exists. + '''() { + + given: + def authenticatedId = "-1" + + when: + def persistedPlayer = playerRepository.findByAuthenticatedUserId authenticatedId + + then: + persistedPlayer == null + } + + + def ''' + Given existent authenticatedUserId, + when search in database, + then the found player have a not null playerId. + '''() { + + given: + def authenticatedId = existentAuthenticatedId + + when: + def persistedPlayer = playerRepository.findByAuthenticatedUserId authenticatedId + + then: + persistedPlayer.getPlayerId() != null + + where: + existentAuthenticatedId << existentAuthIdList + } +} diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000..0de31d7 --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,4 @@ +# Properties for disabling Spring DEBUG & INFO log below Spring banner +logging.level.org.springframework=OFF +logging.level.root=OFF +spring.main.banner-mode=OFF diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml new file mode 100644 index 0000000..4b588a4 --- /dev/null +++ b/src/test/resources/logback-test.xml @@ -0,0 +1,6 @@ + + + + + +