diff --git a/Models/ContentWebhookEndpoint.php b/Models/ContentWebhookEndpoint.php index 3333acc..669416d 100644 --- a/Models/ContentWebhookEndpoint.php +++ b/Models/ContentWebhookEndpoint.php @@ -377,14 +377,14 @@ class ContentWebhookEndpoint extends Model */ public function getStatusColorAttribute(): string { - if (! $this->is_enabled) { - return 'zinc'; - } - if ($this->isCircuitBroken()) { return 'red'; } + if (! $this->is_enabled) { + return 'zinc'; + } + if ($this->failure_count > 0) { return 'yellow'; } @@ -397,14 +397,14 @@ class ContentWebhookEndpoint extends Model */ public function getStatusLabelAttribute(): string { - if (! $this->is_enabled) { - return 'Disabled'; - } - if ($this->isCircuitBroken()) { return 'Circuit Open'; } + if (! $this->is_enabled) { + return 'Disabled'; + } + if ($this->failure_count > 0) { return "Active ({$this->failure_count} failures)"; } diff --git a/Services/HtmlSanitiser.php b/Services/HtmlSanitiser.php index bfad7de..8a8bdfe 100644 --- a/Services/HtmlSanitiser.php +++ b/Services/HtmlSanitiser.php @@ -97,6 +97,9 @@ class HtmlSanitiser $config->set('HTML.Nofollow', true); $config->set('HTML.TargetNoopener', true); + // Allow id attributes (disabled by default in HTMLPurifier) + $config->set('Attr.EnableID', true); + // Safe URI schemes only $config->set('URI.AllowedSchemes', [ 'http' => true, diff --git a/tests/Unit/ContentWebhookEndpointTest.php b/tests/Unit/ContentWebhookEndpointTest.php index cec3c98..d484772 100644 --- a/tests/Unit/ContentWebhookEndpointTest.php +++ b/tests/Unit/ContentWebhookEndpointTest.php @@ -10,6 +10,18 @@ use Tests\TestCase; class ContentWebhookEndpointTest extends TestCase { + protected function setUp(): void + { + parent::setUp(); + + // Register the webhook route if not already defined (routes may not + // load in Orchestra Testbench without the full Core event pipeline) + if (! \Illuminate\Support\Facades\Route::has('api.content.webhooks.receive')) { + \Illuminate\Support\Facades\Route::get('/api/content/webhooks/{endpoint}', fn () => null) + ->name('api.content.webhooks.receive'); + } + } + #[Test] public function it_generates_uuid_on_creation(): void { @@ -73,7 +85,8 @@ class ContentWebhookEndpointTest extends TestCase #[Test] public function it_rejects_webhook_without_secret_when_signature_required(): void { - $endpoint = ContentWebhookEndpoint::factory()->create([ + // Use make() to bypass the creating event which auto-generates secrets + $endpoint = ContentWebhookEndpoint::factory()->make([ 'secret' => null, 'require_signature' => true, ]); @@ -88,7 +101,8 @@ class ContentWebhookEndpointTest extends TestCase #[Test] public function it_allows_webhook_without_secret_when_signature_not_required(): void { - $endpoint = ContentWebhookEndpoint::factory()->create([ + // Use make() to bypass the creating event which auto-generates secrets + $endpoint = ContentWebhookEndpoint::factory()->make([ 'secret' => null, 'require_signature' => false, ]);