Add-on-Panel zeigt freie Boost-Plaetze je Stufe

slotAvailability() liefert zusaetzlich free/limit (knappste Ausgabe, ohne
den eigenen gehaltenen Slot); solange buchbar, steht unter den Kauf-Buttons
"Noch X von Y Plaetzen frei." — bei laufendem Boost weiterhin nur der
Verlaengerungs-Hinweis.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-13 13:12:05 +00:00
parent 842d6a2bd0
commit 0cddf5fbdc
5 changed files with 65 additions and 12 deletions

View file

@ -169,9 +169,24 @@ test('a full homepage slot inventory rejects new home boosts with the next free
$availability = $this->service->slotAvailability($pr, BoostPlacement::Home);
expect($availability['available'])->toBeFalse();
expect($availability['free'])->toBe(0);
expect($availability['limit'])->toBe(5);
expect($availability['freeAt']->timestamp)->toBe(now()->addDay()->timestamp);
});
test('the availability reports the remaining free slots', function () {
$user = User::factory()->create();
$pr = boostableRelease($user, ['portal' => Portal::Presseecho->value]);
expect($this->service->slotAvailability($pr, BoostPlacement::Home))
->toMatchArray(['available' => true, 'free' => 5, 'limit' => 5]);
occupySlots(2, BoostPlacement::Home, Portal::Presseecho);
expect($this->service->slotAvailability($pr, BoostPlacement::Home))
->toMatchArray(['available' => true, 'free' => 3, 'limit' => 5]);
});
test('an extension is allowed even when all slots are taken — the release keeps its slot', function () {
$user = User::factory()->create();
$this->wallet->credit($user, 50);

View file

@ -55,10 +55,34 @@ test('a published green release shows the boost and proof add-ons', function ()
->assertSee('7 Tage für 12 Credits buchen')
->assertSee('Kategorie-Boost')
->assertSee('7 Tage für 6 Credits buchen')
// Slot-Transparenz: freie Plätze je Stufe (5 Startseite, 3 Branchenseite).
->assertSee('Noch 5 von 5 Plätzen frei.')
->assertSee('Noch 3 von 3 Plätzen frei.')
->assertSee('Veröffentlichungsnachweis')
->assertSee('Für 3 Credits kaufen');
});
test('the slot hint counts down when competitors occupy places', function () {
/** @var TestCase $this */
['customer' => $customer, 'pr' => $pr] = publishedGreenPrForOwner();
$this->wallet->credit($customer, 40);
// 2 der 5 Startseiten-Slots der Ausgabe sind belegt.
foreach (range(1, 2) as $i) {
$other = PressRelease::factory()->published()->create([
'portal' => $pr->portal->value,
'classification' => PressReleaseClassification::Green->value,
]);
Boost::factory()->for($other)->create();
}
$this->actingAs($customer);
LivewireVolt::test('customer.press-releases.show', ['id' => $pr->id])
->assertSee('Noch 3 von 5 Plätzen frei.')
->assertSee('Noch 3 von 3 Plätzen frei.');
});
test('add-on buttons only debit after the purchase confirmation modal', function () {
/** @var TestCase $this */
['customer' => $customer, 'pr' => $pr] = publishedGreenPrForOwner();