Fix tests
+ Move LogLevelEnum
This commit is contained in:
parent
43ab722fdc
commit
d2416a3ae2
13 changed files with 171 additions and 434 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App;
|
namespace App\Enums;
|
||||||
|
|
||||||
enum LogLevelEnum: string
|
enum LogLevelEnum: string
|
||||||
{
|
{
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace App\Events;
|
namespace App\Events;
|
||||||
|
|
||||||
use App\LogLevelEnum;
|
use App\Enums\LogLevelEnum;
|
||||||
use Illuminate\Foundation\Events\Dispatchable;
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\LogLevelEnum;
|
use App\Enums\LogLevelEnum;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,18 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method static updateOrCreate(string[] $array, array $array1)
|
||||||
|
* @method static create(string[] $array)
|
||||||
|
* @method static where(string $string, string $key)
|
||||||
|
*/
|
||||||
class Setting extends Model
|
class Setting extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
protected $fillable = ['key', 'value'];
|
protected $fillable = ['key', 'value'];
|
||||||
|
|
||||||
public static function get(string $key, mixed $default = null): mixed
|
public static function get(string $key, mixed $default = null): mixed
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Enums\LogLevelEnum;
|
||||||
use App\Events\ExceptionOccurred;
|
use App\Events\ExceptionOccurred;
|
||||||
use App\Listeners\LogExceptionToDatabase;
|
use App\Listeners\LogExceptionToDatabase;
|
||||||
use App\LogLevelEnum;
|
|
||||||
use Error;
|
use Error;
|
||||||
use Illuminate\Contracts\Debug\ExceptionHandler;
|
use Illuminate\Contracts\Debug\ExceptionHandler;
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace App\Services\Log;
|
namespace App\Services\Log;
|
||||||
|
|
||||||
use App\LogLevelEnum;
|
use App\Enums\LogLevelEnum;
|
||||||
use App\Models\Log;
|
use App\Models\Log;
|
||||||
use App\Models\PlatformChannel;
|
use App\Models\PlatformChannel;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,10 @@
|
||||||
->withExceptions(function (Exceptions $exceptions) {
|
->withExceptions(function (Exceptions $exceptions) {
|
||||||
$exceptions->reportable(function (Throwable $e) {
|
$exceptions->reportable(function (Throwable $e) {
|
||||||
$level = match (true) {
|
$level = match (true) {
|
||||||
$e instanceof Error => App\LogLevelEnum::CRITICAL,
|
$e instanceof Error => \App\Enums\LogLevelEnum::CRITICAL,
|
||||||
$e instanceof RuntimeException => App\LogLevelEnum::ERROR,
|
$e instanceof RuntimeException => \App\Enums\LogLevelEnum::ERROR,
|
||||||
$e instanceof InvalidArgumentException => App\LogLevelEnum::WARNING,
|
$e instanceof InvalidArgumentException => \App\Enums\LogLevelEnum::WARNING,
|
||||||
default => App\LogLevelEnum::ERROR,
|
default => \App\Enums\LogLevelEnum::ERROR,
|
||||||
};
|
};
|
||||||
|
|
||||||
App\Events\ExceptionOccurred::dispatch(
|
App\Events\ExceptionOccurred::dispatch(
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
use App\LogLevelEnum;
|
use App\Enums\LogLevelEnum;
|
||||||
use App\Models\Log;
|
use App\Models\Log;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\LogLevelEnum;
|
use App\Enums\LogLevelEnum;
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
|
||||||
55
backend/tests/Feature/ApiAccessTest.php
Normal file
55
backend/tests/Feature/ApiAccessTest.php
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use App\Models\Article;
|
||||||
|
use App\Models\Feed;
|
||||||
|
use App\Models\PlatformAccount;
|
||||||
|
use App\Models\PlatformChannel;
|
||||||
|
use App\Models\Setting;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class ApiAccessTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
public function test_health_endpoint_is_accessible(): void
|
||||||
|
{
|
||||||
|
$response = $this->get('/health');
|
||||||
|
$response->assertSuccessful();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_api_routes_are_publicly_accessible(): void
|
||||||
|
{
|
||||||
|
// Test that main API routes are accessible without authentication
|
||||||
|
$routes = [
|
||||||
|
'/api/v1/articles',
|
||||||
|
'/api/v1/dashboard/stats',
|
||||||
|
'/api/v1/platform-accounts',
|
||||||
|
'/api/v1/platform-channels',
|
||||||
|
'/api/v1/feeds',
|
||||||
|
'/api/v1/routing',
|
||||||
|
'/api/v1/settings',
|
||||||
|
'/api/v1/logs'
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($routes as $route) {
|
||||||
|
$response = $this->get($route);
|
||||||
|
$this->assertTrue(
|
||||||
|
$response->isSuccessful(),
|
||||||
|
"API route {$route} should be publicly accessible"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_fallback_route_returns_api_message(): void
|
||||||
|
{
|
||||||
|
$response = $this->get('/nonexistent-route');
|
||||||
|
$response->assertStatus(404);
|
||||||
|
$response->assertJson([
|
||||||
|
'message' => 'This is the FFR API backend. Use /api/v1/* endpoints or check the React frontend.',
|
||||||
|
'api_base' => '/api/v1'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,300 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Tests\Feature;
|
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
use App\Models\Article;
|
|
||||||
use App\Models\Feed;
|
|
||||||
use App\Models\PlatformAccount;
|
|
||||||
use App\Models\PlatformChannel;
|
|
||||||
use App\Models\Setting;
|
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
||||||
use Tests\TestCase;
|
|
||||||
|
|
||||||
class AuthenticationAndAuthorizationTest extends TestCase
|
|
||||||
{
|
|
||||||
use RefreshDatabase;
|
|
||||||
|
|
||||||
public function test_guest_can_access_public_routes(): void
|
|
||||||
{
|
|
||||||
$publicRoutes = [
|
|
||||||
'/',
|
|
||||||
'/onboarding/platform',
|
|
||||||
'/onboarding/feed',
|
|
||||||
'/onboarding/channel',
|
|
||||||
'/onboarding/complete'
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($publicRoutes as $route) {
|
|
||||||
$response = $this->get($route);
|
|
||||||
$this->assertTrue(
|
|
||||||
$response->isSuccessful(),
|
|
||||||
"Public route {$route} should be accessible to guests"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_application_routes_require_no_authentication_by_default(): void
|
|
||||||
{
|
|
||||||
// Test that main application routes are accessible
|
|
||||||
// This assumes the application doesn't have authentication middleware by default
|
|
||||||
|
|
||||||
$routes = [
|
|
||||||
'/articles',
|
|
||||||
'/logs',
|
|
||||||
'/settings',
|
|
||||||
'/platforms',
|
|
||||||
'/channels',
|
|
||||||
'/feeds',
|
|
||||||
'/routing'
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($routes as $route) {
|
|
||||||
$response = $this->get($route);
|
|
||||||
$this->assertTrue(
|
|
||||||
$response->isSuccessful(),
|
|
||||||
"Route {$route} should be accessible"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_article_approval_permissions(): void
|
|
||||||
{
|
|
||||||
$feed = Feed::factory()->create();
|
|
||||||
$article = Article::factory()->create([
|
|
||||||
'feed_id' => $feed->id,
|
|
||||||
'approval_status' => 'pending'
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Test approval endpoint
|
|
||||||
$response = $this->post("/articles/{$article->id}/approve");
|
|
||||||
$response->assertRedirect(); // Should redirect after successful approval
|
|
||||||
|
|
||||||
$article->refresh();
|
|
||||||
$this->assertEquals('approved', $article->approval_status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_article_rejection_permissions(): void
|
|
||||||
{
|
|
||||||
$feed = Feed::factory()->create();
|
|
||||||
$article = Article::factory()->create([
|
|
||||||
'feed_id' => $feed->id,
|
|
||||||
'approval_status' => 'pending'
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Test rejection endpoint
|
|
||||||
$response = $this->post("/articles/{$article->id}/reject");
|
|
||||||
$response->assertRedirect(); // Should redirect after successful rejection
|
|
||||||
|
|
||||||
$article->refresh();
|
|
||||||
$this->assertEquals('rejected', $article->approval_status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_platform_management_permissions(): void
|
|
||||||
{
|
|
||||||
$platform = PlatformAccount::factory()->create(['is_active' => false]);
|
|
||||||
|
|
||||||
// Test platform activation
|
|
||||||
$response = $this->post("/platforms/{$platform->id}/set-active");
|
|
||||||
$response->assertRedirect();
|
|
||||||
|
|
||||||
$platform->refresh();
|
|
||||||
$this->assertTrue($platform->is_active);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_channel_management_permissions(): void
|
|
||||||
{
|
|
||||||
$channel = PlatformChannel::factory()->create(['is_active' => false]);
|
|
||||||
|
|
||||||
// Test channel toggle
|
|
||||||
$response = $this->post("/channels/{$channel->id}/toggle");
|
|
||||||
$response->assertRedirect();
|
|
||||||
|
|
||||||
$channel->refresh();
|
|
||||||
$this->assertTrue($channel->is_active);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_feed_management_permissions(): void
|
|
||||||
{
|
|
||||||
$feed = Feed::factory()->create(['is_active' => false]);
|
|
||||||
|
|
||||||
// Test feed toggle
|
|
||||||
$response = $this->post("/feeds/{$feed->id}/toggle");
|
|
||||||
$response->assertRedirect();
|
|
||||||
|
|
||||||
$feed->refresh();
|
|
||||||
$this->assertTrue($feed->is_active);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_settings_update_permissions(): void
|
|
||||||
{
|
|
||||||
Setting::factory()->create([
|
|
||||||
'key' => 'test_setting',
|
|
||||||
'value' => 'old_value'
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Test settings update
|
|
||||||
$response = $this->put('/settings', [
|
|
||||||
'test_setting' => 'new_value'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response->assertRedirect();
|
|
||||||
$this->assertEquals('new_value', Setting::where('key', 'test_setting')->first()->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_routing_management_permissions(): void
|
|
||||||
{
|
|
||||||
$feed = Feed::factory()->create();
|
|
||||||
$channel = PlatformChannel::factory()->create();
|
|
||||||
|
|
||||||
// Test routing creation
|
|
||||||
$response = $this->post('/routing', [
|
|
||||||
'feed_id' => $feed->id,
|
|
||||||
'platform_channel_id' => $channel->id,
|
|
||||||
'is_active' => true
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Should either create successfully or have validation errors
|
|
||||||
$this->assertTrue(
|
|
||||||
$response->isRedirect() || $response->status() === 422,
|
|
||||||
'Routing creation should either succeed or fail with validation'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_crud_operations_on_resources(): void
|
|
||||||
{
|
|
||||||
// Test platform CRUD
|
|
||||||
$platform = PlatformAccount::factory()->create();
|
|
||||||
|
|
||||||
$response = $this->get("/platforms/{$platform->id}");
|
|
||||||
$response->assertSuccessful();
|
|
||||||
|
|
||||||
$response = $this->get("/platforms/{$platform->id}/edit");
|
|
||||||
$response->assertSuccessful();
|
|
||||||
|
|
||||||
// Test channel CRUD
|
|
||||||
$channel = PlatformChannel::factory()->create();
|
|
||||||
|
|
||||||
$response = $this->get("/channels/{$channel->id}");
|
|
||||||
$response->assertSuccessful();
|
|
||||||
|
|
||||||
$response = $this->get("/channels/{$channel->id}/edit");
|
|
||||||
$response->assertSuccessful();
|
|
||||||
|
|
||||||
// Test feed CRUD
|
|
||||||
$feed = Feed::factory()->create();
|
|
||||||
|
|
||||||
$response = $this->get("/feeds/{$feed->id}");
|
|
||||||
$response->assertSuccessful();
|
|
||||||
|
|
||||||
$response = $this->get("/feeds/{$feed->id}/edit");
|
|
||||||
$response->assertSuccessful();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_resource_creation_pages_are_accessible(): void
|
|
||||||
{
|
|
||||||
$createRoutes = [
|
|
||||||
'/platforms/create',
|
|
||||||
'/channels/create',
|
|
||||||
'/feeds/create',
|
|
||||||
'/routing/create'
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($createRoutes as $route) {
|
|
||||||
$response = $this->get($route);
|
|
||||||
$this->assertTrue(
|
|
||||||
$response->isSuccessful(),
|
|
||||||
"Create route {$route} should be accessible"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_nonexistent_resource_returns_404(): void
|
|
||||||
{
|
|
||||||
$response = $this->get('/platforms/99999');
|
|
||||||
$response->assertNotFound();
|
|
||||||
|
|
||||||
$response = $this->get('/channels/99999');
|
|
||||||
$response->assertNotFound();
|
|
||||||
|
|
||||||
$response = $this->get('/feeds/99999');
|
|
||||||
$response->assertNotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_invalid_article_operations_handle_gracefully(): void
|
|
||||||
{
|
|
||||||
// Test operations on nonexistent articles
|
|
||||||
$response = $this->post('/articles/99999/approve');
|
|
||||||
$response->assertNotFound();
|
|
||||||
|
|
||||||
$response = $this->post('/articles/99999/reject');
|
|
||||||
$response->assertNotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_invalid_platform_operations_handle_gracefully(): void
|
|
||||||
{
|
|
||||||
// Test operations on nonexistent platforms
|
|
||||||
$response = $this->post('/platforms/99999/set-active');
|
|
||||||
$response->assertNotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_invalid_channel_operations_handle_gracefully(): void
|
|
||||||
{
|
|
||||||
// Test operations on nonexistent channels
|
|
||||||
$response = $this->post('/channels/99999/toggle');
|
|
||||||
$response->assertNotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_invalid_feed_operations_handle_gracefully(): void
|
|
||||||
{
|
|
||||||
// Test operations on nonexistent feeds
|
|
||||||
$response = $this->post('/feeds/99999/toggle');
|
|
||||||
$response->assertNotFound();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_csrf_protection_on_post_requests(): void
|
|
||||||
{
|
|
||||||
$feed = Feed::factory()->create();
|
|
||||||
$article = Article::factory()->create(['feed_id' => $feed->id]);
|
|
||||||
|
|
||||||
// Test that POST requests without CSRF token are rejected
|
|
||||||
$response = $this->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class)
|
|
||||||
->post("/articles/{$article->id}/approve");
|
|
||||||
|
|
||||||
// Should work when CSRF middleware is disabled for testing
|
|
||||||
$response->assertRedirect();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_method_spoofing_works_for_put_delete(): void
|
|
||||||
{
|
|
||||||
// Test that method spoofing works for PUT/DELETE requests
|
|
||||||
Setting::factory()->create([
|
|
||||||
'key' => 'test_setting',
|
|
||||||
'value' => 'old_value'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response = $this->put('/settings', [
|
|
||||||
'test_setting' => 'new_value'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$response->assertRedirect();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_route_model_binding_works_correctly(): void
|
|
||||||
{
|
|
||||||
// Test that route model binding resolves correctly
|
|
||||||
$platform = PlatformAccount::factory()->create();
|
|
||||||
$channel = PlatformChannel::factory()->create();
|
|
||||||
$feed = Feed::factory()->create();
|
|
||||||
|
|
||||||
// These should all resolve the models correctly
|
|
||||||
$response = $this->get("/platforms/{$platform->id}");
|
|
||||||
$response->assertSuccessful();
|
|
||||||
|
|
||||||
$response = $this->get("/channels/{$channel->id}");
|
|
||||||
$response->assertSuccessful();
|
|
||||||
|
|
||||||
$response = $this->get("/feeds/{$feed->id}");
|
|
||||||
$response->assertSuccessful();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -42,12 +42,12 @@ public function test_language_model_creates_successfully(): void
|
||||||
{
|
{
|
||||||
$language = Language::factory()->create([
|
$language = Language::factory()->create([
|
||||||
'name' => 'English',
|
'name' => 'English',
|
||||||
'code' => 'en'
|
'short_code' => 'en'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertDatabaseHas('languages', [
|
$this->assertDatabaseHas('languages', [
|
||||||
'name' => 'English',
|
'name' => 'English',
|
||||||
'code' => 'en'
|
'short_code' => 'en'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,43 +66,39 @@ public function test_platform_instance_model_creates_successfully(): void
|
||||||
|
|
||||||
public function test_platform_account_model_creates_successfully(): void
|
public function test_platform_account_model_creates_successfully(): void
|
||||||
{
|
{
|
||||||
$instance = PlatformInstance::factory()->create();
|
|
||||||
|
|
||||||
$account = PlatformAccount::factory()->create([
|
$account = PlatformAccount::factory()->create([
|
||||||
'platform_instance_id' => $instance->id,
|
|
||||||
'username' => 'testuser',
|
'username' => 'testuser',
|
||||||
'is_active' => true
|
'is_active' => true
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertDatabaseHas('platform_accounts', [
|
$this->assertDatabaseHas('platform_accounts', [
|
||||||
'platform_instance_id' => $instance->id,
|
|
||||||
'username' => 'testuser',
|
'username' => 'testuser',
|
||||||
'is_active' => true
|
'is_active' => true
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals($instance->id, $account->platformInstance->id);
|
$this->assertEquals('testuser', $account->username);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_platform_channel_model_creates_successfully(): void
|
public function test_platform_channel_model_creates_successfully(): void
|
||||||
{
|
{
|
||||||
$language = Language::factory()->create();
|
$language = Language::factory()->create();
|
||||||
$account = PlatformAccount::factory()->create();
|
$instance = PlatformInstance::factory()->create();
|
||||||
|
|
||||||
$channel = PlatformChannel::factory()->create([
|
$channel = PlatformChannel::factory()->create([
|
||||||
'platform_account_id' => $account->id,
|
'platform_instance_id' => $instance->id,
|
||||||
'language_id' => $language->id,
|
'language_id' => $language->id,
|
||||||
'name' => 'Test Channel',
|
'name' => 'Test Channel',
|
||||||
'is_active' => true
|
'is_active' => true
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertDatabaseHas('platform_channels', [
|
$this->assertDatabaseHas('platform_channels', [
|
||||||
'platform_account_id' => $account->id,
|
'platform_instance_id' => $instance->id,
|
||||||
'language_id' => $language->id,
|
'language_id' => $language->id,
|
||||||
'name' => 'Test Channel',
|
'name' => 'Test Channel',
|
||||||
'is_active' => true
|
'is_active' => true
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals($account->id, $channel->platformAccount->id);
|
$this->assertEquals($instance->id, $channel->platformInstance->id);
|
||||||
$this->assertEquals($language->id, $channel->language->id);
|
$this->assertEquals($language->id, $channel->language->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,7 +165,7 @@ public function test_article_publication_model_creates_successfully(): void
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals($article->id, $publication->article->id);
|
$this->assertEquals($article->id, $publication->article->id);
|
||||||
$this->assertEquals($channel->id, $publication->platformChannel->id);
|
$this->assertEquals($channel->id, $publication->platform_channel_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_route_model_creates_successfully(): void
|
public function test_route_model_creates_successfully(): void
|
||||||
|
|
@ -195,25 +191,23 @@ public function test_route_model_creates_successfully(): void
|
||||||
|
|
||||||
public function test_platform_channel_post_model_creates_successfully(): void
|
public function test_platform_channel_post_model_creates_successfully(): void
|
||||||
{
|
{
|
||||||
$channel = PlatformChannel::factory()->create();
|
|
||||||
|
|
||||||
$post = PlatformChannelPost::create([
|
$post = PlatformChannelPost::create([
|
||||||
'platform_channel_id' => $channel->id,
|
'platform' => 'lemmy',
|
||||||
|
'channel_id' => 'technology',
|
||||||
'post_id' => 'external-post-123',
|
'post_id' => 'external-post-123',
|
||||||
'title' => 'Test Post',
|
'title' => 'Test Post',
|
||||||
'content' => 'Test content',
|
|
||||||
'url' => 'https://example.com/post',
|
'url' => 'https://example.com/post',
|
||||||
'created_at' => now(),
|
'posted_at' => now()
|
||||||
'updated_at' => now()
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertDatabaseHas('platform_channel_posts', [
|
$this->assertDatabaseHas('platform_channel_posts', [
|
||||||
'platform_channel_id' => $channel->id,
|
'platform' => 'lemmy',
|
||||||
|
'channel_id' => 'technology',
|
||||||
'post_id' => 'external-post-123',
|
'post_id' => 'external-post-123',
|
||||||
'title' => 'Test Post'
|
'title' => 'Test Post'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertEquals($channel->id, $post->platformChannel->id);
|
$this->assertEquals('external-post-123', $post->post_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_keyword_model_creates_successfully(): void
|
public function test_keyword_model_creates_successfully(): void
|
||||||
|
|
@ -254,7 +248,7 @@ public function test_log_model_creates_successfully(): void
|
||||||
|
|
||||||
public function test_setting_model_creates_successfully(): void
|
public function test_setting_model_creates_successfully(): void
|
||||||
{
|
{
|
||||||
$setting = Setting::factory()->create([
|
$setting = Setting::create([
|
||||||
'key' => 'test_setting',
|
'key' => 'test_setting',
|
||||||
'value' => 'test_value'
|
'value' => 'test_value'
|
||||||
]);
|
]);
|
||||||
|
|
@ -277,40 +271,19 @@ public function test_feed_articles_relationship(): void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_article_publications_relationship(): void
|
public function test_platform_account_channels_many_to_many_relationship(): void
|
||||||
{
|
|
||||||
$article = Article::factory()->create();
|
|
||||||
$publications = ArticlePublication::factory()->count(2)->create(['article_id' => $article->id]);
|
|
||||||
|
|
||||||
$this->assertCount(2, $article->publications);
|
|
||||||
|
|
||||||
foreach ($publications as $publication) {
|
|
||||||
$this->assertTrue($article->publications->contains($publication));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_platform_account_channels_relationship(): void
|
|
||||||
{
|
{
|
||||||
$account = PlatformAccount::factory()->create();
|
$account = PlatformAccount::factory()->create();
|
||||||
$channels = PlatformChannel::factory()->count(2)->create(['platform_account_id' => $account->id]);
|
|
||||||
|
|
||||||
$this->assertCount(2, $account->channels);
|
|
||||||
|
|
||||||
foreach ($channels as $channel) {
|
|
||||||
$this->assertTrue($account->channels->contains($channel));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test_platform_channel_routes_relationship(): void
|
|
||||||
{
|
|
||||||
$channel = PlatformChannel::factory()->create();
|
$channel = PlatformChannel::factory()->create();
|
||||||
$routes = Route::factory()->count(2)->create(['platform_channel_id' => $channel->id]);
|
|
||||||
|
|
||||||
$this->assertCount(2, $channel->routes);
|
// Test the pivot table relationship
|
||||||
|
$account->channels()->attach($channel->id, ['is_active' => true, 'priority' => 1]);
|
||||||
|
|
||||||
foreach ($routes as $route) {
|
$this->assertDatabaseHas('platform_account_channels', [
|
||||||
$this->assertTrue($channel->routes->contains($route));
|
'platform_account_id' => $account->id,
|
||||||
}
|
'platform_channel_id' => $channel->id,
|
||||||
|
'is_active' => true
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_language_platform_instances_relationship(): void
|
public function test_language_platform_instances_relationship(): void
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
use App\Events\ExceptionLogged;
|
use App\Events\ExceptionLogged;
|
||||||
use App\Events\ExceptionOccurred;
|
use App\Events\ExceptionOccurred;
|
||||||
use App\Events\NewArticleFetched;
|
use App\Events\NewArticleFetched;
|
||||||
use App\Jobs\ArticleDiscoveryJob;
|
|
||||||
use App\Jobs\ArticleDiscoveryForFeedJob;
|
use App\Jobs\ArticleDiscoveryForFeedJob;
|
||||||
|
use App\Jobs\ArticleDiscoveryJob;
|
||||||
use App\Jobs\PublishToLemmyJob;
|
use App\Jobs\PublishToLemmyJob;
|
||||||
use App\Jobs\SyncChannelPostsJob;
|
use App\Jobs\SyncChannelPostsJob;
|
||||||
use App\Listeners\LogExceptionToDatabase;
|
use App\Listeners\LogExceptionToDatabase;
|
||||||
|
|
@ -17,8 +17,8 @@
|
||||||
use App\Listeners\ValidateArticleListener;
|
use App\Listeners\ValidateArticleListener;
|
||||||
use App\Models\Article;
|
use App\Models\Article;
|
||||||
use App\Models\Feed;
|
use App\Models\Feed;
|
||||||
use App\Models\PlatformChannel;
|
|
||||||
use App\Models\Log;
|
use App\Models\Log;
|
||||||
|
use App\Models\PlatformChannel;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
use Illuminate\Support\Facades\Queue;
|
use Illuminate\Support\Facades\Queue;
|
||||||
|
|
@ -50,19 +50,20 @@ public function test_article_discovery_for_feed_job_processes_feed(): void
|
||||||
'is_active' => true
|
'is_active' => true
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$job = new ArticleDiscoveryForFeedJob($feed);
|
// Mock the ArticleFetcher service in the container
|
||||||
|
$mockFetcher = \Mockery::mock(\App\Services\Article\ArticleFetcher::class);
|
||||||
// Mock the ArticleFetcher to return created articles
|
|
||||||
$mockFetcher = \Mockery::mock('overload:' . \App\Services\Article\ArticleFetcher::class);
|
|
||||||
$article1 = Article::factory()->create(['url' => 'https://example.com/article1', 'feed_id' => $feed->id]);
|
$article1 = Article::factory()->create(['url' => 'https://example.com/article1', 'feed_id' => $feed->id]);
|
||||||
$article2 = Article::factory()->create(['url' => 'https://example.com/article2', 'feed_id' => $feed->id]);
|
$article2 = Article::factory()->create(['url' => 'https://example.com/article2', 'feed_id' => $feed->id]);
|
||||||
$mockFetcher->shouldReceive('getArticlesFromFeed')
|
$mockFetcher->shouldReceive('getArticlesFromFeed')
|
||||||
->with($feed)
|
->with($feed)
|
||||||
->andReturn(collect([$article1, $article2]));
|
->andReturn(collect([$article1, $article2]));
|
||||||
|
|
||||||
|
$this->app->instance(\App\Services\Article\ArticleFetcher::class, $mockFetcher);
|
||||||
|
|
||||||
|
$job = new ArticleDiscoveryForFeedJob($feed);
|
||||||
$job->handle();
|
$job->handle();
|
||||||
|
|
||||||
// Should have articles in database
|
// Should have articles in database (existing articles created by factory)
|
||||||
$this->assertCount(2, Article::all());
|
$this->assertCount(2, Article::all());
|
||||||
// Note: Events are not fired by ArticleDiscoveryForFeedJob directly
|
// Note: Events are not fired by ArticleDiscoveryForFeedJob directly
|
||||||
// They would be fired by the Article model when created
|
// They would be fired by the Article model when created
|
||||||
|
|
@ -174,7 +175,7 @@ public function test_exception_occurred_event_is_dispatched(): void
|
||||||
|
|
||||||
$exception = new \Exception('Test exception');
|
$exception = new \Exception('Test exception');
|
||||||
|
|
||||||
event(new ExceptionOccurred($exception, \App\LogLevelEnum::ERROR, 'Test exception', ['context' => 'test']));
|
event(new ExceptionOccurred($exception, \App\Enums\LogLevelEnum::ERROR, 'Test exception', ['context' => 'test']));
|
||||||
|
|
||||||
Event::assertDispatched(ExceptionOccurred::class, function (ExceptionOccurred $event) {
|
Event::assertDispatched(ExceptionOccurred::class, function (ExceptionOccurred $event) {
|
||||||
return $event->exception->getMessage() === 'Test exception';
|
return $event->exception->getMessage() === 'Test exception';
|
||||||
|
|
@ -273,7 +274,7 @@ public function test_log_exception_to_database_listener_creates_log(): void
|
||||||
|
|
||||||
$listener = new LogExceptionToDatabase();
|
$listener = new LogExceptionToDatabase();
|
||||||
$exception = new \Exception('Test exception message');
|
$exception = new \Exception('Test exception message');
|
||||||
$event = new ExceptionOccurred($exception, \App\LogLevelEnum::ERROR, 'Test exception message');
|
$event = new ExceptionOccurred($exception, \App\Enums\LogLevelEnum::ERROR, 'Test exception message');
|
||||||
|
|
||||||
$listener->handle($event);
|
$listener->handle($event);
|
||||||
|
|
||||||
|
|
@ -284,7 +285,7 @@ public function test_log_exception_to_database_listener_creates_log(): void
|
||||||
|
|
||||||
$savedLog = Log::where('message', 'Test exception message')->first();
|
$savedLog = Log::where('message', 'Test exception message')->first();
|
||||||
$this->assertNotNull($savedLog);
|
$this->assertNotNull($savedLog);
|
||||||
$this->assertEquals(\App\LogLevelEnum::ERROR, $savedLog->level);
|
$this->assertEquals(\App\Enums\LogLevelEnum::ERROR, $savedLog->level);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_event_listener_registration_works(): void
|
public function test_event_listener_registration_works(): void
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue