get('https://presseecho.test/robots.txt') ->assertSuccessful() ->assertHeader('Content-Type', 'text/plain; charset=UTF-8') ->assertSee('Disallow: /admin', false) ->assertSee('Sitemap: https://presseecho.test/sitemap.xml', false); $this->get('https://pressekonto.test/robots.txt') ->assertSuccessful() ->assertSee('Sitemap: https://pressekonto.test/sitemap.xml', false); }); test('the spoke sitemap lists static pages, categories, newsrooms and archive releases of its portal', function () { /** @var TestCase $this */ $category = Category::factory()->create(['portal' => Portal::Presseecho, 'is_active' => true]); $category->translations()->create(['locale' => 'de', 'name' => 'Technologie', 'slug' => 'technologie']); $company = Company::factory()->presseecho()->create(['is_active' => true]); PressRelease::factory() ->published() ->forPortal(Portal::Presseecho) ->for($category) ->for($company) ->create(['slug' => 'ki-report', 'published_at' => now()->subDay()]); // Fremd-Portal-PM darf nicht in der presseecho-Sitemap auftauchen. $bpCategory = Category::factory()->create(['portal' => Portal::Businessportal24]); PressRelease::factory() ->published() ->forPortal(Portal::Businessportal24) ->for($bpCategory) ->for(Company::factory()->businessportal24()->create()) ->create(['slug' => 'bp24-only', 'published_at' => now()->subDay()]); $response = $this->get('https://presseecho.test/sitemap.xml')->assertSuccessful(); expect($response->headers->get('Content-Type'))->toContain('application/xml'); expect($response->getContent()) ->toContain('https://presseecho.test/de') ->toContain('https://presseecho.test/de/preise') ->toContain('https://presseecho.test/de/impressum') ->toContain('https://presseecho.test/de/category/technologie') ->toContain('https://presseecho.test/de/newsroom/'.$company->slug.'') ->toContain('https://presseecho.test/de/press-release/ki-report') ->not->toContain('bp24-only') // Suche und Marketing-Platzhalterseiten bleiben draußen. ->not->toContain('/de/suche') ->not->toContain('/de/team'); }); test('the hub sitemap lists the landing and legal pages but no archive content', function () { /** @var TestCase $this */ PressRelease::factory() ->published() ->forPortal(Portal::Presseecho) ->for(Category::factory()->create(['portal' => Portal::Presseecho])) ->for(Company::factory()->presseecho()->create()) ->create(['slug' => 'nicht-im-hub', 'published_at' => now()->subDay()]); $response = $this->get('https://pressekonto.test/sitemap.xml')->assertSuccessful(); expect($response->getContent()) ->toContain('https://pressekonto.test/') ->toContain('https://pressekonto.test/de/impressum') ->toContain('https://pressekonto.test/de/kuendigung') ->not->toContain('press-release') ->not->toContain('newsroom'); }); test('the retired marketing placeholder pages are no longer routed', function (string $page) { /** @var TestCase $this */ // R3.2: Seiten mit Fake-Inhalten zurückgebaut; Legacy-.html-Links // laufen per Alias auf die Startseite. $this->get('https://presseecho.test/de/'.$page)->assertNotFound(); $this->get('https://presseecho.test/de/'.$page.'.html') ->assertRedirect('https://presseecho.test/de'); })->with(['team', 'partner', 'karriere']); test('the retired presse page keeps its legacy redirect to the faq', function () { /** @var TestCase $this */ // Die alte Ratgeber-Strecke /de/presse/* buendelt weiterhin 301 auf /faq // (bestehende SEO-Regel im Legacy-Redirect-Helper). $this->get('https://presseecho.test/de/presse')->assertNotFound(); $this->get('https://presseecho.test/de/presse.html') ->assertRedirect('https://presseecho.test/de/faq'); });