From 5eeb77f7d37d55d12ac8b1aa0c1fb9bc77674292 Mon Sep 17 00:00:00 2001 From: Daniel McCoy Stephenson Date: Fri, 2 Oct 2026 01:07:53 -0600 Subject: [PATCH] Add InputValidator utility for score range checks The 1-5 score range was checked separately in three places across the create and update commands. Both commands now share InputValidator. Co-Authored-By: Claude Opus 5.5 --- .../parpt/command/CreateProjectCommand.java | 6 +-- .../parpt/command/UpdateProjectCommand.java | 7 +-- .../parpt/util/InputValidator.java | 38 ++++++++++++++++ .../parpt/util/InputValidatorTest.java | 43 +++++++++++++++++++ 4 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/preponderous/parpt/util/InputValidator.java create mode 100644 src/test/java/com/preponderous/parpt/util/InputValidatorTest.java diff --git a/src/main/java/com/preponderous/parpt/command/CreateProjectCommand.java b/src/main/java/com/preponderous/parpt/command/CreateProjectCommand.java index 00323b8..5214a93 100644 --- a/src/main/java/com/preponderous/parpt/command/CreateProjectCommand.java +++ b/src/main/java/com/preponderous/parpt/command/CreateProjectCommand.java @@ -6,6 +6,7 @@ import com.preponderous.parpt.score.ScoreCalculator; import com.preponderous.parpt.service.ProjectService; import com.preponderous.parpt.util.ConsoleInputProvider; +import com.preponderous.parpt.util.InputValidator; import org.springframework.shell.standard.ShellComponent; import org.springframework.shell.standard.ShellMethod; import org.springframework.shell.standard.ShellOption; @@ -56,7 +57,7 @@ private int getAverageScore(String[] prompts) throws InvalidScoreException, Crea for (String prompt : prompts) { try { int score = Integer.parseInt(readInput(prompt)); - if (score < 1 || score > 5) { + if (!InputValidator.isValidScore(score)) { throw new InvalidScoreException("Invalid score. Must be between 1 and 5."); } total += score; @@ -133,8 +134,7 @@ public String execute( return CANCELLED_MESSAGE; } - if (impact < 1 || impact > 5 || confidence < 1 || confidence > 5 || - ease < 1 || ease > 5 || reach < 1 || reach > 5 || effort < 1 || effort > 5) { + if (!InputValidator.areValidScores(impact, confidence, ease, reach, effort)) { return "All scores must be between 1 and 5."; } diff --git a/src/main/java/com/preponderous/parpt/command/UpdateProjectCommand.java b/src/main/java/com/preponderous/parpt/command/UpdateProjectCommand.java index 08c360a..39d07cd 100644 --- a/src/main/java/com/preponderous/parpt/command/UpdateProjectCommand.java +++ b/src/main/java/com/preponderous/parpt/command/UpdateProjectCommand.java @@ -4,6 +4,7 @@ import com.preponderous.parpt.repo.ProjectRepository; import com.preponderous.parpt.score.ScoreCalculator; import com.preponderous.parpt.service.ProjectService; +import com.preponderous.parpt.util.InputValidator; import org.springframework.shell.standard.ShellComponent; import org.springframework.shell.standard.ShellMethod; import org.springframework.shell.standard.ShellOption; @@ -21,10 +22,6 @@ public UpdateProjectCommand(ProjectService projectService, ScoreCalculator score this.scoreCalculator = scoreCalculator; } - private static boolean isOutOfRange(Integer score) { - return score != null && (score < 1 || score > 5); - } - @ShellMethod(key = "update", value = "Updates the description or scores of a specific project by name.") public String execute( @ShellOption(help = "The name of the project to update") String projectName, @@ -41,7 +38,7 @@ public String execute( if (description != null && description.isEmpty()) { return "Project description cannot be empty."; } - if (Stream.of(impact, confidence, ease, reach, effort).anyMatch(UpdateProjectCommand::isOutOfRange)) { + if (!InputValidator.areValidScores(impact, confidence, ease, reach, effort)) { return "All scores must be between 1 and 5."; } diff --git a/src/main/java/com/preponderous/parpt/util/InputValidator.java b/src/main/java/com/preponderous/parpt/util/InputValidator.java new file mode 100644 index 0000000..d54c05c --- /dev/null +++ b/src/main/java/com/preponderous/parpt/util/InputValidator.java @@ -0,0 +1,38 @@ +package com.preponderous.parpt.util; + +/** + * Validates user-supplied input, so every command applies the same rules. + */ +public final class InputValidator { + public static final int MIN_SCORE = 1; + public static final int MAX_SCORE = 5; + + private InputValidator() { + } + + /** + * Checks whether a score lies within the allowed range. + * + * @param score The score to check + * @return True if the score is between {@link #MIN_SCORE} and {@link #MAX_SCORE}, inclusive + */ + public static boolean isValidScore(int score) { + return score >= MIN_SCORE && score <= MAX_SCORE; + } + + /** + * Checks whether every given score lies within the allowed range. A null score stands for a + * value that was not supplied and is ignored. + * + * @param scores The scores to check + * @return True if no non-null score is outside the allowed range + */ + public static boolean areValidScores(Integer... scores) { + for (Integer score : scores) { + if (score != null && !isValidScore(score)) { + return false; + } + } + return true; + } +} diff --git a/src/test/java/com/preponderous/parpt/util/InputValidatorTest.java b/src/test/java/com/preponderous/parpt/util/InputValidatorTest.java new file mode 100644 index 0000000..29e1908 --- /dev/null +++ b/src/test/java/com/preponderous/parpt/util/InputValidatorTest.java @@ -0,0 +1,43 @@ +package com.preponderous.parpt.util; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class InputValidatorTest { + + @Test + void testScoresWithinRangeAreValid() { + for (int score = 1; score <= 5; score++) { + assertTrue(InputValidator.isValidScore(score), "Score " + score + " should be valid"); + } + } + + @Test + void testScoresOutsideRangeAreInvalid() { + assertFalse(InputValidator.isValidScore(0)); + assertFalse(InputValidator.isValidScore(6)); + assertFalse(InputValidator.isValidScore(-1)); + assertFalse(InputValidator.isValidScore(Integer.MAX_VALUE)); + assertFalse(InputValidator.isValidScore(Integer.MIN_VALUE)); + } + + @Test + void testAllScoresWithinRangeAreValid() { + assertTrue(InputValidator.areValidScores(1, 2, 3, 4, 5)); + } + + @Test + void testOneScoreOutsideRangeMakesAllInvalid() { + assertFalse(InputValidator.areValidScores(1, 2, 6, 4, 5)); + assertFalse(InputValidator.areValidScores(0, 2, 3, 4, 5)); + } + + @Test + void testNullScoresAreIgnored() { + assertTrue(InputValidator.areValidScores(null, 3, null)); + assertTrue(InputValidator.areValidScores((Integer) null)); + assertFalse(InputValidator.areValidScores(null, 6, null)); + } +}