From 797f92370f31758242e23069b3646321f1bbf410 Mon Sep 17 00:00:00 2001
From: Simon Saye Babu <114667196+SimonSayeBabu@users.noreply.github.com>
Date: Fri, 13 Jun 2025 03:51:26 +0200
Subject: [PATCH] first commit
---
.gitignore | 38 +++
.idea/workspace.xml | 226 ++++++++++++++
interface-contracts.json | 73 +++++
pom.xml | 151 ++++++++++
.../dev62/mylibrary/customer/CustomerDTO.java | 15 +
.../mylibrary/customer/CustomerInfo.java | 4 +
.../customer/converter/CustomerConverter.java | 30 ++
.../mylibrary/customer/entity/Customer.java | 30 ++
.../exception/CustomerNotFoundException.java | 13 +
.../IllegalCustomerPointException.java | 13 +
.../exception/NotValidCustomerException.java | 8 +
.../repository/CustomerRepository.java | 49 +++
.../customer/usecase/CustomerUseCase.java | 81 +++++
.../customer/validator/CustomerValidator.java | 44 +++
.../converter/CustomerConverterTest.java | 97 ++++++
.../customer/entity/CustomerTest.java | 136 +++++++++
.../CustomerNotFoundExceptionTest.java | 49 +++
.../IllegalCustomerPointExceptionTest.java | 69 +++++
.../NotValidCustomerExceptionTest.java | 61 ++++
.../repository/CustomerRepositoryTest.java | 227 ++++++++++++++
.../customer/usecase/CustomerUseCaseTest.java | 279 ++++++++++++++++++
.../validator/CustomerValidatorTest.java | 155 ++++++++++
.../mylibrary/features/RunCucumberTest.java | 14 +
.../features/client/CustomerSteps.java | 223 ++++++++++++++
src/test/resources/features/client.feature | 60 ++++
25 files changed, 2145 insertions(+)
create mode 100644 .gitignore
create mode 100644 .idea/workspace.xml
create mode 100644 interface-contracts.json
create mode 100644 pom.xml
create mode 100644 src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/CustomerDTO.java
create mode 100644 src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/CustomerInfo.java
create mode 100644 src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/converter/CustomerConverter.java
create mode 100644 src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/entity/Customer.java
create mode 100644 src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/CustomerNotFoundException.java
create mode 100644 src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/IllegalCustomerPointException.java
create mode 100644 src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/NotValidCustomerException.java
create mode 100644 src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/repository/CustomerRepository.java
create mode 100644 src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/usecase/CustomerUseCase.java
create mode 100644 src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/validator/CustomerValidator.java
create mode 100644 src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/converter/CustomerConverterTest.java
create mode 100644 src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/entity/CustomerTest.java
create mode 100644 src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/CustomerNotFoundExceptionTest.java
create mode 100644 src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/IllegalCustomerPointExceptionTest.java
create mode 100644 src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/NotValidCustomerExceptionTest.java
create mode 100644 src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/repository/CustomerRepositoryTest.java
create mode 100644 src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/usecase/CustomerUseCaseTest.java
create mode 100644 src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/validator/CustomerValidatorTest.java
create mode 100644 src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/features/RunCucumberTest.java
create mode 100644 src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/features/client/CustomerSteps.java
create mode 100644 src/test/resources/features/client.feature
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..71eeacd
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,226 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "customColor": "",
+ "associatedIndex": 8
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1741880838672
+
+
+ 1741880838672
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/interface-contracts.json b/interface-contracts.json
new file mode 100644
index 0000000..2bd28ea
--- /dev/null
+++ b/interface-contracts.json
@@ -0,0 +1,73 @@
+{
+ "usecases": {
+ "EnregistrerNouveauLivre": {
+ "input": {
+ "isbn": "string(13)",
+ "titre": "string(required)",
+ "auteur": "string(required)",
+ "editeur": "string(required)",
+ "datePublication": "date",
+ "prix": "decimal(positive)",
+ "stockInitial": "integer(min:0)",
+ "categories": "array",
+ "description": "string",
+ "langue": "string"
+ },
+ "output": {
+ "livreId": "uuid"
+ }
+ },
+
+ "PasserCommande": {
+ "input": {
+ "clientId": "uuid",
+ "lignesCommande": [{
+ "livreId": "uuid",
+ "quantite": "integer(positive)"
+ }],
+ "adresseLivraison": {
+ "rue": "string",
+ "ville": "string",
+ "codePostal": "string",
+ "pays": "string"
+ },
+ "modePaiement": "string(enum: CB, PAYPAL, POINTS_FIDELITE)"
+ },
+ "output": {
+ "commandeId": "uuid",
+ "montantTotal": "decimal",
+ "pointsFideliteGagnes": "integer"
+ }
+ },
+ "GererAvis": {
+ "input": {
+ "clientId": "uuid",
+ "livreId": "uuid",
+ "note": "integer(min:1,max:5)",
+ "commentaire": "string",
+ "dateAchat": "date"
+ },
+ "output": {
+ "avisId": "uuid"
+ }
+ },
+
+ "CreerAbonnement": {
+ "input": {
+ "clientId": "uuid",
+ "duree": "integer(enum: 3,6,12)",
+ "modePaiement": {
+ "type": "string(enum: CB, PAYPAL)",
+ "details": "object"
+ },
+ "dateDebutSouhaitee": "date"
+ },
+ "output": {
+ "abonnementId": "uuid",
+ "dateDebut": "date",
+ "dateFin": "date",
+ "montantMensuel": "decimal"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..27ec78e
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,151 @@
+
+
+ 4.0.0
+
+ fr.iut_fbleau.but3.dev62
+ mylibrary
+ 1.0-SNAPSHOT
+
+
+
+ 21
+ 21
+ UTF-8
+
+
+ 1.18.36
+
+
+ 5.11.4
+ 1.11.4
+ 7.21.1
+ 5.16.0
+
+
+ 3.13.0
+ 3.5.2
+
+
+
+
+
+ io.cucumber
+ cucumber-bom
+ ${cucumber.version}
+ pom
+ import
+
+
+ org.junit
+ junit-bom
+ ${junit.version}
+ pom
+ import
+
+
+
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+
+ io.cucumber
+ cucumber-java
+ test
+
+
+
+ io.cucumber
+ cucumber-junit-platform-engine
+ test
+
+
+
+ org.junit.platform
+ junit-platform-suite
+ ${junit.platform.version}
+ test
+
+
+ org.junit.platform
+ junit-platform-engine
+ ${junit.platform.version}
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ ${junit.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit.version}
+ test
+
+
+ org.junit.platform
+ junit-platform-launcher
+ ${junit.platform.version}
+ test
+
+
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ ${mockito.version}
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven.compiler.version}
+
+ ${project.build.sourceEncoding}
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven.surefire.version}
+
+
+
+
+ cucumber.junit-platform.naming-strategy=long
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/CustomerDTO.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/CustomerDTO.java
new file mode 100644
index 0000000..96f626b
--- /dev/null
+++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/CustomerDTO.java
@@ -0,0 +1,15 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer;
+
+import java.util.UUID;
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class CustomerDTO {
+ private final UUID id;
+ private final String firstName;
+ private final String lastName;
+ private final String phoneNumber;
+ private final int loyaltyPoints;
+}
diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/CustomerInfo.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/CustomerInfo.java
new file mode 100644
index 0000000..30ac1e4
--- /dev/null
+++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/CustomerInfo.java
@@ -0,0 +1,4 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer;
+
+public record CustomerInfo(String firstName, String lastName, String phoneNumber) {
+}
diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/converter/CustomerConverter.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/converter/CustomerConverter.java
new file mode 100644
index 0000000..e420020
--- /dev/null
+++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/converter/CustomerConverter.java
@@ -0,0 +1,30 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.converter;
+
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.CustomerDTO;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.CustomerInfo;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.entity.Customer;
+
+public final class CustomerConverter {
+ private CustomerConverter(){
+
+ }
+
+ public static Customer toDomain(CustomerInfo newCustomer) {
+ return Customer.builder()
+ .firstName(newCustomer.firstName())
+ .lastName(newCustomer.lastName())
+ .phoneNumber(newCustomer.phoneNumber())
+ .loyaltyPoints(0)
+ .build();
+ }
+
+ public static CustomerDTO toDTO(Customer customer) {
+ return CustomerDTO.builder()
+ .id(customer.getId())
+ .firstName(customer.getFirstName())
+ .lastName(customer.getLastName())
+ .phoneNumber(customer.getPhoneNumber())
+ .loyaltyPoints(customer.getLoyaltyPoints())
+ .build();
+ }
+}
diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/entity/Customer.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/entity/Customer.java
new file mode 100644
index 0000000..5a2fa69
--- /dev/null
+++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/entity/Customer.java
@@ -0,0 +1,30 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.entity;
+
+
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.exception.IllegalCustomerPointException;
+import java.util.UUID;
+import lombok.Builder;
+import lombok.Getter;
+
+@Builder
+@Getter
+public class Customer {
+ private UUID id;
+ private String firstName;
+ private String lastName;
+ private String phoneNumber;
+ private int loyaltyPoints;
+
+ public void setRandomUUID() {
+ this.id = UUID.randomUUID();
+ }
+
+ public void addLoyaltyPoints(int loyaltyPointToAdd) {
+ this.loyaltyPoints += loyaltyPointToAdd;
+ }
+
+ public void removeLoyaltyPoints(int loyaltyPointToRemove) throws IllegalCustomerPointException {
+ if (loyaltyPointToRemove > this.loyaltyPoints) throw new IllegalCustomerPointException(loyaltyPointToRemove, this.loyaltyPoints);
+ this.loyaltyPoints -= loyaltyPointToRemove;
+ }
+}
diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/CustomerNotFoundException.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/CustomerNotFoundException.java
new file mode 100644
index 0000000..722797c
--- /dev/null
+++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/CustomerNotFoundException.java
@@ -0,0 +1,13 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.exception;
+
+import java.text.MessageFormat;
+import java.util.UUID;
+
+public class CustomerNotFoundException extends Exception {
+
+ public static final String THE_CUSTOMER_WITH_ID_DOES_NOT_EXIST_MESSAGE = "The customer with id {0} does not exist";
+
+ public CustomerNotFoundException(UUID uuid) {
+ super(MessageFormat.format(THE_CUSTOMER_WITH_ID_DOES_NOT_EXIST_MESSAGE, uuid));
+ }
+}
diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/IllegalCustomerPointException.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/IllegalCustomerPointException.java
new file mode 100644
index 0000000..1cca78b
--- /dev/null
+++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/IllegalCustomerPointException.java
@@ -0,0 +1,13 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.exception;
+
+import java.text.MessageFormat;
+
+public class IllegalCustomerPointException extends Exception {
+
+ public static final String CANNOT_REMOVE_LOYALTY_POINTS = "Cannot remove {0} points from {1} points";
+
+ public IllegalCustomerPointException(int needed, int actual) {
+ super(MessageFormat.format(CANNOT_REMOVE_LOYALTY_POINTS, needed,
+ actual));
+ }
+}
diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/NotValidCustomerException.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/NotValidCustomerException.java
new file mode 100644
index 0000000..47779f1
--- /dev/null
+++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/NotValidCustomerException.java
@@ -0,0 +1,8 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.exception;
+
+public class NotValidCustomerException extends Exception {
+
+ public NotValidCustomerException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/repository/CustomerRepository.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/repository/CustomerRepository.java
new file mode 100644
index 0000000..7d79f32
--- /dev/null
+++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/repository/CustomerRepository.java
@@ -0,0 +1,49 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.repository;
+
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.entity.Customer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+public final class CustomerRepository {
+ private final List customers = new ArrayList<>();
+
+ public List findAll() {
+ return customers;
+ }
+
+ public void deleteAll() {
+ customers.clear();
+ }
+
+ public Customer save(Customer newCustomer) {
+ Optional optionalCustomerWithSameId = this.findById(newCustomer.getId());
+ optionalCustomerWithSameId.ifPresentOrElse(customers::remove, newCustomer::setRandomUUID);
+ this.customers.add(newCustomer);
+ return newCustomer;
+ }
+
+ public Optional findById(UUID uuid) {
+ return this.customers.stream()
+ .filter(customer -> customer.getId().equals(uuid))
+ .findFirst();
+ }
+
+ public boolean existsById(UUID uuid) {
+ return this.customers.stream()
+ .anyMatch(customer -> customer.getId().equals(uuid));
+ }
+
+ public Optional findByPhoneNumber(String phoneNumber) {
+ return this.customers.stream()
+ .filter(customer -> customer.getPhoneNumber().equals(phoneNumber))
+ .findFirst();
+ }
+
+ public void delete(Customer customer) {
+ this.customers.remove(customer);
+ }
+}
diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/usecase/CustomerUseCase.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/usecase/CustomerUseCase.java
new file mode 100644
index 0000000..3241c30
--- /dev/null
+++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/usecase/CustomerUseCase.java
@@ -0,0 +1,81 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.usecase;
+
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.CustomerDTO;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.CustomerInfo;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.converter.CustomerConverter;
+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.exception.IllegalCustomerPointException;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.exception.NotValidCustomerException;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.repository.CustomerRepository;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.validator.CustomerValidator;
+import java.util.Optional;
+import java.util.UUID;
+
+public final class CustomerUseCase {
+
+ private final CustomerRepository customerRepository;
+
+ public CustomerUseCase(CustomerRepository customerRepository) {
+ this.customerRepository = customerRepository;
+ }
+
+ public UUID registerCustomer(CustomerInfo newCustomer) throws NotValidCustomerException {
+ CustomerValidator.validate(newCustomer);
+ Customer customerToRegister = CustomerConverter.toDomain(newCustomer);
+ Customer customerToRegistered = customerRepository.save(customerToRegister);
+ return customerToRegistered.getId();
+ }
+
+ public Optional findCustomerByPhoneNumber(String phoneNumber) {
+ Optional optionalCustomer = customerRepository.findByPhoneNumber(phoneNumber);
+ return optionalCustomer.map(CustomerConverter::toDTO);
+ }
+
+ public CustomerDTO updateCustomer(UUID uuid, CustomerInfo customerInfo)
+ throws CustomerNotFoundException, NotValidCustomerException {
+ CustomerValidator.validate(customerInfo);
+ Customer customerByUUID = getCustomerIfDoesNotExistThrowCustomerNotFoundException(
+ uuid);
+ Customer customer = Customer.builder()
+ .id(uuid)
+ .firstName(customerInfo.firstName())
+ .lastName(customerInfo.lastName())
+ .phoneNumber(customerInfo.phoneNumber())
+ .loyaltyPoints(customerByUUID.getLoyaltyPoints())
+ .build();
+ Customer updatedCustomer = customerRepository.save(customer);
+ return CustomerConverter.toDTO(updatedCustomer);
+ }
+
+ public void deleteCustomer(UUID uuid) throws CustomerNotFoundException {
+ Customer customerToDelete = getCustomerIfDoesNotExistThrowCustomerNotFoundException(uuid);
+ this.customerRepository.delete(customerToDelete);
+ }
+
+ public int addLoyaltyPoints(UUID uuid, int loyaltyPointToAdd) throws CustomerNotFoundException {
+ Customer customerToAddLoyaltyPoints = getCustomerIfDoesNotExistThrowCustomerNotFoundException(
+ uuid);
+ customerToAddLoyaltyPoints.addLoyaltyPoints(loyaltyPointToAdd);
+ customerRepository.save(customerToAddLoyaltyPoints);
+ return customerToAddLoyaltyPoints.getLoyaltyPoints();
+ }
+
+ public int subtractLoyaltyPoints(UUID uuid, int loyaltyPointToRemove)
+ throws CustomerNotFoundException, IllegalCustomerPointException {
+ Customer customerToSubtractLoyaltyPoints = getCustomerIfDoesNotExistThrowCustomerNotFoundException(
+ uuid);
+ customerToSubtractLoyaltyPoints.removeLoyaltyPoints(loyaltyPointToRemove);
+ customerRepository.save(customerToSubtractLoyaltyPoints);
+ return customerToSubtractLoyaltyPoints.getLoyaltyPoints();
+ }
+
+ private Customer getCustomerIfDoesNotExistThrowCustomerNotFoundException(UUID uuid)
+ throws CustomerNotFoundException {
+ Optional optionalCustomerById = customerRepository.findById(uuid);
+ if (optionalCustomerById.isEmpty()) {
+ throw new CustomerNotFoundException(uuid);
+ }
+ return optionalCustomerById.get();
+ }
+}
diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/validator/CustomerValidator.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/validator/CustomerValidator.java
new file mode 100644
index 0000000..d9bd9c1
--- /dev/null
+++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/validator/CustomerValidator.java
@@ -0,0 +1,44 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.validator;
+
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.CustomerInfo;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.exception.NotValidCustomerException;
+
+public final class CustomerValidator {
+
+ public static final String PHONE_NUMBER_IS_NOT_VALID = "Phone number is not valid";
+ public static final String LAST_NAME_CANNOT_BE_BLANK = "Last name cannot be blank";
+ public static final String FIRST_NAME_CANNOT_BE_BLANK = "First name cannot be blank";
+ public static final String PHONE_NUMBER_REGEX = "0([67])\\d{8}";
+
+ private CustomerValidator() {
+
+ }
+
+ public static void validate(CustomerInfo newCustomer) throws NotValidCustomerException {
+ validateFirstName(newCustomer);
+ validateLastName(newCustomer);
+ validatePhoneNumber(newCustomer);
+ }
+
+ private static void validatePhoneNumber(CustomerInfo newCustomer)
+ throws NotValidCustomerException {
+ if (newCustomer.phoneNumber().isBlank()) {
+ throw new NotValidCustomerException("Phone number cannot be blank");
+ }
+ if (!newCustomer.phoneNumber().matches(PHONE_NUMBER_REGEX)) {
+ throw new NotValidCustomerException(PHONE_NUMBER_IS_NOT_VALID);
+ }
+ }
+
+ private static void validateLastName(CustomerInfo newCustomer) throws NotValidCustomerException {
+ if (newCustomer.lastName().isBlank()) {
+ throw new NotValidCustomerException(LAST_NAME_CANNOT_BE_BLANK);
+ }
+ }
+
+ private static void validateFirstName(CustomerInfo newCustomer) throws NotValidCustomerException {
+ if (newCustomer.firstName().isBlank()) {
+ throw new NotValidCustomerException(FIRST_NAME_CANNOT_BE_BLANK);
+ }
+ }
+}
diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/converter/CustomerConverterTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/converter/CustomerConverterTest.java
new file mode 100644
index 0000000..231fbab
--- /dev/null
+++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/converter/CustomerConverterTest.java
@@ -0,0 +1,97 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.converter;
+
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.CustomerDTO;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.CustomerInfo;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.entity.Customer;
+import java.util.UUID;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+@DisplayName("CustomerConverter Unit Tests")
+class CustomerConverterTest {
+
+ @Nested
+ @DisplayName("toDomain() method tests")
+ class ToDomainTests {
+
+ @Test
+ @DisplayName("Should convert CustomerInfo to Customer domain object with loyalty points initialized to 0")
+ void shouldConvertCustomerInfoToDomain() {
+ // Given
+ CustomerInfo customerInfo = new CustomerInfo("John", "Doe", "0123456789");
+
+ // When
+ Customer result = CustomerConverter.toDomain(customerInfo);
+
+ // Then
+ assertNotNull(result);
+ assertEquals(customerInfo.firstName(), result.getFirstName());
+ assertEquals(customerInfo.lastName(), result.getLastName());
+ assertEquals(customerInfo.phoneNumber(), result.getPhoneNumber());
+ assertEquals(0, result.getLoyaltyPoints());
+ }
+ }
+
+ @Nested
+ @DisplayName("toDTO() method tests")
+ class ToDTOTests {
+
+ @Test
+ @DisplayName("Should convert Customer domain object to CustomerDTO with all fields mapped correctly")
+ void shouldConvertCustomerToDTO() {
+ Customer customer = Customer.builder()
+ .id(UUID.randomUUID())
+ .firstName("Jane")
+ .lastName("Smith")
+ .phoneNumber("9876543210")
+ .loyaltyPoints(100)
+ .build();
+
+ CustomerDTO result = CustomerConverter.toDTO(customer);
+
+ assertNotNull(result);
+ assertEquals(customer.getId(), result.getId());
+ assertEquals(customer.getFirstName(), result.getFirstName());
+ assertEquals(customer.getLastName(), result.getLastName());
+ assertEquals(customer.getPhoneNumber(), result.getPhoneNumber());
+ assertEquals(customer.getLoyaltyPoints(), result.getLoyaltyPoints());
+ }
+ }
+
+ @Test
+ @DisplayName("Should handle null values properly when converting between objects")
+ void shouldHandleNullValuesGracefully() {
+ Customer customer = Customer.builder()
+ .id(UUID.randomUUID())
+ .firstName(null)
+ .lastName("NullTest")
+ .phoneNumber(null)
+ .loyaltyPoints(50)
+ .build();
+
+ CustomerDTO result = CustomerConverter.toDTO(customer);
+
+ assertNotNull(result);
+ assertNull(result.getFirstName());
+ assertEquals("NullTest", result.getLastName());
+ assertNull(result.getPhoneNumber());
+ }
+
+ @Test
+ @DisplayName("Should preserve empty string values during conversion")
+ void shouldPreserveEmptyStrings() {
+ CustomerInfo customerInfo = new CustomerInfo("", "", "");
+
+ Customer domainResult = CustomerConverter.toDomain(customerInfo);
+ CustomerDTO dtoResult = CustomerConverter.toDTO(domainResult);
+
+ assertEquals("", dtoResult.getFirstName());
+ assertEquals("", dtoResult.getLastName());
+ assertEquals("", dtoResult.getPhoneNumber());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/entity/CustomerTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/entity/CustomerTest.java
new file mode 100644
index 0000000..515187e
--- /dev/null
+++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/entity/CustomerTest.java
@@ -0,0 +1,136 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.entity;
+
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.exception.IllegalCustomerPointException;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.UUID;
+
+class CustomerTest {
+
+ @Test
+ @DisplayName("Builder should create a valid Customer instance")
+ void testCustomerBuilder() {
+ UUID id = UUID.randomUUID();
+ String firstName = "John";
+ String lastName = "Doe";
+ String phoneNumber = "0123456789";
+ int loyaltyPoints = 100;
+
+ Customer customer = Customer.builder()
+ .id(id)
+ .firstName(firstName)
+ .lastName(lastName)
+ .phoneNumber(phoneNumber)
+ .loyaltyPoints(loyaltyPoints)
+ .build();
+
+ assertEquals(id, customer.getId());
+ assertEquals(firstName, customer.getFirstName());
+ assertEquals(lastName, customer.getLastName());
+ assertEquals(phoneNumber, customer.getPhoneNumber());
+ assertEquals(loyaltyPoints, customer.getLoyaltyPoints());
+ }
+
+ @Test
+ @DisplayName("setRandomUUID should change the ID to a new random UUID")
+ void testSetRandomUUID() {
+ Customer customer = Customer.builder().build();
+ UUID originalId = customer.getId();
+
+ customer.setRandomUUID();
+
+ assertNotNull(customer.getId());
+ assertNotEquals(originalId, customer.getId());
+ }
+
+ @Nested
+ @DisplayName("Loyalty Points Tests")
+ class LoyaltyPointsTests {
+
+ @Test
+ @DisplayName("addLoyaltyPoints should correctly increment loyalty points")
+ void testAddLoyaltyPoints() {
+ Customer customer = Customer.builder()
+ .loyaltyPoints(50)
+ .build();
+ int pointsToAdd = 25;
+ int expectedPoints = 75;
+
+ customer.addLoyaltyPoints(pointsToAdd);
+
+ assertEquals(expectedPoints, customer.getLoyaltyPoints());
+ }
+
+ @Test
+ @DisplayName("addLoyaltyPoints should handle zero points correctly")
+ void testAddZeroLoyaltyPoints() {
+ Customer customer = Customer.builder()
+ .loyaltyPoints(50)
+ .build();
+
+ customer.addLoyaltyPoints(0);
+
+ assertEquals(50, customer.getLoyaltyPoints());
+ }
+
+ @Test
+ @DisplayName("removeLoyaltyPoints should correctly decrement loyalty points")
+ void testRemoveLoyaltyPoints() throws IllegalCustomerPointException {
+ Customer customer = Customer.builder()
+ .loyaltyPoints(50)
+ .build();
+ int pointsToRemove = 20;
+ int expectedPoints = 30;
+
+ customer.removeLoyaltyPoints(pointsToRemove);
+
+ assertEquals(expectedPoints, customer.getLoyaltyPoints());
+ }
+
+ @Test
+ @DisplayName("removeLoyaltyPoints should handle removing exactly all points")
+ void testRemoveAllLoyaltyPoints() throws IllegalCustomerPointException {
+ Customer customer = Customer.builder()
+ .loyaltyPoints(50)
+ .build();
+
+ customer.removeLoyaltyPoints(50);
+
+ assertEquals(0, customer.getLoyaltyPoints());
+ }
+
+ @Test
+ @DisplayName("removeLoyaltyPoints should throw exception when trying to remove more points than available")
+ void testRemoveTooManyLoyaltyPoints() {
+ Customer customer = Customer.builder()
+ .loyaltyPoints(50)
+ .build();
+ int pointsToRemove = 75;
+
+ IllegalCustomerPointException exception = assertThrows(
+ IllegalCustomerPointException.class,
+ () -> customer.removeLoyaltyPoints(pointsToRemove)
+ );
+
+ assertEquals(50, customer.getLoyaltyPoints());
+
+ assertTrue(exception.getMessage().contains(String.valueOf(pointsToRemove)));
+ assertTrue(exception.getMessage().contains(String.valueOf(customer.getLoyaltyPoints())));
+ }
+
+ @Test
+ @DisplayName("removeLoyaltyPoints should handle removing zero points correctly")
+ void testRemoveZeroLoyaltyPoints() throws IllegalCustomerPointException {
+ Customer customer = Customer.builder()
+ .loyaltyPoints(50)
+ .build();
+
+ customer.removeLoyaltyPoints(0);
+
+ assertEquals(50, customer.getLoyaltyPoints());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/CustomerNotFoundExceptionTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/CustomerNotFoundExceptionTest.java
new file mode 100644
index 0000000..fcde9da
--- /dev/null
+++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/CustomerNotFoundExceptionTest.java
@@ -0,0 +1,49 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.exception;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class CustomerNotFoundExceptionTest {
+
+ @Test
+ @DisplayName("Exception message should contain the UUID provided")
+ void testExceptionMessageContainsUUID() {
+ UUID uuid = UUID.randomUUID();
+
+ CustomerNotFoundException exception = new CustomerNotFoundException(uuid);
+
+ String expectedMessage = String.format("The customer with id %s does not exist", uuid);
+ assertEquals(expectedMessage, exception.getMessage());
+ }
+
+ @Test
+ @DisplayName("Exception should use the correct constant message format")
+ void testExceptionUsesConstantMessageFormat() {
+ UUID uuid = UUID.randomUUID();
+
+ CustomerNotFoundException exception = new CustomerNotFoundException(uuid);
+
+ String expectedFormatWithPlaceholder = "The customer with id {0} does not exist";
+ assertEquals(CustomerNotFoundException.THE_CUSTOMER_WITH_ID_DOES_NOT_EXIST_MESSAGE,
+ expectedFormatWithPlaceholder);
+ assertTrue(exception.getMessage().contains(uuid.toString()));
+ }
+
+ @Test
+ @DisplayName("Exception should be properly thrown and caught")
+ void testExceptionCanBeThrownAndCaught() {
+ UUID uuid = UUID.randomUUID();
+
+ try {
+ throw new CustomerNotFoundException(uuid);
+ } catch (CustomerNotFoundException e) {
+ String expectedMessage = String.format("The customer with id %s does not exist", uuid);
+ assertEquals(expectedMessage, e.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/IllegalCustomerPointExceptionTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/IllegalCustomerPointExceptionTest.java
new file mode 100644
index 0000000..c89306c
--- /dev/null
+++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/IllegalCustomerPointExceptionTest.java
@@ -0,0 +1,69 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.exception;
+
+import java.text.MessageFormat;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class IllegalCustomerPointExceptionTest {
+
+ @Test
+ @DisplayName("Exception message should contain the needed and actual points")
+ void testExceptionMessageContainsPoints() {
+ int neededPoints = 100;
+ int actualPoints = 50;
+
+ IllegalCustomerPointException exception = new IllegalCustomerPointException(neededPoints, actualPoints);
+
+ String expectedMessage = "Cannot remove 100 points from 50 points";
+ assertEquals(expectedMessage, exception.getMessage());
+ }
+
+ @ParameterizedTest
+ @CsvSource({
+ "100, 50",
+ "75, 25",
+ "200, 150",
+ "1000, 750"
+ })
+ @DisplayName("Exception message should be formatted correctly for different point values")
+ void testExceptionMessageForDifferentPointValues(int neededPoints, int actualPoints) {
+ IllegalCustomerPointException exception = new IllegalCustomerPointException(neededPoints, actualPoints);
+
+ String expectedMessage = MessageFormat.format(IllegalCustomerPointException.CANNOT_REMOVE_LOYALTY_POINTS, neededPoints, actualPoints);
+ assertEquals(expectedMessage, exception.getMessage());
+ }
+
+ @Test
+ @DisplayName("Exception should use the correct constant message format")
+ void testExceptionUsesConstantMessageFormat() {
+ int neededPoints = 100;
+ int actualPoints = 50;
+
+ IllegalCustomerPointException exception = new IllegalCustomerPointException(neededPoints, actualPoints);
+
+ String expectedFormatWithPlaceholder = "Cannot remove {0} points from {1} points";
+ assertEquals(IllegalCustomerPointException.CANNOT_REMOVE_LOYALTY_POINTS,
+ expectedFormatWithPlaceholder);
+ assertTrue(exception.getMessage().contains(String.valueOf(neededPoints)));
+ assertTrue(exception.getMessage().contains(String.valueOf(actualPoints)));
+ }
+
+ @Test
+ @DisplayName("Exception should be properly thrown and caught")
+ void testExceptionCanBeThrownAndCaught() {
+ int neededPoints = 100;
+ int actualPoints = 50;
+
+ try {
+ throw new IllegalCustomerPointException(neededPoints, actualPoints);
+ } catch (IllegalCustomerPointException e) {
+ String expectedMessage = String.format("Cannot remove %d points from %d points", neededPoints, actualPoints);
+ assertEquals(expectedMessage, e.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/NotValidCustomerExceptionTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/NotValidCustomerExceptionTest.java
new file mode 100644
index 0000000..3fba6e1
--- /dev/null
+++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/exception/NotValidCustomerExceptionTest.java
@@ -0,0 +1,61 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.exception;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class NotValidCustomerExceptionTest {
+
+ @Test
+ @DisplayName("Exception should be created with the provided message")
+ void testExceptionCreation() {
+ String errorMessage = "Customer data is not valid";
+
+ NotValidCustomerException exception = new NotValidCustomerException(errorMessage);
+
+ assertEquals(errorMessage, exception.getMessage());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {
+ "First name is required",
+ "Last name cannot be empty",
+ "Phone number format is invalid",
+ "Customer age must be above 18"
+ })
+ @DisplayName("Exception should handle different validation messages")
+ void testExceptionWithDifferentMessages(String errorMessage) {
+ NotValidCustomerException exception = new NotValidCustomerException(errorMessage);
+
+ assertEquals(errorMessage, exception.getMessage());
+ }
+
+ @Test
+ @DisplayName("Exception should be properly thrown and caught")
+ void testExceptionCanBeThrownAndCaught() {
+ String errorMessage = "Required field is missing";
+
+ Exception exception = assertThrows(NotValidCustomerException.class, () -> {
+ throw new NotValidCustomerException(errorMessage);
+ });
+
+ assertEquals(errorMessage, exception.getMessage());
+ }
+
+ @Test
+ @DisplayName("Exception should be catchable as a general Exception")
+ void testExceptionInheritance() {
+ String errorMessage = "Invalid customer data";
+
+ try {
+ throw new NotValidCustomerException(errorMessage);
+ } catch (Exception e) {
+ assertEquals(NotValidCustomerException.class, e.getClass());
+ assertEquals(errorMessage, e.getMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/repository/CustomerRepositoryTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/repository/CustomerRepositoryTest.java
new file mode 100644
index 0000000..4495493
--- /dev/null
+++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/repository/CustomerRepositoryTest.java
@@ -0,0 +1,227 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.repository;
+
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.entity.Customer;
+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 java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class CustomerRepositoryTest {
+
+ private CustomerRepository repository;
+ private Customer customer1;
+ private Customer customer2;
+
+ @BeforeEach
+ void setUp() {
+ repository = new CustomerRepository();
+
+ customer1 = Customer.builder()
+ .firstName("John")
+ .lastName("Doe")
+ .phoneNumber("0123456789")
+ .loyaltyPoints(100)
+ .build();
+ customer1.setRandomUUID();
+
+ customer2 = Customer.builder()
+ .firstName("Jane")
+ .lastName("Smith")
+ .phoneNumber("9876543210")
+ .loyaltyPoints(200)
+ .build();
+ customer2.setRandomUUID();
+ }
+
+ @Test
+ @DisplayName("New repository should be empty")
+ void testNewRepositoryIsEmpty() {
+ List customers = repository.findAll();
+
+ assertTrue(customers.isEmpty());
+ assertEquals(0, customers.size());
+ }
+
+ @Nested
+ @DisplayName("Save operations")
+ class SaveOperations {
+
+ @Test
+ @DisplayName("Save should add a new customer")
+ void testSaveNewCustomer() {
+ Customer savedCustomer = repository.save(customer1);
+
+ assertEquals(1, repository.findAll().size());
+ assertEquals(customer1.getId(), savedCustomer.getId());
+ assertEquals(customer1.getFirstName(), savedCustomer.getFirstName());
+ }
+
+ @Test
+ @DisplayName("Save should update existing customer with same ID")
+ void testSaveUpdatesExistingCustomer() {
+ repository.save(customer1);
+
+ UUID id = customer1.getId();
+ Customer updatedCustomer = Customer.builder()
+ .id(id)
+ .firstName("John")
+ .lastName("Updated")
+ .phoneNumber("1111111111")
+ .loyaltyPoints(150)
+ .build();
+
+ Customer savedCustomer = repository.save(updatedCustomer);
+
+ assertEquals(1, repository.findAll().size());
+ assertEquals(id, savedCustomer.getId());
+ assertEquals("Updated", savedCustomer.getLastName());
+ assertEquals("1111111111", savedCustomer.getPhoneNumber());
+ assertEquals(150, savedCustomer.getLoyaltyPoints());
+ }
+
+ @Test
+ @DisplayName("Save multiple customers should add all of them")
+ void testSaveMultipleCustomers() {
+ repository.save(customer1);
+ repository.save(customer2);
+
+ List customers = repository.findAll();
+
+ assertEquals(2, customers.size());
+ assertTrue(customers.contains(customer1));
+ assertTrue(customers.contains(customer2));
+ }
+ }
+
+ @Nested
+ @DisplayName("Find operations")
+ class FindOperations {
+
+ @BeforeEach
+ void setUpCustomers() {
+ repository.save(customer1);
+ repository.save(customer2);
+ }
+
+ @Test
+ @DisplayName("FindAll should return all customers")
+ void testFindAll() {
+ List customers = repository.findAll();
+
+ assertEquals(2, customers.size());
+ assertTrue(customers.contains(customer1));
+ assertTrue(customers.contains(customer2));
+ }
+
+ @Test
+ @DisplayName("FindById should return customer with matching ID")
+ void testFindById() {
+ Optional foundCustomer = repository.findById(customer1.getId());
+
+ assertTrue(foundCustomer.isPresent());
+ assertEquals(customer1.getFirstName(), foundCustomer.get().getFirstName());
+ assertEquals(customer1.getLastName(), foundCustomer.get().getLastName());
+ }
+
+ @Test
+ @DisplayName("FindById should return empty Optional when ID doesn't exist")
+ void testFindByIdNotFound() {
+ UUID nonExistentId = UUID.randomUUID();
+
+ Optional foundCustomer = repository.findById(nonExistentId);
+
+ assertTrue(foundCustomer.isEmpty());
+ }
+
+ @Test
+ @DisplayName("FindByPhoneNumber should return customer with matching phone number")
+ void testFindByPhoneNumber() {
+ Optional foundCustomer = repository.findByPhoneNumber("0123456789");
+
+ assertTrue(foundCustomer.isPresent());
+ assertEquals(customer1.getId(), foundCustomer.get().getId());
+ assertEquals(customer1.getFirstName(), foundCustomer.get().getFirstName());
+ }
+
+ @Test
+ @DisplayName("FindByPhoneNumber should return empty Optional when phone number doesn't exist")
+ void testFindByPhoneNumberNotFound() {
+ Optional foundCustomer = repository.findByPhoneNumber("0000000000");
+
+ assertTrue(foundCustomer.isEmpty());
+ }
+
+ @Test
+ @DisplayName("ExistsById should return true when ID exists")
+ void testExistsByIdExists() {
+ boolean exists = repository.existsById(customer1.getId());
+
+ assertTrue(exists);
+ }
+
+ @Test
+ @DisplayName("ExistsById should return false when ID doesn't exist")
+ void testExistsByIdNotExists() {
+ UUID nonExistentId = UUID.randomUUID();
+
+ boolean exists = repository.existsById(nonExistentId);
+
+ assertFalse(exists);
+ }
+ }
+
+ @Nested
+ @DisplayName("Delete operations")
+ class DeleteOperations {
+
+ @BeforeEach
+ void setUpCustomers() {
+ repository.save(customer1);
+ repository.save(customer2);
+ }
+
+ @Test
+ @DisplayName("Delete should remove the specified customer")
+ void testDelete() {
+ repository.delete(customer1);
+
+ List customers = repository.findAll();
+
+ assertEquals(1, customers.size());
+ assertFalse(customers.contains(customer1));
+ assertTrue(customers.contains(customer2));
+ }
+
+ @Test
+ @DisplayName("DeleteAll should remove all customers")
+ void testDeleteAll() {
+ repository.deleteAll();
+
+ List customers = repository.findAll();
+
+ assertTrue(customers.isEmpty());
+ assertEquals(0, customers.size());
+ }
+
+ @Test
+ @DisplayName("Delete should not throw exception when customer doesn't exist")
+ void testDeleteNonExistentCustomer() {
+ Customer nonExistentCustomer = Customer.builder()
+ .firstName("Non")
+ .lastName("Existent")
+ .phoneNumber("0000000000")
+ .build();
+ nonExistentCustomer.setRandomUUID();
+
+ assertDoesNotThrow(() -> repository.delete(nonExistentCustomer));
+
+ assertEquals(2, repository.findAll().size());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/usecase/CustomerUseCaseTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/usecase/CustomerUseCaseTest.java
new file mode 100644
index 0000000..7159bdb
--- /dev/null
+++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/usecase/CustomerUseCaseTest.java
@@ -0,0 +1,279 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.usecase;
+
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.CustomerDTO;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.CustomerInfo;
+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.exception.IllegalCustomerPointException;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.exception.NotValidCustomerException;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.repository.CustomerRepository;
+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 java.util.Optional;
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+class CustomerUseCaseTest {
+
+ @Mock
+ private CustomerRepository customerRepository;
+
+ @InjectMocks
+ private CustomerUseCase customerUseCase;
+
+ private UUID customerId;
+ private Customer testCustomer;
+ private CustomerInfo validCustomerInfo;
+
+ @BeforeEach
+ void setUp() {
+ customerId = UUID.randomUUID();
+ testCustomer = Customer.builder()
+ .id(customerId)
+ .firstName("John")
+ .lastName("Doe")
+ .phoneNumber("0612345678")
+ .loyaltyPoints(100)
+ .build();
+
+ validCustomerInfo = new CustomerInfo("John", "Doe", "0612345678");
+ }
+
+ @Nested
+ @DisplayName("Register customer tests")
+ class RegisterCustomerTests {
+
+ @Test
+ @DisplayName("Should register customer when valid data is provided")
+ void testRegisterCustomerWithValidData() throws NotValidCustomerException {
+ when(customerRepository.save(any(Customer.class))).thenReturn(testCustomer);
+
+ UUID registeredId = customerUseCase.registerCustomer(validCustomerInfo);
+
+ assertNotNull(registeredId);
+ assertEquals(customerId, registeredId);
+ verify(customerRepository, times(1)).save(any(Customer.class));
+ }
+
+ @Test
+ @DisplayName("Should throw exception when customer data is not valid")
+ void testRegisterCustomerWithInvalidData() {
+ CustomerInfo invalidCustomerInfo = new CustomerInfo("", "", "");
+
+ assertThrows(NotValidCustomerException.class,
+ () -> customerUseCase.registerCustomer(invalidCustomerInfo));
+
+ verify(customerRepository, never()).save(any(Customer.class));
+ }
+ }
+
+ @Nested
+ @DisplayName("Find customer tests")
+ class FindCustomerTests {
+
+ @Test
+ @DisplayName("Should return customer when phone number exists")
+ void testFindCustomerByPhoneNumber() {
+ when(customerRepository.findByPhoneNumber("0612345678")).thenReturn(Optional.of(testCustomer));
+
+ Optional foundCustomer = customerUseCase.findCustomerByPhoneNumber("0612345678");
+
+ assertTrue(foundCustomer.isPresent());
+ assertEquals(testCustomer.getId(), foundCustomer.get().getId());
+ assertEquals(testCustomer.getFirstName(), foundCustomer.get().getFirstName());
+ verify(customerRepository, times(1)).findByPhoneNumber("0612345678");
+ }
+
+ @Test
+ @DisplayName("Should return empty Optional when phone number doesn't exist")
+ void testFindCustomerByPhoneNumberNotFound() {
+ when(customerRepository.findByPhoneNumber("0799999999")).thenReturn(Optional.empty());
+
+ Optional foundCustomer = customerUseCase.findCustomerByPhoneNumber("0799999999");
+
+ assertTrue(foundCustomer.isEmpty());
+ verify(customerRepository, times(1)).findByPhoneNumber("0799999999");
+ }
+ }
+
+ @Nested
+ @DisplayName("Update customer tests")
+ class UpdateCustomerTests {
+
+ @Test
+ @DisplayName("Should update customer when valid data is provided")
+ void testUpdateCustomerWithValidData() throws CustomerNotFoundException, NotValidCustomerException {
+ when(customerRepository.findById(customerId)).thenReturn(Optional.of(testCustomer));
+
+ Customer updatedCustomer = Customer.builder()
+ .id(customerId)
+ .firstName("John")
+ .lastName("Updated")
+ .phoneNumber("0712345678")
+ .loyaltyPoints(100)
+ .build();
+
+ when(customerRepository.save(any(Customer.class))).thenReturn(updatedCustomer);
+
+ CustomerInfo updateInfo = new CustomerInfo("John", "Updated", "0712345678");
+
+ CustomerDTO result = customerUseCase.updateCustomer(customerId, updateInfo);
+
+ assertNotNull(result);
+ assertEquals(customerId, result.getId());
+ assertEquals("Updated", result.getLastName());
+ assertEquals("0712345678", result.getPhoneNumber());
+ verify(customerRepository, times(1)).findById(customerId);
+ verify(customerRepository, times(1)).save(any(Customer.class));
+ }
+
+ @Test
+ @DisplayName("Should throw exception when customer ID doesn't exist")
+ void testUpdateCustomerNotFound() {
+ UUID nonExistentId = UUID.randomUUID();
+ when(customerRepository.findById(nonExistentId)).thenReturn(Optional.empty());
+
+ CustomerInfo updateInfo = new CustomerInfo("John", "Updated", "0712345678");
+
+ assertThrows(CustomerNotFoundException.class,
+ () -> customerUseCase.updateCustomer(nonExistentId, updateInfo));
+
+ verify(customerRepository, times(1)).findById(nonExistentId);
+ verify(customerRepository, never()).save(any(Customer.class));
+ }
+
+ @Test
+ @DisplayName("Should throw exception when update data is not valid")
+ void testUpdateCustomerWithInvalidData() {
+ CustomerInfo invalidUpdateInfo = new CustomerInfo("", "", "");
+
+ assertThrows(NotValidCustomerException.class,
+ () -> customerUseCase.updateCustomer(customerId, invalidUpdateInfo));
+
+ verify(customerRepository, never()).findById(any(UUID.class));
+ verify(customerRepository, never()).save(any(Customer.class));
+ }
+ }
+
+ @Nested
+ @DisplayName("Delete customer tests")
+ class DeleteCustomerTests {
+
+ @Test
+ @DisplayName("Should delete customer when ID exists")
+ void testDeleteCustomer() throws CustomerNotFoundException {
+ when(customerRepository.findById(customerId)).thenReturn(Optional.of(testCustomer));
+ doNothing().when(customerRepository).delete(testCustomer);
+
+ customerUseCase.deleteCustomer(customerId);
+
+ verify(customerRepository, times(1)).findById(customerId);
+ verify(customerRepository, times(1)).delete(testCustomer);
+ }
+
+ @Test
+ @DisplayName("Should throw exception when customer ID doesn't exist")
+ void testDeleteCustomerNotFound() {
+ UUID nonExistentId = UUID.randomUUID();
+ when(customerRepository.findById(nonExistentId)).thenReturn(Optional.empty());
+
+ assertThrows(CustomerNotFoundException.class,
+ () -> customerUseCase.deleteCustomer(nonExistentId));
+
+ verify(customerRepository, times(1)).findById(nonExistentId);
+ verify(customerRepository, never()).delete(any(Customer.class));
+ }
+ }
+
+ @Nested
+ @DisplayName("Loyalty points tests")
+ class LoyaltyPointsTests {
+
+ @Test
+ @DisplayName("Should add loyalty points to customer")
+ void testAddLoyaltyPoints() throws CustomerNotFoundException {
+ when(customerRepository.findById(customerId)).thenReturn(Optional.of(testCustomer));
+ when(customerRepository.save(testCustomer)).thenReturn(testCustomer);
+
+ int initialPoints = testCustomer.getLoyaltyPoints();
+ int pointsToAdd = 50;
+ int expectedPoints = initialPoints + pointsToAdd;
+
+ int newPoints = customerUseCase.addLoyaltyPoints(customerId, pointsToAdd);
+
+ assertEquals(expectedPoints, newPoints);
+ assertEquals(expectedPoints, testCustomer.getLoyaltyPoints());
+ verify(customerRepository, times(1)).findById(customerId);
+ verify(customerRepository, times(1)).save(testCustomer);
+ }
+
+ @Test
+ @DisplayName("Should throw exception when adding points to non-existent customer")
+ void testAddLoyaltyPointsToNonExistentCustomer() {
+ UUID nonExistentId = UUID.randomUUID();
+ when(customerRepository.findById(nonExistentId)).thenReturn(Optional.empty());
+
+ assertThrows(CustomerNotFoundException.class,
+ () -> customerUseCase.addLoyaltyPoints(nonExistentId, 50));
+
+ verify(customerRepository, times(1)).findById(nonExistentId);
+ verify(customerRepository, never()).save(any(Customer.class));
+ }
+
+ @Test
+ @DisplayName("Should subtract loyalty points from customer")
+ void testSubtractLoyaltyPoints() throws CustomerNotFoundException, IllegalCustomerPointException {
+ when(customerRepository.findById(customerId)).thenReturn(Optional.of(testCustomer));
+ when(customerRepository.save(testCustomer)).thenReturn(testCustomer);
+
+ int initialPoints = testCustomer.getLoyaltyPoints();
+ int pointsToRemove = 30;
+ int expectedPoints = initialPoints - pointsToRemove;
+
+ int newPoints = customerUseCase.subtractLoyaltyPoints(customerId, pointsToRemove);
+
+ assertEquals(expectedPoints, newPoints);
+ assertEquals(expectedPoints, testCustomer.getLoyaltyPoints());
+ verify(customerRepository, times(1)).findById(customerId);
+ verify(customerRepository, times(1)).save(testCustomer);
+ }
+
+ @Test
+ @DisplayName("Should throw exception when trying to remove more points than available")
+ void testSubtractTooManyLoyaltyPoints() {
+ when(customerRepository.findById(customerId)).thenReturn(Optional.of(testCustomer));
+
+ int pointsToRemove = 200;
+
+ assertThrows(IllegalCustomerPointException.class,
+ () -> customerUseCase.subtractLoyaltyPoints(customerId, pointsToRemove));
+
+ verify(customerRepository, times(1)).findById(customerId);
+ verify(customerRepository, never()).save(any(Customer.class));
+ }
+
+ @Test
+ @DisplayName("Should throw exception when subtracting points from non-existent customer")
+ void testSubtractLoyaltyPointsFromNonExistentCustomer() {
+ UUID nonExistentId = UUID.randomUUID();
+ when(customerRepository.findById(nonExistentId)).thenReturn(Optional.empty());
+
+ assertThrows(CustomerNotFoundException.class,
+ () -> customerUseCase.subtractLoyaltyPoints(nonExistentId, 50));
+
+ verify(customerRepository, times(1)).findById(nonExistentId);
+ verify(customerRepository, never()).save(any(Customer.class));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/validator/CustomerValidatorTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/validator/CustomerValidatorTest.java
new file mode 100644
index 0000000..29bb954
--- /dev/null
+++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/customer/validator/CustomerValidatorTest.java
@@ -0,0 +1,155 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.customer.validator;
+
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.CustomerInfo;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.exception.NotValidCustomerException;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class CustomerValidatorTest {
+
+ @Test
+ @DisplayName("Should validate customer with valid data")
+ void testValidateValidCustomer() {
+ CustomerInfo validCustomer = new CustomerInfo("John", "Doe", "0612345678");
+
+ assertDoesNotThrow(() -> CustomerValidator.validate(validCustomer));
+ }
+
+ @Nested
+ @DisplayName("First name validation tests")
+ class FirstNameValidationTests {
+
+ @Test
+ @DisplayName("Should throw exception when first name is blank")
+ void testValidateBlankFirstName() {
+ CustomerInfo customerWithBlankFirstName = new CustomerInfo("", "Doe", "0612345678");
+
+ NotValidCustomerException exception = assertThrows(
+ NotValidCustomerException.class,
+ () -> CustomerValidator.validate(customerWithBlankFirstName)
+ );
+
+ assertEquals(CustomerValidator.FIRST_NAME_CANNOT_BE_BLANK, exception.getMessage());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {" ", " ", "\t", "\n"})
+ @DisplayName("Should throw exception when first name contains only whitespace")
+ void testValidateWhitespaceFirstName(String whitespace) {
+ CustomerInfo customerWithWhitespaceFirstName = new CustomerInfo(whitespace, "Doe", "0612345678");
+
+ NotValidCustomerException exception = assertThrows(
+ NotValidCustomerException.class,
+ () -> CustomerValidator.validate(customerWithWhitespaceFirstName)
+ );
+
+ assertEquals(CustomerValidator.FIRST_NAME_CANNOT_BE_BLANK, exception.getMessage());
+ }
+ }
+
+ @Nested
+ @DisplayName("Last name validation tests")
+ class LastNameValidationTests {
+
+ @Test
+ @DisplayName("Should throw exception when last name is blank")
+ void testValidateBlankLastName() {
+ CustomerInfo customerWithBlankLastName = new CustomerInfo("John", "", "0612345678");
+
+ NotValidCustomerException exception = assertThrows(
+ NotValidCustomerException.class,
+ () -> CustomerValidator.validate(customerWithBlankLastName)
+ );
+
+ assertEquals(CustomerValidator.LAST_NAME_CANNOT_BE_BLANK, exception.getMessage());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {" ", " ", "\t", "\n"})
+ @DisplayName("Should throw exception when last name contains only whitespace")
+ void testValidateWhitespaceLastName(String whitespace) {
+ CustomerInfo customerWithWhitespaceLastName = new CustomerInfo("John", whitespace, "0612345678");
+
+ NotValidCustomerException exception = assertThrows(
+ NotValidCustomerException.class,
+ () -> CustomerValidator.validate(customerWithWhitespaceLastName)
+ );
+
+ assertEquals(CustomerValidator.LAST_NAME_CANNOT_BE_BLANK, exception.getMessage());
+ }
+ }
+
+ @Nested
+ @DisplayName("Phone number validation tests")
+ class PhoneNumberValidationTests {
+
+ @Test
+ @DisplayName("Should throw exception when phone number is blank")
+ void testValidateBlankPhoneNumber() {
+ CustomerInfo customerWithBlankPhoneNumber = new CustomerInfo("John", "Doe", "");
+
+ NotValidCustomerException exception = assertThrows(
+ NotValidCustomerException.class,
+ () -> CustomerValidator.validate(customerWithBlankPhoneNumber)
+ );
+
+ assertEquals("Phone number cannot be blank", exception.getMessage());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {" ", " ", "\t", "\n"})
+ @DisplayName("Should throw exception when phone number contains only whitespace")
+ void testValidateWhitespacePhoneNumber(String whitespace) {
+ CustomerInfo customerWithWhitespacePhoneNumber = new CustomerInfo("John", "Doe", whitespace);
+
+ NotValidCustomerException exception = assertThrows(
+ NotValidCustomerException.class,
+ () -> CustomerValidator.validate(customerWithWhitespacePhoneNumber)
+ );
+
+ assertEquals("Phone number cannot be blank", exception.getMessage());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {
+ "0512345678", // Invalid prefix (not 06 or 07)
+ "0812345678", // Invalid prefix (not 06 or 07)
+ "061234567", // Too short (missing one digit)
+ "06123456789", // Too long (one extra digit)
+ "6123456789", // Missing leading 0
+ "O612345678", // Letter O instead of zero
+ "+33612345678", // International format not supported
+ "06 12 34 56 78" // Contains spaces
+ })
+ @DisplayName("Should throw exception when phone number format is invalid")
+ void testValidateInvalidPhoneNumberFormat(String invalidPhoneNumber) {
+ CustomerInfo customerWithInvalidPhoneNumber = new CustomerInfo("John", "Doe", invalidPhoneNumber);
+
+ NotValidCustomerException exception = assertThrows(
+ NotValidCustomerException.class,
+ () -> CustomerValidator.validate(customerWithInvalidPhoneNumber)
+ );
+
+ assertEquals(CustomerValidator.PHONE_NUMBER_IS_NOT_VALID, exception.getMessage());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {
+ "0612345678", // Valid 06 number
+ "0712345678", // Valid 07 number
+ "0699999999", // Valid 06 number with all 9s
+ "0700000000" // Valid 07 number with all 0s
+ })
+ @DisplayName("Should validate when phone number format is valid")
+ void testValidateValidPhoneNumberFormat(String validPhoneNumber) {
+ CustomerInfo customerWithValidPhoneNumber = new CustomerInfo("John", "Doe", validPhoneNumber);
+
+ assertDoesNotThrow(() -> CustomerValidator.validate(customerWithValidPhoneNumber));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/features/RunCucumberTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/features/RunCucumberTest.java
new file mode 100644
index 0000000..6080357
--- /dev/null
+++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/features/RunCucumberTest.java
@@ -0,0 +1,14 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.features;
+
+import org.junit.platform.suite.api.*;
+
+import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;
+import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME;
+
+@Suite
+@IncludeEngines("cucumber")
+@SelectClasspathResource("features")
+@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty")
+@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "fr.iut_fbleau.but3.dev62.mylibrary.features")
+public class RunCucumberTest {
+}
diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/features/client/CustomerSteps.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/features/client/CustomerSteps.java
new file mode 100644
index 0000000..e71f786
--- /dev/null
+++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/features/client/CustomerSteps.java
@@ -0,0 +1,223 @@
+package fr.iut_fbleau.but3.dev62.mylibrary.features.client;
+
+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.customer.CustomerDTO;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.CustomerInfo;
+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.exception.IllegalCustomerPointException;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.exception.NotValidCustomerException;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.repository.CustomerRepository;
+import fr.iut_fbleau.but3.dev62.mylibrary.customer.usecase.CustomerUseCase;
+import io.cucumber.datatable.DataTable;
+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.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+
+public class CustomerSteps {
+
+ private final CustomerRepository customerRepository = new CustomerRepository();
+ private final CustomerUseCase customerUseCase = new CustomerUseCase(customerRepository);
+
+ private final Map customerPhoneUUID = new HashMap<>();
+ private UUID customerRegistration;
+ private Optional customerByPhoneNumber;
+ private Customer updatedCustomer;
+ private IllegalCustomerPointException illegalCustomerPointException;
+ private NotValidCustomerException notValidCustomerException;
+
+ @Given("the system has the following customers:")
+ public void theSystemHasTheFollowingCustomers(DataTable dataTable) {
+ int size = customerRepository.findAll().size();
+
+ if (size > 0) {
+ customerRepository.deleteAll();
+ }
+
+ List