mivita/tests/Feature/AboRepositoryDateChangeTest.php

206 lines
5.7 KiB
PHP

<?php
use App\Models\Country;
use App\Models\ShoppingUser;
use App\Models\UserAbo;
use App\Repositories\AboRepository;
use App\User;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(Tests\TestCase::class, RefreshDatabase::class);
beforeEach(function () {
$this->repository = new AboRepository;
});
afterEach(function () {
Carbon::setTestNow();
});
/**
* Szenario: Heute = 15. März, next_date = 5. April (März-Ausführung bereits erfolgt).
* Änderung auf Tag 20 → neues Datum soll der 20. April sein, NICHT der 20. März.
*/
it('erlaubt Datumsänderung auf den 20. wenn next_date im April liegt und heute der 15. März ist', function () {
Carbon::setTestNow('2026-03-15');
$abo = new UserAbo;
$abo->next_date = '2026-04-05';
$this->repository->setModel($abo);
$newNextDate = invadePrivateMethod($this->repository, 'calculateNewNextDate', [20]);
expect($newNextDate->format('Y-m-d'))->toBe('2026-04-20');
Carbon::setTestNow();
});
/**
* Szenario: Heute = 15. März, next_date = 25. März (im selben Monat, noch nicht ausgeführt).
* Änderung auf Tag 20 → 20. März ist nur 5 Tage entfernt → Referenz bleibt now().
* setNextDate gibt 20. März zurück (5 Tage → zu nah).
*/
it('berechnet neues Datum im selben Monat wenn next_date noch im März liegt', function () {
Carbon::setTestNow('2026-03-15');
$abo = new UserAbo;
$abo->next_date = '2026-03-25';
$this->repository->setModel($abo);
$newNextDate = invadePrivateMethod($this->repository, 'calculateNewNextDate', [20]);
expect($newNextDate->format('Y-m-d'))->toBe('2026-03-20');
Carbon::setTestNow();
});
/**
* Szenario: Heute = 15. März, next_date = 5. April.
* Änderung auf Tag 5 → neues Datum soll 5. April sein (identisch mit aktuell).
*/
it('setzt Datum auf den 5. April wenn Tag 5 gewählt und next_date im April liegt', function () {
Carbon::setTestNow('2026-03-15');
$abo = new UserAbo;
$abo->next_date = '2026-04-05';
$this->repository->setModel($abo);
$newNextDate = invadePrivateMethod($this->repository, 'calculateNewNextDate', [5]);
expect($newNextDate->format('Y-m-d'))->toBe('2026-04-05');
Carbon::setTestNow();
});
/**
* Szenario: Heute = 15. März, kein next_date gesetzt → Referenz ist now().
*/
it('verwendet heute als Referenz wenn kein next_date gesetzt ist', function () {
Carbon::setTestNow('2026-03-15');
$abo = new UserAbo;
$abo->next_date = null;
$this->repository->setModel($abo);
$newNextDate = invadePrivateMethod($this->repository, 'calculateNewNextDate', [20]);
expect($newNextDate->format('Y-m-d'))->toBe('2026-03-20');
Carbon::setTestNow();
});
it('erlaubt Admins den nächsten Ausführungstermin ohne User-Sperrfrist direkt zu setzen', function () {
Carbon::setTestNow('2026-03-19 12:00:00');
$abo = createRepositoryTestAbo([
'abo_interval' => 5,
'next_date' => '2026-03-20',
]);
$this->repository->setModel($abo);
$result = $this->repository->update([
'action' => 'abo_update_settings',
'id' => $abo->id,
'view' => 'admin',
'abo_interval' => 20,
'abo_next_month' => '2026-03',
'abo_is_active' => 'true',
]);
expect($result)->toBeTrue();
expect($abo->refresh()->abo_interval)->toBe(20);
expect($abo->getRawOriginal('next_date'))->toBe('2026-03-20');
});
it('behält die User-Sperrfrist für normale Abo-Änderungen bei', function () {
Carbon::setTestNow('2026-03-19 12:00:00');
$abo = createRepositoryTestAbo([
'abo_interval' => 5,
'next_date' => '2026-03-20',
]);
$this->actingAs($abo->user);
$this->repository->setModel($abo);
$result = $this->repository->update([
'action' => 'abo_update_settings',
'id' => $abo->id,
'view' => 'me',
'abo_interval' => 20,
'abo_is_active' => 'true',
]);
expect($result)->toBeFalse();
expect($abo->refresh()->abo_interval)->toBe(5);
expect($abo->getRawOriginal('next_date'))->toBe('2026-03-20');
});
/**
* Hilfsfunktion zum Aufruf privater Methoden.
*
* @param array<mixed> $args
*/
function invadePrivateMethod(object $object, string $methodName, array $args = []): mixed
{
$reflection = new ReflectionMethod($object, $methodName);
$reflection->setAccessible(true);
return $reflection->invoke($object, ...$args);
}
/**
* @param array<string, mixed> $overrides
*/
function createRepositoryTestAbo(array $overrides = []): UserAbo
{
$country = Country::create([
'code' => 'DE',
'phone' => '49',
'en' => 'Germany',
'de' => 'Deutschland',
'es' => 'Alemania',
'fr' => 'Allemagne',
'it' => 'Germania',
'ru' => 'Deutschland',
]);
$user = User::forceCreate([
'email' => 'abo-repository-'.uniqid('', true).'@example.com',
'password' => bcrypt('secret'),
'lang' => 'de',
'admin' => 0,
]);
$shoppingUser = ShoppingUser::create([
'auth_user_id' => $user->id,
'member_id' => $user->id,
'billing_country_id' => $country->id,
'shipping_country_id' => $country->id,
'billing_email' => $user->email,
'is_for' => 'me',
'is_from' => 'user_order',
]);
return UserAbo::create(array_merge([
'user_id' => $user->id,
'member_id' => $user->id,
'shopping_user_id' => $shoppingUser->id,
'is_for' => 'me',
'email' => $user->email,
'payone_userid' => random_int(100000, 999999),
'clearingtype' => 'cc',
'active' => true,
'status' => 2,
'abo_interval' => 5,
'start_date' => '2026-01-05',
'last_date' => '2026-02-05',
'next_date' => '2026-03-05',
], $overrides));
}