Skip to content

Commit

Permalink
implement tests for whole flow
Browse files Browse the repository at this point in the history
  • Loading branch information
salehhashemi1992 committed Dec 23, 2023
1 parent cbeeb46 commit 845ac83
Show file tree
Hide file tree
Showing 8 changed files with 301 additions and 5 deletions.
273 changes: 273 additions & 0 deletions tests/RepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
namespace Salehhashemi\Repository\Tests;

use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\DB;
use InvalidArgumentException;
use Salehhashemi\Repository\Tests\TestSupport\Models\Category;
use Salehhashemi\Repository\Tests\TestSupport\Models\Post;
use Salehhashemi\Repository\Tests\TestSupport\Repositories\Criterias\FeaturedPostCriteria;
use Salehhashemi\Repository\Tests\TestSupport\Repositories\PostRepository;
use Salehhashemi\Repository\Tests\TestSupport\Repositories\PostRepositoryInterface;

Expand Down Expand Up @@ -31,6 +37,106 @@ public function testFindOneReturnsModelInstance()
$this->assertEquals($post->id, $foundPost->id);
}

public function testFindOneReturnsNullIfNotFound()
{
$postRepository = new PostRepository();
$nonExistentId = 99999; // This ID does not exist in the database

$foundPost = $postRepository->findOne($nonExistentId);

$this->assertNull($foundPost);
}

public function testFindOneOrFailReturnsModelInstance()
{
$post = Post::factory()->create();

$postRepo = $this->app->make(PostRepositoryInterface::class);

$foundPost = $postRepo->findOneOrFail($post->id);

$this->assertInstanceOf(Post::class, $foundPost);
$this->assertEquals($post->id, $foundPost->id);
}

public function testFindOneOrFailThrowsExceptionIfNotFound()
{
$this->expectException(ModelNotFoundException::class);

$postRepository = new PostRepository();
$nonExistentId = 99999; // This ID does not exist in the database

$postRepository->findOneOrFail($nonExistentId);
}

public function testFindAllRetrievesAllRecords()
{
Post::factory()->count(5)->create();

$postRepo = $this->app->make(PostRepositoryInterface::class);

$posts = $postRepo->findAll();

$this->assertCount(5, $posts);
$this->assertInstanceOf(EloquentCollection::class, $posts);
}

public function testFindAllWithLimitOption()
{
Post::factory()->count(10)->create();

$postRepo = $this->app->make(PostRepositoryInterface::class);

$posts = $postRepo->findAll(['limit' => 5]);

$this->assertCount(5, $posts);
}

public function testFindAllWithOffsetAndLimitOptions()
{
Post::factory()->count(10)->create();

$postRepo = $this->app->make(PostRepositoryInterface::class);

$posts = $postRepo->findAll(['offset' => 5, 'limit' => 4]);

$this->assertCount(4, $posts);

$expectedId = 5; // This depends on how IDs are assigned in your test database
$firstPostAfterOffset = $posts->first();
$this->assertEquals($expectedId, $firstPostAfterOffset->id);
}

public function testFindListRetrievesDefaultKeyValuePairs()
{
Post::factory()->count(3)->create();

$postRepo = $this->app->make(PostRepositoryInterface::class);

$list = $postRepo->findList();

$this->assertCount(3, $list);
foreach ($list as $key => $value) {
$this->assertIsNumeric($key); // Default key is 'id'
$this->assertIsNumeric($value); // Default value is from 'getDisplayField'
}
}

public function testFindListWithCustomKeyValuePairs()
{
Post::factory()->count(3)->create();

$postRepo = $this->app->make(PostRepositoryInterface::class);

$list = $postRepo->findList('id', 'title');

$this->assertCount(3, $list);
foreach ($list as $key => $title) {
$this->assertIsNumeric($key);
$this->assertIsString($title);
}
}

public function testPaginateWithSpecifiedPerPage()
{
Post::factory()->count(15)->create();
Expand Down Expand Up @@ -58,4 +164,171 @@ public function testPaginateWithDefaultPerPage()
$this->assertInstanceOf(Paginator::class, $paginatedResults);
$this->assertCount(min(10, $defaultPerPage), $paginatedResults->items());
}

public function testInvalidPageSizeThrowsException()
{
$this->expectException(InvalidArgumentException::class);

$postRepo = $this->app->make(PostRepositoryInterface::class);

$postRepo->paginate(0);
}

public function testGetFilteredPosts()
{
$category = Category::factory()->create();

$post = Post::factory()->create([
'title' => 'test',
'status' => 'published',
'created_at' => now()->subDay(),
]);

$post->categories()->attach($category->id);

Post::factory()->create(['status' => 'draft', 'created_at' => now()->subHour()]);

$postRepo = $this->app->make(PostRepositoryInterface::class);

// Define filter options
$filterOptions = [
'title' => 'test',
'status' => 'published',
'orderBy' => 'created_at',
'orderDirection' => 'ASC',
'category_id' => $category->id,
];

$postRepo->orderBy('created_at');

/** @var \Illuminate\Database\Eloquent\Collection $filteredPosts */
$filteredPosts = $postRepo->search($filterOptions);

$this->assertCount(1, $filteredPosts);
$this->assertEquals('published', $filteredPosts->first()->status);
$this->assertEquals(
now()->subDay()->format('Y-m-d H:i:s'),
$filteredPosts->first()->created_at->format('Y-m-d H:i:s')
);
}

public function testGetCriteriaPosts()
{
Post::factory()->create(['is_featured' => 1]);
Post::factory()->create();

$postRepo = $this->app->make(PostRepositoryInterface::class);

$postRepo->addCriteria(new FeaturedPostCriteria());

$filteredPosts = $postRepo->findAll();

$this->assertCount(1, $filteredPosts);
}

public function testFindAllFeatured()
{
Post::factory()->count(3)->create(['is_featured' => 1]);
Post::factory()->count(2)->create(['is_featured' => 0]);

$postRepo = $this->app->make(PostRepositoryInterface::class);
$featuredPosts = $postRepo->findAllFeatured();

$this->assertCount(3, $featuredPosts);
foreach ($featuredPosts as $post) {
$this->assertEquals(1, $post->is_featured);
}
}

public function testSearchVisible()
{
Post::factory()->count(6)->create(['status' => 'draft']);
Post::factory()->count(4)->create(['status' => 'published']);

$postRepo = $this->app->make(PostRepositoryInterface::class);
$queryParams = ['status' => 'draft'];
$paginatedPosts = $postRepo->searchVisible($queryParams, 5);

$this->assertInstanceOf(Paginator::class, $paginatedPosts);
$this->assertCount(5, $paginatedPosts->items());
}

public function testFindOnePublishedOrFail()
{
$publishedPost = Post::factory()->create(['is_published' => 1]);

$postRepo = $this->app->make(PostRepositoryInterface::class);

$foundPost = $postRepo->findOnePublishedOrFail($publishedPost->id);
$this->assertInstanceOf(Post::class, $foundPost);
$this->assertEquals(1, $foundPost->is_published);

$this->expectException(ModelNotFoundException::class);
$postRepo->findOnePublishedOrFail(999); // Non-existent ID
}

public function testWithComments()
{
$post = Post::factory()->hasComments(3)->create();

$postRepo = $this->app->make(PostRepositoryInterface::class);
$postRepo->withComments();
$foundPost = $postRepo->findOne($post->id);

$this->assertCount(3, $foundPost->comments);
}

public function testWithCategories()
{
// Create posts and associate them with categories
$post = Post::factory()->hasCategories(3)->create();

$postRepo = $this->app->make(PostRepositoryInterface::class);
$postRepo->withCategories();

$retrievedPost = $postRepo->findOne($post->id);

$this->assertTrue($retrievedPost->relationLoaded('categories'));
$this->assertCount(3, $retrievedPost->categories);

foreach ($retrievedPost->categories as $category) {
$this->assertNotEmpty($category->name);
}
}

public function testLockForUpdateUsage()
{
$post = Post::factory()->create();

DB::beginTransaction();

$postRepo = $this->app->make(PostRepositoryInterface::class);
$postRepo->lockForUpdate();

$lockedPost = $postRepo->findOne($post->id);
$lockedPost->title = 'Updated Title';
$lockedPost->save();

DB::commit();

$updatedPost = Post::query()->find($post->id);
$this->assertEquals('Updated Title', $updatedPost->title);
}

public function testSharedLockUsage()
{
$post = Post::factory()->create();

DB::beginTransaction();

$postRepo = $this->app->make(PostRepositoryInterface::class);
$postRepo->sharedLock();

$lockedPost = $postRepo->findOne($post->id);

DB::commit();

$this->assertInstanceOf(Post::class, $lockedPost);
$this->assertEquals($post->id, $lockedPost->id);
}
}
2 changes: 2 additions & 0 deletions tests/TestSupport/Models/Category.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
* @property int $id
* @property string $name
* @property \Illuminate\Database\Eloquent\Collection|\Salehhashemi\Repository\Tests\TestSupport\Models\Post[] $posts
*
* @method static CategoryFactory factory($count = null, $state = [])
*/
class Category extends Model
{
Expand Down
2 changes: 2 additions & 0 deletions tests/TestSupport/Models/Comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
* @property string $content
* @property int $post_id
* @property \Salehhashemi\Repository\Tests\TestSupport\Models\Post $post
*
* @method static CommentFactory factory($count = null, $state = [])
*/
class Comment extends Model
{
Expand Down
4 changes: 3 additions & 1 deletion tests/TestSupport/Models/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@
* @property string $content
* @property string $status
* @property bool $is_published
* @property bool $is_featured
* @property \Illuminate\Database\Eloquent\Collection|\Salehhashemi\Repository\Tests\TestSupport\Models\Comment[] $comments
* @property \Illuminate\Database\Eloquent\Collection| \Salehhashemi\Repository\Tests\TestSupport\Models\Category[] $categories
*
* @method static \Illuminate\Database\Eloquent\Builder|Post newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Post newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|Post query()
* @method static PostFactory factory($count = null, $state = [])
*/
class Post extends Model
{
use HasFactory;

protected $fillable = ['title', 'content', 'status', 'is_published'];
protected $fillable = ['title', 'content', 'status', 'is_published', 'is_featured'];

/**
* {@inheritDoc}
Expand Down
4 changes: 2 additions & 2 deletions tests/TestSupport/Repositories/PostRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ protected function getFilterManager(): PostFilter
return $filterManager;
}

public function findAllFeatured(array $queryParams): EloquentCollection
public function findAllFeatured(): EloquentCollection
{
$this->addCriteria(new FeaturedPostCriteria());

Expand All @@ -36,7 +36,7 @@ public function findAllFeatured(array $queryParams): EloquentCollection

public function searchVisible(array $queryParams, int $perPage): Paginator
{
$this->orderBy('sort');
$this->orderBy('id');
$this->withCategories();

return $this->search($queryParams, $perPage);
Expand Down
2 changes: 1 addition & 1 deletion tests/TestSupport/Repositories/PostRepositoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*/
interface PostRepositoryInterface extends RepositoryInterface, SearchableRepositoryInterface
{
public function findAllFeatured(array $queryParams): EloquentCollection;
public function findAllFeatured(): EloquentCollection;

public function searchVisible(array $queryParams, int $perPage): Paginator;

Expand Down
18 changes: 17 additions & 1 deletion tests/TestSupport/database/factories/PostFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace Salehhashemi\Repository\Tests\TestSupport\database\factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use Salehhashemi\Repository\Tests\TestSupport\Models\Category;
use Salehhashemi\Repository\Tests\TestSupport\Models\Comment;
use Salehhashemi\Repository\Tests\TestSupport\Models\Post;

class PostFactory extends Factory
Expand All @@ -18,7 +20,21 @@ public function definition(): array
'title' => $this->faker->sentence,
'content' => $this->faker->paragraph,
'status' => $this->faker->randomElement(['draft', 'published']),
'is_published' => $this->faker->boolean,
'is_published' => false,
'is_featured' => false,
];
}

public function hasComments(int $count): Factory
{
return $this->has(Comment::factory()->count($count), 'comments');
}

public function hasCategories(int $count): Factory
{
return $this->afterCreating(function (Post $post) use ($count) {
$categories = Category::factory()->count($count)->create();
$post->categories()->attach($categories);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public function up(): void
$table->text('content');
$table->string('status')->default('draft');
$table->boolean('is_published')->default(false);
$table->boolean('is_featured')->default(false);

$table->timestamps();
});
Expand Down

0 comments on commit 845ac83

Please sign in to comment.