reglage order

This commit is contained in:
2026-04-12 16:59:07 +02:00
parent 45bb71b480
commit 2c777021b9
2 changed files with 449 additions and 0 deletions
@@ -0,0 +1,223 @@
package fr.iut_fbleau.but3.dev62.mylibrary.features.order;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book;
import fr.iut_fbleau.but3.dev62.mylibrary.book.repository.BookRepository;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.entity.Customer;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.exception.CustomerNotFoundException;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.repository.CustomerRepository;
import fr.iut_fbleau.but3.dev62.mylibrary.order.AdresseLivraison;
import fr.iut_fbleau.but3.dev62.mylibrary.order.LigneCommandeInfo;
import fr.iut_fbleau.but3.dev62.mylibrary.order.ModePaiement;
import fr.iut_fbleau.but3.dev62.mylibrary.order.OrderDTO;
import fr.iut_fbleau.but3.dev62.mylibrary.order.OrderInfo;
import fr.iut_fbleau.but3.dev62.mylibrary.order.exception.NotValidOrderException;
import fr.iut_fbleau.but3.dev62.mylibrary.order.repository.OrderRepository;
import fr.iut_fbleau.but3.dev62.mylibrary.order.usecase.OrderUseCase;
import io.cucumber.datatable.DataTable;
import io.cucumber.java.Before;
import io.cucumber.java.en.And;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class OrderSteps {
private final CustomerRepository customerRepository = new CustomerRepository();
private final BookRepository bookRepository = new BookRepository();
private final OrderRepository orderRepository = new OrderRepository();
private final OrderUseCase orderUseCase = new OrderUseCase(orderRepository, customerRepository, bookRepository);
private final Map<String, UUID> customerPhoneUUID = new HashMap<>();
private final Map<String, UUID> bookIsbnUUID = new HashMap<>();
private OrderDTO orderResult;
private NotValidOrderException notValidOrderException;
private boolean customerNotFoundThrown = false;
@Before
public void setUp() {
customerRepository.deleteAll();
bookRepository.deleteAll();
orderRepository.deleteAll();
customerPhoneUUID.clear();
bookIsbnUUID.clear();
orderResult = null;
notValidOrderException = null;
customerNotFoundThrown = false;
}
@Given("the system has the following customers for order:")
public void theSystemHasTheFollowingCustomersForOrder(DataTable dataTable) {
List<Map<String, String>> customers = dataTable.asMaps(String.class, String.class);
for (Map<String, String> customer : customers) {
String phone = customer.get("numeroTelephone");
Customer newCustomer = Customer.builder()
.firstName(customer.get("prenom"))
.lastName(customer.get("nom"))
.phoneNumber(phone)
.loyaltyPoints(Integer.parseInt(customer.get("pointsFidelite")))
.build();
Customer saved = customerRepository.save(newCustomer);
customerPhoneUUID.put(phone, saved.getId());
}
assertEquals(customers.size(), customerRepository.findAll().size());
}
@And("the catalog has the following books for order:")
public void theCatalogHasTheFollowingBooksForOrder(DataTable dataTable) {
List<Map<String, String>> books = dataTable.asMaps(String.class, String.class);
for (Map<String, String> book : books) {
String isbn = book.get("isbn");
Book newBook = Book.builder()
.isbn(isbn)
.title(book.get("titre"))
.author(book.get("auteur"))
.publisher(book.get("editeur"))
.publicationDate(LocalDate.parse(book.get("datePublication")))
.price(new BigDecimal(book.get("prix")))
.stock(Integer.parseInt(book.get("stockInitial")))
.categories(List.of(book.get("categories").split(";")))
.description(book.get("description"))
.language(book.get("langue"))
.build();
Book saved = bookRepository.save(newBook);
bookIsbnUUID.put(isbn, saved.getId());
}
assertEquals(books.size(), bookRepository.findAll().size());
}
@When("I place an order for customer {string} with:")
public void iPlaceAnOrderForCustomerWith(String phoneNumber, DataTable dataTable)
throws NotValidOrderException, CustomerNotFoundException {
Map<String, String> row = dataTable.asMaps(String.class, String.class).getFirst();
UUID customerId = customerPhoneUUID.get(phoneNumber);
UUID livreId = bookIsbnUUID.get(row.get("livreIsbn"));
AdresseLivraison adresse = new AdresseLivraison(
row.get("rue"), row.get("ville"), row.get("codePostal"), row.get("pays")
);
OrderInfo orderInfo = new OrderInfo(
customerId,
List.of(new LigneCommandeInfo(livreId, Integer.parseInt(row.get("quantite")))),
adresse,
ModePaiement.valueOf(row.get("modePaiement"))
);
orderResult = orderUseCase.passerCommande(orderInfo);
}
@Then("a new order is created")
public void aNewOrderIsCreated() {
assertNotNull(orderResult);
assertNotNull(orderResult.getCommandeId());
}
@And("the order total is {double}")
public void theOrderTotalIs(double expectedTotal) {
assertEquals(0, new BigDecimal(String.valueOf(expectedTotal)).compareTo(orderResult.getMontantTotal()));
}
@And("the customer {string} now has {int} loyalty points")
public void theCustomerNowHasLoyaltyPoints(String phoneNumber, int expectedPoints) {
UUID customerId = customerPhoneUUID.get(phoneNumber);
Customer customer = customerRepository.findById(customerId).orElseThrow();
assertEquals(expectedPoints, customer.getLoyaltyPoints());
}
@When("I try to place an order for customer {string} with no items:")
public void iTryToPlaceAnOrderForCustomerWithNoItems(String phoneNumber, DataTable dataTable) {
Map<String, String> row = dataTable.asMaps(String.class, String.class).getFirst();
UUID customerId = customerPhoneUUID.get(phoneNumber);
AdresseLivraison adresse = new AdresseLivraison(
row.get("rue"), row.get("ville"), row.get("codePostal"), row.get("pays")
);
OrderInfo orderInfo = new OrderInfo(
customerId, List.of(), adresse, ModePaiement.valueOf(row.get("modePaiement"))
);
notValidOrderException = assertThrows(NotValidOrderException.class,
() -> orderUseCase.passerCommande(orderInfo));
}
@When("I try to place an order for customer {string} with invalid quantity:")
public void iTryToPlaceAnOrderForCustomerWithInvalidQuantity(String phoneNumber, DataTable dataTable) {
Map<String, String> row = dataTable.asMaps(String.class, String.class).getFirst();
UUID customerId = customerPhoneUUID.get(phoneNumber);
UUID livreId = bookIsbnUUID.get(row.get("livreIsbn"));
AdresseLivraison adresse = new AdresseLivraison(
row.get("rue"), row.get("ville"), row.get("codePostal"), row.get("pays")
);
OrderInfo orderInfo = new OrderInfo(
customerId,
List.of(new LigneCommandeInfo(livreId, Integer.parseInt(row.get("quantite")))),
adresse,
ModePaiement.valueOf(row.get("modePaiement"))
);
notValidOrderException = assertThrows(NotValidOrderException.class,
() -> orderUseCase.passerCommande(orderInfo));
}
@When("I try to place an order for an unknown customer with:")
public void iTryToPlaceAnOrderForAnUnknownCustomerWith(DataTable dataTable) {
Map<String, String> row = dataTable.asMaps(String.class, String.class).getFirst();
UUID unknownId = UUID.randomUUID();
UUID livreId = bookIsbnUUID.get(row.get("livreIsbn"));
AdresseLivraison adresse = new AdresseLivraison(
row.get("rue"), row.get("ville"), row.get("codePostal"), row.get("pays")
);
OrderInfo orderInfo = new OrderInfo(
unknownId,
List.of(new LigneCommandeInfo(livreId, Integer.parseInt(row.get("quantite")))),
adresse,
ModePaiement.valueOf(row.get("modePaiement"))
);
try {
orderUseCase.passerCommande(orderInfo);
} catch (CustomerNotFoundException e) {
customerNotFoundThrown = true;
} catch (NotValidOrderException e) {
notValidOrderException = e;
}
}
@Then("the order placement fails")
public void theOrderPlacementFails() {
assertNotNull(notValidOrderException);
}
@Then("the order placement fails with customer not found")
public void theOrderPlacementFailsWithCustomerNotFound() {
assertTrue(customerNotFoundThrown);
}
@And("I receive a validation order error containing {string}")
public void iReceiveAValidationOrderErrorContaining(String errorMessage) {
assertEquals(errorMessage, notValidOrderException.getMessage());
}
}
@@ -0,0 +1,226 @@
package fr.iut_fbleau.but3.dev62.mylibrary.order.usecase;
import fr.iut_fbleau.but3.dev62.mylibrary.book.entity.Book;
import fr.iut_fbleau.but3.dev62.mylibrary.book.repository.BookRepository;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.entity.Customer;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.exception.CustomerNotFoundException;
import fr.iut_fbleau.but3.dev62.mylibrary.customer.repository.CustomerRepository;
import fr.iut_fbleau.but3.dev62.mylibrary.order.AdresseLivraison;
import fr.iut_fbleau.but3.dev62.mylibrary.order.LigneCommandeInfo;
import fr.iut_fbleau.but3.dev62.mylibrary.order.ModePaiement;
import fr.iut_fbleau.but3.dev62.mylibrary.order.OrderDTO;
import fr.iut_fbleau.but3.dev62.mylibrary.order.OrderInfo;
import fr.iut_fbleau.but3.dev62.mylibrary.order.entity.Order;
import fr.iut_fbleau.but3.dev62.mylibrary.order.exception.NotValidOrderException;
import fr.iut_fbleau.but3.dev62.mylibrary.order.repository.OrderRepository;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class OrderUseCaseTest {
@Mock
private OrderRepository orderRepository;
@Mock
private CustomerRepository customerRepository;
@Mock
private BookRepository bookRepository;
@InjectMocks
private OrderUseCase orderUseCase;
private UUID customerId;
private UUID bookId;
private Customer testCustomer;
private Book testBook;
private AdresseLivraison adresse;
private OrderInfo validOrderInfo;
@BeforeEach
void setUp() {
customerId = UUID.randomUUID();
bookId = UUID.randomUUID();
testCustomer = Customer.builder()
.id(customerId)
.firstName("Marie")
.lastName("Dupont")
.phoneNumber("0612345678")
.loyaltyPoints(100)
.build();
testBook = Book.builder()
.id(bookId)
.isbn("9782016289308")
.title("Le Petit Prince")
.author("Antoine de Saint-Exupery")
.publisher("Gallimard")
.publicationDate(LocalDate.of(1943, 4, 6))
.price(new BigDecimal("12.90"))
.stock(10)
.categories(List.of("Roman"))
.description("Un classique")
.language("FR")
.build();
adresse = new AdresseLivraison("1 rue de Paris", "Paris", "75001", "France");
validOrderInfo = new OrderInfo(
customerId,
List.of(new LigneCommandeInfo(bookId, 2)),
adresse,
ModePaiement.CB
);
}
@Nested
@DisplayName("PasserCommande tests")
class PasserCommandeTests {
@Test
@DisplayName("Should place order when valid data is provided")
void testPasserCommandeWithValidData() throws NotValidOrderException, CustomerNotFoundException {
when(customerRepository.findById(customerId)).thenReturn(Optional.of(testCustomer));
when(bookRepository.findById(bookId)).thenReturn(Optional.of(testBook));
when(customerRepository.save(any(Customer.class))).thenReturn(testCustomer);
UUID orderId = UUID.randomUUID();
Order savedOrder = Order.builder()
.id(orderId)
.clientId(customerId)
.montantTotal(new BigDecimal("25.80"))
.pointsFideliteGagnes(25)
.build();
when(orderRepository.save(any(Order.class))).thenReturn(savedOrder);
OrderDTO result = orderUseCase.passerCommande(validOrderInfo);
assertNotNull(result);
assertEquals(orderId, result.getCommandeId());
verify(orderRepository, times(1)).save(any(Order.class));
verify(customerRepository, times(1)).save(any(Customer.class));
}
@Test
@DisplayName("Should throw exception when customer does not exist")
void testPasserCommandeWithUnknownCustomer() {
when(customerRepository.findById(customerId)).thenReturn(Optional.empty());
assertThrows(CustomerNotFoundException.class,
() -> orderUseCase.passerCommande(validOrderInfo));
verify(orderRepository, never()).save(any(Order.class));
}
@Test
@DisplayName("Should throw exception when order has no items")
void testPasserCommandeWithNoItems() {
OrderInfo emptyOrder = new OrderInfo(customerId, List.of(), adresse, ModePaiement.CB);
assertThrows(NotValidOrderException.class,
() -> orderUseCase.passerCommande(emptyOrder));
verify(orderRepository, never()).save(any(Order.class));
}
@Test
@DisplayName("Should throw exception when quantity is zero or negative")
void testPasserCommandeWithInvalidQuantity() {
OrderInfo invalidQty = new OrderInfo(
customerId,
List.of(new LigneCommandeInfo(bookId, 0)),
adresse,
ModePaiement.CB
);
assertThrows(NotValidOrderException.class,
() -> orderUseCase.passerCommande(invalidQty));
verify(orderRepository, never()).save(any(Order.class));
}
@Test
@DisplayName("Should throw exception when clientId is null")
void testPasserCommandeWithNullClientId() {
OrderInfo nullClient = new OrderInfo(
null,
List.of(new LigneCommandeInfo(bookId, 1)),
adresse,
ModePaiement.CB
);
assertThrows(NotValidOrderException.class,
() -> orderUseCase.passerCommande(nullClient));
verify(orderRepository, never()).save(any(Order.class));
}
@Test
@DisplayName("Should throw exception when payment method is null")
void testPasserCommandeWithNullModePaiement() {
OrderInfo nullPayment = new OrderInfo(
customerId,
List.of(new LigneCommandeInfo(bookId, 1)),
adresse,
null
);
assertThrows(NotValidOrderException.class,
() -> orderUseCase.passerCommande(nullPayment));
verify(orderRepository, never()).save(any(Order.class));
}
}
@Nested
@DisplayName("FindOrder tests")
class FindOrderTests {
@Test
@DisplayName("Should return order when ID exists")
void testFindOrderById() {
UUID orderId = UUID.randomUUID();
Order order = Order.builder()
.id(orderId)
.clientId(customerId)
.montantTotal(new BigDecimal("25.80"))
.pointsFideliteGagnes(25)
.build();
when(orderRepository.findById(orderId)).thenReturn(Optional.of(order));
Optional<OrderDTO> result = orderUseCase.findOrderById(orderId);
assertTrue(result.isPresent());
assertEquals(orderId, result.get().getCommandeId());
}
@Test
@DisplayName("Should return empty Optional when ID does not exist")
void testFindOrderByIdNotFound() {
UUID nonExistentId = UUID.randomUUID();
when(orderRepository.findById(nonExistentId)).thenReturn(Optional.empty());
Optional<OrderDTO> result = orderUseCase.findOrderById(nonExistentId);
assertTrue(result.isEmpty());
}
}
}