Create one and see its secret once, send a test, change the secret, and read each delivery with what the other end answered. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
133 lines
4.2 KiB
PHP
133 lines
4.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Feature\Panel;
|
|
|
|
use App\Filament\Resources\Webhooks\Pages\CreateWebhook;
|
|
use App\Filament\Resources\Webhooks\Pages\EditWebhook;
|
|
use App\Filament\Resources\Webhooks\RelationManagers\DeliveriesRelationManager;
|
|
use App\Filament\Resources\Webhooks\WebhookResource;
|
|
use App\Models\Webhook;
|
|
use App\Services\Media\HostResolver;
|
|
use Database\Seeders\RolePermissionSeeder;
|
|
use Filament\Notifications\Notification;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Livewire\Livewire;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use Tests\FakesPireon;
|
|
use Tests\TestCase;
|
|
|
|
/**
|
|
* Webhooks from the panel: the same rules as the API, plus the secret shown
|
|
* once and the deliveries at hand.
|
|
*/
|
|
class WebhookPanelTest extends TestCase
|
|
{
|
|
use FakesPireon, RefreshDatabase;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
$this->seed(RolePermissionSeeder::class);
|
|
|
|
$this->app->instance(HostResolver::class, new class extends HostResolver
|
|
{
|
|
public function resolve(string $host): array
|
|
{
|
|
return ['hooks.example.org' => ['93.184.216.34'], 'internal.example.org' => ['10.0.0.5']][$host] ?? [];
|
|
}
|
|
});
|
|
}
|
|
|
|
#[Test]
|
|
public function an_admin_registers_one_and_sees_its_secret_once(): void
|
|
{
|
|
$this->actingAs($admin = $this->userWithRoles('admin'));
|
|
|
|
Livewire::test(CreateWebhook::class)
|
|
->fillForm([
|
|
'name' => 'Avisos',
|
|
'url' => 'https://hooks.example.org/pireon',
|
|
'events' => ['application.received'],
|
|
])
|
|
->call('create')
|
|
->assertHasNoFormErrors();
|
|
|
|
$webhook = Webhook::query()->sole();
|
|
|
|
$this->assertSame(40, strlen($webhook->secret));
|
|
$this->assertSame($admin->id, $webhook->created_by);
|
|
|
|
Notification::assertNotified(
|
|
Notification::make()
|
|
->title(__('panel.webhooks.secret.title'))
|
|
->body(__('panel.webhooks.secret.body', ['secret' => $webhook->secret]))
|
|
->warning()
|
|
->persistent(),
|
|
);
|
|
}
|
|
|
|
#[Test]
|
|
public function an_address_inside_the_network_is_refused(): void
|
|
{
|
|
$this->actingAs($this->userWithRoles('admin'));
|
|
|
|
Livewire::test(CreateWebhook::class)
|
|
->fillForm(['name' => 'X', 'url' => 'https://internal.example.org/x', 'events' => ['*']])
|
|
->call('create')
|
|
->assertHasFormErrors(['url']);
|
|
|
|
$this->assertSame(0, Webhook::query()->count());
|
|
}
|
|
|
|
#[Test]
|
|
public function a_test_is_sent_and_shows_among_the_deliveries(): void
|
|
{
|
|
Http::fake(['hooks.example.org/*' => Http::response('ok')]);
|
|
|
|
$this->actingAs($this->userWithRoles('admin'));
|
|
|
|
$webhook = Webhook::factory()->create(['url' => 'https://hooks.example.org/x']);
|
|
|
|
Livewire::test(EditWebhook::class, ['record' => $webhook->getRouteKey()])
|
|
->callAction('ping');
|
|
|
|
Livewire::test(DeliveriesRelationManager::class, ['ownerRecord' => $webhook, 'pageClass' => EditWebhook::class])
|
|
->assertCanSeeTableRecords($webhook->deliveries()->get())
|
|
->assertSee('ping');
|
|
}
|
|
|
|
#[Test]
|
|
public function rotating_the_secret_shows_the_new_one(): void
|
|
{
|
|
$this->actingAs($this->userWithRoles('admin'));
|
|
|
|
$webhook = Webhook::factory()->create(['secret' => 'old-secret-old-secret']);
|
|
|
|
Livewire::test(EditWebhook::class, ['record' => $webhook->getRouteKey()])
|
|
->callAction('rotate_secret');
|
|
|
|
$new = $webhook->fresh()->secret;
|
|
|
|
$this->assertNotSame('old-secret-old-secret', $new);
|
|
Notification::assertNotified(
|
|
Notification::make()
|
|
->title(__('panel.webhooks.secret.title'))
|
|
->body(__('panel.webhooks.secret.body', ['secret' => $new]))
|
|
->warning()
|
|
->persistent(),
|
|
);
|
|
}
|
|
|
|
#[Test]
|
|
public function an_editor_does_not_see_them(): void
|
|
{
|
|
$this->actingAs($this->userWithRoles('editor'));
|
|
|
|
$this->get(WebhookResource::getUrl('index'))->assertForbidden();
|
|
}
|
|
}
|