Full text
acceptance-test1.sh 1 #!/bin/bashsetcattestif$RESULTthenelsefi"Content-Type: application/json" '{"Acceptance Test 1": "'${STATUS}'" }'$METRICS_URLexit$RESULT 2 3 -x 4 5 METRICS_URL=` .metrics-url` 6 7 ./mvnw - Dtest=%regex[com.equalexperts.recipefinder.acceptance.challenge1.*] 8 9 RESULT=$? 10 11 [ == 0 ]; 12 STATUS=pass 13 14 STATUS=fail 15 16 17 curl -X POST -H --data 18 19 20
acceptance-test2.sh 1 #!/bin/bashsetcattestif$RESULTthenelsefi"Content-Type: application/json" '{"Acceptance Test 2": "'${STATUS}'" }'$METRICS_URLexit$RESULT 2 3 -x 4 5 METRICS_URL=` .metrics-url` 6 7 ./mvnw - Dtest=%regex[com.equalexperts.recipefinder.acceptance.challenge2.*] 8 9 RESULT=$? 10 11 [ == 0 ]; 12 STATUS=pass 13 14 STATUS=fail 15 16 17 curl -X POST -H --data 18 19 20
mvnw 1 #!/bin/sh 2 # ---------------------------------------------------------------------------- 3 # Licensed to the Apache Software Foundation (ASF) under one 4 # or more contributor license agreements. See the NOTICE file 5 # distributed with this work for additional information 6 # regarding copyright ownership. The ASF licenses this file 7 # to you under the Apache License, Version 2.0 (the 8 # "License"); you may not use this file except in compliance 9 # with the License. You may obtain a copy of the License at 10 # 11 # https://www.apache.org/licenses/LICENSE-2.0 12 # 13 # Unless required by applicable law or agreed to in writing, 14 # software distributed under the License is distributed on an 15 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 # KIND, either express or implied. See the License for the 17 # specific language governing permissions and limitations 18 # under the License. 19 # ---------------------------------------------------------------------------- 20 21 # ---------------------------------------------------------------------------- 22 # Apache Maven Wrapper startup batch script, version 3.2.0 23 # 24 # Required ENV vars: 25 # ------------------ 26 # JAVA_HOME - location of a JDK home dir 27 # 28 # Optional ENV vars 29 # ----------------- 30 # MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 # e.g. to debug Maven itself, use 32 # set MAVEN_OPTS=-Xdebug - Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 # ---------------------------------------------------------------------------- 35 36 if [ -z "$MAVEN_SKIP_RC" ] ; then 37 38 if [ -f /usr/local/etc/mavenrc ] ; then 39 . /usr/local/etc/mavenrc 40 fi 41 42 if [ -f /etc/mavenrc ] ; then 43 . /etc/mavenrc 44 fi 45 46 if [ -f "$HOME/.mavenrc" ] ; then 47 . "$HOME/.mavenrc" 48 fi 49 50 fi 51 52 # OS specific support. $var _must_ be set to either true or false. 53 cygwin=false;
54 darwin=false; 55 mingw=false 56 case "$(uname)" in 57 CYGWIN*) cygwin=true ;; 58 MINGW*) mingw=true;; 59 Darwin*) darwin=true 60 # Use /usr/libexec/java_home if available, otherwise fall back to / Library/Java/Home 61 # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 62 if [ -z "$JAVA_HOME" ]; then 63 if [ -x "/usr/libexec/java_home" ]; then 64 JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME 65 else 66 JAVA_HOME="/Library/Java/Home"; export JAVA_HOME 67 fi 68 fi 69 ;; 70 esac 71 72 if [ -z "$JAVA_HOME" ] ; then 73 if [ -r /etc/gentoo-release ] ; then 74 JAVA_HOME=$(java-config --jre-home) 75 fi 76 fi 77 78 # For Cygwin, ensure paths are in UNIX format before anything is touched 79 if $cygwin ; then 80 [ -n "$JAVA_HOME" ] && 81 JAVA_HOME=$(cygpath --unix "$JAVA_HOME") 82 [ -n "$CLASSPATH" ] && 83 CLASSPATH=$(cygpath --path --unix "$CLASSPATH") 84 fi 85 86 # For Mingw, ensure paths are in UNIX format before anything is touched 87 if $mingw ; then 88 [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && 89 JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" 90 fi 91 92 if [ -z "$JAVA_HOME" ]; then 93 javaExecutable="$(which javac)" 94 if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then 95 # readlink(1) is not available as standard on Solaris 10. 96 readLink=$(which readlink) 97 if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then 98 if $darwin ; then 99 javaHome="$(dirname "\"$javaExecutable\"")" 100 javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" 101 else 102 javaExecutable="$(readlink -f "\"$javaExecutable\"")" 103 fi 104 javaHome="$(dirname "\"$javaExecutable\"")" 105 javaHome=$(expr "$javaHome" : '\(.*\)/bin') 106 JAVA_HOME="$javaHome" 107 export JAVA_HOME 108 fi 109 fi 110 fi 111
112 if [ -z "$JAVACMD" ] ; then 113 if [ -n "$JAVA_HOME" ] ; then 114 if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 115 # IBM's JDK on AIX uses strange locations for the executables 116 JAVACMD="$JAVA_HOME/jre/sh/java" 117 else 118 JAVACMD="$JAVA_HOME/bin/java" 119 fi 120 else 121 JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" 122 fi 123 fi 124 125 if [ ! -x "$JAVACMD" ] ; then 126 echo "Error: JAVA_HOME is not defined correctly." >&2 127 echo " We cannot execute $JAVACMD" >&2 128 exit 1 129 fi 130 131 if [ -z "$JAVA_HOME" ] ; then 132 echo "Warning: JAVA_HOME environment variable is not set." 133 fi 134 135 # traverses directory structure from process work directory to filesystem root 136 # first directory with .mvn subdirectory is considered project base directory 137 find_maven_basedir() { 138 if [ -z "$1" ] 139 then 140 echo "Path not specified to find_maven_basedir" 141 return 1 142 fi 143 144 basedir="$1" 145 wdir="$1" 146 while [ "$wdir" != '/' ] ; do 147 if [ -d "$wdir"/.mvn ] ; then 148 basedir=$wdir 149 break 150 fi 151 # workaround for JBEAP-8937 (on Solaris 10/Sparc) 152 if [ -d "${wdir}" ]; then 153 wdir=$(cd "$wdir/.." || exit 1; pwd) 154 fi 155 # end of workaround 156 done 157 printf '%s' "$(cd "$basedir" || exit 1; pwd)" 158 } 159 160 # concatenates all lines of a file 161 concat_lines() { 162 if [ -f "$1" ]; then 163 # Remove \r in case we run on Windows within Git Bash 164 # and check out the repository with auto CRLF management 165 # enabled. Otherwise, we may read lines that are delimited with 166 # \r\n and produce $'-Xarg\r' rather than -Xarg due to word 167 # splitting rules. 168 tr -s '\r\n' ' ' < "$1" 169 fi 170 }
171 172 log() { 173 if [ "$MVNW_VERBOSE" = true ]; then 174 printf '%s\n' "$1" 175 fi 176 } 177 178 BASE_DIR=$(find_maven_basedir "$(dirname "$0")") 179 if [ -z "$BASE_DIR" ]; then 180 exit 1; 181 fi 182 183 MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR 184 log "$MAVEN_PROJECTBASEDIR" 185 186 ########################################################################## ################ 187 # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 188 # This allows using the maven wrapper in projects that prohibit checking in binary data. 189 ########################################################################## ################ 190 wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" 191 if [ -r "$wrapperJarPath" ]; then 192 log "Found $wrapperJarPath" 193 else 194 log "Couldn't find $wrapperJarPath, downloading it ..." 195 196 if [ -n "$MVNW_REPOURL" ]; then 197 wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/mavenwrapper/3.2.0/maven-wrapper-3.2.0.jar" 198 else 199 wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/ wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" 200 fi 201 while IFS="=" read -r key value; do 202 # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) 203 safeValue=$(echo "$value" | tr -d '\r') 204 case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; 205 esac 206 done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 207 log "Downloading from: $wrapperUrl" 208 209 if $cygwin; then 210 wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") 211 fi 212 213 if command -v wget > /dev/null; then 214 log "Found wget ... using wget" 215 [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" 216 if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 217 wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" 218 else 219 wget $QUIET --http-user="$MVNW_USERNAME" --httppassword="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
220 fi 221 elif command -v curl > /dev/null; then 222 log "Found curl ... using curl" 223 [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" 224 if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 225 curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 226 else 227 curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" 228 fi 229 else 230 log "Falling back to using Java to download" 231 javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/ MavenWrapperDownloader.java" 232 javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/ MavenWrapperDownloader.class" 233 # For Cygwin, switch paths to Windows format before running javac 234 if $cygwin; then 235 javaSource=$(cygpath --path --windows "$javaSource") 236 javaClass=$(cygpath --path --windows "$javaClass") 237 fi 238 if [ -e "$javaSource" ]; then 239 if [ ! -e "$javaClass" ]; then 240 log " - Compiling MavenWrapperDownloader.java ..." 241 ("$JAVA_HOME/bin/javac" "$javaSource") 242 fi 243 if [ -e "$javaClass" ]; then 244 log " - Running MavenWrapperDownloader.java ..." 245 ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" 246 fi 247 fi 248 fi 249 fi 250 ########################################################################## ################ 251 # End of extension 252 ########################################################################## ################ 253 254 # If specified, validate the SHA-256 sum of the Maven wrapper jar file 255 wrapperSha256Sum="" 256 while IFS="=" read -r key value; do 257 case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; 258 esac 259 done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" 260 if [ -n "$wrapperSha256Sum" ]; then 261 wrapperSha256Result=false 262 if command -v sha256sum > /dev/null; then 263 if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/ null 2>&1; then 264 wrapperSha256Result=true 265 fi 266 elif command -v shasum > /dev/null; then 267 if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > / dev/null 2>&1; then 268 wrapperSha256Result=true 269 fi 270 else
271 echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." 272 echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." 273 exit 1 274 fi 275 if [ $wrapperSha256Result = false ]; then 276 echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 277 echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 278 echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 279 exit 1 280 fi 281 fi 282 283 MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 284 285 # For Cygwin, switch paths to Windows format before running java 286 if $cygwin; then 287 [ -n "$JAVA_HOME" ] && 288 JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") 289 [ -n "$CLASSPATH" ] && 290 CLASSPATH=$(cygpath --path --windows "$CLASSPATH") 291 [ -n "$MAVEN_PROJECTBASEDIR" ] && 292 MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") 293 fi 294 295 # Provide a "standardized" way to retrieve the CLI args that will 296 # work with both Windows and non-Windows executions. 297 MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" 298 export MAVEN_CMD_LINE_ARGS 299 300 WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 301 302 # shellcheck disable=SC2086 # safe args 303 exec "$JAVACMD" \ 304 $MAVEN_OPTS \ 305 $MAVEN_DEBUG_OPTS \ 306 -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 307 "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 308 ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 309
mvnw.cmd 1 @REM ---------------------------------------------------------------------------- @REM Licensed to the Apache Software Foundation (ASF) under one@REM or more contributor license agreements. See the NOTICE file@REM distributed with this work for additional information@REM regarding copyright ownership. The ASF licenses this file@REM to you under the Apache License, Version 2.0 (the @REM "License"); you may not use this file except in compliance@REM with the License. You may obtain a copy of the License at@REM@REM https:// www.apache.org/licenses/LICENSE-2.0@REM@REM Unless required by applicable law or agreed to in writing,@REM software distributed under the License is distributed on an@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @REM KIND, either express or implied. See the License for the@REM specific language governing permissions and limitations@REM under the License.@REM ---------------------------------------------------------------------------- 2 @REM ---------------------------------------------------------------------------- @REM Apache Maven Wrapper startup batch script, version 3.2.0@REM@REM Required ENV vars:@REM JAVA_HOME - location of a JDK home dir@REM@REM Optional ENV vars@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven@REM e.g. to debug Maven itself, use@REM set MAVEN_OPTS=-Xdebug - Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files@REM ---------------------------------------------------------------------------- 3 @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'echo @REM set title of command windowtitle0@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'if%MAVEN_BATCH_ECHO%echo%MAVEN_BATCH_ECHO% 4 @REM set %HOME% to equivalent of $HOMEif%HOME%set%HOMEDRIVE%%HOMEPATH% 5 @REM Execute a user defined script before this oneifnot%MAVEN_SKIP_RC%goto @REM check for pre script, once with legacy .bat ending and once with .cmd endingifexist%USERPROFILE%call%USERPROFILE%ifexist%USERPROFILE%cmdcall %USERPROFILE%cmdsetlocalset0 6 @REM To isolate internal variables from possible post scripts, we use another setlocalsetlocal 7 @REM ==== START VALIDATION ====ifnot%JAVA_HOME%gotoechoechonotin2echosetin 2echo2echogotoifexist%JAVA_HOME%gotoechoechoset2echo%JAVA_HOME%2echosetin2echo 2echogoto 8 @REM ==== END VALIDATION ==== 9 @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".@REM Fallback to current working directory if not found.set %MAVEN_BASEDIR%IFNOT%MAVEN_PROJECTBASEDIR%gotoset%CD%set%EXEC_DIR%IFEXIST %WDIR%gotocdIF%WDIR%%CD%gotoset%CD%gotoset%WDIR%cd%EXEC_DIR%gotoset%EXEC_DIR% cd%EXEC_DIR%IFNOTEXIST%MAVEN_PROJECTBASEDIR%gotosetlocalfor%%ain %MAVEN_PROJECTBASEDIR%doset!JVM_CONFIG_MAVEN_PROPS!%%aendlocalset %JVM_CONFIG_MAVEN_PROPS%SET%JAVA_HOME%set%MAVEN_PROJECTBASEDIR%setset320320FOR 12%%AIN%MAVEN_PROJECTBASEDIR%DOIF%%ASET%%B 10 @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central@REM This allows using the maven wrapper in projects that prohibit checking in binary data.ifexist%WRAPPER_JAR%if%MVNW_VERBOSE%echo %WRAPPER_JAR%elseifnot%MVNW_REPOURL%SET%MVNW_REPOURL%320320if%MVNW_VERBOSE% echofind%WRAPPER_JAR%echo%WRAPPER_URL%Netifnot%MVNW_USERNAME%%MVNW_PASSWORD% Net%MVNW_USERNAME%%MVNW_PASSWORD%NetNet%WRAPPER_URL%%WRAPPER_JAR%if
90 ™™“à</span> 91 ™™• 92 ™™“à</span> 93 ™™™></span>report></span> 94 ™™™></span>prepare-package></span> 95 ™™™></span> 96 ™™™“à</span>report></span> 97 ™™™></span> 98 ™™“à</span> 99 ™™></span> 100 ™“à</span> 101 ™“à</span> 102 ™™></span>com.github.funthomas424242></span> 103 ™™></span>plantuml-maven-plugin></span> 104 ™™></span>1.5.2></span> 105 ™™></span> 106 ™™“à</span>src/main/*></span> 107 ™™“à</span> 108 ™™™></span>${basedir}></span> 109 ™™™></span> 110 ™™™“à</span>src/main/plantuml/**/*.puml></span> 111 ™™™></span> 112 ™™“à</span> 113 ™™“à</span>true></span> 114 ™™></span> 115 ™™></span> 116 ™™“à</span> 117 ™™™></span>net.sourceforge.plantuml></span> 118 ™™™></span>plantuml></span> 119 ™™™></span>1.2023.9></span> 120 ™™™></span>runtime></span> 121 ™™“à</span> 122 ™™></span> 123 ™“à</span> 124 ></span> 125 ></span>org.apache.maven.plugins></span> 126 ></span>maven-surefire-plugin></span> 127 ></span> 128 ></span> 129 ></span> %regex[com.equalexperts.recipefinder.acceptance.*]></span> 130 ></span> 131 ></span> 132 ></span> 133 ></span> 134 “à</span> 135 ></span> 136
src/main/java/com/equalexperts/recipefinder/ RecipeFinderApplication.java 1 packageimportimportimport@EnableAsync@SpringBootApplicationpublicclass RecipeFinderApplicationpublicstaticvoidmain(String[] args) com.equalexperts.recipefinder; 2 3 org.springframework.boot.SpringApplication; 4 org.springframework.boot.autoconfigure.SpringBootApplication; 5 org.springframework.scheduling.annotation.EnableAsync; 6 7 8 9 { 10 ’° 11 ™SpringApplication.run(RecipeFinderApplication.class, args); 12 —Ð 13 }
src/main/java/com/equalexperts/recipefinder/controller/ RecipeAdminController.java 1 packageimportimportimportimportimportimportimportimportimportimportimport importimportimportimportimportimportimportimportimportstaticimportstatic @Controller()publicclassRecipeAdminControllerprivateprivate@Autowiredpublic RecipeAdminController(RecipeAPIClient client, RecipeRepository recipeRepository)thisthis@Transactionalpublicpersist(Recipe recipe)this"Saved Recipe %d%n"return@Asyncprotectedvoidenrich(RecipeDTO dto)Reciperecipe=new RecipeIngredientsDTOingredients=thisassertnullRecipefinalRecipe=Ingredient ingredient=newIngredientreturnDietsDTOdiets=thisassertnullDietdiet=newDiet returnMethodDTOmethod=thisassertnullMethodm=newMethodreturn "=====================================================================================" @GetMapping("/admin/import")publicdownloadRecipes(Model model)thisifnull "numDownloads"0return"download"this"numDownloads"return"download" com.equalexperts.recipefinder.controller; 2 3 com.equalexperts.recipefinder.dto.DietsDTO; 4 com.equalexperts.recipefinder.dto.IngredientsDTO; 5 com.equalexperts.recipefinder.dto.MethodDTO; 6 com.equalexperts.recipefinder.dto.RecipeDTO; 7 com.equalexperts.recipefinder.entity.Diet; 8 com.equalexperts.recipefinder.entity.Ingredient; 9 com.equalexperts.recipefinder.entity.Method; 10 com.equalexperts.recipefinder.entity.Recipe; 11 com.equalexperts.recipefinder.integration.RecipeAPIClient; 12 com.equalexperts.recipefinder.repository.RecipeRepository; 13 org.springframework.beans.factory.annotation.Autowired; 14 org.springframework.scheduling.annotation.Async; 15 org.springframework.stereotype.Controller; 16 org.springframework.ui.Model; 17 org.springframework.web.bind.annotation.GetMapping; 18 org.springframework.web.bind.annotation.RequestParam; 19 20 javax.transaction.Transactional; 21 java.util.List; 22 java.util.stream.Collectors; 23 24 java.util.stream.Collectors.toList; 25 java.util.stream.Collectors.toSet; 26 27 28 { 29 RecipeAPIClient recipeAPIClient; 30 RecipeRepository recipeRepository; 31 32 33 { 34 .recipeAPIClient = client; 35 .recipeRepository = recipeRepository; 36 } 37 38 39 Recipe { 40 recipe = .recipeRepository.save(recipe); 41 System.out.printf(, recipe.getId()); 42 recipe; 43 } 44 45
46 { 47 (); 48 recipe.setName(dto.getName()); 49 recipe.setDescription(dto.getDescription()); 50 recipe.setServings(dto.getServings()); 51 recipe.setCookingTimeMin(dto.getCookingTimeMin()); 52 recipe.setPrepTimeMin(dto.getPreparationTimeMin()); 53 recipe.setEstimatedCostDollars(dto.getEstimatedCostDollars()); 54 55 recipe = persist(recipe); 56 57 System.out.println(dto); 58 59 .recipeAPIClient.getIngredients(dto.getId()).block(); 60 ingredients != ; 61 recipe; 62 recipe.setIngredients(ingredients.getIngredients().stream().map(it -> { 63 (); 64 ingredient.setQuantity(it.getQuantity()); 65 ingredient.setName(it.getName()); 66 ingredient.setUnitOfMeasurement(it.getUnitOfMeasurement()); 67 ingredient.setRecipe(finalRecipe); 68 ingredient; 69 }).collect(toSet())); 70 System.out.println(ingredients); 71 72 .recipeAPIClient.getDiets(dto.getId()).block(); 73 diets != ; 74 recipe.setDiets(diets.getDiets().stream().map(it -> { 75 (); 76 diet.setName(it); 77 diet.setRecipe(finalRecipe); 78 diet; 79 }).collect(toSet())); 80 System.out.println(diets); 81 82 .recipeAPIClient.getMethod(dto.getId()).block(); 83 method != ; 84 recipe.setMethod(method.getMethod().stream().map(it-> { 85 (); 86 m.setDescription(it); 87 m.setRecipe(finalRecipe); 88 m; 89 }).collect(toSet())); 90 91 System.out.println(method); 92 System.out.println(); 93 94 persist(recipe); 95 } 96 97 98 String { 99 List<RecipeDTO> output = .recipeAPIClient.getRecipeList().block(); 100 (output == ) { 101 model.addAttribute(, ); 102 ; 103 } 104 output.forEach(::enrich); 105 model.addAttribute(, output.size());
106 ; 107 } 108 } 109
src/main/java/com/equalexperts/recipefinder/controller/ RecipeSearchController.java 1 packageimportimportimportimportimportimportimportimportimportimportimport importimportimportimportstatic@Controller()publicclassRecipeSearchController private@AutowiredpublicRecipeSearchController(RecipeRepository recipeRepository)this@GetMapping("/recipes")publicsearch( @RequestParam(name="query", required=false)"recipes"ifnullreturntrueifreturn trueifreturntruelongcount=0Lforifif0returntrue0forifif0returntrue0forifif0 returntrue0returnfalsereturn"recipe-search" com.equalexperts.recipefinder.controller; 2 3 com.equalexperts.recipefinder.dto.RecipeDTO; 4 com.equalexperts.recipefinder.entity.Diet; 5 com.equalexperts.recipefinder.entity.Ingredient; 6 com.equalexperts.recipefinder.entity.Method; 7 com.equalexperts.recipefinder.entity.Recipe; 8 com.equalexperts.recipefinder.integration.RecipeAPIClient; 9 com.equalexperts.recipefinder.repository.RecipeRepository; 10 org.springframework.beans.factory.annotation.Autowired; 11 org.springframework.stereotype.Controller; 12 org.springframework.ui.Model; 13 org.springframework.web.bind.annotation.GetMapping; 14 org.springframework.web.bind.annotation.RequestParam; 15 16 java.util.List; 17 java.util.stream.Collectors; 18 19 java.util.stream.Collectors.toList; 20 21 22 { 23 RecipeRepository recipeRepository; 24 25 26 { 27 .recipeRepository = recipeRepository; 28 } 29 30 31 String String query, Model model)</span> { 32 List<Recipe> recipes = recipeRepository.findAll(); 33 model.addAttribute(, recipes.stream().filter(recipe -> { 34 (query == ) { 35 ; 36 } 37 (recipe.getName().toLowerCase().contains(query.toLowerCase())) ; 38 (recipe.getDescription().toLowerCase().contains(query.toLowerCase())) ; 39 ; 40 (Ingredient x : recipe.getIngredients()) { 41 (x.getName().toLowerCase().contains(query.toLowerCase())) { 42 count++; 43 } 44 } 45 (count > ) ; 46 count = ; 47 (Method m : recipe.getMethod()) {
48 (m.getDescription().toLowerCase().contains(query.toLowerCase())) { 49 count++; 50 } 51 } 52 (count > ) ; 53 count = ; 54 (Diet diet : recipe.getDiets()) { 55 (diet.getName().toLowerCase().contains(query.toLowerCase())) { 56 count++; 57 } 58 } 59 (count > ) ; 60 count = ; 61 62 ; 63 }).collect(toList())); 64 65 ; 66 } 67 } 68
src/main/java/com/equalexperts/recipefinder/controller/ RecipeViewController.java 1 packageimportimportimportimportimportimportimportimport@Controller()public classRecipeViewControllerprivate@AutowiredpublicRecipeViewController (RecipeRepository recipeRepository)this@GetMapping("/recipe")publicview( @RequestParam(name="id", required=false)"recipe"return"recipe-view" com.equalexperts.recipefinder.controller; 2 3 com.equalexperts.recipefinder.entity.Recipe; 4 com.equalexperts.recipefinder.repository.RecipeRepository; 5 org.springframework.beans.factory.annotation.Autowired; 6 org.springframework.stereotype.Controller; 7 org.springframework.ui.Model; 8 org.springframework.web.bind.annotation.GetMapping; 9 org.springframework.web.bind.annotation.RequestParam; 10 11 java.util.Optional; 12 13 14 { 15 RecipeRepository recipeRepository; 16 17 18 { 19 .recipeRepository = recipeRepository; 20 } 21 22 23 String Long id, Model model)</span> { 24 Optional<Recipe> recipe = recipeRepository.findById(id); 25 model.addAttribute(, recipe.get()); 26 ; 27 } 28 } 29
src/main/java/com/equalexperts/recipefinder/dto/DietsDTO.java 1 packageimportimportpublicclassDietsDTOprivatepublicgetDiets()returnpublic voidsetDiets(List<String> diets)this@Overridepublicbooleanequals(Object o)if thisreturntrueifnullreturnfalseDietsDTOdietsDTO=return@Overridepublicint hashCode()return@OverridepublictoString()return"DietsDTO{""diets="'}' com.equalexperts.recipefinder.dto; 2 3 java.util.List; 4 java.util.Objects; 5 6 { 7 List<String> diets; 8 9 List<String> { 10 diets; 11 } 12 13 { 14 .diets = diets; 15 } 16 17 18 { 19 ( == o) ; 20 (o == || getClass() != o.getClass()) ; 21 (DietsDTO) o; 22 Objects.equals(diets, dietsDTO.diets); 23 } 24 25 26 { 27 Objects.hash(diets); 28 } 29 30 31 String { 32 + 33 + diets + 34 ; 35 } 36 } 37
src/main/java/com/equalexperts/recipefinder/dto/IngredientDTO.java 1 packageimportimportpublicclassIngredientDTO @JsonProperty("unit_of_measurement")privateprivateprivatepublic getUnitOfMeasurement()returnpublicvoidsetUnitOfMeasurement(String unitOfMeasurement)thispublicgetQuantity()returnpublicvoidsetQuantity(Long quantity)thispublicgetName()returnpublicvoidsetName(String name)this@Override publicbooleanequals(Object o)ifthisreturntrueifnullreturnfalseIngredientDTO that=return@OverridepublicinthashCode()return@OverridepublictoString()return "IngredientDTO{""unitOfMeasurement='"'\''", quantity="", name='"'\'''}' com.equalexperts.recipefinder.dto; 2 3 com.fasterxml.jackson.annotation.JsonProperty; 4 5 java.util.Objects; 6 7 { 8 9 String unitOfMeasurement; 10 Long quantity; 11 String name; 12 13 String { 14 unitOfMeasurement; 15 } 16 17 { 18 .unitOfMeasurement = unitOfMeasurement; 19 } 20 21 Long { 22 quantity; 23 } 24 25 { 26 .quantity = quantity; 27 } 28 29 String { 30 name; 31 } 32 33 { 34 .name = name; 35 } 36 37 38 { 39 ( == o) ; 40 (o == || getClass() != o.getClass()) ; 41 (IngredientDTO) o; 42 Objects.equals(unitOfMeasurement, that.unitOfMeasurement) && Objects.equals(quantity, that.quantity) && Objects.equals(name, that.name); 43 } 44 45 46 { 47 Objects.hash(unitOfMeasurement, quantity, name); 48 } 49
52 53 { 54 Objects.hash(id, name); 55 } 56 57 58 String { 59 + 60 + id + 61 + name + + 62 ; 63 } 64 } 65
src/main/java/com/equalexperts/recipefinder/entity/Ingredient.java 1 packageimportimport@Entity@Table(name="ingredients")publicclassIngredient @Id@GeneratedValue(strategy = GenerationType.AUTO)privateprivateprivateprivate @ManyToOne@JoinColumn(name = "recipe_id")privatepublicgetUnitOfMeasurement() returnpublicvoidsetUnitOfMeasurement(String unitOfMeasurement)thispublic getQuantity()returnpublicvoidsetQuantity(Long quantity)thispublicgetName() returnpublicvoidsetName(String name)thispublicgetRecipe()returnpublicvoid setRecipe(Recipe recipe)thispublicgetId()returnpublicvoidsetId(Long id)this @OverridepublictoString()return"Ingredient{""unitOfMeasurement='"'\''", quantity="", name='"'\'''}'@Overridepublicbooleanequals(Object o)ifthisreturn trueifnullreturnfalseIngredientthat=return@OverridepublicinthashCode()return com.equalexperts.recipefinder.entity; 2 3 javax.persistence.*; 4 java.util.Objects; 5 6 7 8 { 9 10 11 12 Long id; 13 14 String unitOfMeasurement; 15 Long quantity; 16 String name; 17 18 19 20 Recipe recipe; 21 22 String { 23 unitOfMeasurement; 24 } 25 26 { 27 .unitOfMeasurement = unitOfMeasurement; 28 } 29 30 Long { 31 quantity; 32 } 33 34 { 35 .quantity = quantity; 36 } 37 38 String { 39 name; 40 } 41 42 { 43 .name = name; 44 } 45 46 Recipe { 47 recipe; 48 }
49 50 { 51 .recipe = recipe; 52 } 53 54 Long { 55 id; 56 } 57 58 { 59 .id = id; 60 } 61 62 63 String { 64 + 65 + unitOfMeasurement + + 66 + quantity + 67 + name + + 68 ; 69 } 70 71 72 { 73 ( == o) ; 74 (o == || getClass() != o.getClass()) ; 75 (Ingredient) o; 76 Objects.equals(unitOfMeasurement, that.unitOfMeasurement) && Objects.equals(quantity, that.quantity) && Objects.equals(name, that.name); 77 } 78 79 80 { 81 Objects.hash(unitOfMeasurement, quantity, name); 82 } 83 } 84
src/main/java/com/equalexperts/recipefinder/entity/Method.java 1 packageimportimport@Entity@Table(name="method")publicclassMethod@Id @GeneratedValue(strategy = GenerationType.AUTO)privateprivate@ManyToOne @JoinColumn(name = "recipe_id")privatepublicgetDescription()returnpublicvoid setDescription(String description)thispublicgetRecipe()returnpublicvoid setRecipe(Recipe recipe)thispublicgetId()returnpublicvoidsetId(Long id)this @Overridepublicbooleanequals(Object o)ifthisreturntrueifnullreturnfalseMethod method=return@OverridepublicinthashCode()return@OverridepublictoString()return "Method{""id="", description='"'\'''}' com.equalexperts.recipefinder.entity; 2 3 javax.persistence.*; 4 java.util.Objects; 5 6 7 8 { 9 10 11 12 Long id; 13 14 String description; 15 16 17 18 Recipe recipe; 19 20 String { 21 description; 22 } 23 24 { 25 .description = description; 26 } 27 28 Recipe { 29 recipe; 30 } 31 32 { 33 .recipe = recipe; 34 } 35 36 Long { 37 id; 38 } 39 40 { 41 .id = id; 42 } 43 44 45 { 46 ( == o) ; 47 (o == || getClass() != o.getClass()) ; 48 (Method) o; 49 Objects.equals(id, method.id) && Objects.equals(description, method.description); 50 }
51 52 53 { 54 Objects.hash(id, description); 55 } 56 57 58 String { 59 + 60 + id + 61 + description + + 62 ; 63 } 64 } 65
src/main/java/com/equalexperts/recipefinder/entity/Recipe.java 1 packageimportimportimportimportimportimportimportimportimport@Entity @Table(name="recipes")publicclassRecipe@Id@GeneratedValue(strategy = GenerationType.AUTO)privateprivateprivateprivateprivateprivateprivate @OneToMany(mappedBy="recipe", cascade = CascadeType.ALL, fetch = FetchType.EAGER)private@OneToMany(mappedBy="recipe", cascade = CascadeType.ALL)private@OneToMany(mappedBy="recipe", cascade = CascadeType.ALL)privatepublicRecipe()publicRecipe(RecipeDTO dto)thisthisthis thisthisthispublicsetIngredients(IngredientsDTO dto)thisIngredienti=new IngredientthisreturnreturnthispublicsetMethod(MethodDTO dto)thisMethodm=new MethodthisreturnreturnthispublicsetDiets(DietsDTO dto)thisDietd=newDietreturn returnthispublicgetId()returnpublicvoidsetId(Long id)thispublicgetName()return publicvoidsetName(String name)thispublicgetDescription()returnpublicvoid setDescription(String description)thispublicgetServings()returnpublicvoid setServings(Long servings)thispublicgetCookingTimeMin()returnpublicvoid setCookingTimeMin(Long cookingTimeMin)thispublicgetEstimatedCostDollars() returnpublicvoidsetEstimatedCostDollars(Long estimatedCostDollars)thispublic getIngredients()returnpublicvoidsetIngredients(Set<Ingredient> ingredients) thispublicgetMethod()returnpublicvoidsetMethod(Set<Method> method)thispublic getDiets()returnpublicvoidsetDiets(Set<Diet> diets)thispublicgetPrepTimeMin() returnpublicvoidsetPrepTimeMin(Long prepTimeMin)this@Overridepublicboolean equals(Object o)ifthisreturntrueifnullreturnfalseReciperecipe=return@Override publicinthashCode()return@OverridepublictoString()return"Recipe{""id="", name='"'\''", description='"'\''", servings="", cookingTimeMin="", prepTimeMin="", estimatedCostDollars="'}' com.equalexperts.recipefinder.entity; 2 3 com.equalexperts.recipefinder.dto.DietsDTO; 4 com.equalexperts.recipefinder.dto.IngredientsDTO; 5 com.equalexperts.recipefinder.dto.MethodDTO; 6 com.equalexperts.recipefinder.dto.RecipeDTO; 7 8 javax.persistence.*; 9 java.util.List; 10 java.util.Objects; 11 java.util.Set; 12 java.util.stream.Collectors; 13 14 15 16 { 17 18 19 Long id; 20 21 String name; 22 String description; 23 Long servings; 24 Long cookingTimeMin; 25 Long prepTimeMin; 26 Long estimatedCostDollars; 27 28 29 Set<Ingredient> ingredients; 30 31 32 Set<Method> method; 33 34
35 Set<Diet> diets; 36 37 { 38 39 } 40 { 41 .setName(dto.getName()); 42 .setDescription(dto.getDescription()); 43 .setCookingTimeMin(dto.getCookingTimeMin()); 44 .setEstimatedCostDollars(dto.getEstimatedCostDollars()); 45 .setPrepTimeMin(dto.getPreparationTimeMin()); 46 .setServings(dto.getServings()); 47 } 48 49 Recipe { 50 .setIngredients(dto.getIngredients().stream().map(ingredientDTO - > { 51 (); 52 i.setName(ingredientDTO.getName()); 53 i.setQuantity(ingredientDTO.getQuantity()); 54 i.setUnitOfMeasurement(ingredientDTO.getUnitOfMeasurement()); 55 i.setRecipe(); 56 i; 57 }).collect(Collectors.toSet())); 58 ; 59 } 60 61 Recipe { 62 .setMethod(dto.getMethod().stream().map(x -> { 63 (); 64 m.setRecipe(); 65 m.setDescription(x); 66 m; 67 }).collect(Collectors.toSet())); 68 ; 69 } 70 71 Recipe { 72 .setDiets(dto.getDiets().stream().map(x -> { 73 (); 74 d.setName(x); 75 d; 76 }).collect(Collectors.toSet())); 77 ; 78 } 79 80 Long { 81 id; 82 } 83 84 { 85 .id = id; 86 } 87 88 String { 89 name; 90 } 91 92 { 93 .name = name; 94 }
95 96 String { 97 description; 98 } 99 100 { 101 .description = description; 102 } 103 104 Long { 105 servings; 106 } 107 108 { 109 .servings = servings; 110 } 111 112 Long { 113 cookingTimeMin; 114 } 115 116 { 117 .cookingTimeMin = cookingTimeMin; 118 } 119 120 Long { 121 estimatedCostDollars; 122 } 123 124 { 125 .estimatedCostDollars = estimatedCostDollars; 126 } 127 128 Set<Ingredient> { 129 ingredients; 130 } 131 132 { 133 .ingredients = ingredients; 134 } 135 136 Set<Method> { 137 method; 138 } 139 140 { 141 .method = method; 142 } 143 144 Set<Diet> { 145 diets; 146 } 147 148 { 149 .diets = diets; 150 } 151 152 Long { 153 prepTimeMin; 154 } 155
156 { 157 .prepTimeMin = prepTimeMin; 158 } 159 160 161 { 162 ( == o) ; 163 (o == || getClass() != o.getClass()) ; 164 (Recipe) o; 165 Objects.equals(id, recipe.id) && Objects.equals(name, recipe.name) && Objects.equals(description, recipe.description) && Objects.equals(servings, recipe.servings) && Objects.equals(cookingTimeMin, recipe.cookingTimeMin) && Objects.equals(prepTimeMin, recipe.prepTimeMin) && Objects.equals(estimatedCostDollars, recipe.estimatedCostDollars); 166 } 167 168 169 { 170 Objects.hash(id, name, description, servings, cookingTimeMin, prepTimeMin, estimatedCostDollars); 171 } 172 173 174 String { 175 + 176 + id + 177 + name + + 178 + description + + 179 + servings + 180 + cookingTimeMin + 181 + prepTimeMin + 182 + estimatedCostDollars + 183 ; 184 } 185 } 186
src/main/java/com/equalexperts/recipefinder/integration/ RecipeAPIClient.java 1 packageimportimportimportimportimportimportimportimportimportimportimport @ComponentpublicclassRecipeAPIClientprivatefinal@Autowiredpublic RecipeAPIClient(WebClient.Builder webClientBuilder, @Value("${api}")thispublic getRecipeList()returnthis"/list.json"newParameterizedTypeReferencepublic getSummary(String recipeId)returnthis"/%s/summary.json"new ParameterizedTypeReferencepublicgetIngredients(String recipeId)returnthis"/%s/ ingredients.json"newParameterizedTypeReferencepublicgetDiets(String recipeId) returnthis"/%s/diets.json"newParameterizedTypeReferencepublicgetMethod(String recipeId)returnthis"/%s/method.json"newParameterizedTypeReference com.equalexperts.recipefinder.integration; 2 3 com.equalexperts.recipefinder.dto.DietsDTO; 4 com.equalexperts.recipefinder.dto.IngredientsDTO; 5 com.equalexperts.recipefinder.dto.MethodDTO; 6 com.equalexperts.recipefinder.dto.RecipeDTO; 7 org.springframework.beans.factory.annotation.Autowired; 8 org.springframework.beans.factory.annotation.Value; 9 org.springframework.core.ParameterizedTypeReference; 10 org.springframework.stereotype.Component; 11 org.springframework.web.reactive.function.client.WebClient; 12 reactor.core.publisher.Mono; 13 14 java.util.List; 15 16 17 { 18 WebClient webClient; 19 20 21 String baseUrl)</span> { 22 .webClient = webClientBuilder 23 .baseUrl(baseUrl) 24 .build(); 25 } 26 27 Mono<List<RecipeDTO>> { 28 .webClient.get() 29 .uri() 30 .retrieve() 31 .bodyToMono( <>(){}); 32 } 33 34 Mono<RecipeDTO> { 35 .webClient.get() 36 .uri(String.format(, recipeId)) 37 .retrieve() 38 .bodyToMono( <>(){}); 39 } 40 41 Mono<IngredientsDTO> { 42 .webClient.get() 43 .uri(String.format(, recipeId)) 44 .retrieve() 45 .bodyToMono( <>(){}); 46 } 47 48 Mono<DietsDTO> {
45 ></span> 46 ></span> 47 ></span> 48 ></span> 49 ></span>></span>Ingredients></span>></span> 50 ></span> 51 =></span> 52 =></span>></span> 53 ></span> 54 ></span> 55 ></span> 56 ></span> 57 ></span> 58 ></span> 59 ></span>></span>Method></span>></span> 60 ></span> 61 =></span> 62 =></span>></span> 63 ></span> 64 ></span> 65 ></span> 66 ></span> 67 68 69 ></span> 70 /></span> 71 ></span> 72 73 ></span> 74 75 ></span> 76 ></span>
src/main/resources/templates/recipe-view.html 1 <!DOCTYPE HTML<htmlxmlns:th"http://www.thymeleaf.org"<head<title</title< metahttp-equiv"Content-Type"content"text/html; charset=UTF-8"</head<body<table <table<tr<td<ahref"http://localhost:8080/recipe?id=${recipe.id}"th:text "${recipe.name}"</a</td</tr<tr<table<tr<tdth:text"'Cooking Time: ' + ${recipe.cookingTimeMin}"</td<tdth:text"'Preperation Time: ' + ${recipe.prepTimeMin}"</td</tr<tr<tdth:text"'Servings: ' + ${recipe.servings}" </td<tdth:text"'Estimated Cost: $' + ${recipe.estimatedCostDollars}"</td</tr</ table</tr<br<tr<td<b</b</td</tr<trth:each"diet : ${recipe.diets}"<tdth:text "${diet.name}"</td</tr<tr<td<table<tr<td<b</b</td</tr<trth:each"ingredient : ${recipe.ingredients}"<tdth:text"'* ' + ${ingredient.quantity} + 'x ' + ${ingredient.unitOfMeasurement} + ' ' + ${ingredient.name}"</td</tr</table</td <td<table<tr<td<b</b</td</tr<trth:each"method : ${recipe.method}"<tdth:text "${method.description}"</td</tr</table</td</tr<br<hr</table</table</body</html ></span> 2 =></span> 3 ></span> 4 ></span>Getting Started: Serving Web Content></span> 5 = = /></span> 6 ></span> 7 ></span> 8 9 ></span> 10 ></span> 11 ></span> 12 ></span> = =></span>></span>></span> 13 ></span> 14 ></span> 15 ></span> 16 ></span> 17 =></span>></span> 18 =></span>></span> 19 ></span> 20 ></span> 21 =></span>></span> 22 =></span>></span> 23 ></span> 24 ></span> 25 ></span> 26 27 ></span> 28 29 ></span> 30 ></span>></span>Diets></span>></span> 31 ></span> 32 =></span> 33 =></span>></span> 34 ></span> 35 ></span> 36 ></span> 37 ></span> 38 ></span> 39 ></span>></span>Ingredients></span>></span> 40 ></span> 41 =></span> 42 =></span>></span> 43 ></span> 44 ></span> 45 ></span>
46 ></span> 47 ></span> 48 ></span> 49 ></span>></span>Method></span>></span> 50 ></span> 51 =></span> 52 =></span>></span> 53 ></span> 54 ></span> 55 ></span> 56 ></span> 57 58 59 ></span> 60 /></span> 61 ></span> 62 63 ></span> 64 65 ></span> 66 ></span>
src/test/java/com/equalexperts/recipefinder/ RecipeFinderApplicationTests.java 1 packageimportimport@SpringBootTestclassRecipeFinderApplicationTests@Test voidcontextLoads() com.equalexperts.recipefinder; 2 3 org.junit.jupiter.api.Test; 4 org.springframework.boot.test.context.SpringBootTest; 5 6 7 { 8 9 • 10 ’° 11 —Ð 12 13 } 14
src/test/java/com/equalexperts/recipefinder/acceptance/challenge1/ RecipeAdminControllerTest.java 1 packageimportimportimportimportimportimportimportimportimportimportimport importimportimportimportstaticimportstaticimportstaticimportstatic @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureWebTestClient@ActiveProfiles("test")publicclass RecipeAdminControllerTest@Autowired@Autowired@Autowired@MockBean@Test @TransactionalpublicvoidimportShouldSucceed()finalRecipeDTOrecipeDTO=final RecipeDTOrecipeFromListDTO="/admin/import"StringresponseBody="Downloading"// Adjust based on actual responsefinalReciperecipe=011111 com.equalexperts.recipefinder.acceptance.challenge1; 2 3 com.equalexperts.recipefinder.controller.RecipeAdminController; 4 com.equalexperts.recipefinder.dto.RecipeDTO; 5 com.equalexperts.recipefinder.entity.Recipe; 6 com.equalexperts.recipefinder.integration.RecipeAPIClient; 7 com.equalexperts.recipefinder.repository.RecipeRepository; 8 org.junit.jupiter.api.Test; 9 org.springframework.beans.factory.annotation.Autowired; 10 org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebT estClient; 11 org.springframework.boot.test.context.SpringBootTest; 12 org.springframework.boot.test.mock.mockito.MockBean; 13 org.springframework.test.context.ActiveProfiles; 14 org.springframework.test.web.reactive.server.WebTestClient; 15 org.springframework.transaction.annotation.Transactional; 16 17 java.util.List; 18 19 com.equalexperts.recipefinder.util.Data.*; 20 org.junit.jupiter.api.Assertions.*; 21 org.mockito.Mockito.*; 22 reactor.core.publisher.Mono.just; 23 24 25 26 27 { 28 29 30 WebTestClient webTestClient; 31 32 33 RecipeAdminController controller; 34 35 36 RecipeRepository repository; 37 38 39 RecipeAPIClient apiClient; 40 41 42 43 { 44 avoOnToastRecipeDTO(); 45 avoOnToastRecipeFromListDTO(); 46 47 when(apiClient.getRecipeList()).thenReturn(just(List.of(recipeFromListDTO)));
48 when(apiClient.getSummary(any())).thenReturn(just(recipeDTO)); 49 when(apiClient.getMethod(any())).thenReturn(just(avoOnToastMethod())); 50 when(apiClient.getDiets(any())).thenReturn(just(avoOnToastDiets())); 51 when(apiClient.getIngredients(any())).thenReturn(just(avoOnToastIng redients())); 52 53 webTestClient 54 .get() 55 .uri() 56 .exchange() 57 .expectStatus().isOk() 58 .expectBody(String.class).consumeWith(response -> { 59 response.getResponseBody(); 60 assertTrue(responseBody.contains()); 61 }); 62 63 64 repository.findAll().get(); 65 66 assertFalse(recipe.getMethod().isEmpty()); 67 assertFalse(recipe.getDiets().isEmpty()); 68 assertFalse(recipe.getIngredients().isEmpty()); 69 70 assertEquals(recipeDTO.getName(), recipe.getName()); 71 assertEquals(recipeDTO.getDescription(), recipe.getDescription()); 72 assertEquals(recipeDTO.getServings(), recipe.getServings()); 73 assertEquals(recipeDTO.getCookingTimeMin(), recipe.getCookingTimeMin()); 74 assertEquals(recipeDTO.getPreparationTimeMin(), recipe.getPrepTimeMin()); 75 assertEquals(recipeDTO.getEstimatedCostDollars(), recipe.getEstimatedCostDollars()); 76 77 verify(apiClient, times()).getRecipeList(); 78 verify(apiClient, times()).getSummary(any()); 79 verify(apiClient, times()).getMethod(any()); 80 verify(apiClient, times()).getDiets(any()); 81 verify(apiClient, times()).getIngredients(any()); 82 } 83 }
src/test/java/com/equalexperts/recipefinder/acceptance/challenge1/ TotalTimeAcceptanceTest.java 1 packageimportimportimportimportimportimportimportimportimportimportimport importimportimportimportimportimportimportstaticimportstaticimportstaticimport static@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)@AutoConfigureWebTestClient @AutoConfigureMockMvc@ActiveProfiles("test")publicclassTotalTimeAcceptanceTest @Autowired@Autowired@Autowired@MockBean@BeforeEachpublicvoidsetUp(@Autowired newRecipenewRecipe@Testpublicvoidtime_up_to_30()throws"/recipes?time=30" "recipe-search""recipes""recipes"1@Testpublicvoidtime_up_to_500()throws"/ recipes?time=500""recipe-search""recipes""recipes"2@Testpublicvoid time_up_to_30_with_avo()throws"/recipes?query=toast&time=30""recipe-search" "recipes""recipes"1 com.equalexperts.recipefinder.acceptance.challenge1; 2 3 com.equalexperts.recipefinder.controller.RecipeAdminController; 4 com.equalexperts.recipefinder.entity.Recipe; 5 com.equalexperts.recipefinder.repository.RecipeRepository; 6 com.equalexperts.recipefinder.util.Data; 7 org.junit.jupiter.api.BeforeEach; 8 org.junit.jupiter.api.Test; 9 org.springframework.beans.factory.annotation.Autowired; 10 org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebT estClient; 11 org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 12 org.springframework.boot.test.context.SpringBootTest; 13 org.springframework.boot.test.mock.mockito.MockBean; 14 org.springframework.test.context.ActiveProfiles; 15 org.springframework.test.web.reactive.server.WebTestClient; 16 org.springframework.test.web.servlet.MockMvc; 17 org.springframework.test.web.servlet.setup.MockMvcBuilders; 18 org.springframework.web.context.WebApplicationContext; 19 20 java.util.List; 21 22 org.hamcrest.Matchers.hasSize; 23 org.mockito.BDDMockito.given; 24 org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 25 org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 26 27 28 29 30 31 { 32 33 34 MockMvc mockMvc; 35 36 37 WebTestClient webTestClient; 38 39 40 RecipeAdminController controller; 41 42 43 RecipeRepository repository; 44 45
46 47 WebApplicationContext webApplicationContext)</span> { 48 mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); 49 50 given(repository.findAll()).willReturn(List.of( 51 (Data.avoOnToastRecipeDTO()) 52 .setDiets(Data.avoOnToastDiets()) 53 .setIngredients(Data.avoOnToastIngredients()) 54 .setMethod(Data.avoOnToastMethod()), 55 (Data.burntToastRecipeDTO()) 56 .setDiets(Data.burntToastDiets()) 57 .setIngredients(Data.burntToastIngredients()) 58 .setMethod(Data.burntToastMethod()) 59 )); 60 } 61 62 63 Exception { 64 mockMvc.perform(get()) 65 .andExpect(status().isOk()) 66 .andExpect(view().name()) 67 .andExpect(model().attributeExists()) 68 .andExpect(model().attribute(, hasSize())) 69 ; 70 } 71 72 Exception { 73 mockMvc.perform(get()) 74 .andExpect(status().isOk()) 75 .andExpect(view().name()) 76 .andExpect(model().attributeExists()) 77 .andExpect(model().attribute(, hasSize())) 78 ; 79 } 80 81 82 Exception { 83 mockMvc.perform(get()) 84 .andExpect(status().isOk()) 85 .andExpect(view().name()) 86 .andExpect(model().attributeExists()) 87 .andExpect(model().attribute(, hasSize())) 88 ; 89 } 90 } 91 92
src/test/java/com/equalexperts/recipefinder/acceptance/challenge2/ CostAcceptanceTest.java 1 packageimportimportimportimportimportimportimportimportimportimportimport importimportimportimportimportimportimportstaticimportstaticimportstaticimport static@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)@AutoConfigureWebTestClient @AutoConfigureMockMvc@ActiveProfiles("test")publicclassCostAcceptanceTest @Autowired@Autowired@Autowired@MockBean@BeforeEachpublicvoidsetUp(@Autowired newRecipenewRecipe@Testpublicvoidcost_up_to_4()throws"/recipes?cost=4""recipesearch""recipes""recipes"1@Testpublicvoidcost_up_to_500()throws"/recipes? cost=500""recipe-search""recipes""recipes"2@Testpublicvoid cost_up_to_5_with_avo()throws"/recipes?query=avo&cost=5""recipe-search" "recipes""recipes"1 com.equalexperts.recipefinder.acceptance.challenge2; 2 3 com.equalexperts.recipefinder.controller.RecipeAdminController; 4 com.equalexperts.recipefinder.entity.Recipe; 5 com.equalexperts.recipefinder.repository.RecipeRepository; 6 com.equalexperts.recipefinder.util.Data; 7 org.junit.jupiter.api.BeforeEach; 8 org.junit.jupiter.api.Test; 9 org.springframework.beans.factory.annotation.Autowired; 10 org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebT estClient; 11 org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; 12 org.springframework.boot.test.context.SpringBootTest; 13 org.springframework.boot.test.mock.mockito.MockBean; 14 org.springframework.test.context.ActiveProfiles; 15 org.springframework.test.web.reactive.server.WebTestClient; 16 org.springframework.test.web.servlet.MockMvc; 17 org.springframework.test.web.servlet.setup.MockMvcBuilders; 18 org.springframework.web.context.WebApplicationContext; 19 20 java.util.List; 21 22 org.hamcrest.Matchers.hasSize; 23 org.mockito.BDDMockito.given; 24 org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 25 org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 26 27 28 29 30 31 { 32 33 34 MockMvc mockMvc; 35 36 37 WebTestClient webTestClient; 38 39 40 RecipeAdminController controller; 41 42 43 RecipeRepository repository; 44 45
46 47 WebApplicationContext webApplicationContext)</span> { 48 mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); 49 50 given(repository.findAll()).willReturn(List.of( 51 (Data.avoOnToastRecipeDTO()) 52 .setDiets(Data.avoOnToastDiets()) 53 .setIngredients(Data.avoOnToastIngredients()) 54 .setMethod(Data.avoOnToastMethod()), 55 (Data.burntToastRecipeDTO()) 56 .setDiets(Data.burntToastDiets()) 57 .setIngredients(Data.burntToastIngredients()) 58 .setMethod(Data.burntToastMethod()) 59 )); 60 } 61 62 63 Exception { 64 mockMvc.perform(get()) 65 .andExpect(status().isOk()) 66 .andExpect(view().name()) 67 .andExpect(model().attributeExists()) 68 .andExpect(model().attribute(, hasSize())) 69 ; 70 } 71 72 73 Exception { 74 mockMvc.perform(get()) 75 .andExpect(status().isOk()) 76 .andExpect(view().name()) 77 .andExpect(model().attributeExists()) 78 .andExpect(model().attribute(, hasSize())) 79 ; 80 } 81 82 83 Exception { 84 mockMvc.perform(get()) 85 .andExpect(status().isOk()) 86 .andExpect(view().name()) 87 .andExpect(model().attributeExists()) 88 .andExpect(model().attribute(, hasSize())) 89 ; 90 } 91 92 } 93 94
41 42 MethodDTO { 43 (); 44 method.setMethod(List.of( 45 , 46 , 47 , 48 , 49 , 50 51 )); 52 method; 53 } 54 55 MethodDTO { 56 (); 57 method.setMethod(List.of( 58 , 59 60 )); 61 method; 62 } 63 64 DietsDTO { 65 (); 66 diets.setDiets(List.of(, )); 67 diets; 68 } 69 70 DietsDTO { 71 (); 72 diets.setDiets(List.of(, )); 73 diets; 74 } 75 76 IngredientsDTO { 77 (); 78 List<IngredientDTO> ingredientsList = <>(); 79 (); 80 bread.setUnitOfMeasurement(); 81 bread.setQuantity(); 82 bread.setName(); 83 ingredientsList.add(bread); 84 (); 85 avo.setQuantity(); 86 avo.setName(); 87 ingredientsList.add(avo); 88 ingredients.setIngredients(ingredientsList); 89 ingredients; 90 } 91 92 IngredientsDTO { 93 (); 94 List<IngredientDTO> ingredientsList = <>(); 95 (); 96 bread.setUnitOfMeasurement(); 97 bread.setQuantity(); 98 bread.setName(); 99 ingredientsList.add(bread); 100 ingredients.setIngredients(ingredientsList); 101 ingredients;
102 } 103 } 104