forked from pierront/mylibrary-template
		
	🎉
This commit is contained in:
		
							
								
								
									
										38
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										151
									
								
								pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								pom.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,151 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
 | 
			
		||||
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 | 
			
		||||
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 | 
			
		||||
  <modelVersion>4.0.0</modelVersion>
 | 
			
		||||
 | 
			
		||||
  <groupId>fr.iut_fbleau.but3.dev62</groupId>
 | 
			
		||||
  <artifactId>mylibrary</artifactId>
 | 
			
		||||
  <version>1.0-SNAPSHOT</version>
 | 
			
		||||
 | 
			
		||||
  <properties>
 | 
			
		||||
    <!--    Your java version-->
 | 
			
		||||
    <maven.compiler.source>21</maven.compiler.source>
 | 
			
		||||
    <maven.compiler.target>21</maven.compiler.target>
 | 
			
		||||
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 | 
			
		||||
 | 
			
		||||
    <!--    Main dependencies -->
 | 
			
		||||
    <lombok.version>1.18.36</lombok.version>
 | 
			
		||||
 | 
			
		||||
    <!--    Test Verisons-->
 | 
			
		||||
    <junit.version>5.11.4</junit.version>
 | 
			
		||||
    <junit.platform.version>1.11.4</junit.platform.version>
 | 
			
		||||
    <cucumber.version>7.21.1</cucumber.version>
 | 
			
		||||
    <mockito.version>5.16.0</mockito.version>
 | 
			
		||||
 | 
			
		||||
    <!--  Maven build version  -->
 | 
			
		||||
    <maven.compiler.version>3.13.0</maven.compiler.version>
 | 
			
		||||
    <maven.surefire.version>3.5.2</maven.surefire.version>
 | 
			
		||||
  </properties>
 | 
			
		||||
 | 
			
		||||
  <dependencyManagement>
 | 
			
		||||
    <dependencies>
 | 
			
		||||
      <dependency>
 | 
			
		||||
        <groupId>io.cucumber</groupId>
 | 
			
		||||
        <artifactId>cucumber-bom</artifactId>
 | 
			
		||||
        <version>${cucumber.version}</version>
 | 
			
		||||
        <type>pom</type>
 | 
			
		||||
        <scope>import</scope>
 | 
			
		||||
      </dependency>
 | 
			
		||||
      <dependency>
 | 
			
		||||
        <groupId>org.junit</groupId>
 | 
			
		||||
        <artifactId>junit-bom</artifactId>
 | 
			
		||||
        <version>${junit.version}</version>
 | 
			
		||||
        <type>pom</type>
 | 
			
		||||
        <scope>import</scope>
 | 
			
		||||
      </dependency>
 | 
			
		||||
    </dependencies>
 | 
			
		||||
  </dependencyManagement>
 | 
			
		||||
 | 
			
		||||
  <dependencies>
 | 
			
		||||
    <dependency>
 | 
			
		||||
      <groupId>org.projectlombok</groupId>
 | 
			
		||||
      <artifactId>lombok</artifactId>
 | 
			
		||||
      <version>${lombok.version}</version>
 | 
			
		||||
      <scope>provided</scope>
 | 
			
		||||
    </dependency>
 | 
			
		||||
 | 
			
		||||
    <dependency>
 | 
			
		||||
      <groupId>io.cucumber</groupId>
 | 
			
		||||
      <artifactId>cucumber-java</artifactId>
 | 
			
		||||
      <scope>test</scope>
 | 
			
		||||
    </dependency>
 | 
			
		||||
 | 
			
		||||
    <dependency>
 | 
			
		||||
      <groupId>io.cucumber</groupId>
 | 
			
		||||
      <artifactId>cucumber-junit-platform-engine</artifactId>
 | 
			
		||||
      <scope>test</scope>
 | 
			
		||||
    </dependency>
 | 
			
		||||
 | 
			
		||||
    <dependency>
 | 
			
		||||
      <groupId>org.junit.platform</groupId>
 | 
			
		||||
      <artifactId>junit-platform-suite</artifactId>
 | 
			
		||||
      <version>${junit.platform.version}</version>
 | 
			
		||||
      <scope>test</scope>
 | 
			
		||||
    </dependency>
 | 
			
		||||
    <dependency>
 | 
			
		||||
      <groupId>org.junit.platform</groupId>
 | 
			
		||||
      <artifactId>junit-platform-engine</artifactId>
 | 
			
		||||
      <version>${junit.platform.version}</version>
 | 
			
		||||
      <scope>test</scope>
 | 
			
		||||
    </dependency>
 | 
			
		||||
 | 
			
		||||
    <dependency>
 | 
			
		||||
      <groupId>org.junit.jupiter</groupId>
 | 
			
		||||
      <artifactId>junit-jupiter-api</artifactId>
 | 
			
		||||
      <version>${junit.version}</version>
 | 
			
		||||
      <scope>test</scope>
 | 
			
		||||
    </dependency>
 | 
			
		||||
    <dependency>
 | 
			
		||||
      <groupId>org.junit.jupiter</groupId>
 | 
			
		||||
      <artifactId>junit-jupiter-params</artifactId>
 | 
			
		||||
      <version>${junit.version}</version>
 | 
			
		||||
      <scope>test</scope>
 | 
			
		||||
    </dependency>
 | 
			
		||||
    <dependency>
 | 
			
		||||
      <groupId>org.junit.jupiter</groupId>
 | 
			
		||||
      <artifactId>junit-jupiter-engine</artifactId>
 | 
			
		||||
      <version>${junit.version}</version>
 | 
			
		||||
      <scope>test</scope>
 | 
			
		||||
    </dependency>
 | 
			
		||||
    <dependency>
 | 
			
		||||
      <groupId>org.junit.platform</groupId>
 | 
			
		||||
      <artifactId>junit-platform-launcher</artifactId>
 | 
			
		||||
      <version>${junit.platform.version}</version>
 | 
			
		||||
      <scope>test</scope>
 | 
			
		||||
    </dependency>
 | 
			
		||||
 | 
			
		||||
    <dependency>
 | 
			
		||||
      <groupId>org.mockito</groupId>
 | 
			
		||||
      <artifactId>mockito-core</artifactId>
 | 
			
		||||
      <version>${mockito.version}</version>
 | 
			
		||||
      <scope>test</scope>
 | 
			
		||||
    </dependency>
 | 
			
		||||
    <dependency>
 | 
			
		||||
      <groupId>org.mockito</groupId>
 | 
			
		||||
      <artifactId>mockito-junit-jupiter</artifactId>
 | 
			
		||||
      <version>${mockito.version}</version>
 | 
			
		||||
      <scope>test</scope>
 | 
			
		||||
    </dependency>
 | 
			
		||||
  </dependencies>
 | 
			
		||||
 | 
			
		||||
  <build>
 | 
			
		||||
    <plugins>
 | 
			
		||||
      <plugin>
 | 
			
		||||
        <groupId>org.apache.maven.plugins</groupId>
 | 
			
		||||
        <artifactId>maven-compiler-plugin</artifactId>
 | 
			
		||||
        <version>${maven.compiler.version}</version>
 | 
			
		||||
        <configuration>
 | 
			
		||||
          <encoding>${project.build.sourceEncoding}</encoding>
 | 
			
		||||
          <source>${maven.compiler.source}</source>
 | 
			
		||||
          <target>${maven.compiler.target}</target>
 | 
			
		||||
        </configuration>
 | 
			
		||||
      </plugin>
 | 
			
		||||
      <plugin>
 | 
			
		||||
        <groupId>org.apache.maven.plugins</groupId>
 | 
			
		||||
        <artifactId>maven-surefire-plugin</artifactId>
 | 
			
		||||
        <version>${maven.surefire.version}</version>
 | 
			
		||||
        <configuration>
 | 
			
		||||
          <properties>
 | 
			
		||||
            <!-- Work around. Surefire does not include enough
 | 
			
		||||
                 information to disambiguate between different
 | 
			
		||||
                 examples and scenarios. -->
 | 
			
		||||
            <configurationParameters>
 | 
			
		||||
              cucumber.junit-platform.naming-strategy=long
 | 
			
		||||
            </configurationParameters>
 | 
			
		||||
          </properties>
 | 
			
		||||
        </configuration>
 | 
			
		||||
      </plugin>
 | 
			
		||||
    </plugins>
 | 
			
		||||
  </build>
 | 
			
		||||
</project>
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
package fr.iut_fbleau.but3.dev62.mylibrary.customer;
 | 
			
		||||
 | 
			
		||||
public record CustomerInfo(String firstName, String lastName, String phoneNumber) {
 | 
			
		||||
}
 | 
			
		||||
@@ -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();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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;
 | 
			
		||||
 }
 | 
			
		||||
}
 | 
			
		||||
@@ -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));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,8 @@
 | 
			
		||||
package fr.iut_fbleau.but3.dev62.mylibrary.customer.exception;
 | 
			
		||||
 | 
			
		||||
public class NotValidCustomerException extends Exception {
 | 
			
		||||
 | 
			
		||||
  public NotValidCustomerException(String message) {
 | 
			
		||||
    super(message);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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<Customer> customers = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
  public List<Customer> findAll() {
 | 
			
		||||
    return customers;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void deleteAll() {
 | 
			
		||||
    customers.clear();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public Customer save(Customer newCustomer) {
 | 
			
		||||
    Optional<Customer> optionalCustomerWithSameId = this.findById(newCustomer.getId());
 | 
			
		||||
    optionalCustomerWithSameId.ifPresentOrElse(customers::remove, newCustomer::setRandomUUID);
 | 
			
		||||
    this.customers.add(newCustomer);
 | 
			
		||||
    return newCustomer;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public Optional<Customer> 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<Customer> findByPhoneNumber(String phoneNumber) {
 | 
			
		||||
    return this.customers.stream()
 | 
			
		||||
        .filter(customer -> customer.getPhoneNumber().equals(phoneNumber))
 | 
			
		||||
        .findFirst();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void delete(Customer customer) {
 | 
			
		||||
    this.customers.remove(customer);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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<CustomerDTO> findCustomerByPhoneNumber(String phoneNumber) {
 | 
			
		||||
    Optional<Customer> 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<Customer> optionalCustomerById = customerRepository.findById(uuid);
 | 
			
		||||
    if (optionalCustomerById.isEmpty()) {
 | 
			
		||||
      throw new CustomerNotFoundException(uuid);
 | 
			
		||||
    }
 | 
			
		||||
    return optionalCustomerById.get();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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<Customer> 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<Customer> 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<Customer> 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<Customer> 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<Customer> foundCustomer = repository.findById(nonExistentId);
 | 
			
		||||
 | 
			
		||||
      assertTrue(foundCustomer.isEmpty());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    @DisplayName("FindByPhoneNumber should return customer with matching phone number")
 | 
			
		||||
    void testFindByPhoneNumber() {
 | 
			
		||||
      Optional<Customer> 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<Customer> 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<Customer> 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<Customer> 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());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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<CustomerDTO> 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<CustomerDTO> 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));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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 {
 | 
			
		||||
}
 | 
			
		||||
@@ -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<String, UUID> customerPhoneUUID = new HashMap<>();
 | 
			
		||||
  private UUID customerRegistration;
 | 
			
		||||
  private Optional<CustomerDTO> 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<Map<String, String>> customers = dataTable.asMaps(String.class, String.class);
 | 
			
		||||
 | 
			
		||||
    for (Map<String, String> customer : customers) {
 | 
			
		||||
      String numeroTelephone = customer.get("numeroTelephone");
 | 
			
		||||
      Customer newCustomer = Customer.builder()
 | 
			
		||||
          .firstName(customer.get("prenom"))
 | 
			
		||||
          .lastName(customer.get("nom"))
 | 
			
		||||
          .phoneNumber(numeroTelephone)
 | 
			
		||||
          .loyaltyPoints(Integer.parseInt(customer.get("pointsFidelite")))
 | 
			
		||||
          .build();
 | 
			
		||||
      Customer save = customerRepository.save(newCustomer);
 | 
			
		||||
      customerPhoneUUID.put(numeroTelephone, save.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    assertEquals(customers.size(), customerRepository.findAll().size());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @When("I create a new customer with the following information:")
 | 
			
		||||
  public void iCreateANewCustomerWithTheFollowingInformation(DataTable dataTable) throws NotValidCustomerException {
 | 
			
		||||
    List<Map<String, String>> rows = dataTable.asMaps(String.class, String.class);
 | 
			
		||||
 | 
			
		||||
    Map<String, String> customerInfo = rows.getFirst();
 | 
			
		||||
 | 
			
		||||
    CustomerInfo newCustomer = new CustomerInfo(
 | 
			
		||||
        customerInfo.get("prenom"),
 | 
			
		||||
        customerInfo.get("nom"),
 | 
			
		||||
        customerInfo.get("numeroTelephone")
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    customerRegistration = customerUseCase.registerCustomer(newCustomer);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @And("the system now has {int} customers")
 | 
			
		||||
  public void theSystemNowHasCustomers(int numberOfCustomers) {
 | 
			
		||||
    assertEquals(numberOfCustomers, customerRepository.findAll().size());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @And("the customer has {int} loyalty points")
 | 
			
		||||
  public void theCustomerHasLoyaltyPoints(int loyaltyPoints) {
 | 
			
		||||
    Customer customer = customerRepository.findById(customerRegistration).orElseThrow();
 | 
			
		||||
    assertEquals(loyaltyPoints, customer.getLoyaltyPoints());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Then("a new customer is created")
 | 
			
		||||
  public void aNewCustomerIsCreated() {
 | 
			
		||||
    assertNotNull(customerRegistration);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @When("I request the customer with phone number {string}")
 | 
			
		||||
  public void iRequestTheCustomerWithPhoneNumber(String phoneNumber) {
 | 
			
		||||
    customerByPhoneNumber = customerUseCase.findCustomerByPhoneNumber(phoneNumber);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Then("I receive the following customer information:")
 | 
			
		||||
  public void iReceiveTheFollowingCustomerInformation(DataTable dataTable) {
 | 
			
		||||
    List<Map<String, String>> customers = dataTable.asMaps(String.class, String.class);
 | 
			
		||||
    Map<String, String> customerInfo = customers.getFirst();
 | 
			
		||||
    assertTrue(customerByPhoneNumber.isPresent());
 | 
			
		||||
    CustomerDTO customerDTO = customerByPhoneNumber.get();
 | 
			
		||||
    assertEquals(customerInfo.get("prenom"), customerDTO.getFirstName());
 | 
			
		||||
    assertEquals(customerInfo.get("nom"), customerDTO.getLastName());
 | 
			
		||||
    assertEquals(customerInfo.get("numeroTelephone"), customerDTO.getPhoneNumber());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @When("I update customer {string} with the following information:")
 | 
			
		||||
  public void iUpdateCustomerWithTheFollowingInformation(String phoneNumber, DataTable dataTable)
 | 
			
		||||
      throws CustomerNotFoundException, NotValidCustomerException {
 | 
			
		||||
    List<Map<String, String>> rows = dataTable.asMaps(String.class, String.class);
 | 
			
		||||
 | 
			
		||||
    Map<String, String> customerData = rows.getFirst();
 | 
			
		||||
    CustomerInfo customerInfo = new CustomerInfo(
 | 
			
		||||
        customerData.get("prenom"),
 | 
			
		||||
        customerData.get("nom"),
 | 
			
		||||
        customerData.get("numeroTelephone")
 | 
			
		||||
    );
 | 
			
		||||
    UUID uuid = customerPhoneUUID.get(phoneNumber);
 | 
			
		||||
    customerUseCase.updateCustomer(uuid, customerInfo);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Then("the customer {string} has the following updated information:")
 | 
			
		||||
  public void theCustomerHasTheFollowingUpdatedInformation(String phoneNumber, DataTable dataTable) {
 | 
			
		||||
    List<Map<String, String>> rows = dataTable.asMaps(String.class, String.class);
 | 
			
		||||
 | 
			
		||||
    Map<String, String> updatedDate = rows.getFirst();
 | 
			
		||||
 | 
			
		||||
    UUID uuid = customerPhoneUUID.get(phoneNumber);
 | 
			
		||||
    updatedCustomer = customerRepository.findById(uuid).orElseThrow();
 | 
			
		||||
    assertEquals(updatedDate.get("numeroTelephone"), updatedCustomer.getPhoneNumber());
 | 
			
		||||
    assertEquals(updatedDate.get("prenom"), updatedCustomer.getFirstName());
 | 
			
		||||
    assertEquals(updatedDate.get("nom"), updatedCustomer.getLastName());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @And("the loyalty points remain unchanged at {int}")
 | 
			
		||||
  public void theLoyaltyPointsRemainUnchangedAt(int expectedLoyaltyPoint) {
 | 
			
		||||
    assertEquals(expectedLoyaltyPoint, updatedCustomer.getLoyaltyPoints());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @When("I delete the customer with phone number {string}")
 | 
			
		||||
  public void iDeleteTheCustomerWithPhoneNumber(String phoneNumber) throws CustomerNotFoundException {
 | 
			
		||||
    UUID uuid = customerPhoneUUID.get(phoneNumber);
 | 
			
		||||
    customerUseCase.deleteCustomer(uuid);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Then("the customer {string} is removed from the system")
 | 
			
		||||
  public void theCustomerIsRemovedFromTheSystem(String phoneNumber) {
 | 
			
		||||
    UUID uuid = customerPhoneUUID.get(phoneNumber);
 | 
			
		||||
    assertFalse(customerRepository.existsById(uuid));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @When("I add {int} loyalty points to customer {string}")
 | 
			
		||||
  public void iAddLoyaltyPointsToCustomer(int loyaltyPointToAdd, String phoneNumber) throws CustomerNotFoundException {
 | 
			
		||||
    UUID uuid = customerPhoneUUID.get(phoneNumber);
 | 
			
		||||
    customerUseCase.addLoyaltyPoints(uuid, loyaltyPointToAdd);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Then("customer {string} now has {int} loyalty points")
 | 
			
		||||
  public void customerNowHasLoyaltyPoints(String phoneNumber, int expectedLoyaltyPoints) {
 | 
			
		||||
    UUID uuid = customerPhoneUUID.get(phoneNumber);
 | 
			
		||||
    Customer customer = customerRepository.findById(uuid).orElseThrow();
 | 
			
		||||
    assertEquals(expectedLoyaltyPoints, customer.getLoyaltyPoints());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @When("I deduct {int} loyalty points from customer {string} for a purchase")
 | 
			
		||||
  public void iDeductLoyaltyPointsFromCustomerForAPurchase(int pointsToRemove, String phoneNumber) throws CustomerNotFoundException, IllegalCustomerPointException {
 | 
			
		||||
    UUID uuid = customerPhoneUUID.get(phoneNumber);
 | 
			
		||||
    customerUseCase.subtractLoyaltyPoints(uuid, pointsToRemove);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @When("I try to create a new customer with the following information:")
 | 
			
		||||
  public void iTryToCreateANewCustomerWithTheFollowingInformation(DataTable ddataTable) {
 | 
			
		||||
    List<Map<String, String>> rows = ddataTable.asMaps(String.class, String.class);
 | 
			
		||||
 | 
			
		||||
    Map<String, String> customerInfo = rows.getFirst();
 | 
			
		||||
 | 
			
		||||
    CustomerInfo newCustomer = new CustomerInfo(
 | 
			
		||||
        customerInfo.get("prenom"),
 | 
			
		||||
        customerInfo.get("nom"),
 | 
			
		||||
        customerInfo.get("numeroTelephone")
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    notValidCustomerException = assertThrows(NotValidCustomerException.class, () -> customerUseCase.registerCustomer(newCustomer));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Then("the creation fails")
 | 
			
		||||
  public void theCreationFails() {
 | 
			
		||||
    assertNotNull(notValidCustomerException);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  @And("I receive an error for validation customer message containing {string}")
 | 
			
		||||
  public void iReceiveAnErrorMessageContaining(String errorMessage) {
 | 
			
		||||
    assertEquals(errorMessage, notValidCustomerException.getMessage());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @And("the system still has {int} customers")
 | 
			
		||||
  public void theSystemStillHasCustomers(int expectedNumberOfUser) {
 | 
			
		||||
    assertEquals(expectedNumberOfUser, customerRepository.findAll().size());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @When("I try to deduct {int} loyalty points from customer {string} for a purchase")
 | 
			
		||||
  public void iTryToDeductLoyaltyPointsFromCustomerForAPurchase(int points, String phoneNumber) {
 | 
			
		||||
    UUID uuid = customerPhoneUUID.get(phoneNumber);
 | 
			
		||||
    illegalCustomerPointException = assertThrows(IllegalCustomerPointException.class, () -> customerUseCase.subtractLoyaltyPoints(uuid, points));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Then("the deduction fails")
 | 
			
		||||
  public void theDeductionFails() {
 | 
			
		||||
    assertNotNull(illegalCustomerPointException);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @And("I receive an error for illegal customer exception message containing {string}")
 | 
			
		||||
  public void iReceiveAnErrorForIllegalCustomerExceptionMessageContaining(String errorMessage) {
 | 
			
		||||
    assertEquals(errorMessage, illegalCustomerPointException.getMessage());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										60
									
								
								src/test/resources/features/client.feature
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/test/resources/features/client.feature
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
# language: en
 | 
			
		||||
 | 
			
		||||
Feature: Manage customer accounts
 | 
			
		||||
 | 
			
		||||
  Background:
 | 
			
		||||
    Given the system has the following customers:
 | 
			
		||||
      | prenom | nom    | numeroTelephone | pointsFidelite |
 | 
			
		||||
      | Marie  | Dupont | 0612345678      | 100            |
 | 
			
		||||
      | Jean   | Martin | 0687654321      | 50             |
 | 
			
		||||
      | Sophie | Dubois | 0698765432      | 0              |
 | 
			
		||||
 | 
			
		||||
  Scenario: Create a new customer account
 | 
			
		||||
    When I create a new customer with the following information:
 | 
			
		||||
      | prenom | nom     | numeroTelephone |
 | 
			
		||||
      | Pierre | Lambert | 0611223344      |
 | 
			
		||||
    Then a new customer is created
 | 
			
		||||
    And the customer has 0 loyalty points
 | 
			
		||||
    And the system now has 4 customers
 | 
			
		||||
 | 
			
		||||
  Scenario: Retrieve a customer by ID
 | 
			
		||||
    When I request the customer with phone number "0612345678"
 | 
			
		||||
    Then I receive the following customer information:
 | 
			
		||||
      | prenom | nom    | numeroTelephone | pointsFidelite |
 | 
			
		||||
      | Marie  | Dupont | 0612345678      | 100            |
 | 
			
		||||
 | 
			
		||||
  Scenario: Update a customer's information
 | 
			
		||||
    When I update customer "0687654321" with the following information:
 | 
			
		||||
      | prenom | nom     | numeroTelephone |
 | 
			
		||||
      | Jean   | Bernard | 0666666666      |
 | 
			
		||||
    Then the customer "0687654321" has the following updated information:
 | 
			
		||||
      | prenom | nom     | numeroTelephone |
 | 
			
		||||
      | Jean   | Bernard | 0666666666      |
 | 
			
		||||
    And the loyalty points remain unchanged at 50
 | 
			
		||||
 | 
			
		||||
  Scenario: Delete a customer
 | 
			
		||||
    When I delete the customer with phone number "0698765432"
 | 
			
		||||
    Then the customer "0698765432" is removed from the system
 | 
			
		||||
    And the system now has 2 customers
 | 
			
		||||
 | 
			
		||||
  Scenario: Add loyalty points to a customer
 | 
			
		||||
    When I add 25 loyalty points to customer "0687654321"
 | 
			
		||||
    Then customer "0687654321" now has 75 loyalty points
 | 
			
		||||
 | 
			
		||||
  Scenario: Deduct loyalty points for a purchase
 | 
			
		||||
    When I deduct 30 loyalty points from customer "0612345678" for a purchase
 | 
			
		||||
    Then customer "0612345678" now has 70 loyalty points
 | 
			
		||||
 | 
			
		||||
  Scenario: Attempt to create a customer with invalid phone number
 | 
			
		||||
    When I try to create a new customer with the following information:
 | 
			
		||||
      | prenom | nom   | numeroTelephone |
 | 
			
		||||
      | Thomas | Petit | abcdefgh        |
 | 
			
		||||
    Then the creation fails
 | 
			
		||||
    And I receive an error for validation customer message containing "Phone number is not valid"
 | 
			
		||||
    And the system still has 3 customers
 | 
			
		||||
 | 
			
		||||
  Scenario: Attempt to deduct more loyalty points than available
 | 
			
		||||
    When I try to deduct 150 loyalty points from customer "0687654321" for a purchase
 | 
			
		||||
    Then the deduction fails
 | 
			
		||||
    And I receive an error for illegal customer exception message containing "Cannot remove 150 points from 50 points"
 | 
			
		||||
    And customer "0687654321" now has 50 loyalty points
 | 
			
		||||
		Reference in New Issue
	
	Block a user