first commit
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 | ||||
							
								
								
									
										226
									
								
								.idea/workspace.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								.idea/workspace.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,226 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project version="4"> | ||||
|   <component name="AutoImportSettings"> | ||||
|     <option name="autoReloadType" value="SELECTIVE" /> | ||||
|   </component> | ||||
|   <component name="ChangeListManager"> | ||||
|     <list default="true" id="006a6fd0-05b3-45d6-960c-e40a12142c26" name="Changes" comment=":white_check_mark: Book feature"> | ||||
|       <changelist_data name="Maxime Pierront" email="maxime.pierront.ext@u-pec.fr" automatic="false" /> | ||||
|     </list> | ||||
|     <option name="SHOW_DIALOG" value="false" /> | ||||
|     <option name="HIGHLIGHT_CONFLICTS" value="true" /> | ||||
|     <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" /> | ||||
|     <option name="LAST_RESOLUTION" value="IGNORE" /> | ||||
|   </component> | ||||
|   <component name="FileTemplateManagerImpl"> | ||||
|     <option name="RECENT_TEMPLATES"> | ||||
|       <list> | ||||
|         <option value="Enum" /> | ||||
|         <option value="Exception" /> | ||||
|         <option value="Class" /> | ||||
|       </list> | ||||
|     </option> | ||||
|   </component> | ||||
|   <component name="Git.Settings"> | ||||
|     <option name="PREVIOUS_COMMIT_AUTHORS"> | ||||
|       <list> | ||||
|         <option value="Maxime Pierront <maxime.pierront.ext@u-pec.fr>" /> | ||||
|       </list> | ||||
|     </option> | ||||
|     <option name="RECENT_BRANCH_BY_REPOSITORY"> | ||||
|       <map> | ||||
|         <entry key="$PROJECT_DIR$" value="main" /> | ||||
|       </map> | ||||
|     </option> | ||||
|     <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" /> | ||||
|     <option name="RESET_MODE" value="HARD" /> | ||||
|   </component> | ||||
|   <component name="HighlightingSettingsPerFile"> | ||||
|     <setting file="jar://$USER_HOME$/.jdks/corretto-21.0.6/lib/src.zip!/java.base/java/lang/NumberFormatException.java" root0="SKIP_INSPECTION" /> | ||||
|   </component> | ||||
|   <component name="ProblemsViewState"> | ||||
|     <option name="selectedTabId" value="CurrentFile" /> | ||||
|   </component> | ||||
|   <component name="ProjectColorInfo">{ | ||||
|   "customColor": "", | ||||
|   "associatedIndex": 8 | ||||
| }</component> | ||||
|   <component name="ProjectId" id="2uGhUz90SJjPl4SBlMEx6xesVyL" /> | ||||
|   <component name="ProjectViewState"> | ||||
|     <option name="hideEmptyMiddlePackages" value="true" /> | ||||
|     <option name="showLibraryContents" value="true" /> | ||||
|   </component> | ||||
|   <component name="PropertiesComponent"><![CDATA[{ | ||||
|   "keyToString": { | ||||
|     "Cucumber Java.All Features in: mylibrary-money.executor": "Run", | ||||
|     "Cucumber Java.Feature: book.executor": "Run", | ||||
|     "Cucumber Java.Feature: client.executor": "Run", | ||||
|     "Cucumber Java.Feature: command.executor": "Run", | ||||
|     "Cucumber Java.Feature: order.executor": "Run", | ||||
|     "Cucumber Java.Feature: review.executor": "Run", | ||||
|     "Cucumber Java.Feature: subscription.executor": "Run", | ||||
|     "Cucumber Java.Scenario: Create a new customer account.executor": "Run", | ||||
|     "Cucumber Java.Scenario: Creer un nouveau livre.executor": "Run", | ||||
|     "Cucumber Java.Scenario: Créer une commande avec une carte de crédit.executor": "Run", | ||||
|     "Cucumber Java.Scenario: Essayer de créer une commande avec des points de fidélité insuffisants.executor": "Run", | ||||
|     "Cucumber Java.Scenario: Essayer de créer une commande avec un client inconnu.executor": "Run", | ||||
|     "Cucumber Java.Scenario: Essayer de récupérer une commande avec un ID inconnu.executor": "Run", | ||||
|     "Cucumber Java.Scenario: Modifier les informations d'un livre.executor": "Run", | ||||
|     "JUnit.IllegalOrderPointExceptionTest.executor": "Run", | ||||
|     "JUnit.OrderConverterTest$ToDTOTests.executor": "Run", | ||||
|     "JUnit.OrderConverterTest$ToDomainTests.shouldConvertOrderInfoToDomain.executor": "Debug", | ||||
|     "JUnit.OrderConverterTest.executor": "Run", | ||||
|     "JUnit.OrderNotFoundExceptionTest.executor": "Run", | ||||
|     "JUnit.OrderQuantityExceptionTest.executor": "Run", | ||||
|     "JUnit.OrderRepositoryTest.executor": "Run", | ||||
|     "JUnit.OrderTest.executor": "Run", | ||||
|     "JUnit.OrderUseCaseTest.executor": "Run", | ||||
|     "JUnit.OrderValidatorTest.executor": "Run", | ||||
|     "JUnit.ReviewTest.executor": "Run", | ||||
|     "JUnit.ReviewUseCaseTest.executor": "Run", | ||||
|     "JUnit.WrongAddressExceptionTest.executor": "Run", | ||||
|     "JUnit.fr.iut_fbleau.but3.dev62.mylibrary.features.order in mylibrary.executor": "Run", | ||||
|     "JUnit.fr.iut_fbleau.but3.dev62.mylibrary.order in mylibrary.executor": "Run", | ||||
|     "JUnit.fr.iut_fbleau.but3.dev62.mylibrary.review in mylibrary.executor": "Run", | ||||
|     "JUnit.fr.iut_fbleau.but3.dev62.mylibrary.subscription in mylibrary.executor": "Debug", | ||||
|     "Maven.mylibrary [clean].executor": "Run", | ||||
|     "Maven.mylibrary [compile].executor": "Run", | ||||
|     "Maven.mylibrary [install].executor": "Run", | ||||
|     "Maven.mylibrary [package].executor": "Run", | ||||
|     "Maven.mylibrary [test].executor": "Run", | ||||
|     "RunOnceActivity.ShowReadmeOnStart": "true", | ||||
|     "RunOnceActivity.git.unshallow": "true", | ||||
|     "git-widget-placeholder": "book", | ||||
|     "ignore.virus.scanning.warn.message": "true", | ||||
|     "kotlin-language-version-configured": "true", | ||||
|     "last_opened_file_path": "C:/Users/simon/OneDrive/Bureau/school/info/mylibrary-money/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/order", | ||||
|     "project.structure.last.edited": "Project", | ||||
|     "project.structure.proportion": "0.15", | ||||
|     "project.structure.side.proportion": "0.2", | ||||
|     "settings.editor.selected.configurable": "preferences.pluginManager" | ||||
|   } | ||||
| }]]></component> | ||||
|   <component name="RecentsManager"> | ||||
|     <key name="CopyFile.RECENT_KEYS"> | ||||
|       <recent name="C:\Users\simon\OneDrive\Bureau\school\info\mylibrary-money\src\test\java\fr\iut_fbleau\but3\dev62\mylibrary\order" /> | ||||
|       <recent name="C:\Users\simon\OneDrive\Bureau\school\info\mylibrary-money\src\test\resources\features" /> | ||||
|     </key> | ||||
|     <key name="MoveFile.RECENT_KEYS"> | ||||
|       <recent name="C:\Users\simon\OneDrive\Bureau\school\info\mylibrary-money\src\main\java\fr\iut_fbleau\but3\dev62\mylibrary" /> | ||||
|       <recent name="C:\Users\simon\OneDrive\Bureau\school\info\mylibrary-money\src\test\java\fr\iut_fbleau\but3\dev62\mylibrary" /> | ||||
|       <recent name="C:\Users\simon\OneDrive\Bureau\school\info\mylibrary-money\src\test\java\fr\iut_fbleau\but3\dev62\mylibrary\features\subscription" /> | ||||
|       <recent name="C:\Users\simon\OneDrive\Bureau\school\info\mylibrary-money\src\test\resources\features" /> | ||||
|     </key> | ||||
|   </component> | ||||
|   <component name="RunManager" selected="JUnit.fr.iut_fbleau.but3.dev62.mylibrary.subscription in mylibrary"> | ||||
|     <configuration name="ReviewTest" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true"> | ||||
|       <module name="mylibrary" /> | ||||
|       <extension name="coverage"> | ||||
|         <pattern> | ||||
|           <option name="PATTERN" value="fr.iut_fbleau.but3.dev62.mylibrary.review.entity.*" /> | ||||
|           <option name="ENABLED" value="true" /> | ||||
|         </pattern> | ||||
|       </extension> | ||||
|       <option name="PACKAGE_NAME" value="fr.iut_fbleau.but3.dev62.mylibrary.review.entity" /> | ||||
|       <option name="MAIN_CLASS_NAME" value="fr.iut_fbleau.but3.dev62.mylibrary.review.entity.ReviewTest" /> | ||||
|       <option name="TEST_OBJECT" value="class" /> | ||||
|       <method v="2"> | ||||
|         <option name="Make" enabled="true" /> | ||||
|       </method> | ||||
|     </configuration> | ||||
|     <configuration name="ReviewUseCaseTest" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true"> | ||||
|       <module name="mylibrary" /> | ||||
|       <extension name="coverage"> | ||||
|         <pattern> | ||||
|           <option name="PATTERN" value="fr.iut_fbleau.but3.dev62.mylibrary.review.usecase.*" /> | ||||
|           <option name="ENABLED" value="true" /> | ||||
|         </pattern> | ||||
|       </extension> | ||||
|       <option name="PACKAGE_NAME" value="fr.iut_fbleau.but3.dev62.mylibrary.review.usecase" /> | ||||
|       <option name="MAIN_CLASS_NAME" value="fr.iut_fbleau.but3.dev62.mylibrary.review.usecase.ReviewUseCaseTest" /> | ||||
|       <option name="TEST_OBJECT" value="class" /> | ||||
|       <method v="2"> | ||||
|         <option name="Make" enabled="true" /> | ||||
|       </method> | ||||
|     </configuration> | ||||
|     <configuration name="fr.iut_fbleau.but3.dev62.mylibrary.order in mylibrary" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true"> | ||||
|       <module name="mylibrary" /> | ||||
|       <extension name="coverage"> | ||||
|         <pattern> | ||||
|           <option name="PATTERN" value="fr.iut_fbleau.but3.dev62.mylibrary.order.*" /> | ||||
|           <option name="ENABLED" value="true" /> | ||||
|         </pattern> | ||||
|       </extension> | ||||
|       <option name="PACKAGE_NAME" value="fr.iut_fbleau.but3.dev62.mylibrary.order" /> | ||||
|       <option name="TEST_OBJECT" value="package" /> | ||||
|       <method v="2"> | ||||
|         <option name="Make" enabled="true" /> | ||||
|       </method> | ||||
|     </configuration> | ||||
|     <configuration name="fr.iut_fbleau.but3.dev62.mylibrary.review in mylibrary" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true"> | ||||
|       <module name="mylibrary" /> | ||||
|       <extension name="coverage"> | ||||
|         <pattern> | ||||
|           <option name="PATTERN" value="fr.iut_fbleau.but3.dev62.mylibrary.review.*" /> | ||||
|           <option name="ENABLED" value="true" /> | ||||
|         </pattern> | ||||
|       </extension> | ||||
|       <option name="PACKAGE_NAME" value="fr.iut_fbleau.but3.dev62.mylibrary.review" /> | ||||
|       <option name="TEST_OBJECT" value="package" /> | ||||
|       <method v="2"> | ||||
|         <option name="Make" enabled="true" /> | ||||
|       </method> | ||||
|     </configuration> | ||||
|     <configuration name="fr.iut_fbleau.but3.dev62.mylibrary.subscription in mylibrary" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true"> | ||||
|       <module name="mylibrary" /> | ||||
|       <extension name="coverage"> | ||||
|         <pattern> | ||||
|           <option name="PATTERN" value="fr.iut_fbleau.but3.dev62.mylibrary.subscription.*" /> | ||||
|           <option name="ENABLED" value="true" /> | ||||
|         </pattern> | ||||
|       </extension> | ||||
|       <option name="PACKAGE_NAME" value="fr.iut_fbleau.but3.dev62.mylibrary.subscription" /> | ||||
|       <option name="TEST_OBJECT" value="package" /> | ||||
|       <method v="2"> | ||||
|         <option name="Make" enabled="true" /> | ||||
|       </method> | ||||
|     </configuration> | ||||
|     <recent_temporary> | ||||
|       <list> | ||||
|         <item itemvalue="JUnit.fr.iut_fbleau.but3.dev62.mylibrary.subscription in mylibrary" /> | ||||
|         <item itemvalue="JUnit.ReviewUseCaseTest" /> | ||||
|         <item itemvalue="JUnit.fr.iut_fbleau.but3.dev62.mylibrary.review in mylibrary" /> | ||||
|         <item itemvalue="JUnit.ReviewTest" /> | ||||
|         <item itemvalue="JUnit.fr.iut_fbleau.but3.dev62.mylibrary.order in mylibrary" /> | ||||
|       </list> | ||||
|     </recent_temporary> | ||||
|   </component> | ||||
|   <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" /> | ||||
|   <component name="TaskManager"> | ||||
|     <task active="true" id="Default" summary="Default task"> | ||||
|       <changelist id="006a6fd0-05b3-45d6-960c-e40a12142c26" name="Changes" comment="" /> | ||||
|       <created>1741880838672</created> | ||||
|       <option name="number" value="Default" /> | ||||
|       <option name="presentableId" value="Default" /> | ||||
|       <updated>1741880838672</updated> | ||||
|     </task> | ||||
|     <servers /> | ||||
|   </component> | ||||
|   <component name="Vcs.Log.Tabs.Properties"> | ||||
|     <option name="TAB_STATES"> | ||||
|       <map> | ||||
|         <entry key="MAIN"> | ||||
|           <value> | ||||
|             <State /> | ||||
|           </value> | ||||
|         </entry> | ||||
|       </map> | ||||
|     </option> | ||||
|   </component> | ||||
|   <component name="VcsManagerConfiguration"> | ||||
|     <MESSAGE value="Book" /> | ||||
|     <MESSAGE value="Téléverser les fichiers vers "/"" /> | ||||
|     <MESSAGE value=":white_check_mark: Book feature" /> | ||||
|     <option name="LAST_COMMIT_MESSAGE" value=":white_check_mark: Book feature" /> | ||||
|   </component> | ||||
| </project> | ||||
							
								
								
									
										73
									
								
								interface-contracts.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								interface-contracts.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| { | ||||
|   "usecases": { | ||||
|     "EnregistrerNouveauLivre": { | ||||
|       "input": { | ||||
|         "isbn": "string(13)",  | ||||
|         "titre": "string(required)", | ||||
|         "auteur": "string(required)", | ||||
|         "editeur": "string(required)", | ||||
|         "datePublication": "date", | ||||
|         "prix": "decimal(positive)", | ||||
|         "stockInitial": "integer(min:0)", | ||||
|         "categories": "array<string>", | ||||
|         "description": "string", | ||||
|         "langue": "string" | ||||
|       }, | ||||
|       "output": { | ||||
|         "livreId": "uuid" | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     "PasserCommande": { | ||||
|       "input": { | ||||
|         "clientId": "uuid", | ||||
|         "lignesCommande": [{ | ||||
|           "livreId": "uuid", | ||||
|           "quantite": "integer(positive)" | ||||
|         }], | ||||
|         "adresseLivraison": { | ||||
|           "rue": "string", | ||||
|           "ville": "string", | ||||
|           "codePostal": "string", | ||||
|           "pays": "string" | ||||
|         }, | ||||
|         "modePaiement": "string(enum: CB, PAYPAL, POINTS_FIDELITE)" | ||||
|       }, | ||||
|       "output": { | ||||
|         "commandeId": "uuid", | ||||
|         "montantTotal": "decimal", | ||||
|         "pointsFideliteGagnes": "integer" | ||||
|       } | ||||
|     }, | ||||
|     "GererAvis": { | ||||
|       "input": { | ||||
|         "clientId": "uuid", | ||||
|         "livreId": "uuid", | ||||
|         "note": "integer(min:1,max:5)", | ||||
|         "commentaire": "string", | ||||
|         "dateAchat": "date" | ||||
|       }, | ||||
|       "output": { | ||||
|         "avisId": "uuid" | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     "CreerAbonnement": { | ||||
|       "input": { | ||||
|         "clientId": "uuid", | ||||
|         "duree": "integer(enum: 3,6,12)", | ||||
|         "modePaiement": { | ||||
|           "type": "string(enum: CB, PAYPAL)", | ||||
|           "details": "object" | ||||
|         }, | ||||
|         "dateDebutSouhaitee": "date" | ||||
|       }, | ||||
|       "output": { | ||||
|         "abonnementId": "uuid", | ||||
|         "dateDebut": "date", | ||||
|         "dateFin": "date", | ||||
|         "montantMensuel": "decimal" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										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