300 lines
9.2 KiB
PHP
300 lines
9.2 KiB
PHP
|
|
<?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();
|
||
|
|
}
|
||
|
|
}
|