Changeset View
Changeset View
Standalone View
Standalone View
src/tests/Feature/Jobs/WalletCheckTest.php
<?php | <?php | ||||
namespace Tests\Feature\Jobs; | namespace Tests\Feature\Jobs; | ||||
use App\Jobs\WalletCheck; | use App\Jobs\WalletCheck; | ||||
use App\User; | use App\User; | ||||
use App\Wallet; | |||||
use Carbon\Carbon; | use Carbon\Carbon; | ||||
use Illuminate\Support\Facades\Mail; | use Illuminate\Support\Facades\Mail; | ||||
use Tests\TestCase; | use Tests\TestCase; | ||||
class WalletCheckTest extends TestCase | class WalletCheckTest extends TestCase | ||||
{ | { | ||||
/** | /** | ||||
* {@inheritDoc} | * {@inheritDoc} | ||||
*/ | */ | ||||
public function setUp(): void | public function setUp(): void | ||||
{ | { | ||||
parent::setUp(); | parent::setUp(); | ||||
$ned = $this->getTestUser('ned@kolab.org'); | |||||
if ($ned->isSuspended()) { | |||||
$ned->status -= User::STATUS_SUSPENDED; | |||||
$ned->save(); | |||||
} | |||||
$this->deleteTestUser('wallet-check@kolabnow.com'); | $this->deleteTestUser('wallet-check@kolabnow.com'); | ||||
} | } | ||||
/** | /** | ||||
* {@inheritDoc} | * {@inheritDoc} | ||||
*/ | */ | ||||
public function tearDown(): void | public function tearDown(): void | ||||
{ | { | ||||
$ned = $this->getTestUser('ned@kolab.org'); | |||||
if ($ned->isSuspended()) { | |||||
$ned->status -= User::STATUS_SUSPENDED; | |||||
$ned->save(); | |||||
} | |||||
$this->deleteTestUser('wallet-check@kolabnow.com'); | $this->deleteTestUser('wallet-check@kolabnow.com'); | ||||
parent::tearDown(); | parent::tearDown(); | ||||
} | } | ||||
/** | /** | ||||
* Test job handle, initial negative-balance notification | * Test job handle, initial negative-balance notification | ||||
*/ | */ | ||||
public function testHandleInitial(): void | public function testHandleInitial(): void | ||||
{ | { | ||||
Mail::fake(); | Mail::fake(); | ||||
$user = $this->getTestUser('ned@kolab.org'); | $user = $this->prepareTestUser($wallet); | ||||
$user->setSetting('external_email', 'external@test.com'); | |||||
$wallet = $user->wallets()->first(); | |||||
$now = Carbon::now(); | $now = Carbon::now(); | ||||
// Balance is not negative, double-update+save for proper resetting of the state | |||||
$wallet->balance = -100; | |||||
$wallet->save(); | |||||
$wallet->balance = 0; | $wallet->balance = 0; | ||||
$wallet->save(); | $wallet->save(); | ||||
$job = new WalletCheck($wallet); | $job = new WalletCheck($wallet); | ||||
$job->handle(); | $job->handle(); | ||||
Mail::assertNothingSent(); | Mail::assertNothingSent(); | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | class WalletCheckTest extends TestCase | ||||
* Test job handle, top-up before reminder notification | * Test job handle, top-up before reminder notification | ||||
* | * | ||||
* @depends testHandleInitial | * @depends testHandleInitial | ||||
*/ | */ | ||||
public function testHandleBeforeReminder(): void | public function testHandleBeforeReminder(): void | ||||
{ | { | ||||
Mail::fake(); | Mail::fake(); | ||||
$user = $this->getTestUser('ned@kolab.org'); | $user = $this->prepareTestUser($wallet); | ||||
$wallet = $user->wallets()->first(); | |||||
$now = Carbon::now(); | $now = Carbon::now(); | ||||
// Balance turned negative 7-1 days ago | // Balance turned negative 7-1 days ago | ||||
$wallet->setSetting('balance_negative_since', $now->subDays(7 - 1)->toDateTimeString()); | $wallet->setSetting('balance_negative_since', $now->subDays(7 - 1)->toDateTimeString()); | ||||
$job = new WalletCheck($wallet); | $job = new WalletCheck($wallet); | ||||
$res = $job->handle(); | $res = $job->handle(); | ||||
Mail::assertNothingSent(); | Mail::assertNothingSent(); | ||||
// TODO: Test that it actually executed the topUpWallet() | // TODO: Test that it actually executed the topUpWallet() | ||||
$this->assertSame(WalletCheck::THRESHOLD_BEFORE_REMINDER, $res); | $this->assertSame(WalletCheck::THRESHOLD_BEFORE_REMINDER, $res); | ||||
$this->assertFalse($user->fresh()->isSuspended()); | $this->assertFalse($user->fresh()->isSuspended()); | ||||
} | } | ||||
/** | /** | ||||
* Test job handle, reminder notification | * Test job handle, reminder notification | ||||
* | * | ||||
* @depends testHandleBeforeReminder | * @depends testHandleBeforeReminder | ||||
*/ | */ | ||||
public function testHandleReminder(): void | public function testHandleReminder(): void | ||||
{ | { | ||||
Mail::fake(); | Mail::fake(); | ||||
$user = $this->getTestUser('ned@kolab.org'); | $user = $this->prepareTestUser($wallet); | ||||
$user->setSetting('external_email', 'external@test.com'); | |||||
$wallet = $user->wallets()->first(); | |||||
$now = Carbon::now(); | $now = Carbon::now(); | ||||
// Balance turned negative 7+1 days ago, expect mail sent | // Balance turned negative 7+1 days ago, expect mail sent | ||||
$wallet->setSetting('balance_negative_since', $now->subDays(7 + 1)->toDateTimeString()); | $wallet->setSetting('balance_negative_since', $now->subDays(7 + 1)->toDateTimeString()); | ||||
$job = new WalletCheck($wallet); | $job = new WalletCheck($wallet); | ||||
$job->handle(); | $job->handle(); | ||||
// Assert the mail was sent to the user's email, but not to his external email | // Assert the mail was sent to the user's email and to his external email | ||||
Mail::assertSent(\App\Mail\NegativeBalanceReminder::class, 1); | Mail::assertSent(\App\Mail\NegativeBalanceReminderDegrade::class, 1); | ||||
Mail::assertSent(\App\Mail\NegativeBalanceReminder::class, function ($mail) use ($user) { | Mail::assertSent(\App\Mail\NegativeBalanceReminderDegrade::class, function ($mail) use ($user) { | ||||
return $mail->hasTo($user->email) && !$mail->hasCc('external@test.com'); | return $mail->hasTo($user->email) && $mail->hasCc('external@test.com'); | ||||
}); | }); | ||||
// Run the job again to make sure the notification is not sent again | // Run the job again to make sure the notification is not sent again | ||||
Mail::fake(); | Mail::fake(); | ||||
$job = new WalletCheck($wallet); | $job = new WalletCheck($wallet); | ||||
$job->handle(); | $job->handle(); | ||||
Mail::assertNothingSent(); | Mail::assertNothingSent(); | ||||
} | } | ||||
/** | /** | ||||
* Test job handle, top-up wallet before account suspending | * Test job handle, top-up wallet before account suspending | ||||
* | * | ||||
* @depends testHandleReminder | * @depends testHandleReminder | ||||
*/ | */ | ||||
/* | |||||
public function testHandleBeforeSuspended(): void | public function testHandleBeforeSuspended(): void | ||||
{ | { | ||||
Mail::fake(); | Mail::fake(); | ||||
$user = $this->getTestUser('ned@kolab.org'); | $user = $this->prepareTestUser($wallet); | ||||
$wallet = $user->wallets()->first(); | |||||
$now = Carbon::now(); | $now = Carbon::now(); | ||||
// Balance turned negative 7+14-1 days ago | // Balance turned negative 7+14-1 days ago | ||||
$days = 7 + 14 - 1; | $days = 7 + 14 - 1; | ||||
$wallet->setSetting('balance_negative_since', $now->subDays($days)->toDateTimeString()); | $wallet->setSetting('balance_negative_since', $now->subDays($days)->toDateTimeString()); | ||||
$job = new WalletCheck($wallet); | $job = new WalletCheck($wallet); | ||||
$res = $job->handle(); | $res = $job->handle(); | ||||
Mail::assertNothingSent(); | Mail::assertNothingSent(); | ||||
// TODO: Test that it actually executed the topUpWallet() | // TODO: Test that it actually executed the topUpWallet() | ||||
$this->assertSame(WalletCheck::THRESHOLD_BEFORE_SUSPEND, $res); | $this->assertSame(WalletCheck::THRESHOLD_BEFORE_SUSPEND, $res); | ||||
$this->assertFalse($user->fresh()->isSuspended()); | $this->assertFalse($user->fresh()->isSuspended()); | ||||
} | } | ||||
*/ | |||||
/** | /** | ||||
* Test job handle, account suspending | * Test job handle, account suspending | ||||
* | * | ||||
* @depends testHandleBeforeSuspended | * @depends testHandleBeforeSuspended | ||||
*/ | */ | ||||
/* | |||||
public function testHandleSuspended(): void | public function testHandleSuspended(): void | ||||
{ | { | ||||
Mail::fake(); | Mail::fake(); | ||||
$user = $this->getTestUser('ned@kolab.org'); | $user = $this->prepareTestUser($wallet); | ||||
$user->setSetting('external_email', 'external@test.com'); | |||||
$wallet = $user->wallets()->first(); | |||||
$now = Carbon::now(); | $now = Carbon::now(); | ||||
// Balance turned negative 7+14+1 days ago, expect mail sent | // Balance turned negative 7+14+1 days ago, expect mail sent | ||||
$days = 7 + 14 + 1; | $days = 7 + 14 + 1; | ||||
$wallet->setSetting('balance_negative_since', $now->subDays($days)->toDateTimeString()); | $wallet->setSetting('balance_negative_since', $now->subDays($days)->toDateTimeString()); | ||||
$job = new WalletCheck($wallet); | $job = new WalletCheck($wallet); | ||||
$job->handle(); | $job->handle(); | ||||
// Assert the mail was sent to the user's email, but not to his external email | // Assert the mail was sent to the user's email, but not to his external email | ||||
Mail::assertSent(\App\Mail\NegativeBalanceSuspended::class, 1); | Mail::assertSent(\App\Mail\NegativeBalanceSuspended::class, 1); | ||||
Mail::assertSent(\App\Mail\NegativeBalanceSuspended::class, function ($mail) use ($user) { | Mail::assertSent(\App\Mail\NegativeBalanceSuspended::class, function ($mail) use ($user) { | ||||
return $mail->hasTo($user->email) && $mail->hasCc('external@test.com'); | return $mail->hasTo($user->email) && $mail->hasCc('external@test.com'); | ||||
}); | }); | ||||
// Check that it has been suspended | // Check that it has been suspended | ||||
$this->assertTrue($user->fresh()->isSuspended()); | $this->assertTrue($user->fresh()->isSuspended()); | ||||
// TODO: Test that group account members/domain are also being suspended | // TODO: Test that group account members/domain are also being suspended | ||||
/* | |||||
foreach ($wallet->entitlements()->fresh()->get() as $entitlement) { | |||||
if ( | |||||
$entitlement->entitleable_type == \App\Domain::class | |||||
|| $entitlement->entitleable_type == \App\User::class | |||||
) { | |||||
$this->assertTrue($entitlement->entitleable->isSuspended()); | |||||
} | |||||
} | |||||
*/ | |||||
// Run the job again to make sure the notification is not sent again | // Run the job again to make sure the notification is not sent again | ||||
Mail::fake(); | Mail::fake(); | ||||
$job = new WalletCheck($wallet); | $job = new WalletCheck($wallet); | ||||
$job->handle(); | $job->handle(); | ||||
Mail::assertNothingSent(); | Mail::assertNothingSent(); | ||||
} | } | ||||
*/ | |||||
/** | /** | ||||
* Test job handle, final warning before delete | * Test job handle, final warning before delete | ||||
* | * | ||||
* @depends testHandleSuspended | * @depends testHandleSuspended | ||||
*/ | */ | ||||
/* | |||||
public function testHandleBeforeDelete(): void | public function testHandleBeforeDelete(): void | ||||
{ | { | ||||
Mail::fake(); | Mail::fake(); | ||||
$user = $this->getTestUser('ned@kolab.org'); | $user = $this->prepareTestUser($wallet); | ||||
$user->setSetting('external_email', 'external@test.com'); | |||||
$wallet = $user->wallets()->first(); | |||||
$now = Carbon::now(); | $now = Carbon::now(); | ||||
// Balance turned negative 7+14+21-3+1 days ago, expect mail sent | // Balance turned negative 7+14+21-3+1 days ago, expect mail sent | ||||
$days = 7 + 14 + 21 - 3 + 1; | $days = 7 + 14 + 21 - 3 + 1; | ||||
$wallet->setSetting('balance_negative_since', $now->subDays($days)->toDateTimeString()); | $wallet->setSetting('balance_negative_since', $now->subDays($days)->toDateTimeString()); | ||||
$job = new WalletCheck($wallet); | $job = new WalletCheck($wallet); | ||||
$job->handle(); | $job->handle(); | ||||
Show All 9 Lines | public function testHandleBeforeDelete(): void | ||||
// Run the job again to make sure the notification is not sent again | // Run the job again to make sure the notification is not sent again | ||||
Mail::fake(); | Mail::fake(); | ||||
$job = new WalletCheck($wallet); | $job = new WalletCheck($wallet); | ||||
$job->handle(); | $job->handle(); | ||||
Mail::assertNothingSent(); | Mail::assertNothingSent(); | ||||
} | } | ||||
*/ | |||||
/** | /** | ||||
* Test job handle, account delete | * Test job handle, account delete | ||||
* | * | ||||
* @depends testHandleBeforeDelete | * @depends testHandleBeforeDelete | ||||
*/ | */ | ||||
/* | |||||
public function testHandleDelete(): void | public function testHandleDelete(): void | ||||
{ | { | ||||
Mail::fake(); | Mail::fake(); | ||||
$user = $this->getTestUser('wallet-check@kolabnow.com'); | $user = $this->prepareTestUser($wallet); | ||||
$wallet = $user->wallets()->first(); | |||||
$wallet->balance = -100; | |||||
$wallet->save(); | |||||
$now = Carbon::now(); | $now = Carbon::now(); | ||||
$package = \App\Package::where('title', 'kolab')->first(); | |||||
$user->assignPackage($package); | |||||
$this->assertFalse($user->isDeleted()); | $this->assertFalse($user->isDeleted()); | ||||
$this->assertCount(4, $user->entitlements()->get()); | $this->assertCount(4, $user->entitlements()->get()); | ||||
// Balance turned negative 7+14+21+1 days ago, expect mail sent | // Balance turned negative 7+14+21+1 days ago, expect mail sent | ||||
$days = 7 + 14 + 21 + 1; | $days = 7 + 14 + 21 + 1; | ||||
$wallet->setSetting('balance_negative_since', $now->subDays($days)->toDateTimeString()); | $wallet->setSetting('balance_negative_since', $now->subDays($days)->toDateTimeString()); | ||||
$job = new WalletCheck($wallet); | $job = new WalletCheck($wallet); | ||||
$job->handle(); | $job->handle(); | ||||
Mail::assertNothingSent(); | Mail::assertNothingSent(); | ||||
// Check that it has not been deleted | // Check that it has not been deleted | ||||
$this->assertTrue($user->fresh()->trashed()); | $this->assertTrue($user->fresh()->trashed()); | ||||
$this->assertCount(0, $user->entitlements()->get()); | $this->assertCount(0, $user->entitlements()->get()); | ||||
// TODO: Test it deletes all members of the group account | // TODO: Test it deletes all members of the group account | ||||
} | } | ||||
*/ | |||||
/** | |||||
* Test job handle, account degrade | |||||
* | |||||
* @depends testHandleReminder | |||||
*/ | |||||
public function testHandleDegrade(): void | |||||
{ | |||||
Mail::fake(); | |||||
$user = $this->prepareTestUser($wallet); | |||||
$now = Carbon::now(); | |||||
$this->assertFalse($user->isDegraded()); | |||||
// Balance turned negative 7+7+1 days ago, expect mail sent | |||||
$days = 7 + 7 + 1; | |||||
$wallet->setSetting('balance_negative_since', $now->subDays($days)->toDateTimeString()); | |||||
$job = new WalletCheck($wallet); | |||||
$job->handle(); | |||||
// Assert the mail was sent to the user's email, and his external email | |||||
Mail::assertSent(\App\Mail\NegativeBalanceDegraded::class, 1); | |||||
Mail::assertSent(\App\Mail\NegativeBalanceDegraded::class, function ($mail) use ($user) { | |||||
return $mail->hasTo($user->email) && $mail->hasCc('external@test.com'); | |||||
}); | |||||
// Check that it has been degraded | |||||
$this->assertTrue($user->fresh()->isDegraded()); | |||||
} | |||||
/** | |||||
* Test job handle, periodic reminder to a degraded account | |||||
* | |||||
* @depends testHandleDegrade | |||||
*/ | |||||
public function testHandleDegradeReminder(): void | |||||
{ | |||||
Mail::fake(); | |||||
$user = $this->prepareTestUser($wallet); | |||||
$user->update(['status' => $user->status | User::STATUS_DEGRADED]); | |||||
$now = Carbon::now(); | |||||
$this->assertTrue($user->isDegraded()); | |||||
// Test degraded_last_reminder not set | |||||
$wallet->setSetting('degraded_last_reminder', null); | |||||
$job = new WalletCheck($wallet); | |||||
$res = $job->handle(); | |||||
Mail::assertNothingSent(); | |||||
$_last = Wallet::find($wallet->id)->getSetting('degraded_last_reminder'); | |||||
$this->assertSame(Carbon::now()->toDateTimeString(), $_last); | |||||
$this->assertSame(WalletCheck::THRESHOLD_DEGRADE_REMINDER, $res); | |||||
// Test degraded_last_reminder set, but 14 days didn't pass yet | |||||
$last = $now->copy()->subDays(10); | |||||
$wallet->setSetting('degraded_last_reminder', $last->toDateTimeString()); | |||||
$job = new WalletCheck($wallet); | |||||
$res = $job->handle(); | |||||
Mail::assertNothingSent(); | |||||
$_last = $wallet->fresh()->getSetting('degraded_last_reminder'); | |||||
$this->assertSame(WalletCheck::THRESHOLD_DEGRADE_REMINDER, $res); | |||||
$this->assertSame($last->toDateTimeString(), $_last); | |||||
// Test degraded_last_reminder set, and 14 days passed | |||||
$wallet->setSetting('degraded_last_reminder', $now->copy()->subDays(14)->setSeconds(0)); | |||||
$job = new WalletCheck($wallet); | |||||
$res = $job->handle(); | |||||
// Assert the mail was sent to the user's email, and his external email | |||||
Mail::assertSent(\App\Mail\DegradedAccountReminder::class, 1); | |||||
Mail::assertSent(\App\Mail\DegradedAccountReminder::class, function ($mail) use ($user) { | |||||
return $mail->hasTo($user->email) && $mail->hasCc('external@test.com'); | |||||
}); | |||||
$_last = $wallet->fresh()->getSetting('degraded_last_reminder'); | |||||
$this->assertSame(Carbon::now()->toDateTimeString(), $_last); | |||||
$this->assertSame(WalletCheck::THRESHOLD_DEGRADE_REMINDER, $res); | |||||
} | |||||
/** | |||||
* A helper to prepare a user for tests | |||||
*/ | |||||
private function prepareTestUser(&$wallet) | |||||
{ | |||||
$user = $this->getTestUser('wallet-check@kolabnow.com'); | |||||
$user->setSetting('external_email', 'external@test.com'); | |||||
$wallet = $user->wallets()->first(); | |||||
$package = \App\Package::where('title', 'kolab')->first(); | |||||
$user->assignPackage($package); | |||||
$wallet->balance = -100; | |||||
$wallet->save(); | |||||
return $user; | |||||
} | |||||
} | } |