$calls */ private function recordingClient(array &$calls, int $status = 200): HttpClientInterface { return new MockHttpClient(function (string $method, string $url, array $options) use (&$calls, $status) { $calls[] = [$method, $url, $options]; return new MockResponse('{"revalidated":true}', ['http_code' => $status]); }); } public function testSendsTagsForSlugUuidAndList(): void { $calls = []; $blog = $this->makeBlog(); (new BlogCacheInvalidator( $this->recordingClient($calls), new NullLogger(), 'https://nobat724.com/api/revalidate', 's3cret', ))->invalidate($blog); self::assertCount(1, $calls); [$method, $url, $options] = $calls[0]; self::assertSame('POST', $method); self::assertSame('https://nobat724.com/api/revalidate', $url); self::assertContains('X-Revalidate-Secret: s3cret', $options['headers']); $body = json_decode($options['body'], true); self::assertSame( ['blog-' . $blog->getSlug(), 'blog-' . $blog->getUuid(), 'blog-list'], $body['tags'] ); } public function testNetworkFailureIsSwallowed(): void { $client = new MockHttpClient(function (): MockResponse { throw new class ('boom') extends \RuntimeException implements TransportExceptionInterface {}; }); $invalidator = new BlogCacheInvalidator($client, new NullLogger(), 'https://nobat724.com/api/revalidate', 's3cret'); $invalidator->invalidate($this->makeBlog()); self::assertTrue(true, 'شکست شبکه نباید exception بدهد'); } public function testNoRequestWhenWebhookIsNotConfigured(): void { $calls = []; // URL خالی — محیط dev/تست بدون سایت عمومی (new BlogCacheInvalidator($this->recordingClient($calls), new NullLogger(), '', 's3cret')) ->invalidate($this->makeBlog()); // سکرت خالی — پیکربندی ناقص نباید درخواست بدون احراز بفرستد (new BlogCacheInvalidator($this->recordingClient($calls), new NullLogger(), 'https://nobat724.com/api/revalidate', '')) ->invalidate($this->makeBlog()); self::assertSame([], $calls); } }