Test JSON API relationships

This commit is contained in:
Christopher C. Wells 2021-04-02 21:39:27 -07:00 committed by Christopher Charbonneau Wells
parent 3eebcf2756
commit da39143113
14 changed files with 200 additions and 18 deletions

View File

@ -27,6 +27,7 @@ class RecipeFactory extends Factory
'source' => $this->faker->optional()->url,
'servings' => $this->faker->numberBetween(1, 10),
'weight' => $this->faker->randomFloat(1, 60, 2000),
'tags' => $this->faker->words,
];
}
}

View File

@ -3,12 +3,15 @@
namespace Tests\Feature\JsonApi;
use App\Models\Food;
use App\Models\Recipe;
use Database\Factories\FoodFactory;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\Feature\JsonApi\Traits\HasTags;
class FoodApiTest extends JsonApiTestCase
{
use RefreshDatabase;
use RefreshDatabase, HasTags;
/**
* @inheritdoc
@ -41,7 +44,7 @@ class FoodApiTest extends JsonApiTestCase
foreach ($attributes as $attribute => $value) {
$partial = substr($value, rand(0, 3), 3);
$search_route = route($this->indexRouteName, [
$search_route = route("$this->routeBase.index", [
'filter' => ['search' => $partial]
]);
$response = $this->get($search_route);

View File

@ -3,14 +3,14 @@
namespace Tests\Feature\JsonApi;
use App\Models\Goal;
use App\Models\User;
use Database\Factories\GoalFactory;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\Feature\JsonApi\Traits\BelongsToUser;
class GoalApiTest extends JsonApiTestCase
{
use RefreshDatabase;
use RefreshDatabase, BelongsToUser;
/**
* @inheritdoc
@ -32,7 +32,7 @@ class GoalApiTest extends JsonApiTestCase
* @inheritdoc
*/
protected function createInstances(int $count = 1): Collection {
return User::factory()->count(1)->hasGoals($count)->create();
return $this->factory()->count($count)->for($this->user)->create();
}
}

View File

@ -2,7 +2,10 @@
namespace Tests\Feature\JsonApi;
use App\Models\Food;
use App\Models\IngredientAmount;
use App\Models\JournalEntry;
use App\Models\Recipe;
use Database\Factories\IngredientAmountFactory;
use Illuminate\Foundation\Testing\RefreshDatabase;
@ -26,4 +29,28 @@ class IngredientAmountApiTest extends JsonApiTestCase
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');
}
}

View File

@ -5,10 +5,11 @@ namespace Tests\Feature\JsonApi;
use App\Models\JournalEntry;
use Database\Factories\JournalEntryFactory;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\Feature\JsonApi\Traits\BelongsToUser;
class JournalEntryApiTest extends JsonApiTestCase
{
use RefreshDatabase;
use RefreshDatabase, BelongsToUser;
/**
* @inheritdoc
@ -26,4 +27,24 @@ class JournalEntryApiTest extends JsonApiTestCase
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');
}
}

View File

@ -4,15 +4,16 @@ namespace Tests\Feature\JsonApi;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Database\Eloquent\Model;
use Tests\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.
@ -28,7 +29,7 @@ abstract class JsonApiTestCase extends LoggedInTestCase
{
parent::setUp();
$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();
}
/**
* 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
{
$this->createInstances(10);
$index_url = route($this->indexRouteName);
$index_url = route("$this->routeBase.index");
$response = $this->get($index_url);
$response->assertOk();
$response->assertJson(['data' => true]);

View File

@ -5,10 +5,11 @@ namespace Tests\Feature\JsonApi;
use App\Models\Recipe;
use Database\Factories\RecipeFactory;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\Feature\JsonApi\Traits\HasTags;
class RecipeApiTest extends JsonApiTestCase
{
use RefreshDatabase;
use RefreshDatabase, HasTags;
/**
* @inheritdoc
@ -26,6 +27,36 @@ class RecipeApiTest extends JsonApiTestCase
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 {
$attributes = [
'name' => 'Chocolate Chip Cookies',
@ -41,7 +72,7 @@ class RecipeApiTest extends JsonApiTestCase
foreach ($attributes as $attribute => $value) {
$partial = substr($value, rand(0, 5), 5);
$search_route = route($this->indexRouteName, [
$search_route = route("$this->routeBase.index", [
'filter' => ['search' => $partial]
]);
$response = $this->get($search_route);

View File

@ -7,10 +7,11 @@ use App\Models\RecipeSeparator;
use Database\Factories\RecipeSeparatorFactory;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\Feature\JsonApi\Traits\BelongsToRecipe;
class RecipeSeparatorApiTest extends JsonApiTestCase
{
use RefreshDatabase;
use RefreshDatabase, BelongsToRecipe;
/**
* @inheritdoc
@ -32,7 +33,8 @@ class RecipeSeparatorApiTest extends JsonApiTestCase
* @inheritdoc
*/
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();
}
}

View File

@ -7,10 +7,11 @@ use App\Models\RecipeStep;
use Database\Factories\RecipeStepFactory;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\Feature\JsonApi\Traits\BelongsToRecipe;
class RecipeStepApiTest extends JsonApiTestCase
{
use RefreshDatabase;
use RefreshDatabase, BelongsToRecipe;
/**
* @inheritdoc
@ -32,7 +33,8 @@ class RecipeStepApiTest extends JsonApiTestCase
* @inheritdoc
*/
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();
}
}

View File

@ -34,7 +34,7 @@ class TagApiTest extends JsonApiTestCase
foreach ($names as $name) {
$partial = substr($name, rand(0, 2), 3);
$search_route = route($this->indexRouteName, [
$search_route = route("$this->routeBase.index", [
'filter' => ['name' => $partial]
]);
$response = $this->get($search_route);

View File

@ -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');
}
}

View File

@ -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');
}
}

View File

@ -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');
}
}

View File

@ -30,11 +30,31 @@ class UserApiTest extends JsonApiTestCase
{
// Initial user created by test so only make 9 new instances.
$this->createInstances(9);
$index_url = route($this->indexRouteName);
$index_url = route("$this->routeBase.index");
$response = $this->get($index_url);
$response->assertOk();
$response->assertJson(['data' => true]);
$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');
}
}