253 lines
8.3 KiB
PHP
253 lines
8.3 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Http\Controllers\Api\V1;
|
|
|
|
use App\Enums\ApprovalStatusEnum;
|
|
use App\Events\RouteArticleApproved;
|
|
use App\Models\Article;
|
|
use App\Models\Feed;
|
|
use App\Models\Route;
|
|
use App\Models\RouteArticle;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Event;
|
|
use Tests\TestCase;
|
|
|
|
class RouteArticlesControllerTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
private function createRouteArticle(ApprovalStatusEnum $status = ApprovalStatusEnum::PENDING): RouteArticle
|
|
{
|
|
$feed = Feed::factory()->create();
|
|
|
|
/** @var Route $route */
|
|
$route = Route::factory()->active()->create(['feed_id' => $feed->id]);
|
|
$article = Article::factory()->create(['feed_id' => $feed->id]);
|
|
|
|
/** @var RouteArticle $routeArticle */
|
|
$routeArticle = RouteArticle::factory()->forRoute($route)->create([
|
|
'article_id' => $article->id,
|
|
'approval_status' => $status,
|
|
'validated_at' => now(),
|
|
]);
|
|
|
|
return $routeArticle;
|
|
}
|
|
|
|
public function test_index_returns_successful_response(): void
|
|
{
|
|
$response = $this->getJson('/api/v1/route-articles');
|
|
|
|
$response->assertStatus(200)
|
|
->assertJsonStructure([
|
|
'success',
|
|
'data' => [
|
|
'route_articles',
|
|
'pagination' => [
|
|
'current_page',
|
|
'last_page',
|
|
'per_page',
|
|
'total',
|
|
'from',
|
|
'to',
|
|
],
|
|
],
|
|
'message',
|
|
]);
|
|
}
|
|
|
|
public function test_index_returns_route_articles_with_pagination(): void
|
|
{
|
|
$feed = Feed::factory()->create();
|
|
/** @var Route $route */
|
|
$route = Route::factory()->active()->create(['feed_id' => $feed->id]);
|
|
|
|
for ($i = 0; $i < 20; $i++) {
|
|
$article = Article::factory()->create(['feed_id' => $feed->id]);
|
|
RouteArticle::factory()->forRoute($route)->create([
|
|
'article_id' => $article->id,
|
|
'validated_at' => now(),
|
|
]);
|
|
}
|
|
|
|
$response = $this->getJson('/api/v1/route-articles?per_page=10');
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'success' => true,
|
|
'data' => [
|
|
'pagination' => [
|
|
'per_page' => 10,
|
|
'total' => 20,
|
|
'last_page' => 2,
|
|
],
|
|
],
|
|
]);
|
|
|
|
$this->assertCount(10, $response->json('data.route_articles'));
|
|
}
|
|
|
|
public function test_index_filters_by_status(): void
|
|
{
|
|
$this->createRouteArticle(ApprovalStatusEnum::PENDING);
|
|
$this->createRouteArticle(ApprovalStatusEnum::PENDING);
|
|
$this->createRouteArticle(ApprovalStatusEnum::APPROVED);
|
|
$this->createRouteArticle(ApprovalStatusEnum::REJECTED);
|
|
|
|
$response = $this->getJson('/api/v1/route-articles?status=pending');
|
|
|
|
$response->assertStatus(200);
|
|
$this->assertCount(2, $response->json('data.route_articles'));
|
|
}
|
|
|
|
public function test_index_returns_all_when_no_status_filter(): void
|
|
{
|
|
$this->createRouteArticle(ApprovalStatusEnum::PENDING);
|
|
$this->createRouteArticle(ApprovalStatusEnum::APPROVED);
|
|
$this->createRouteArticle(ApprovalStatusEnum::REJECTED);
|
|
|
|
$response = $this->getJson('/api/v1/route-articles');
|
|
|
|
$response->assertStatus(200);
|
|
$this->assertCount(3, $response->json('data.route_articles'));
|
|
}
|
|
|
|
public function test_index_includes_article_and_route_data(): void
|
|
{
|
|
$routeArticle = $this->createRouteArticle();
|
|
|
|
$response = $this->getJson('/api/v1/route-articles');
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$data = $response->json('data.route_articles.0');
|
|
$this->assertArrayHasKey('article', $data);
|
|
$this->assertArrayHasKey('title', $data['article']);
|
|
$this->assertArrayHasKey('url', $data['article']);
|
|
$this->assertArrayHasKey('route_name', $data);
|
|
$this->assertArrayHasKey('approval_status', $data);
|
|
}
|
|
|
|
public function test_approve_route_article_successfully(): void
|
|
{
|
|
Event::fake([RouteArticleApproved::class]);
|
|
|
|
$routeArticle = $this->createRouteArticle(ApprovalStatusEnum::PENDING);
|
|
|
|
$response = $this->postJson("/api/v1/route-articles/{$routeArticle->id}/approve");
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'success' => true,
|
|
'message' => 'Route article approved and queued for publishing.',
|
|
]);
|
|
|
|
$this->assertEquals(ApprovalStatusEnum::APPROVED, $routeArticle->fresh()->approval_status);
|
|
|
|
Event::assertDispatched(RouteArticleApproved::class, function ($event) use ($routeArticle) {
|
|
return $event->routeArticle->id === $routeArticle->id;
|
|
});
|
|
}
|
|
|
|
public function test_approve_nonexistent_route_article_returns_404(): void
|
|
{
|
|
$response = $this->postJson('/api/v1/route-articles/999/approve');
|
|
|
|
$response->assertStatus(404);
|
|
}
|
|
|
|
public function test_reject_route_article_successfully(): void
|
|
{
|
|
$routeArticle = $this->createRouteArticle(ApprovalStatusEnum::PENDING);
|
|
|
|
$response = $this->postJson("/api/v1/route-articles/{$routeArticle->id}/reject");
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'success' => true,
|
|
'message' => 'Route article rejected.',
|
|
]);
|
|
|
|
$this->assertEquals(ApprovalStatusEnum::REJECTED, $routeArticle->fresh()->approval_status);
|
|
}
|
|
|
|
public function test_reject_nonexistent_route_article_returns_404(): void
|
|
{
|
|
$response = $this->postJson('/api/v1/route-articles/999/reject');
|
|
|
|
$response->assertStatus(404);
|
|
}
|
|
|
|
public function test_restore_route_article_successfully(): void
|
|
{
|
|
$routeArticle = $this->createRouteArticle(ApprovalStatusEnum::REJECTED);
|
|
|
|
$response = $this->postJson("/api/v1/route-articles/{$routeArticle->id}/restore");
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'success' => true,
|
|
'message' => 'Route article restored to pending.',
|
|
]);
|
|
|
|
$this->assertEquals(ApprovalStatusEnum::PENDING, $routeArticle->fresh()->approval_status);
|
|
}
|
|
|
|
public function test_restore_nonexistent_route_article_returns_404(): void
|
|
{
|
|
$response = $this->postJson('/api/v1/route-articles/999/restore');
|
|
|
|
$response->assertStatus(404);
|
|
}
|
|
|
|
public function test_clear_rejects_all_pending_route_articles(): void
|
|
{
|
|
$this->createRouteArticle(ApprovalStatusEnum::PENDING);
|
|
$this->createRouteArticle(ApprovalStatusEnum::PENDING);
|
|
$this->createRouteArticle(ApprovalStatusEnum::PENDING);
|
|
$this->createRouteArticle(ApprovalStatusEnum::APPROVED);
|
|
|
|
$response = $this->postJson('/api/v1/route-articles/clear');
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'success' => true,
|
|
'data' => [
|
|
'rejected_count' => 3,
|
|
],
|
|
]);
|
|
|
|
$this->assertEquals(0, RouteArticle::where('approval_status', ApprovalStatusEnum::PENDING)->count());
|
|
$this->assertEquals(1, RouteArticle::where('approval_status', ApprovalStatusEnum::APPROVED)->count());
|
|
$this->assertEquals(3, RouteArticle::where('approval_status', ApprovalStatusEnum::REJECTED)->count());
|
|
}
|
|
|
|
public function test_clear_returns_zero_when_no_pending(): void
|
|
{
|
|
$this->createRouteArticle(ApprovalStatusEnum::APPROVED);
|
|
|
|
$response = $this->postJson('/api/v1/route-articles/clear');
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'success' => true,
|
|
'data' => [
|
|
'rejected_count' => 0,
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function test_index_respects_per_page_limit(): void
|
|
{
|
|
$response = $this->getJson('/api/v1/route-articles?per_page=150');
|
|
|
|
$response->assertStatus(200)
|
|
->assertJson([
|
|
'data' => [
|
|
'pagination' => [
|
|
'per_page' => 100,
|
|
],
|
|
],
|
|
]);
|
|
}
|
|
}
|