From 05736cec30b935bf52e4f1d6656776f2c03f094e Mon Sep 17 00:00:00 2001 From: "Christopher C. Wells" Date: Thu, 8 Apr 2021 16:54:01 -0700 Subject: [PATCH] Add tests and documentation for nutrient rounding changes --- app/Support/Nutrients.php | 43 ++++++++++++++++++++++--- tests/Unit/Support/NutrientsTest.php | 48 ++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 tests/Unit/Support/NutrientsTest.php diff --git a/app/Support/Nutrients.php b/app/Support/Nutrients.php index a582465..354e5a6 100644 --- a/app/Support/Nutrients.php +++ b/app/Support/Nutrients.php @@ -198,14 +198,47 @@ class Nutrients * zero. * * @url https://labelcalc.com/food-labeling/a-guide-to-using-fda-rounding-rules-for-your-food-label/ + * + * @throws \InvalidArgumentException */ public static function round(float $amount, string $nutrient): float { return match ($nutrient) { - 'calories' => ($amount < 5 ? 0 : ($amount <= 50 ? round( $amount / 5 ) * 5 : round( $amount / 10 ) * 10)), - 'carbohydrates', 'protein' => ($amount < 1 ? 0 : round( $amount)), - 'cholesterol', 'fat' => ($amount < 0.5 ? 0 : ($amount <= 5 ? round( $amount / 5, 1 ) * 5 : round($amount))), - 'sodium' => ($amount < 5 ? 0 : ($amount <= 140 ? round( $amount / 5 ) * 5 : round( $amount / 10 ) * 10)), - default => throw new \UnexpectedValueException() + + /* + * Calories: + * - Less than 5 goes to zero. + * - Between 5 and 50 rounds to nearest number divisible by 5. + * - Greater than 50 rounds to nearest number divisible by 10. + */ + 'calories' => ($amount < 5 ? 0 : ($amount <= 50 ? round($amount / 5 ) * 5 : round($amount / 10 ) * 10)), + + /* + * Carbohydrates and protein: + * - Less than 1 goes to zero. + * - Greater than 1 rounds to nearest whole. + */ + 'carbohydrates', 'protein' => ($amount < 1 ? 0 : round($amount)), + + /* + * Cholesterol and fat: + * - Less than 0.5 goes to zero. + * - Between 0.5 and 5 rounds to nearest half. + * - Greater than 5 rounds to nearest whole. + */ + 'cholesterol', 'fat' => ($amount < 0.5 ? 0 : ($amount <= 5 ? round($amount / 5, 1 ) * 5 : round($amount))), + + /* + * Sodium: + * - Less than 5 goes to zero. + * - Between 5 and 140 rounds to nearest number divisible by 5. + * - Greater than 140 rounds to nearest number divisible by 10. + */ + 'sodium' => ($amount < 5 ? 0 : ($amount <= 140 ? round($amount / 5 ) * 5 : round($amount / 10 ) * 10)), + + /* + * Anything else excepts! + */ + default => throw new \InvalidArgumentException("Unrecognized nutrient {$nutrient}.") }; } } diff --git a/tests/Unit/Support/NutrientsTest.php b/tests/Unit/Support/NutrientsTest.php new file mode 100644 index 0000000..e7af25c --- /dev/null +++ b/tests/Unit/Support/NutrientsTest.php @@ -0,0 +1,48 @@ +assertIsFloat($result); + $this->assertEquals($expectedFloat, $result); + } + + public function testNutrientRoundingExcepts(): void + { + $this->expectException(\InvalidArgumentException::class); + Nutrients::round(1, 'pancake'); + } + + /** + * Data providers. + */ + + /** + * Provide nutrient amounts for and expected rounded results. + */ + public function nutrientAmountsProvider(): array { + return [ + [0, 'calories', 0], [1, 'calories', 0], [2, 'calories', 0], [3, 'calories', 0], [4, 'calories', 0], [5, 'calories', 5], [21, 'calories', 20], [23, 'calories', 25], [45, 'calories', 45], [50, 'calories', 50], + [0, 'carbohydrates', 0], [0.1, 'carbohydrates', 0], [0.2, 'carbohydrates', 0], [0.3, 'carbohydrates', 0], [0.4, 'carbohydrates', 0], [0.5, 'carbohydrates', 0], [0.9, 'carbohydrates', 0], [1, 'carbohydrates', 1], [2.25, 'carbohydrates', 2], [2.75, 'carbohydrates', 3], + [0, 'protein', 0], [0.1, 'protein', 0], [0.2, 'protein', 0], [0.3, 'protein', 0], [0.4, 'protein', 0], [0.5, 'protein', 0], [0.9, 'protein', 0], [1, 'protein', 1], [2.25, 'protein', 2], [2.75, 'protein', 3], + [0, 'cholesterol', 0], [0.1, 'cholesterol', 0], [0.2, 'cholesterol', 0], [0.3, 'cholesterol', 0], [0.4, 'cholesterol', 0], [0.5, 'cholesterol', 0.5], [0.9, 'cholesterol', 1], [1, 'cholesterol', 1], [1.2, 'cholesterol', 1], [1.4, 'cholesterol', 1.5], [5, 'cholesterol', 5], [6, 'cholesterol', 6], [6.25, 'cholesterol', 6], [6.75, 'cholesterol', 7], + [0, 'fat', 0], [0.1, 'fat', 0], [0.2, 'fat', 0], [0.3, 'fat', 0], [0.4, 'fat', 0], [0.5, 'fat', 0.5], [0.9, 'fat', 1], [1, 'fat', 1], [1.2, 'fat', 1], [1.4, 'fat', 1.5], [5, 'fat', 5], [6, 'fat', 6], [6.25, 'fat', 6], [6.75, 'fat', 7], + [0, 'sodium', 0], [1, 'sodium', 0], [2, 'sodium', 0], [3, 'sodium', 0], [4, 'sodium', 0], [5, 'sodium', 5], [6, 'sodium', 5], [7, 'sodium', 5], [8, 'sodium', 10], [9, 'sodium', 10], [10, 'sodium', 10], [139, 'sodium', 140], [140, 'sodium', 140], [146, 'sodium', 150], [151, 'sodium', 150], [159, 'sodium', 160], + ]; + } +}