Skip to content

Commit

Permalink
Merge pull request #207 from bounswe/backend/feature/206-formatting-r…
Browse files Browse the repository at this point in the history
…esponses-/search

Formatting responses for /search (dishes)
  • Loading branch information
EnesBaserr authored May 13, 2024
2 parents 8044ed0 + 98abe2a commit 4f05546
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 112 deletions.
12 changes: 12 additions & 0 deletions backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.jena</groupId>
<artifactId>apache-jena-libs</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.group1.cuisines.dao.response.AuthenticationTokenResponse;
import com.group1.cuisines.services.AuthenticationService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -23,13 +24,27 @@ public class AuthenticationController {
public ResponseEntity<ApiResponse<AuthenticationTokenResponse>> signup(
@RequestBody SignUpRequest request
) {
return ResponseEntity.ok(authenticationService.signup(request)); // Return response
ApiResponse<AuthenticationTokenResponse> response = authenticationService.signup(request);

if (response.getStatus() == 409) {
return ResponseEntity.status(HttpStatus.CONFLICT).body(response);
} else if (response.getStatus() == 400) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
} else {
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}
}

@PostMapping("/login") // Sign in endpoint
public ResponseEntity<ApiResponse<AuthenticationTokenResponse>> signin(
@RequestBody SignInRequest request
) {
return ResponseEntity.ok(authenticationService.signin(request)); // Return response
ApiResponse<AuthenticationTokenResponse> response = authenticationService.signin(request);

if (response.getStatus() == 401) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
} else {
return ResponseEntity.ok(response);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.group1.cuisines.controllers;

import com.group1.cuisines.dao.response.ApiResponse;
import com.group1.cuisines.dto.DishResponseDto;
import com.group1.cuisines.entities.Dish;
import com.group1.cuisines.entities.User;
import com.group1.cuisines.services.SearchService;
Expand Down Expand Up @@ -34,9 +35,9 @@ public ResponseEntity<?> searchUsers(@RequestParam(required = false) String q) {
}

@GetMapping("/dishes")
public ApiResponse<List<Dish>> searchDishes(@RequestParam(required = false) String q,
@RequestParam(required = false) String cuisine,
@RequestParam(required = false) String foodType) {
public ApiResponse<List<DishResponseDto>> searchDishes(@RequestParam(required = false) String q,
@RequestParam(required = false) String cuisine,
@RequestParam(required = false) String foodType) {
return new ApiResponse<>(
200,
"Search completed",
Expand Down
19 changes: 19 additions & 0 deletions backend/src/main/java/com/group1/cuisines/dto/DishResponseDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.group1.cuisines.dto;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DishResponseDto {
private String id;
private String name;
private String image;
private String description;
private String countries;
private String ingredients;
private String foodTypes;
private String cuisines;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.group1.cuisines.exceptions;

import com.group1.cuisines.dao.response.ApiResponse;
import org.springframework.boot.context.config.ConfigDataResourceNotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(Exception.class)
public ResponseEntity<ApiResponse<String>> handleException(Exception e) {
ApiResponse<String> response = new ApiResponse<>(500, "An unexpected error occurred: " + e.getMessage(), null);
return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
}

@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ApiResponse<String>> handleResourceNotFoundException(ResourceNotFoundException e) {
ApiResponse<String> response = new ApiResponse<>(400, e.getMessage(), null);
return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.group1.cuisines.exceptions;

public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public ApiResponse<AuthenticationTokenResponse> signup(
String token = jwtService.generateToken(user);

return new ApiResponse<>(
200,
201,
"User registered successfully.",
AuthenticationTokenResponse.builder().token(token).build()
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.group1.cuisines.services;

import com.group1.cuisines.dto.DishDto;
import com.group1.cuisines.dto.DishResponseDto;
import com.group1.cuisines.entities.Dish;
import com.group1.cuisines.exceptions.ResourceNotFoundException;
import com.group1.cuisines.repositories.DishRepository;
import com.group1.cuisines.repositories.UserRepository;
import lombok.RequiredArgsConstructor;
Expand All @@ -16,17 +19,23 @@
public class SearchService {

private final DishRepository dishRepository;
public List<Dish> searchDishes(String query, String cuisine, String foodType) {
public List<DishResponseDto> searchDishes(String query, String cuisine, String foodType) {
List<Dish> dishes = dishRepository.findAll();

// Filter by dish name
if (query != null && !query.isEmpty()) {
dishes = dishRepository.findByNameContainingIgnoreCase(query);
if (dishes.isEmpty()) {
throw new ResourceNotFoundException("No dishes found with the given name query.");
}
}

// Filter by cuisine name
if (cuisine != null && !cuisine.isEmpty()) {
List<Dish> dishesByCuisine = dishRepository.findByCuisinesName(cuisine);
if (dishesByCuisine.isEmpty()) {
throw new ResourceNotFoundException("No dishes found with the given cuisine.");
}
dishes = dishes.stream()
.filter(dishesByCuisine::contains)
.collect(Collectors.toList());
Expand All @@ -37,9 +46,25 @@ public List<Dish> searchDishes(String query, String cuisine, String foodType) {
dishes = dishes.stream()
.filter(d -> d.getFoodTypes() != null && d.getFoodTypes().contains(foodType))
.collect(Collectors.toList());

if (dishes.isEmpty()) {
throw new ResourceNotFoundException("No dishes found with the given food type.");
}
}

return dishes;
// Map to DishResponseDto
return dishes.stream()
.map(d -> new DishResponseDto(
d.getId(),
d.getName(),
d.getImage(),
d.getDescription(),
d.getCountries(),
d.getIngredients(),
d.getFoodTypes(),
d.getCuisines().isEmpty() ? null : d.getCuisines().get(0).getName()
))
.collect(Collectors.toList());
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

public class AuthenticationControllerTest {
Expand All @@ -31,123 +32,65 @@ public void setUp() {

@Test
public void shouldReturnSuccessOnValidSignin() {
SignInRequest signInRequest = new SignInRequest(
"testUser",
"testPassword"
);
ApiResponse<AuthenticationTokenResponse> apiResponse =
new ApiResponse<>(
200,
"Success",
new AuthenticationTokenResponse("token")
);
when(authenticationService.signin(signInRequest)).thenReturn(
apiResponse
);
ResponseEntity<
ApiResponse<AuthenticationTokenResponse>
> responseEntity = authenticationController.signin(signInRequest);
assertEquals(
200,
responseEntity.getBody().getStatus(),
"Status code does not match expected value on successful signin"
);
assertEquals(
apiResponse,
responseEntity.getBody(),
"Response body does not match expected value on successful signin"
);
SignInRequest signInRequest = new SignInRequest("testUser", "testPassword");
ApiResponse<AuthenticationTokenResponse> apiResponse = new ApiResponse<>(200, "Success", new AuthenticationTokenResponse("token"));
when(authenticationService.signin(signInRequest)).thenReturn(apiResponse);

ResponseEntity<ApiResponse<AuthenticationTokenResponse>> responseEntity = authenticationController.signin(signInRequest);

assertEquals(HttpStatus.OK.value(), responseEntity.getStatusCodeValue(), "Status code does not match expected value on successful signin");
assertEquals(apiResponse, responseEntity.getBody(), "Response body does not match expected value on successful signin");
}

@Test
public void shouldReturnFailureOnInvalidSignin() {
SignInRequest signInRequest = new SignInRequest(
"testUser",
"wrongPassword"
);
ApiResponse<AuthenticationTokenResponse> apiResponse =
new ApiResponse<>(401, "Failure", null);
when(authenticationService.signin(signInRequest)).thenReturn(
apiResponse
);
ResponseEntity<
ApiResponse<AuthenticationTokenResponse>
> responseEntity = authenticationController.signin(signInRequest);
assertEquals(
401,
responseEntity.getBody().getStatus(),
"Status code does not match expected value on failed signin"
);
assertEquals(
apiResponse,
responseEntity.getBody(),
"Response body does not match expected value on failed signin"
);
SignInRequest signInRequest = new SignInRequest("testUser", "wrongPassword");
ApiResponse<AuthenticationTokenResponse> apiResponse = new ApiResponse<>(401, "Invalid email/username or password.", null);
when(authenticationService.signin(signInRequest)).thenReturn(apiResponse);

ResponseEntity<ApiResponse<AuthenticationTokenResponse>> responseEntity = authenticationController.signin(signInRequest);

assertEquals(HttpStatus.UNAUTHORIZED.value(), responseEntity.getStatusCodeValue(), "Status code does not match expected value on failed signin");
assertEquals(apiResponse, responseEntity.getBody(), "Response body does not match expected value on failed signin");
}

@Test
public void shouldReturnSuccessOnValidSignup() {
SignUpRequest signUpRequest = SignUpRequest.builder()
.email("[email protected]")
.username("newUser")
.country("USA")
.bio("Bio of the new user")
.password("newPassword")
.firstName("New")
.lastName("User")
.build();
ApiResponse<AuthenticationTokenResponse> apiResponse =
new ApiResponse<>(
200,
"Success",
new AuthenticationTokenResponse("token")
);
when(authenticationService.signup(signUpRequest)).thenReturn(
apiResponse
);
ResponseEntity<
ApiResponse<AuthenticationTokenResponse>
> responseEntity = authenticationController.signup(signUpRequest);
assertEquals(
200,
responseEntity.getBody().getStatus(),
"Status code does not match expected value on successful signup"
);
assertEquals(
apiResponse,
responseEntity.getBody(),
"Response body does not match expected value on successful signup"
);
.email("[email protected]")
.username("newUser")
.country("USA")
.bio("Bio of the new user")
.password("newPassword")
.firstName("New")
.lastName("User")
.build();
ApiResponse<AuthenticationTokenResponse> apiResponse = new ApiResponse<>(201, "User registered successfully.", new AuthenticationTokenResponse("token"));
when(authenticationService.signup(signUpRequest)).thenReturn(apiResponse);

ResponseEntity<ApiResponse<AuthenticationTokenResponse>> responseEntity = authenticationController.signup(signUpRequest);

assertEquals(HttpStatus.CREATED.value(), responseEntity.getStatusCodeValue(), "Status code does not match expected value on successful signup");
assertEquals(apiResponse, responseEntity.getBody(), "Response body does not match expected value on successful signup");
}

@Test
public void shouldReturnFailureOnInvalidSignup() {
SignUpRequest signUpRequest = SignUpRequest.builder()
.email("[email protected]")
.username("newUser")
.country("USA")
.bio("Bio of the new user")
.password("newPassword")
.firstName("New")
.lastName("User")
.build();
ApiResponse<AuthenticationTokenResponse> apiResponse =
new ApiResponse<>(409, "Failure", null);
when(authenticationService.signup(signUpRequest)).thenReturn(
apiResponse
);
ResponseEntity<
ApiResponse<AuthenticationTokenResponse>
> responseEntity = authenticationController.signup(signUpRequest);
assertEquals(
409,
responseEntity.getBody().getStatus(),
"Status code does not match expected value on failed signup"
);
assertEquals(
apiResponse,
responseEntity.getBody(),
"Response body does not match expected value on failed signup"
);
.email("[email protected]")
.username("newUser")
.country("USA")
.bio("Bio of the new user")
.password("newPassword")
.firstName("New")
.lastName("User")
.build();
ApiResponse<AuthenticationTokenResponse> apiResponse = new ApiResponse<>(409, "Email or username already exists.", null);
when(authenticationService.signup(signUpRequest)).thenReturn(apiResponse);

ResponseEntity<ApiResponse<AuthenticationTokenResponse>> responseEntity = authenticationController.signup(signUpRequest);

assertEquals(HttpStatus.CONFLICT.value(), responseEntity.getStatusCodeValue(), "Status code does not match expected value on failed signup");
assertEquals(apiResponse, responseEntity.getBody(), "Response body does not match expected value on failed signup");
}
}

0 comments on commit 4f05546

Please sign in to comment.