Skip to content

Commit

Permalink
Added some more features
Browse files Browse the repository at this point in the history
  • Loading branch information
wakaleo committed Jun 14, 2015
1 parent e236be7 commit 2fa84b9
Show file tree
Hide file tree
Showing 14 changed files with 347 additions and 30 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.gradle
build/
target/

# Ignore Gradle GUI config
gradle-app.setting
Expand Down
14 changes: 14 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ dependencies {
compile("org.springframework.boot:spring-boot-starter-actuator")
compile("org.springframework.boot:spring-boot-starter-data-mongodb")
compile "org.apache.commons:commons-lang3:3.4"
// compile "com.mangofactory:swagger-springmvc:1.0.2"

compile 'io.springfox:springfox-swagger2:2.0.1'
compile 'io.springfox:springfox-swagger-ui:2.0.1'

// compile("org.springframework.boot:spring-boot-starter-data-rest")
// compile("org.springframework.boot:spring-boot-starter-integration")
Expand Down Expand Up @@ -71,3 +75,13 @@ eclipse {
task wrapper(type: Wrapper) {
gradleVersion = '2.3'
}

test {
exclude '**/integration/**'
maxParallelForks = 4
}

task integrationTests(type: Test) {
include '**/integration/**'
maxParallelForks = 4
}
33 changes: 27 additions & 6 deletions src/main/java/com/wakaleo/myflix/movies/MovieController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,27 @@
import com.wakaleo.myflix.movies.model.Movie;
import com.wakaleo.myflix.movies.model.MovieNotFound;
import com.wakaleo.myflix.movies.repository.MovieRepository;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

import static org.springframework.web.bind.annotation.RequestMethod.*;

import java.util.List;

import static org.apache.commons.lang3.text.WordUtils.capitalizeFully;

@RestController
@RequestMapping("/movies")
@Api(value = "/movies", description = "Movie catalog")
public class MovieController {

@Autowired
private MovieRepository repository;

@RequestMapping("/movies/{id}")
@RequestMapping(value = "/{id}", method=GET)
@ApiOperation(value = "Find a specific movie", httpMethod="GET")
public Movie findById(@PathVariable String id) {
Movie movie = repository.findOne(id);
if (movie == null) {
Expand All @@ -27,14 +32,30 @@ public Movie findById(@PathVariable String id) {
return movie;
}

@RequestMapping("/movies/findByDirector/{director}")
@RequestMapping(value="/findByDirector/{director}", method=GET)
@ApiOperation(value = "Find movies from a given director",
httpMethod="GET",
response = Movie.class,
responseContainer = "List")
public List<Movie> findByDirector(@PathVariable String director) {
return repository.findByDirector(capitalizeFully(director.trim()));
}

@RequestMapping("/movies")
@RequestMapping(method=GET)
@ApiOperation("List all the movies in the catalog")
public List<Movie> findAll() {
return repository.findAll();
}

@RequestMapping(method=POST)
@ApiOperation(value = "Add a new movie to the catalog", httpMethod = "POST")
public Movie add(@RequestBody Movie newMovie) {
return repository.save(newMovie);
}

@RequestMapping(value = "/{id}", method=DELETE)
@ApiOperation(value = "Removing a movie from the catalog", httpMethod = "POST")
public void delete(@PathVariable String id) {
repository.delete(id);
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,90 @@
package com.wakaleo.myflix.movies;

import com.fasterxml.classmate.TypeResolver;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.async.DeferredResult;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.schema.WildcardType;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.List;

import static com.google.common.collect.Lists.newArrayList;
import static springfox.documentation.schema.AlternateTypeRules.newRule;

//@SpringBootApplication
@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableSwagger2
public class MovieServiceApplication {

public static void main(String[] args) {
SpringApplication.run(MovieServiceApplication.class, args);
}

@Bean
public Docket petApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.pathMapping("/")
.directModelSubstitute(LocalDate.class,
String.class)
.genericModelSubstitutes(ResponseEntity.class)
.alternateTypeRules(
newRule(typeResolver.resolve(DeferredResult.class,
typeResolver.resolve(ResponseEntity.class, WildcardType.class)),
typeResolver.resolve(WildcardType.class)))
.useDefaultResponseMessages(false)
.globalResponseMessage(RequestMethod.GET,
newArrayList(new ResponseMessageBuilder()
.code(500)
.message("500 message")
.responseModel(new ModelRef("Error"))
.build()))
// .securitySchemes(newArrayList(apiKey()))
// .securityContexts(newArrayList(securityContext()))
;
}

@Autowired
private TypeResolver typeResolver;

// private ApiKey apiKey() {
// return new ApiKey("mykey", "api_key", "header");
// }
//
// private SecurityContext securityContext() {
// return SecurityContext.builder()
// .securityReferences(defaultAuth())
// .forPaths(PathSelectors.regex("/movies.*"))
// .build();
// }
//
// List<SecurityReference> defaultAuth() {
// AuthorizationScope authorizationScope
// = new AuthorizationScope("global", "accessEverything");
// AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
// authorizationScopes[0] = authorizationScope;
// return newArrayList(new SecurityReference("mykey", authorizationScopes));
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.wakaleo.myflix.movies

import com.wakaleo.myflix.movies.repository.MovieRepository
import spock.lang.Specification
import spock.lang.Unroll


class MovieControllerSpecs extends Specification {

MovieRepository movieRepository = Mock()

@Unroll
def "should find by director regardless of case (#director -> #filteredDirector)"() {
given:
def controller = new MovieController(repository: movieRepository)
when:
controller.findByDirector(director)
then:
1*movieRepository.findByDirector(filteredDirector)
where:
director | filteredDirector
"Clint Eastwood" | "Clint Eastwood"
"Clint eastwood" | "Clint Eastwood"
"clint eastwood" | "Clint Eastwood"
" clint eastwood " | "Clint Eastwood"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.wakaleo.myflix.movies.integration;

import com.jayway.restassured.RestAssured
import com.wakaleo.myflix.movies.MovieServiceApplication
import com.wakaleo.myflix.movies.model.Movie;
import com.wakaleo.myflix.movies.repository.MovieRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationContextLoader;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;
import spock.lang.Specification

import static com.jayway.restassured.RestAssured.when;

@ContextConfiguration(loader = SpringApplicationContextLoader.class,
classes = MovieServiceApplication.class)
@WebAppConfiguration
@IntegrationTest("server.port:0")
class WhenFindingMoviesViaTheRestAPI extends Specification {

@Autowired
MovieRepository movieRepository;

@Value('${local.server.port}')
int port;

def GLADIATOR = new Movie(title:"Gladiator", director:"Ridley Scott",
description:"Sword and sandles", actors:["Russel Crowe","Joaquin Phoenix"]);
def LETTERS_FROM_IWO_JIMA = new Movie(title:"Letters from Iwo Jima", director:"Clint Eastwood",
description:"The story of the battle of Iwo Jima...", actors:["Ken Watanabe"]);
def GRAN_TORINO = new Movie(title:"Gran Torino", director:"Clint Eastwood",
description:"Disgruntled Korean War veteran", actors:[["Clint Eastwood", "Bee Vang"]]);

def setup() {
movieRepository.deleteAll();
RestAssured.port = port;
}

def "should list all movies"() {
given:
movieCatalogContains([GLADIATOR, LETTERS_FROM_IWO_JIMA, GRAN_TORINO])
when:
def movies = when().get("/movies").as(List)
then:
!movies.isEmpty()
}

def "should return empty list if the catalog is empty"() {
given:
movieCatalogContains([])
when:
def movies = when().get("/movies").as(List)
then:
movies.isEmpty()
}

def "should list movies by director"() {
given:
movieCatalogContains([GLADIATOR, LETTERS_FROM_IWO_JIMA, GRAN_TORINO])
when:
List<Movie> movies = when().get("/movies/findByDirector/Clint Eastwood").as(List)
then:
movies.collect {movie -> movie.title} == ["Letters from Iwo Jima", "Gran Torino"]
}

def "should return empty list if no matching films found"() {
given:
movieCatalogContains([GLADIATOR, LETTERS_FROM_IWO_JIMA, GRAN_TORINO])
when:
List<Movie> movies = when().get("/movies/findByDirector/Peter Jackson").as(List)
then:
movies.isEmpty()
}

def movieCatalogContains(List<Movie> movies) {
movieRepository.save(movies)
}


}
17 changes: 0 additions & 17 deletions src/test/java/com/wakaleo/myflix/MovieServiceApplicationTests.java

This file was deleted.

10 changes: 10 additions & 0 deletions src/test/java/com/wakaleo/myflix/movies/features/Catalog.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.wakaleo.myflix.movies.features;

import cucumber.api.CucumberOptions;
import net.serenitybdd.cucumber.CucumberWithSerenity;
import org.junit.runner.RunWith;

@RunWith(CucumberWithSerenity.class)
@CucumberOptions(features="src/test/resources/features/catalog")
public class Catalog {
}
4 changes: 0 additions & 4 deletions src/test/java/com/wakaleo/myflix/movies/features/Search.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
import cucumber.api.CucumberOptions;
import net.serenitybdd.cucumber.CucumberWithSerenity;
import org.junit.runner.RunWith;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationContextLoader;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;

@RunWith(CucumberWithSerenity.class)
@CucumberOptions(features="src/test/resources/features/search")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.wakaleo.myflix.movies.MovieServiceApplication;
import com.wakaleo.myflix.movies.model.Movie;
import com.wakaleo.myflix.movies.repository.MovieRepository;
import net.serenitybdd.core.Serenity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationContextLoader;
import org.springframework.test.context.ContextConfiguration;
Expand All @@ -20,6 +21,12 @@ public class MovieCatalog {

public void hasTheFollowingMovies(List<Movie> movies) {
movieRepository.deleteAll();
movieRepository.save(movies);
Serenity.setSessionVariable("savedMovies").to(movieRepository.save(movies));
}

public String getIdForMovieWithTitle(String title) {
List<Movie> savedMovies = (List<Movie>) Serenity.sessionVariableCalled("savedMovies");
return savedMovies.stream().filter(movie -> movie.getTitle().equals(title))
.findFirst().get().getId();
}
}
Loading

0 comments on commit 2fa84b9

Please sign in to comment.