Revert "Merge branch 'backend' into 'main'"

This reverts merge request !2
This commit is contained in:
Zhongheng Liu 2025-11-27 14:29:18 +01:00
commit 07d3fe304d
7 changed files with 0 additions and 899 deletions

View file

@ -1,216 +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 commons;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.Entity;
import jakarta.persistence.CollectionTable;
import jakarta.persistence.Column;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OrderColumn;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.ElementCollection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Collection;
// TABLE named recipes
@Entity
@Table(name = "recipes")
public class Recipe {
// PRIMARY Key, unique id for recipe, generated automatically.
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false, unique = true)
private Long id;
// Recipe name
@Column(name = "name", nullable = false, unique = true)
private String name;
/**
* Creates another table named recipe_ingredients which stores:
* recipe_ingredients(recipe_id -> recipes(id), ingredient).
* <p>
* Example recipe_ingredients table:
* <pre>
* | recipe_id | ingredient |
* |---------------------|------------|
* | 0 (Chocolate Cake) | Egg |
* | 0 (Chocolate Cake) | Egg |
* | 0 (Chocolate Cake) | Flour |
* | 1 (Steak) | 40g salt |
* | 1 (Steak) | 40g pepper |
* | 1 (Steak) | Meat |
* |----------------------------------|
* </pre>
* TODO: Replace String with Embeddable Ingredient Class
*/
@ElementCollection
@CollectionTable(name = "recipe_ingredients", joinColumns = @JoinColumn(name = "recipe_id"))
@Column(name = "ingredient")
private List<String> ingredients = new ArrayList<>();
/**
* Creates another table named recipe_preparation which stores:
* recipe_preparation(recipe_id -> recipes(id), preparation_step, step_order).
* <p>
* Example recipe_preparation table:
* <pre>
* | recipe_id | preparation_step | step_order |
* |---------------------|----------------------|------------|
* | 0 (Chocolate Cake) | Preheat oven | 1 |
* | 0 (Chocolate Cake) | Mix eggs and sugar | 2 |
* | 0 (Chocolate Cake) | Add flour gradually | 3 |
* | 1 (Steak) | Season meat | 1 |
* | 1 (Steak) | Heat pan | 2 |
* |---------------------------------------------------------|
* </pre>
*/
@ElementCollection
@CollectionTable(name = "recipe_preparation", joinColumns = @JoinColumn(name = "recipe_id"))
@Column(name = "preparation_step")
@OrderColumn(name = "step_order")
private List<String> preparationSteps = new ArrayList<>();
@SuppressWarnings("unused")
public Recipe() {
// for object mapper
}
public Recipe(Long id, String name) {
// Not used by JPA/Spring
this.id = id;
this.name = name;
}
// TODO: Replace String with Embeddable Ingredient Class for ingredients
public Recipe(Long id, String name, List<String> ingredients, List<String> preparationSteps) {
// Not used by JPA/Spring
this.id = id;
this.name = name;
this.ingredients = ingredients;
this.preparationSteps = preparationSteps;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* Returns an unmodifiable view of the ingredients list.
* <p>
* The returned list cannot be modified directly. To modify ingredients,
* create a copy using {@link List#copyOf(Collection)} or create your own list,
* populate it, and use {@link #setIngredients(List)} to update.
*
* @return An unmodifiable list of ingredients.
* @see #setIngredients(List)
*/
// TODO: Replace String with Embeddable Ingredient Class
public List<String> getIngredients() {
// Disallow modifying the returned list.
// You can still copy it with List.copyOf(...)
return Collections.unmodifiableList(ingredients);
}
// TODO: Replace String with Embeddable Ingredient Class
public void setIngredients(List<String> ingredients) {
this.ingredients = ingredients;
}
/**
* Returns an unmodifiable view of the preparation steps list.
* <p>
* The returned list cannot be modified directly. To modify preparation steps,
* create a copy using {@link List#copyOf(Collection)} or create your own list,
* populate it, and use {@link #setPreparationSteps(List)} to update.
*
* @return An unmodifiable list of preparation steps in order.
* @see #setPreparationSteps(List)
*/
public List<String> getPreparationSteps() {
// Disallow modifying the returned list.
// You can still copy it with List.copyOf(...)
return Collections.unmodifiableList(preparationSteps);
}
public void setPreparationSteps(List<String> preparationSteps) {
this.preparationSteps = preparationSteps;
}
@Override
public boolean equals(Object o) {
// Faster/Better equals than reflectionEquals
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Recipe recipe = (Recipe) o;
return Objects.equals(id, recipe.id); // Check only for ID, as its unique!
}
@Override
public int hashCode() {
return Objects.hash(id); // Use ID only, as its unique.
}
@Override
public String toString() {
return "Recipe{" +
"name='" + name + '\'' +
", ingredientsCount=" + ingredients.size() +
", preparationStepsCount=" + preparationSteps.size() +
"}";
}
/**
* Returns a more detailed string than {@link #toString()} of this recipe, including
* the full contents of all ingredients and preparation steps.
* <p>
* Intended only for debugging.
*
* @return A detailed string representation containing all recipe data.
* @see #toString()
*/
@SuppressWarnings("unused")
public String toDetailedString() {
return "Recipe{" +
"name='" + name + '\'' +
", ingredients=" + ingredients +
", preparationSteps=" + preparationSteps +
'}';
}
}

View file

@ -1,121 +0,0 @@
package commons;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class RecipeTest {
Recipe recipe;
static final Long RECIPE_ID = 1L;
@BeforeEach
void setupRecipe() {
this.recipe = new Recipe(RECIPE_ID, "Chocolate Cake");
}
@Test
void getId() {
assertEquals(RECIPE_ID, recipe.getId());
}
@Test
void setId() {
recipe.setId(RECIPE_ID + 1);
assertEquals(RECIPE_ID + 1, recipe.getId());
}
@Test
void getName() {
assertEquals("Chocolate Cake", recipe.getName());
}
@Test
void setName() {
recipe.setName("Steak");
assertEquals("Steak", recipe.getName());
}
@Test
void getIngredientsAddThrow() {
// TODO: Change to actual Ingredient class later
assertThrows(UnsupportedOperationException.class, () -> recipe.getIngredients().add("Lasagna"));
}
@Test
void getIngredientsClearThrow() {
assertThrows(UnsupportedOperationException.class, () -> recipe.getIngredients().clear());
}
@Test
void setIngredients() {
// TODO: Change to actual Ingredient class later
List<String> ingredients = new ArrayList<>(List.of("Chocolate", "Flour", "Egg"));
recipe.setIngredients(ingredients);
assertEquals(recipe.getIngredients(), ingredients);
assertEquals(recipe.getIngredients().size(), ingredients.size());
}
@Test
void getPreparationStepsAddThrow() {
assertThrows(UnsupportedOperationException.class, () -> recipe.getPreparationSteps().add("Preheat Oven"));
}
@Test
void getPreparationStepsClearThrow() {
assertThrows(UnsupportedOperationException.class, () -> recipe.getPreparationSteps().clear());
}
@Test
void setPreparationSteps() {
List<String> steps = new ArrayList<>(List.of("Preheat oven", "Mix stuff", "decorate"));
recipe.setPreparationSteps(steps);
assertEquals(recipe.getPreparationSteps(), steps);
assertEquals(recipe.getPreparationSteps().size(), steps.size());
}
@Test
void testEqualsSame() {
Recipe recipe2 = new Recipe(RECIPE_ID, "Chocolate Cake");
assertEquals(recipe, recipe2);
}
@Test
void testEqualsSameExceptId() {
Recipe recipe2 = new Recipe(RECIPE_ID + 1, "Chocolate Cake");
assertNotEquals(recipe, recipe2);
}
@Test
void testEqualsOnlySameId() {
Recipe recipe2 = new Recipe(RECIPE_ID, "Some random recipe");
assertEquals(recipe, recipe2); // Equals, we only look at ID!!!
}
@Test
void testHashCodeSame() {
Recipe recipe2 = new Recipe(RECIPE_ID, "Chocolate Cake");
assertEquals(recipe.hashCode(), recipe2.hashCode());
}
@Test
void testHashCodeSameExceptId() {
Recipe recipe2 = new Recipe(RECIPE_ID + 1, "Chocolate Cake");
assertNotEquals(recipe.hashCode(), recipe2.hashCode());
}
@Test
void testHashCodeOnlySameId() {
Recipe recipe2 = new Recipe(RECIPE_ID, "Some random recipe");
assertEquals(recipe.hashCode(), recipe2.hashCode()); // Same, only looks at ID!!!
}
}

View file

@ -1,243 +0,0 @@
## Recipe API
Base path: `/api`
This API allows clients to create, read, update, and delete `Recipe` resources.
---
## Endpoints
### Get a Recipe by ID
**GET** `/api/recipe/{id}`
Retrieves a specific recipe by its unique identifier.
* **Path Parameters**
| Name | Type | Required | Description |
| ---- | ------ | -------- | ------------------------------ |
| `id` | `Long` | Yes | The ID of the recipe to fetch. |
* **Responses**
| Status Code | Description |
| --------------- | ------------------------------------- |
| `200 OK` | Returns the recipe with the given ID. |
| `404 Not Found` | No recipe exists with that ID. |
* **Example Request**
```bash
curl -X GET "http://SERVER_ADDRESS/api/recipe/1" \
-H "Accept: application/json"
```
* **Example Response (200)**
```json
{
"id": 1,
"name": "Pancakes",
"ingredients": ["Ingredient 1", "Ingredient 2"],
"preparationSteps": ["Step 1", "Step 2"]
}
```
---
### List Recipes
**GET** `/api/recipes`
Retrieves a list of recipes. Supports optional pagination via a `limit` query parameter.
* **Query Parameters**
| Name | Type | Required | Description |
| ------- | --------- | -------- | ---------------------------------------------------------------------------- |
| `limit` | `Integer` | No | Maximum number of recipes to return. If not provided, returns *all* recipes. |
* **Responses**
| Status Code | Description |
| ----------- | --------------------------------------------- |
| `200 OK` | Returns a list of recipes (possibly limited). |
* **Example Request (no limit)**
```bash
curl -X GET "http://SERVER_ADDRESS/api/recipes" \
-H "Accept: application/json"
```
* **Example Request (with limit)**
```bash
curl -X GET "http://SERVER_ADDRESS/api/recipes?limit=10" \
-H "Accept: application/json"
```
* **Example Response (200)**
```json
[
{
"id": 10,
"name": "Recipe 0",
"ingredients": ["Flour", "Milk"],
"preparationSteps": ["Do something", "Do something else"]
},
{
"id": 11,
"name": "Recipe 1",
"ingredients": ["Flour", "Milk"],
"preparationSteps": ["Do something", "Do something else"]
}
// etc. max {limit} items
]
```
---
### Create a New Recipe
**PUT** `/api/recipe/new`
Creates a new recipe. The recipe name must be unique in the repository.
* **Request Body**
A JSON object representing the recipe. Example:
```json
{
"name": "Pancakes",
"ingredients": ["Flour", "Milk", "Eggs"],
"preparationSteps": ["Step 1", "Step 2"]
}
```
* **Responses**
| Status Code | Description |
| ----------------- | -------------------------------------------------------------------------------------------- |
| `200 OK` | The recipe was successfully created. Returns the created recipe (including its assigned ID). |
| `400 Bad Request` | A recipe with the same name already exists. |
* **Example Request**
```bash
curl -X PUT "https://SERVER_ADDRESS/api/recipe/new" \
-H "Content-Type: application/json" \
-d '{
"name": "Pancakes",
"ingredients": ["Flour", "Milk", "Eggs"],
"preparationSteps": ["Step 1", "Step 2"]
}'
```
* **Example Response (200)**
```json
{
"id": 125,
"name": "Pancakes",
"ingredients": ["Flour", "Milk", "Eggs"],
"preparationSteps": ["Step 1", "Step 2"]
}
```
---
### Update an Existing Recipe
**POST** `/api/recipe/{id}`
Replaces or updates the recipe with the given ID.
* **Path Parameters**
| Name | Type | Required | Description |
| ---- | ------ | -------- | ------------------------------- |
| `id` | `Long` | Yes | The ID of the recipe to update. |
* **Request Body**
A JSON object containing the new recipe data. It is expected to include the ID (or the server-side save will override it), or at least map correctly to the stored entity.
Example:
```json
{
"id": 123,
"name": "Better Pancakes",
"ingredients": ["Flour", "Almond milk", "Eggs"],
"preparationSteps": ["Step 10", "Step 11"]
}
```
* **Responses**
| Status Code | Description |
| ----------------- | ---------------------------------------------------------------- |
| `200 OK` | The recipe was successfully updated. Returns the updated recipe. |
| `400 Bad Request` | No recipe exists with the given ID. |
* **Example Request**
```bash
curl -X POST "https://your-domain.com/api/recipe/123" \
-H "Content-Type: application/json" \
-d '{
"id": 123,
"name": "Better Pancakes",
"ingredients": ["Flour", "Almond milk", "Eggs"],
"preparationSteps": ["Step 10", "Step 11"]
}'
```
* **Example Response (200)**
```json
{
"id": 123,
"name": "Updated Pancakes",
"ingredients": ["Flour", "Almond milk", "Eggs"],
"preparationSteps": "Mix and fry differently."
}
```
---
### Delete a Recipe
**DELETE** `/api/recipe/{id}`
Deletes the recipe with the given ID.
* **Path Parameters**
| Name | Type | Required | Description |
| ---- | ------ | -------- | ------------------------------- |
| `id` | `Long` | Yes | The ID of the recipe to delete. |
* **Responses**
| Status Code | Description |
| ----------------- | ---------------------------------------------------- |
| `200 OK` | The recipe was successfully deleted. Returns `true`. |
| `400 Bad Request` | No recipe exists with the given ID. |
* **Example Request**
```bash
curl -X DELETE "https://your-domain.com/api/recipe/123"
```
* **Example Response (200)**
```json
true
```

View file

@ -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);
}
}

View file

@ -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> {}

View file

@ -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

View file

@ -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());
}
}