web: Portal-Inhalte sind auf dem Hub nicht mehr erreichbar (Anhang 2, E10)
Kategorien, Jahresarchive, Meldungen und Newsrooms liefen auch unter pressekonto.com — die Ausgabe-Routen gelten für alle Hosts, und der Portal-Kontext fällt dort auf businessportal24 zurück. Jetzt 301 auf das Portal. Meldung und Newsroom folgen ihrem eigenen Portal, nicht einer festen Vorgabe; bei Doppelveröffentlichung (gleicher Slug auf beiden Portalen) gewinnt die Erstquelle, sonst endete die Weiterleitung auf der Kopie. Kategorie, Archiv und Suche gibt es auf beiden Portalen — dort entscheidet canonical.portal_only_host. Bewusst nicht weitergeleitet wird ein unbekannter Slug (sonst 301 in ein 404) und alles, was kein GET ist (ein 301 auf POST verliert die Anfrage — Newsroom beanspruchen und Share-Zählung laufen weiter). Query-Parameter bleiben erhalten. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5dcaf4e7b0
commit
edb2d49199
5 changed files with 222 additions and 28 deletions
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
use App\Enums\Portal;
|
||||
use App\Models\Category;
|
||||
use App\Models\Company;
|
||||
use App\Models\PressRelease;
|
||||
use App\Services\PressRelease\CanonicalAssigner;
|
||||
use Tests\TestCase;
|
||||
|
||||
test('portal-only pages redirect from the hub to the leading portal', function (string $path) {
|
||||
|
|
@ -60,15 +63,113 @@ test('the retired contact and about pages redirect to the home page in one hop',
|
|||
['https://presseecho.test', 'https://presseecho.test/de'],
|
||||
]);
|
||||
|
||||
test('portal content served through the hub keeps the portal as canonical', function () {
|
||||
test('portal content keeps its own portal as canonical', function () {
|
||||
/** @var TestCase $this */
|
||||
// Die Ausgabe-Routen gelten für alle Hosts, deshalb sind Kategorien und
|
||||
// Meldungen auch unter pressekonto.com erreichbar. Sie rendern dort das
|
||||
// Portal — der Canonical muss dorthin zeigen, nie auf den Hub.
|
||||
// Sicherheitsnetz hinter der Weiterleitung: Portal-Inhalte, die über den
|
||||
// Hub-Kontext gerendert werden, dürfen niemals pressekonto als Canonical
|
||||
// tragen (`webPortalContextApplied`).
|
||||
$category = Category::factory()->create(['portal' => Portal::Both]);
|
||||
$category->translations()->create(['locale' => 'de', 'name' => 'Handel', 'slug' => 'handel']);
|
||||
|
||||
$this->get('https://pressekonto.test/de/category/handel')->assertSuccessful()
|
||||
->assertSee('<link rel="canonical" href="https://businessportal24.test/de/category/handel">', false)
|
||||
->assertDontSee('<link rel="canonical" href="https://pressekonto.test/de/category/handel">', false);
|
||||
$this->get('https://businessportal24.test/de/category/handel')->assertSuccessful()
|
||||
->assertSee('<link rel="canonical" href="https://businessportal24.test/de/category/handel">', false);
|
||||
$this->get('https://presseecho.test/de/category/handel')->assertSuccessful()
|
||||
->assertSee('<link rel="canonical" href="https://presseecho.test/de/category/handel">', false);
|
||||
});
|
||||
|
||||
test('portal content is no longer reachable on the hub and lands on its own portal', function () {
|
||||
/** @var TestCase $this */
|
||||
$category = Category::factory()->create(['portal' => Portal::Both]);
|
||||
$category->translations()->create(['locale' => 'de', 'name' => 'Handel', 'slug' => 'handel']);
|
||||
$company = Company::factory()->businessportal24()->create(['slug' => 'muster-gmbh']);
|
||||
|
||||
$release = PressRelease::factory()->published()->forPortal(Portal::Businessportal24)->for($category)->for($company)
|
||||
->create(['slug' => 'hub-umleitung-pm', 'published_at' => now()->subDay()]);
|
||||
|
||||
// Meldung und Newsroom folgen ihrem eigenen Portal.
|
||||
$this->get('https://pressekonto.test/de/press-release/hub-umleitung-pm')
|
||||
->assertStatus(301)->assertRedirect('https://businessportal24.test/de/press-release/hub-umleitung-pm');
|
||||
$this->get('https://pressekonto.test/de/newsroom/muster-gmbh')
|
||||
->assertStatus(301)->assertRedirect('https://businessportal24.test/de/newsroom/muster-gmbh');
|
||||
$this->get('https://pressekonto.test/de/newsroom/muster-gmbh/verwalten')
|
||||
->assertStatus(301)->assertRedirect('https://businessportal24.test/de/newsroom/muster-gmbh/verwalten');
|
||||
|
||||
// Kategorie und Jahresarchiv gibt es auf beiden Portalen: Standard-Portal,
|
||||
// Query-Parameter bleiben erhalten.
|
||||
$this->get('https://pressekonto.test/de/category/handel')
|
||||
->assertStatus(301)->assertRedirect('https://presseecho.test/de/category/handel');
|
||||
$this->get('https://pressekonto.test/de/category/handel/archiv/'.now()->year)
|
||||
->assertStatus(301)->assertRedirect('https://presseecho.test/de/category/handel/archiv/'.now()->year);
|
||||
$this->get('https://pressekonto.test/de/suche?q=muster')
|
||||
->assertStatus(301)->assertRedirect('https://presseecho.test/de/suche?q=muster');
|
||||
|
||||
// Presseecho-Meldung geht auf presseecho, nicht auf das Standard-Portal des Hubs.
|
||||
PressRelease::factory()->published()->forPortal(Portal::Presseecho)->for($category)
|
||||
->for(Company::factory()->create(['portal' => Portal::Presseecho]))
|
||||
->create(['slug' => 'nur-presseecho-pm', 'published_at' => now()->subDay()]);
|
||||
|
||||
$this->get('https://pressekonto.test/de/press-release/nur-presseecho-pm')
|
||||
->assertStatus(301)->assertRedirect('https://presseecho.test/de/press-release/nur-presseecho-pm');
|
||||
|
||||
// Die Portale liefern weiterhin selbst aus.
|
||||
$this->get('https://businessportal24.test/de/press-release/hub-umleitung-pm')->assertSuccessful();
|
||||
$this->get('https://presseecho.test/de/category/handel')->assertSuccessful();
|
||||
|
||||
expect($release->fresh())->not->toBeNull();
|
||||
});
|
||||
|
||||
test('a duplicate release redirects to the portal that holds the original', function () {
|
||||
/** @var TestCase $this */
|
||||
// Beide Fassungen tragen denselben Slug (so legt die API sie an) — die
|
||||
// Weiterleitung darf nicht auf der Kopie landen.
|
||||
config()->set('canonical.enabled', true);
|
||||
config()->set('canonical.portal_by_category', ['it' => 'businessportal24']);
|
||||
|
||||
$category = Category::factory()->create(['portal' => Portal::Both]);
|
||||
$category->translations()->create(['locale' => 'de', 'name' => 'IT', 'slug' => 'it']);
|
||||
$company = Company::factory()->create(['portal' => Portal::Both]);
|
||||
$text = '<p>Die Doppel GmbH eröffnet einen neuen Standort.</p>';
|
||||
|
||||
$copy = PressRelease::factory()->published()->forPortal(Portal::Presseecho)->for($category)->for($company)
|
||||
->create(['slug' => 'doppel-standort', 'title' => 'Neuer Standort', 'text' => $text, 'published_at' => now()->subHours(2)]);
|
||||
$source = PressRelease::factory()->published()->forPortal(Portal::Businessportal24)->for($category)->for($company)
|
||||
->create(['slug' => 'doppel-standort', 'title' => 'Neuer Standort', 'text' => $text, 'published_at' => now()->subHour()]);
|
||||
|
||||
app(CanonicalAssigner::class)->assignFor($source);
|
||||
|
||||
expect($copy->fresh()->canonical_press_release_id)->toBe($source->id);
|
||||
|
||||
$this->get('https://pressekonto.test/de/press-release/doppel-standort')
|
||||
->assertStatus(301)
|
||||
->assertRedirect('https://businessportal24.test/de/press-release/doppel-standort');
|
||||
});
|
||||
|
||||
test('an unknown slug on the hub stays a 404 instead of bouncing to the portal', function () {
|
||||
/** @var TestCase $this */
|
||||
$this->get('https://pressekonto.test/de/press-release/gibt-es-nicht')->assertNotFound();
|
||||
$this->get('https://pressekonto.test/de/newsroom/gibt-es-nicht')->assertNotFound();
|
||||
});
|
||||
|
||||
test('a removed release keeps its tombstone on the portal', function () {
|
||||
/** @var TestCase $this */
|
||||
$category = Category::factory()->create(['portal' => Portal::Both]);
|
||||
$category->translations()->create(['locale' => 'de', 'name' => 'Handel', 'slug' => 'handel']);
|
||||
|
||||
PressRelease::factory()->published()->forPortal(Portal::Businessportal24)->for($category)
|
||||
->for(Company::factory()->businessportal24()->create())
|
||||
->create(['slug' => 'entfernte-pm', 'published_at' => now()->subDay(), 'gone_at' => now()]);
|
||||
|
||||
$this->get('https://pressekonto.test/de/press-release/entfernte-pm')
|
||||
->assertStatus(301)->assertRedirect('https://businessportal24.test/de/press-release/entfernte-pm');
|
||||
});
|
||||
|
||||
test('posting to a portal route on the hub is not turned into a redirect', function () {
|
||||
/** @var TestCase $this */
|
||||
$company = Company::factory()->businessportal24()->create(['slug' => 'post-gmbh', 'email' => 'presse@post.example']);
|
||||
|
||||
// 301 auf ein POST würde die Anfrage verlieren — die Route bleibt.
|
||||
$response = $this->post('https://pressekonto.test/de/newsroom/post-gmbh/verwalten', []);
|
||||
|
||||
expect($response->status())->not->toBe(301)
|
||||
->and($company->fresh())->not->toBeNull();
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue