mirror of https://github.com/kcal-app/kcal.git
Add tests for Support classes
This commit is contained in:
parent
d69d962287
commit
01b414c22c
|
@ -71,12 +71,6 @@ class Nutrients
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate a nutrient multiplier for a Food.
|
* Calculate a nutrient multiplier for a Food.
|
||||||
*
|
|
||||||
* @param \App\Models\Food $food
|
|
||||||
* @param float $amount
|
|
||||||
* @param string|null $fromUnit
|
|
||||||
*
|
|
||||||
* @return float
|
|
||||||
*/
|
*/
|
||||||
public static function calculateFoodNutrientMultiplier(
|
public static function calculateFoodNutrientMultiplier(
|
||||||
Food $food,
|
Food $food,
|
||||||
|
@ -93,6 +87,7 @@ class Nutrients
|
||||||
return $amount / $food->serving_weight;
|
return $amount / $food->serving_weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @todo Determine if `empty($food->serving_unit)` case makes sense.
|
||||||
if (
|
if (
|
||||||
empty($fromUnit)
|
empty($fromUnit)
|
||||||
|| empty($food->serving_unit)
|
|| empty($food->serving_unit)
|
||||||
|
@ -130,13 +125,6 @@ class Nutrients
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate a nutrient amount for a recipe.
|
* Calculate a nutrient amount for a recipe.
|
||||||
*
|
|
||||||
* @param \App\Models\Recipe $recipe
|
|
||||||
* @param string $nutrient
|
|
||||||
* @param float $amount
|
|
||||||
* @param string $fromUnit
|
|
||||||
*
|
|
||||||
* @return float
|
|
||||||
*/
|
*/
|
||||||
public static function calculateRecipeNutrientAmount(
|
public static function calculateRecipeNutrientAmount(
|
||||||
Recipe $recipe,
|
Recipe $recipe,
|
||||||
|
|
|
@ -8,21 +8,81 @@ use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
class FoodFactory extends Factory
|
class FoodFactory extends Factory
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The name of the factory's corresponding model.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
*/
|
||||||
protected $model = Food::class;
|
protected $model = Food::class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the model's default state.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
public function definition()
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
//
|
'name' => $this->faker->word,
|
||||||
|
'detail' => $this->faker->sentence(2),
|
||||||
|
'brand' => $this->faker->word,
|
||||||
|
'source' => $this->faker->url,
|
||||||
|
'serving_size' => $this->faker->randomFloat(2, 1/2, 5),
|
||||||
|
'serving_unit' => $this->faker->randomElement(['tsp', 'tbsp', 'cup']),
|
||||||
|
'serving_weight' => $this->faker->numberBetween(5, 500),
|
||||||
|
'calories' => $this->faker->randomFloat(2, 0, 100),
|
||||||
|
'fat' => $this->faker->randomFloat(2, 0, 10),
|
||||||
|
'cholesterol' => $this->faker->randomFloat(2, 0, 100),
|
||||||
|
'sodium' => $this->faker->randomFloat(2, 0, 500),
|
||||||
|
'carbohydrates' => $this->faker->randomFloat(2, 0, 20),
|
||||||
|
'protein' => $this->faker->randomFloat(2, 0, 20),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make instance with "tsp" serving unit.
|
||||||
|
*/
|
||||||
|
public function tspServingUnit()
|
||||||
|
{
|
||||||
|
return $this->state(function (array $attributes) {
|
||||||
|
return [
|
||||||
|
'serving_unit' => 'tsp',
|
||||||
|
'serving_size' => 1,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make instance with "tbsp" serving unit.
|
||||||
|
*/
|
||||||
|
public function tbspServingUnit()
|
||||||
|
{
|
||||||
|
return $this->state(function (array $attributes) {
|
||||||
|
return [
|
||||||
|
'serving_unit' => 'tbsp',
|
||||||
|
'serving_size' => 1,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make instance with "cup" serving unit.
|
||||||
|
*/
|
||||||
|
public function cupServingUnit()
|
||||||
|
{
|
||||||
|
return $this->state(function (array $attributes) {
|
||||||
|
return [
|
||||||
|
'serving_unit' => 'cup',
|
||||||
|
'serving_size' => 1,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make instance with no" serving unit.
|
||||||
|
*/
|
||||||
|
public function noServingUnit()
|
||||||
|
{
|
||||||
|
return $this->state(function (array $attributes) {
|
||||||
|
return [
|
||||||
|
'serving_unit' => null,
|
||||||
|
'serving_unit_name' => 'head'
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
<server name="APP_ENV" value="testing"/>
|
<server name="APP_ENV" value="testing"/>
|
||||||
<server name="BCRYPT_ROUNDS" value="4"/>
|
<server name="BCRYPT_ROUNDS" value="4"/>
|
||||||
<server name="CACHE_DRIVER" value="array"/>
|
<server name="CACHE_DRIVER" value="array"/>
|
||||||
<!-- <server name="DB_CONNECTION" value="sqlite"/> -->
|
<server name="DB_CONNECTION" value="sqlite"/>
|
||||||
<!-- <server name="DB_DATABASE" value=":memory:"/> -->
|
<server name="DB_DATABASE" value=":memory:"/>
|
||||||
<server name="MAIL_MAILER" value="array"/>
|
<server name="MAIL_MAILER" value="array"/>
|
||||||
<server name="QUEUE_CONNECTION" value="sync"/>
|
<server name="QUEUE_CONNECTION" value="sync"/>
|
||||||
<server name="SESSION_DRIVER" value="array"/>
|
<server name="SESSION_DRIVER" value="array"/>
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Feature;
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
||||||
use Tests\TestCase;
|
|
||||||
|
|
||||||
class ExampleTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* A basic test example.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function testBasicTest()
|
|
||||||
{
|
|
||||||
$response = $this->get('/');
|
|
||||||
|
|
||||||
$response->assertStatus(200);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Feature;
|
|
||||||
|
|
||||||
use App\Providers\RouteServiceProvider;
|
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
||||||
use Tests\TestCase;
|
|
||||||
|
|
||||||
class RegistrationTest extends TestCase
|
|
||||||
{
|
|
||||||
use RefreshDatabase;
|
|
||||||
|
|
||||||
public function test_registration_screen_can_be_rendered()
|
|
||||||
{
|
|
||||||
$response = $this->get('/register');
|
|
||||||
|
|
||||||
$response->assertStatus(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_new_users_can_register()
|
|
||||||
{
|
|
||||||
$response = $this->post('/register', [
|
|
||||||
'name' => 'Test User',
|
|
||||||
'email' => 'test@example.com',
|
|
||||||
'password' => 'password',
|
|
||||||
'password_confirmation' => 'password',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->assertAuthenticated();
|
|
||||||
$response->assertRedirect(RouteServiceProvider::HOME);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Support;
|
||||||
|
|
||||||
|
use App\Models\Food;
|
||||||
|
use App\Support\Nutrients;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class NutrientsTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test invalid Food nutrient multiplier calculation.
|
||||||
|
*
|
||||||
|
* @dataProvider foodsInvalidNutrientMultipliersProvider
|
||||||
|
*/
|
||||||
|
public function testCalculateFoodInvalidNutrientMultiplier(
|
||||||
|
Food $food,
|
||||||
|
float $amount,
|
||||||
|
string $fromUnit,
|
||||||
|
): void {
|
||||||
|
$this->expectException(\DomainException::class);
|
||||||
|
Nutrients::calculateFoodNutrientMultiplier($food, $amount, $fromUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test valid Food nutrient multiplier calculation.
|
||||||
|
*
|
||||||
|
* @dataProvider foodsValidNutrientMultipliersProvider
|
||||||
|
*/
|
||||||
|
public function testCalculateFoodValidNutrientMultiplier(
|
||||||
|
Food $food,
|
||||||
|
float $amount,
|
||||||
|
string $fromUnit,
|
||||||
|
float $expectedMultiplier
|
||||||
|
): void {
|
||||||
|
$this->assertEquals(
|
||||||
|
Nutrients::calculateFoodNutrientMultiplier($food, $amount, $fromUnit),
|
||||||
|
$expectedMultiplier
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data providers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide example foods and expected nutrient multipliers.
|
||||||
|
*/
|
||||||
|
public function foodsInvalidNutrientMultipliersProvider(): array {
|
||||||
|
$this->refreshApplication();
|
||||||
|
|
||||||
|
/** @var \App\Models\Food $foodInvalidUnit */
|
||||||
|
$foodInvalidUnit = Food::factory()->make(['serving_unit' => 'invalid']);
|
||||||
|
|
||||||
|
return [
|
||||||
|
[$foodInvalidUnit, 1, 'tsp'],
|
||||||
|
[$foodInvalidUnit, 1, 'tbsp'],
|
||||||
|
[$foodInvalidUnit, 1, 'cup'],
|
||||||
|
[Food::factory()->tspServingUnit()->make(), 1, 'invalid'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide example foods and expected nutrient multipliers.
|
||||||
|
*/
|
||||||
|
public function foodsValidNutrientMultipliersProvider(): array {
|
||||||
|
$this->refreshApplication();
|
||||||
|
|
||||||
|
/** @var \App\Models\Food[] $foods */
|
||||||
|
$foods = [
|
||||||
|
'tsp' => Food::factory()->tspServingUnit()->make(),
|
||||||
|
'tbsp' => Food::factory()->tbspServingUnit()->make(),
|
||||||
|
'cup' => Food::factory()->cupServingUnit()->make(),
|
||||||
|
'none' => Food::factory()->noServingUnit()->make(),
|
||||||
|
];
|
||||||
|
|
||||||
|
return [
|
||||||
|
[$foods['tsp'], $foods['tsp']->serving_weight, 'oz', Nutrients::$gramsPerOunce],
|
||||||
|
[$foods['tsp'], 1, 'serving', 1],
|
||||||
|
[$foods['tsp'], $foods['tsp']->serving_weight * 1.5, 'gram', 1.5],
|
||||||
|
[$foods['tsp'], 2, 'tsp', 2],
|
||||||
|
[$foods['tsp'], 1, 'tbsp', 3],
|
||||||
|
[$foods['tsp'], 1, 'cup', 48],
|
||||||
|
[$foods['tbsp'], $foods['tbsp']->serving_weight, 'oz', Nutrients::$gramsPerOunce],
|
||||||
|
[$foods['tbsp'], 1, 'serving', 1],
|
||||||
|
[$foods['tbsp'], $foods['tbsp']->serving_weight * 2, 'gram', 2],
|
||||||
|
[$foods['tbsp'], 2, 'tsp', 2/3],
|
||||||
|
[$foods['tbsp'], 1, 'tbsp', 1],
|
||||||
|
[$foods['tbsp'], 2, 'cup', 32],
|
||||||
|
[$foods['cup'], $foods['cup']->serving_weight, 'oz', Nutrients::$gramsPerOunce],
|
||||||
|
[$foods['cup'], 1, 'serving', 1],
|
||||||
|
[$foods['cup'], $foods['cup']->serving_weight * 2.25, 'gram', 2.25],
|
||||||
|
[$foods['cup'], 3, 'tsp', 1/16],
|
||||||
|
[$foods['cup'], 2, 'tbsp', 1/8],
|
||||||
|
[$foods['cup'], 5, 'cup', 5],
|
||||||
|
[$foods['none'], $foods['none']->serving_weight, 'oz', Nutrients::$gramsPerOunce],
|
||||||
|
[$foods['none'], 1, 'serving', 1],
|
||||||
|
[$foods['none'], $foods['none']->serving_weight * 3.0125, 'gram', 3.0125],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Unit;
|
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
class ExampleTest extends TestCase
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* A basic test example.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function testBasicTest()
|
|
||||||
{
|
|
||||||
$this->assertTrue(true);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit\Support;
|
||||||
|
|
||||||
|
use App\Support\ArrayFormat;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class ArrayFormatTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test input array "flipping".
|
||||||
|
*
|
||||||
|
* @see \App\Support\ArrayFormat::flipTwoDimensionalKeys()
|
||||||
|
*/
|
||||||
|
public function testFlipTwoDimensionalKeys(): void
|
||||||
|
{
|
||||||
|
$input = [
|
||||||
|
'ingredient' => [
|
||||||
|
0 => 'ingredient-0',
|
||||||
|
1 => 'ingredient-1',
|
||||||
|
2 => 'ingredient-2',
|
||||||
|
3 => 'ingredient-3',
|
||||||
|
],
|
||||||
|
'amount' => [
|
||||||
|
0 => 'amount-0',
|
||||||
|
1 => 'amount-1',
|
||||||
|
2 => 'amount-2',
|
||||||
|
3 => 'amount-3',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
$expected = [
|
||||||
|
['ingredient' => 'ingredient-0', 'amount' => 'amount-0'],
|
||||||
|
['ingredient' => 'ingredient-1', 'amount' => 'amount-1'],
|
||||||
|
['ingredient' => 'ingredient-2', 'amount' => 'amount-2'],
|
||||||
|
['ingredient' => 'ingredient-3', 'amount' => 'amount-3'],
|
||||||
|
];
|
||||||
|
$this->assertEqualsCanonicalizing($expected, ArrayFormat::flipTwoDimensionalKeys($input));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit\Support;
|
||||||
|
|
||||||
|
use App\Support\Number;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class NumberTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test float to string conversion.
|
||||||
|
*
|
||||||
|
* @dataProvider decimalStringFloatsProvider
|
||||||
|
* @dataProvider fractionStringFloatsProvider
|
||||||
|
*
|
||||||
|
* @see \App\Support\Number::floatFromString()
|
||||||
|
*/
|
||||||
|
public function testFloatFromString(string $string, float $expectedFloat): void
|
||||||
|
{
|
||||||
|
$result = Number::floatFromString($string);
|
||||||
|
$this->assertIsFloat($result);
|
||||||
|
$this->assertEquals($expectedFloat, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test (fraction) string to float conversion.
|
||||||
|
*
|
||||||
|
* @dataProvider fractionStringFloatsProvider
|
||||||
|
*
|
||||||
|
* @see \App\Support\Number::fractionStringFromFloat()
|
||||||
|
*/
|
||||||
|
public function testFractionStringFromFloat(string $expectedString, float $float): void
|
||||||
|
{
|
||||||
|
$result = Number::fractionStringFromFloat($float);
|
||||||
|
$this->assertIsString($result);
|
||||||
|
$this->assertEquals($expectedString, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data providers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide decimal string and float data.
|
||||||
|
*
|
||||||
|
* @see \Tests\Unit\Support\NumberTest::testFloatFromString()
|
||||||
|
*/
|
||||||
|
public function decimalStringFloatsProvider(): array {
|
||||||
|
return [
|
||||||
|
['0.0', 0.0], ['0.125', 1/8], ['0.25', 1/4], ['0.5', 1/2],
|
||||||
|
['0.75', 3/4], ['1.0', 1.0], ['1.25', 1.25], ['1.5', 1.5],
|
||||||
|
['2.5', 2.5], ['2.75', 2.75],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide fraction string and float data.
|
||||||
|
*
|
||||||
|
* @see \Tests\Unit\Support\NumberTest::testFloatFromString()
|
||||||
|
* @see \Tests\Unit\Support\NumberTest::testFractionStringFromFloat()
|
||||||
|
*/
|
||||||
|
public function fractionStringFloatsProvider(): array {
|
||||||
|
return [
|
||||||
|
['0', 0.0], ['1/8', 1/8], ['1/4', 1/4], ['1/3', 1/3], ['1/2', 1/2],
|
||||||
|
['2/3', 2/3], ['3/4', 3/4], ['1', 1.0], ['1 1/4', 1.25],
|
||||||
|
['1 1/2', 1.5], ['2 1/2', 2.5], ['2 3/4', 2.75],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue