mirror of https://github.com/kcal-app/kcal.git
Test JSON API relationships
This commit is contained in:
parent
3eebcf2756
commit
da39143113
|
@ -27,6 +27,7 @@ class RecipeFactory extends Factory
|
||||||
'source' => $this->faker->optional()->url,
|
'source' => $this->faker->optional()->url,
|
||||||
'servings' => $this->faker->numberBetween(1, 10),
|
'servings' => $this->faker->numberBetween(1, 10),
|
||||||
'weight' => $this->faker->randomFloat(1, 60, 2000),
|
'weight' => $this->faker->randomFloat(1, 60, 2000),
|
||||||
|
'tags' => $this->faker->words,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,15 @@
|
||||||
namespace Tests\Feature\JsonApi;
|
namespace Tests\Feature\JsonApi;
|
||||||
|
|
||||||
use App\Models\Food;
|
use App\Models\Food;
|
||||||
|
use App\Models\Recipe;
|
||||||
use Database\Factories\FoodFactory;
|
use Database\Factories\FoodFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\Feature\JsonApi\Traits\HasTags;
|
||||||
|
|
||||||
class FoodApiTest extends JsonApiTestCase
|
class FoodApiTest extends JsonApiTestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase, HasTags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
|
@ -41,7 +44,7 @@ class FoodApiTest extends JsonApiTestCase
|
||||||
|
|
||||||
foreach ($attributes as $attribute => $value) {
|
foreach ($attributes as $attribute => $value) {
|
||||||
$partial = substr($value, rand(0, 3), 3);
|
$partial = substr($value, rand(0, 3), 3);
|
||||||
$search_route = route($this->indexRouteName, [
|
$search_route = route("$this->routeBase.index", [
|
||||||
'filter' => ['search' => $partial]
|
'filter' => ['search' => $partial]
|
||||||
]);
|
]);
|
||||||
$response = $this->get($search_route);
|
$response = $this->get($search_route);
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
namespace Tests\Feature\JsonApi;
|
namespace Tests\Feature\JsonApi;
|
||||||
|
|
||||||
use App\Models\Goal;
|
use App\Models\Goal;
|
||||||
use App\Models\User;
|
|
||||||
use Database\Factories\GoalFactory;
|
use Database\Factories\GoalFactory;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\Feature\JsonApi\Traits\BelongsToUser;
|
||||||
|
|
||||||
class GoalApiTest extends JsonApiTestCase
|
class GoalApiTest extends JsonApiTestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase, BelongsToUser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
|
@ -32,7 +32,7 @@ class GoalApiTest extends JsonApiTestCase
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected function createInstances(int $count = 1): Collection {
|
protected function createInstances(int $count = 1): Collection {
|
||||||
return User::factory()->count(1)->hasGoals($count)->create();
|
return $this->factory()->count($count)->for($this->user)->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
namespace Tests\Feature\JsonApi;
|
namespace Tests\Feature\JsonApi;
|
||||||
|
|
||||||
|
use App\Models\Food;
|
||||||
use App\Models\IngredientAmount;
|
use App\Models\IngredientAmount;
|
||||||
|
use App\Models\JournalEntry;
|
||||||
|
use App\Models\Recipe;
|
||||||
use Database\Factories\IngredientAmountFactory;
|
use Database\Factories\IngredientAmountFactory;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
@ -26,4 +29,28 @@ class IngredientAmountApiTest extends JsonApiTestCase
|
||||||
return 'ingredient-amounts';
|
return 'ingredient-amounts';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCanGetRelatedIngredient(): void {
|
||||||
|
$ingredient = Food::factory()->create();
|
||||||
|
$record = $this->factory()->ingredient($ingredient)->create();
|
||||||
|
$this->getRelatedData($record, 'ingredient', 'foods');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanIncludeRelatedIngredient(): void {
|
||||||
|
$ingredient = Recipe::factory()->create();
|
||||||
|
$record = $this->factory()->ingredient($ingredient)->create();
|
||||||
|
$this->getRelatedData($record, 'ingredient', 'recipes');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanGetRelatedParent(): void {
|
||||||
|
$parent = Recipe::factory()->create();
|
||||||
|
$record = $this->factory()->parent($parent)->create();
|
||||||
|
$this->getRelatedData($record, 'parent', 'recipes');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanIncludeRelatedParent(): void {
|
||||||
|
$parent = JournalEntry::factory()->create();
|
||||||
|
$record = $this->factory()->parent($parent)->create();
|
||||||
|
$this->getRelatedData($record, 'parent', 'journal-entries');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,11 @@ namespace Tests\Feature\JsonApi;
|
||||||
use App\Models\JournalEntry;
|
use App\Models\JournalEntry;
|
||||||
use Database\Factories\JournalEntryFactory;
|
use Database\Factories\JournalEntryFactory;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\Feature\JsonApi\Traits\BelongsToUser;
|
||||||
|
|
||||||
class JournalEntryApiTest extends JsonApiTestCase
|
class JournalEntryApiTest extends JsonApiTestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase, BelongsToUser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
|
@ -26,4 +27,24 @@ class JournalEntryApiTest extends JsonApiTestCase
|
||||||
return 'journal-entries';
|
return 'journal-entries';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCanGetRelatedFoods(): void {
|
||||||
|
$record = $this->factory()->hasFoods(2)->create();
|
||||||
|
$this->getRelatedData($record, 'foods');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanIncludeRelatedFoods(): void {
|
||||||
|
$record = $this->factory()->hasFoods(2)->create();
|
||||||
|
$this->getRelatedData($record, 'foods');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanGetRelatedRecipes(): void {
|
||||||
|
$record = $this->factory()->hasRecipes(2)->create();
|
||||||
|
$this->getRelatedData($record, 'recipes');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanIncludeRelatedRecipes(): void {
|
||||||
|
$record = $this->factory()->hasRecipes(2)->create();
|
||||||
|
$this->getRelatedData($record, 'recipes');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,15 +4,16 @@ namespace Tests\Feature\JsonApi;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Tests\LoggedInTestCase;
|
use Tests\LoggedInTestCase;
|
||||||
|
|
||||||
abstract class JsonApiTestCase extends LoggedInTestCase
|
abstract class JsonApiTestCase extends LoggedInTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API index route name.
|
* API route base.
|
||||||
*/
|
*/
|
||||||
protected string $indexRouteName;
|
protected string $routeBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the factory of the model to be tested.
|
* Get the factory of the model to be tested.
|
||||||
|
@ -28,7 +29,7 @@ abstract class JsonApiTestCase extends LoggedInTestCase
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$route_prefix = config('json-api-v1.url.name');
|
$route_prefix = config('json-api-v1.url.name');
|
||||||
$this->indexRouteName = "{$route_prefix}{$this->resourceName()}.index";
|
$this->routeBase = "{$route_prefix}{$this->resourceName()}";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,10 +39,36 @@ abstract class JsonApiTestCase extends LoggedInTestCase
|
||||||
return $this->factory()->count($count)->create();
|
return $this->factory()->count($count)->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a template for getting related data.
|
||||||
|
*/
|
||||||
|
protected function getRelatedData(Model $record, string $related, string $expectedType = NULL): void {
|
||||||
|
$related_route = route(
|
||||||
|
"{$this->routeBase}.relationships.{$related}",
|
||||||
|
['record' => $record]
|
||||||
|
);
|
||||||
|
$response = $this->get($related_route);
|
||||||
|
$response->assertOk();
|
||||||
|
$response->assertJsonFragment(['type' => $expectedType ?? $related]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a template for included related data.
|
||||||
|
*/
|
||||||
|
protected function includeRelatedData(Model $record, string $related, string $expectedType = NULL): void {
|
||||||
|
$related_route = route(
|
||||||
|
"{$this->routeBase}.read",
|
||||||
|
['record' => $record, 'include' => $related]
|
||||||
|
);
|
||||||
|
$response = $this->get($related_route);
|
||||||
|
$response->assertOk();
|
||||||
|
$response->assertJsonPath('included.0.type', $expectedType ?? $related);
|
||||||
|
}
|
||||||
|
|
||||||
public function testCanGetIndex(): void
|
public function testCanGetIndex(): void
|
||||||
{
|
{
|
||||||
$this->createInstances(10);
|
$this->createInstances(10);
|
||||||
$index_url = route($this->indexRouteName);
|
$index_url = route("$this->routeBase.index");
|
||||||
$response = $this->get($index_url);
|
$response = $this->get($index_url);
|
||||||
$response->assertOk();
|
$response->assertOk();
|
||||||
$response->assertJson(['data' => true]);
|
$response->assertJson(['data' => true]);
|
||||||
|
|
|
@ -5,10 +5,11 @@ namespace Tests\Feature\JsonApi;
|
||||||
use App\Models\Recipe;
|
use App\Models\Recipe;
|
||||||
use Database\Factories\RecipeFactory;
|
use Database\Factories\RecipeFactory;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\Feature\JsonApi\Traits\HasTags;
|
||||||
|
|
||||||
class RecipeApiTest extends JsonApiTestCase
|
class RecipeApiTest extends JsonApiTestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase, HasTags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
|
@ -26,6 +27,36 @@ class RecipeApiTest extends JsonApiTestCase
|
||||||
return 'recipes';
|
return 'recipes';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCanGetRelatedIngredientAmounts(): void {
|
||||||
|
$record = $this->factory()->hasIngredientAmounts(2)->create();
|
||||||
|
$this->getRelatedData($record, 'ingredient-amounts');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanIncludeRelatedIngredientAmounts(): void {
|
||||||
|
$record = $this->factory()->hasIngredientAmounts(2)->create();
|
||||||
|
$this->getRelatedData($record, 'ingredient-amounts');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanGetRelatedSeparators(): void {
|
||||||
|
$record = $this->factory()->hasSeparators(2)->create();
|
||||||
|
$this->getRelatedData($record, 'separators', 'recipe-separators');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanIncludeRelatedSeparators(): void {
|
||||||
|
$record = $this->factory()->hasSeparators(2)->create();
|
||||||
|
$this->getRelatedData($record, 'separators', 'recipe-separators');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanGetRelatedSteps(): void {
|
||||||
|
$record = $this->factory()->hasSteps(2)->create();
|
||||||
|
$this->getRelatedData($record, 'steps', 'recipe-steps');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanIncludeRelatedSteps(): void {
|
||||||
|
$record = $this->factory()->hasSteps(2)->create();
|
||||||
|
$this->getRelatedData($record, 'steps', 'recipe-steps');
|
||||||
|
}
|
||||||
|
|
||||||
public function testCanUseSearchFilter(): void {
|
public function testCanUseSearchFilter(): void {
|
||||||
$attributes = [
|
$attributes = [
|
||||||
'name' => 'Chocolate Chip Cookies',
|
'name' => 'Chocolate Chip Cookies',
|
||||||
|
@ -41,7 +72,7 @@ class RecipeApiTest extends JsonApiTestCase
|
||||||
|
|
||||||
foreach ($attributes as $attribute => $value) {
|
foreach ($attributes as $attribute => $value) {
|
||||||
$partial = substr($value, rand(0, 5), 5);
|
$partial = substr($value, rand(0, 5), 5);
|
||||||
$search_route = route($this->indexRouteName, [
|
$search_route = route("$this->routeBase.index", [
|
||||||
'filter' => ['search' => $partial]
|
'filter' => ['search' => $partial]
|
||||||
]);
|
]);
|
||||||
$response = $this->get($search_route);
|
$response = $this->get($search_route);
|
||||||
|
|
|
@ -7,10 +7,11 @@ use App\Models\RecipeSeparator;
|
||||||
use Database\Factories\RecipeSeparatorFactory;
|
use Database\Factories\RecipeSeparatorFactory;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\Feature\JsonApi\Traits\BelongsToRecipe;
|
||||||
|
|
||||||
class RecipeSeparatorApiTest extends JsonApiTestCase
|
class RecipeSeparatorApiTest extends JsonApiTestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase, BelongsToRecipe;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
|
@ -32,7 +33,8 @@ class RecipeSeparatorApiTest extends JsonApiTestCase
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected function createInstances(int $count = 1): Collection {
|
protected function createInstances(int $count = 1): Collection {
|
||||||
return Recipe::factory()->count(1)->hasSeparators($count)->create();
|
$recipe = Recipe::factory()->create();
|
||||||
|
return $this->factory()->count($count)->for($recipe)->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,11 @@ use App\Models\RecipeStep;
|
||||||
use Database\Factories\RecipeStepFactory;
|
use Database\Factories\RecipeStepFactory;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\Feature\JsonApi\Traits\BelongsToRecipe;
|
||||||
|
|
||||||
class RecipeStepApiTest extends JsonApiTestCase
|
class RecipeStepApiTest extends JsonApiTestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase, BelongsToRecipe;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
|
@ -32,7 +33,8 @@ class RecipeStepApiTest extends JsonApiTestCase
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
protected function createInstances(int $count = 1): Collection {
|
protected function createInstances(int $count = 1): Collection {
|
||||||
return Recipe::factory()->count(1)->hasSteps($count)->create();
|
$recipe = Recipe::factory()->create();
|
||||||
|
return $this->factory()->count($count)->for($recipe)->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ class TagApiTest extends JsonApiTestCase
|
||||||
|
|
||||||
foreach ($names as $name) {
|
foreach ($names as $name) {
|
||||||
$partial = substr($name, rand(0, 2), 3);
|
$partial = substr($name, rand(0, 2), 3);
|
||||||
$search_route = route($this->indexRouteName, [
|
$search_route = route("$this->routeBase.index", [
|
||||||
'filter' => ['name' => $partial]
|
'filter' => ['name' => $partial]
|
||||||
]);
|
]);
|
||||||
$response = $this->get($search_route);
|
$response = $this->get($search_route);
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\JsonApi\Traits;
|
||||||
|
|
||||||
|
trait BelongsToRecipe
|
||||||
|
{
|
||||||
|
public function testCanGetRelatedUser(): void {
|
||||||
|
$record = $this->createInstances()->first();
|
||||||
|
$this->getRelatedData($record, 'recipe', 'recipes');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanIncludeRelatedUser(): void {
|
||||||
|
$record = $this->createInstances()->first();
|
||||||
|
$this->getRelatedData($record, 'recipe', 'recipes');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\JsonApi\Traits;
|
||||||
|
|
||||||
|
trait BelongsToUser
|
||||||
|
{
|
||||||
|
public function testCanGetRelatedUser(): void {
|
||||||
|
$record = $this->createInstances()->first();
|
||||||
|
$this->getRelatedData($record, 'user', 'users');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanIncludeRelatedUser(): void {
|
||||||
|
$record = $this->createInstances()->first();
|
||||||
|
$this->getRelatedData($record, 'user', 'users');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\JsonApi\Traits;
|
||||||
|
|
||||||
|
trait HasTags
|
||||||
|
{
|
||||||
|
public function testCanGetRelatedTags(): void {
|
||||||
|
$record = $this->createInstances()->first();
|
||||||
|
$this->getRelatedData($record, 'tags');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanIncludeRelatedTags(): void {
|
||||||
|
$record = $this->createInstances()->first();
|
||||||
|
$this->getRelatedData($record, 'tags');
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,11 +30,31 @@ class UserApiTest extends JsonApiTestCase
|
||||||
{
|
{
|
||||||
// Initial user created by test so only make 9 new instances.
|
// Initial user created by test so only make 9 new instances.
|
||||||
$this->createInstances(9);
|
$this->createInstances(9);
|
||||||
$index_url = route($this->indexRouteName);
|
$index_url = route("$this->routeBase.index");
|
||||||
$response = $this->get($index_url);
|
$response = $this->get($index_url);
|
||||||
$response->assertOk();
|
$response->assertOk();
|
||||||
$response->assertJson(['data' => true]);
|
$response->assertJson(['data' => true]);
|
||||||
$response->assertJsonCount(10, 'data');
|
$response->assertJsonCount(10, 'data');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCanGetRelatedGoals(): void {
|
||||||
|
$record = $this->factory()->hasGoals(2)->create();
|
||||||
|
$this->getRelatedData($record, 'goals');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanIncludeRelatedGoals(): void {
|
||||||
|
$record = $this->factory()->hasGoals(2)->create();
|
||||||
|
$this->getRelatedData($record, 'goals');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanGetRelatedJournalEntries(): void {
|
||||||
|
$record = $this->factory()->hasJournalEntries(2)->create();
|
||||||
|
$this->getRelatedData($record, 'journal-entries');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanIncludeRelatedJournalEntries(): void {
|
||||||
|
$record = $this->factory()->hasJournalEntries(2)->create();
|
||||||
|
$this->getRelatedData($record, 'journal-entries');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue