client = static::createClient(); $this->registry = new LandingRegistry(); } private function html(string $path): string { $this->client->request('GET', $path); return $this->client->getResponse()->getContent(); } public function testEveryLandingRenders(): void { foreach ($this->registry->all() as $slug => $page) { $html = $this->html('/' . $slug); self::assertSame(200, $this->client->getResponse()->getStatusCode(), "صفحهٔ «{$slug}» باز نشد"); self::assertStringContainsString('

' . $page->h1 . '

', $html); self::assertStringContainsString('' . $page->metaTitle . '', $html); self::assertStringContainsString('content="' . $page->metaDescription . '"', $html); } } public function testCanonicalPointsAtTheSamePage(): void { foreach (array_keys($this->registry->all()) as $slug) { $html = $this->html('/' . $slug); self::assertMatchesRegularExpression( '~~u', $html, "canonical صفحهٔ «{$slug}» به خودش اشاره نمی‌کند", ); } } public function testUnknownSlugIsNotFound(): void { $this->client->request('GET', '/یک-اسلاگ-که-وجود-ندارد'); self::assertSame(404, $this->client->getResponse()->getStatusCode()); } /** روت catch-all نباید صفحهٔ اصلی را بخورد. */ public function testHomePageStillWorks(): void { $html = $this->html('/'); self::assertSame(200, $this->client->getResponse()->getStatusCode()); self::assertStringContainsString('هوشمند، سریع و', $html); } public function testExistingRoutesAreNotShadowed(): void { foreach (['/sitemap.xml', '/health'] as $path) { $this->client->request('GET', $path); self::assertSame(200, $this->client->getResponse()->getStatusCode(), "{$path} گرفته شد"); } } public function testSitemapListsHomeAndEveryLanding(): void { $xml = $this->html('/sitemap.xml'); $doc = new \SimpleXMLElement($xml); // خانه + هر صفحهٔ فرود. عدد از خودِ رجیستری می‌آید تا افزودن خوشهٔ کلیدواژهٔ // تازه این تست را نشکند، ولی جاافتادن یک صفحه از sitemap هنوز قرمز شود. self::assertCount(1 + count($this->registry->all()), $doc->url); foreach (array_keys($this->registry->all()) as $slug) { self::assertStringContainsString(rawurlencode($slug), $xml, "«{$slug}» در sitemap نیست"); } } /** بدون لینک داخلی، صفحات فقط از sitemap دیده می‌شوند. */ public function testFooterLinksToTheFeaturedLandingsOnEveryPage(): void { foreach (['/', '/' . LandingRegistry::CRM] as $path) { $html = $this->html($path); foreach ($this->registry->featured() as $page) { self::assertStringContainsString('href="/' . $page->slug . '"', $html, "لینک «{$page->slug}» در {$path} نیست"); } } } /** * فوتر دیگر همهٔ صفحه‌ها را فهرست نمی‌کند، پس باید ثابت بماند که از همان چند * لینکِ فوتر، با دنبال‌کردن «راهکارهای دیگر»، به هر صفحه می‌رسیم. صفحه‌ای که فقط * در sitemap باشد عملاً بدون لینک داخلی است و رتبه نمی‌گیرد. */ public function testEveryLandingIsReachableFromTheFooterLinks(): void { $pages = $this->registry->all(); $queue = array_map(static fn ($page): string => $page->slug, $this->registry->featured()); $reached = array_flip($queue); while ($queue !== []) { $slug = array_shift($queue); foreach ($pages[$slug]->related as $next) { if (!isset($reached[$next])) { $reached[$next] = true; $queue[] = $next; } } } foreach (array_keys($pages) as $slug) { self::assertArrayHasKey($slug, $reached, "«{$slug}» از هیچ صفحه‌ای لینک نمی‌گیرد"); } } public function testStructuredDataIsValidJson(): void { foreach (array_keys($this->registry->all()) as $slug) { $html = $this->html('/' . $slug); preg_match('~~s', $html, $m); self::assertNotEmpty($m, "صفحهٔ «{$slug}» بلاک JSON-LD ندارد"); $data = json_decode(html_entity_decode($m[1]), true, flags: JSON_THROW_ON_ERROR); $types = array_column($data['@graph'], '@type'); self::assertContains('SoftwareApplication', $types); self::assertContains('BreadcrumbList', $types); self::assertContains('FAQPage', $types); } } /** تم مشترک است، پس همان CSS صفحهٔ اصلی باید بارگذاری شود. */ public function testLandingUsesTheHomepageTheme(): void { preg_match_all('~href="(/build/[^"]+\.css)"~', $this->html('/'), $home); preg_match_all('~href="(/build/[^"]+\.css)"~', $this->html('/' . LandingRegistry::BEAUTY), $landing); self::assertNotEmpty($home[1]); self::assertSame($home[1], $landing[1], 'لندینگ باید همان CSS صفحهٔ اصلی را بارگذاری کند'); } }