Revert "Merge branch 'backend' into 'main'"
This reverts merge request !2
This commit is contained in:
parent
79fa5d5f8b
commit
07d3fe304d
7 changed files with 0 additions and 899 deletions
|
|
@ -1,130 +0,0 @@
|
|||
package server.api;
|
||||
|
||||
import commons.Recipe;
|
||||
|
||||
import org.springframework.data.domain.Example;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import server.database.RecipeRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class RecipeController {
|
||||
private final RecipeRepository recipeRepository; // JPA repository used in this controller
|
||||
|
||||
public RecipeController(RecipeRepository recipeRepository) {
|
||||
this.recipeRepository = recipeRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping for <code>GET /recipe/{id}</code>
|
||||
* <p>
|
||||
* Gets a specific recipe by its unique id.
|
||||
* </p>
|
||||
* @param id id of the recipe
|
||||
* @return The recipe if it exists in the repository; otherwise returns 404 Not Found status
|
||||
*/
|
||||
@GetMapping("/recipe/{id}")
|
||||
public ResponseEntity<Recipe> getRecipe(@PathVariable Long id) {
|
||||
if (!recipeRepository.existsById(id)) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
return ResponseEntity.ok(recipeRepository.findById(id).get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping for <code>GET /recipes(?limit=)</code>
|
||||
* <p>
|
||||
* If the limit parameter is unspecified, return all recipes in the repository.
|
||||
* @param limit Integer limit of items you want to get
|
||||
* @return The list of recipes
|
||||
*/
|
||||
@GetMapping("/recipes")
|
||||
public ResponseEntity<List<Recipe>> getRecipes(@RequestParam Optional<Integer> limit) {
|
||||
if (limit.isPresent()) {
|
||||
return ResponseEntity.ok(
|
||||
recipeRepository.findAll(
|
||||
PageRequest.of(0, limit.get())
|
||||
).toList());
|
||||
}
|
||||
return ResponseEntity.ok(recipeRepository.findAll());
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping for <code>POST /recipe/{id}</code>
|
||||
* @param id The recipe id to replace
|
||||
* @param recipe The new recipe to be replaced from the original
|
||||
* @return The changed recipe; returns 400 Bad Request if the recipe does not exist
|
||||
*/
|
||||
@PostMapping("/recipe/{id}")
|
||||
public ResponseEntity<Recipe> updateRecipe(@PathVariable Long id, @RequestBody Recipe recipe) {
|
||||
if (!recipeRepository.existsById(id)) {
|
||||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
|
||||
// TODO: Send WS update to all subscribers with the updated recipe
|
||||
|
||||
return ResponseEntity.ok(recipeRepository.save(recipe));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping for <code>PUT /recipe/new</code>
|
||||
* <p>
|
||||
* Inserts a new recipe into the repository
|
||||
* </p>
|
||||
* @param recipe The new recipe as a request body
|
||||
* @return 200 OK with the recipe you added; or 400 Bad Request if the recipe already exists by name
|
||||
*/
|
||||
@PutMapping("/recipe/new")
|
||||
public ResponseEntity<Recipe> createRecipe(@RequestBody Recipe recipe) {
|
||||
|
||||
// We initialize a new example recipe with the name of input recipe
|
||||
// This is the only attribute we are concerned about making sure it's unique
|
||||
Recipe example = new Recipe();
|
||||
example.setName(recipe.getName());
|
||||
|
||||
/* Here we use very funny JPA magic repository.exists(Example<Recipe>)
|
||||
We check if any recipe in the repository has the same name as the input
|
||||
*/
|
||||
if (recipeRepository.exists(Example.of(example))) {
|
||||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
|
||||
// TODO: Send WS update to all subscribers with the new recipe
|
||||
|
||||
return ResponseEntity.ok(recipeRepository.save(recipe));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping for <code>DELETE /recipe/{id}</code>
|
||||
* <p>
|
||||
* Deletes a recipe identified by its <code>id</code>.
|
||||
* </p>
|
||||
* @param id The id of the recipe to be deleted.
|
||||
* @return 200 OK with true; or 400 Bad Request if the recipe doesn't exist.
|
||||
*/
|
||||
@DeleteMapping("/recipe/{id}")
|
||||
public ResponseEntity<Boolean> deleteRecipe(@PathVariable Long id) {
|
||||
if (!recipeRepository.existsById(id)) {
|
||||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
recipeRepository.deleteById(id);
|
||||
|
||||
// TODO: Send WS update to propagate deletion
|
||||
return ResponseEntity.ok(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 Delft University of Technology
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package server.database;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import commons.Recipe;
|
||||
|
||||
public interface RecipeRepository extends JpaRepository<Recipe, Long> {}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
spring.datasource.driverClassName=org.h2.Driver
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=
|
||||
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
||||
|
||||
# use one of these alternatives...
|
||||
# ... purely in-memory, wiped on restart, but great for testing
|
||||
spring.datasource.url=jdbc:h2:mem:testdb
|
||||
# ... persisted on disk (in project directory)
|
||||
#spring.datasource.url=jdbc:h2:file:./h2-database
|
||||
|
||||
# enable DB view on http://localhost:8080/h2-console
|
||||
spring.h2.console.enabled=true
|
||||
|
||||
# strategy for table (re-)generation
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
# show auto-generated SQL commands
|
||||
#spring.jpa.hibernate.show_sql=true
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
package server.api;
|
||||
|
||||
|
||||
import commons.Recipe;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import server.database.RecipeRepository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.LongStream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
// Spring Boot unit testing magic
|
||||
// Before each test the state of the repository is reset by
|
||||
// rolling back transaction of changes from previous test
|
||||
@DataJpaTest
|
||||
|
||||
// This test sources its application profile from
|
||||
// resources/application-mock-data-test.properties
|
||||
// This config uses an in-memory database
|
||||
@ActiveProfiles("mock-data-test")
|
||||
public class RecipeControllerTest {
|
||||
private RecipeController controller;
|
||||
private List<Recipe> recipes;
|
||||
private final RecipeRepository recipeRepository;
|
||||
private List<Long> recipeIds;
|
||||
public static final int NUM_RECIPES = 10;
|
||||
|
||||
// Injects a test repository into the test class
|
||||
@Autowired
|
||||
public RecipeControllerTest(RecipeRepository recipeRepository) {
|
||||
this.recipeRepository = recipeRepository;
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setup(TestInfo info) {
|
||||
recipes = LongStream
|
||||
.range(0, NUM_RECIPES)
|
||||
.mapToObj(x -> new Recipe(null, "Recipe " + x, List.of(), List.of()))
|
||||
.toList();
|
||||
controller = new RecipeController(recipeRepository);
|
||||
Set<String> tags = info.getTags();
|
||||
List<Long> ids = new ArrayList<>();
|
||||
|
||||
// Some tests want initial data to be created.
|
||||
if (tags.contains("test-from-init-data")) {
|
||||
ids = LongStream
|
||||
.range(0, NUM_RECIPES)
|
||||
.map(idx -> recipeRepository.save(recipes.get((int) idx)).getId())
|
||||
.boxed().toList();
|
||||
}
|
||||
|
||||
// Some tests need to know the stored IDs of objects
|
||||
if (tags.contains("need-ids")) {
|
||||
recipeIds = ids;
|
||||
}
|
||||
|
||||
// If no tags specified, the repository is initialized as empty.
|
||||
}
|
||||
@Test
|
||||
public void createOneRecipe() {
|
||||
controller.createRecipe(recipes.getFirst());
|
||||
|
||||
// There is 1 recipe in the repository
|
||||
assertEquals(1, recipeRepository.count());
|
||||
}
|
||||
@Test
|
||||
public void createManyRecipes() {
|
||||
recipes.forEach(recipe -> controller.createRecipe(recipe));
|
||||
|
||||
// There are the same number of recipes in the repository as the input list
|
||||
assertEquals(recipes.size(), recipeRepository.count());
|
||||
}
|
||||
@Test
|
||||
@Tag("test-from-init-data")
|
||||
public void getManyRecipes() {
|
||||
// The number of recipes returned is the same as the entire input list
|
||||
assertEquals(recipes.size(), controller.getRecipes(Optional.empty()).getBody().size());
|
||||
}
|
||||
@Test
|
||||
@Tag("test-from-init-data")
|
||||
public void getSomeRecipes() {
|
||||
final int LIMIT = 5;
|
||||
// The number of recipes returned is the same as the entire input list
|
||||
assertEquals(LIMIT, controller.getRecipes(Optional.of(LIMIT)).getBody().size());
|
||||
}
|
||||
@Test
|
||||
@Tag("test-from-init-data")
|
||||
@Tag("need-ids")
|
||||
public void findOneRecipeExists() {
|
||||
final int CHECK_INDEX = 3;
|
||||
// The third item in the input list is the same as the third item retrieved from the database
|
||||
assertEquals(
|
||||
recipes.get(CHECK_INDEX),
|
||||
controller.getRecipe(recipeIds.get(CHECK_INDEX)).getBody());
|
||||
}
|
||||
@Test
|
||||
public void findOneRecipeNotExists() {
|
||||
final int CHECK_INDEX = 3;
|
||||
// There does not exist a recipe with ID=3 since there are no items in the repository.
|
||||
assertEquals(
|
||||
HttpStatus.NOT_FOUND,
|
||||
controller.getRecipe((long) CHECK_INDEX).getStatusCode());
|
||||
}
|
||||
@Test
|
||||
@Tag("test-from-init-data")
|
||||
@Tag("need-ids")
|
||||
public void deleteOneRecipeGood() {
|
||||
final int DELETE_INDEX = 5;
|
||||
|
||||
// The object has been successfully deleted
|
||||
assertEquals(HttpStatus.OK, controller.deleteRecipe(recipeIds.get(DELETE_INDEX)).getStatusCode());
|
||||
}
|
||||
@Test
|
||||
@Tag("test-from-init-data")
|
||||
@Tag("need-ids")
|
||||
public void deleteOneRecipeCountGood() {
|
||||
final int DELETE_INDEX = 5;
|
||||
controller.deleteRecipe(recipeIds.get(DELETE_INDEX));
|
||||
// The count of items decreased by 1 after the 5th item has been removed.
|
||||
assertEquals(recipeIds.size() - 1, recipeRepository.count());
|
||||
}
|
||||
@Test
|
||||
public void deleteOneRecipeFail() {
|
||||
final Long DELETE_INDEX = 5L;
|
||||
assertEquals(HttpStatus.BAD_REQUEST, controller.deleteRecipe(DELETE_INDEX).getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Tag("test-from-init-data")
|
||||
@Tag("need-ids")
|
||||
public void updateOneRecipeHasNewData() {
|
||||
final int UPDATE_INDEX = 5;
|
||||
Recipe newRecipe = controller.getRecipe(recipeIds.get(UPDATE_INDEX)).getBody();
|
||||
newRecipe.setName("New recipe");
|
||||
controller.updateRecipe(newRecipe.getId(), newRecipe);
|
||||
assertEquals("New recipe", recipeRepository.getReferenceById(recipeIds.get(UPDATE_INDEX)).getName());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue