Page MenuHomePhorge

D3590.1775332865.diff
No OneTemporary

Authored By
Unknown
Size
26 KB
Referenced Files
None
Subscribers
None

D3590.1775332865.diff

diff --git a/src/.env.example b/src/.env.example
--- a/src/.env.example
+++ b/src/.env.example
@@ -172,3 +172,4 @@
KB_ACCOUNT_DELETE=
KB_ACCOUNT_SUSPENDED=
+KB_PAYMENT_SYSTEM=
diff --git a/src/app/Console/Commands/Wallet/TrialEndCommand.php b/src/app/Console/Commands/Wallet/TrialEndCommand.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/Wallet/TrialEndCommand.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace App\Console\Commands\Wallet;
+
+use App\Console\Command;
+
+class TrialEndCommand extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'wallet:trial-end';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Notify wallet (account) owners about an end of the trial period.';
+
+ /**
+ * Execute the console command.
+ *
+ * @return mixed
+ */
+ public function handle()
+ {
+ // Get all wallets, excluding deleted/inactive accounts
+ // created precisely a month ago
+ $wallets = \App\Wallet::select('wallets.*')
+ ->join('users', 'users.id', '=', 'wallets.user_id')
+ ->leftJoin('wallet_settings', function ($join) {
+ $join->on('wallet_settings.wallet_id', '=', 'wallets.id')
+ ->where('wallet_settings.key', 'trial_end_notice');
+ })
+ ->withEnvTenantContext('users')
+ ->whereNull('users.deleted_at')
+ ->where('users.status', '&', \App\User::STATUS_IMAP_READY)
+ ->where('users.created_at', '>', \now()->subMonthsNoOverflow(2))
+ ->whereNull('wallet_settings.value')
+ ->cursor();
+
+ foreach ($wallets as $wallet) {
+ // Send the email asynchronously
+ \App\Jobs\TrialEndEmail::dispatch($wallet->owner);
+
+ // Store the timestamp
+ $wallet->setSetting('trial_end_notice', (string) \now());
+ }
+ }
+}
diff --git a/src/app/Console/Kernel.php b/src/app/Console/Kernel.php
--- a/src/app/Console/Kernel.php
+++ b/src/app/Console/Kernel.php
@@ -16,25 +16,20 @@
*/
protected function schedule(Schedule $schedule)
{
- // This command imports countries and the current set of IPv4 and IPv6 networks allocated to countries.
+ // This imports countries and the current set of IPv4 and IPv6 networks allocated to countries.
$schedule->command('data:import')->dailyAt('05:00');
// This notifies users about coming password expiration
$schedule->command('password:retention')->dailyAt('06:00');
- // These apply wallet charges
- $schedule->command('wallet:charge')->dailyAt('00:00');
- $schedule->command('wallet:charge')->dailyAt('04:00');
- $schedule->command('wallet:charge')->dailyAt('08:00');
- $schedule->command('wallet:charge')->dailyAt('12:00');
- $schedule->command('wallet:charge')->dailyAt('16:00');
- $schedule->command('wallet:charge')->dailyAt('20:00');
+ // This applies wallet charges
+ $schedule->command('wallet:charge')->everyFourHours();
- // this is a laravel 8-ism
- //$schedule->command('wallet:charge')->everyFourHours();
-
- // This command removes deleted storage files/file chunks from the filesystem
+ // This removes deleted storage files/file chunks from the filesystem
$schedule->command('fs:expunge')->hourly();
+
+ // This notifies users about an end of the trial period
+ $schedule->command('wallet:trial-end')->dailyAt('07:00');
}
/**
diff --git a/src/app/Jobs/TrialEndEmail.php b/src/app/Jobs/TrialEndEmail.php
new file mode 100644
--- /dev/null
+++ b/src/app/Jobs/TrialEndEmail.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Mail\TrialEnd;
+use App\User;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Queue\InteractsWithQueue;
+
+class TrialEndEmail implements ShouldQueue
+{
+ use Dispatchable;
+ use InteractsWithQueue;
+ use Queueable;
+ use SerializesModels;
+
+ /** @var int The number of times the job may be attempted. */
+ public $tries = 3;
+
+ /** @var bool Delete the job if its models no longer exist. */
+ public $deleteWhenMissingModels = true;
+
+ /** @var \App\User The account owner */
+ protected $account;
+
+ /**
+ * Create a new job instance.
+ *
+ * @param \App\User $account The account owner
+ *
+ * @return void
+ */
+ public function __construct(User $account)
+ {
+ $this->account = $account;
+ }
+
+ /**
+ * Determine the time at which the job should timeout.
+ *
+ * @return \DateTime
+ */
+ public function retryUntil()
+ {
+ // FIXME: I think it does not make sense to continue trying after 24 hours
+ return now()->addHours(24);
+ }
+
+ /**
+ * Execute the job.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+ \App\Mail\Helper::sendMail(
+ new TrialEnd($this->account),
+ $this->account->tenant_id,
+ ['to' => $this->account->email]
+ );
+ }
+}
diff --git a/src/app/Mail/DegradedAccountReminder.php b/src/app/Mail/DegradedAccountReminder.php
--- a/src/app/Mail/DegradedAccountReminder.php
+++ b/src/app/Mail/DegradedAccountReminder.php
@@ -55,7 +55,7 @@
'site' => $appName,
'subject' => $subject,
'username' => $this->user->name(true),
- 'supportUrl' => $supportUrl,
+ 'supportUrl' => Utils::serviceUrl($supportUrl, $this->user->tenant_id),
'walletUrl' => Utils::serviceUrl('/wallet', $this->user->tenant_id),
'dashboardUrl' => Utils::serviceUrl('/dashboard', $this->user->tenant_id),
]);
diff --git a/src/app/Mail/NegativeBalance.php b/src/app/Mail/NegativeBalance.php
--- a/src/app/Mail/NegativeBalance.php
+++ b/src/app/Mail/NegativeBalance.php
@@ -55,7 +55,7 @@
'site' => $appName,
'subject' => $subject,
'username' => $this->user->name(true),
- 'supportUrl' => $supportUrl,
+ 'supportUrl' => Utils::serviceUrl($supportUrl, $this->user->tenant_id),
'walletUrl' => Utils::serviceUrl('/wallet', $this->user->tenant_id),
]);
diff --git a/src/app/Mail/NegativeBalanceBeforeDelete.php b/src/app/Mail/NegativeBalanceBeforeDelete.php
--- a/src/app/Mail/NegativeBalanceBeforeDelete.php
+++ b/src/app/Mail/NegativeBalanceBeforeDelete.php
@@ -57,7 +57,7 @@
'site' => $appName,
'subject' => $subject,
'username' => $this->user->name(true),
- 'supportUrl' => $supportUrl,
+ 'supportUrl' => Utils::serviceUrl($supportUrl, $this->user->tenant_id),
'walletUrl' => Utils::serviceUrl('/wallet', $this->user->tenant_id),
'date' => $threshold->toDateString(),
]);
diff --git a/src/app/Mail/NegativeBalanceDegraded.php b/src/app/Mail/NegativeBalanceDegraded.php
--- a/src/app/Mail/NegativeBalanceDegraded.php
+++ b/src/app/Mail/NegativeBalanceDegraded.php
@@ -56,7 +56,7 @@
'site' => $appName,
'subject' => $subject,
'username' => $this->user->name(true),
- 'supportUrl' => $supportUrl,
+ 'supportUrl' => Utils::serviceUrl($supportUrl, $this->user->tenant_id),
'walletUrl' => Utils::serviceUrl('/wallet', $this->user->tenant_id),
]);
diff --git a/src/app/Mail/NegativeBalanceReminder.php b/src/app/Mail/NegativeBalanceReminder.php
--- a/src/app/Mail/NegativeBalanceReminder.php
+++ b/src/app/Mail/NegativeBalanceReminder.php
@@ -57,7 +57,7 @@
'site' => $appName,
'subject' => $subject,
'username' => $this->user->name(true),
- 'supportUrl' => $supportUrl,
+ 'supportUrl' => Utils::serviceUrl($supportUrl, $this->user->tenant_id),
'walletUrl' => Utils::serviceUrl('/wallet', $this->user->tenant_id),
'date' => $threshold->toDateString(),
]);
diff --git a/src/app/Mail/NegativeBalanceReminderDegrade.php b/src/app/Mail/NegativeBalanceReminderDegrade.php
--- a/src/app/Mail/NegativeBalanceReminderDegrade.php
+++ b/src/app/Mail/NegativeBalanceReminderDegrade.php
@@ -57,7 +57,7 @@
'site' => $appName,
'subject' => $subject,
'username' => $this->user->name(true),
- 'supportUrl' => $supportUrl,
+ 'supportUrl' => Utils::serviceUrl($supportUrl, $this->user->tenant_id),
'walletUrl' => Utils::serviceUrl('/wallet', $this->user->tenant_id),
'date' => $threshold->toDateString(),
]);
diff --git a/src/app/Mail/NegativeBalanceSuspended.php b/src/app/Mail/NegativeBalanceSuspended.php
--- a/src/app/Mail/NegativeBalanceSuspended.php
+++ b/src/app/Mail/NegativeBalanceSuspended.php
@@ -57,7 +57,7 @@
'site' => $appName,
'subject' => $subject,
'username' => $this->user->name(true),
- 'supportUrl' => $supportUrl,
+ 'supportUrl' => Utils::serviceUrl($supportUrl, $this->user->tenant_id),
'walletUrl' => Utils::serviceUrl('/wallet', $this->user->tenant_id),
'date' => $threshold->toDateString(),
]);
diff --git a/src/app/Mail/PasswordExpirationReminder.php b/src/app/Mail/PasswordExpirationReminder.php
--- a/src/app/Mail/PasswordExpirationReminder.php
+++ b/src/app/Mail/PasswordExpirationReminder.php
@@ -44,7 +44,6 @@
public function build()
{
$appName = Tenant::getConfig($this->user->tenant_id, 'app.name');
- $supportUrl = Tenant::getConfig($this->user->tenant_id, 'app.support_url');
$href = Utils::serviceUrl('profile', $this->user->tenant_id);
$params = [
diff --git a/src/app/Mail/PasswordReset.php b/src/app/Mail/PasswordReset.php
--- a/src/app/Mail/PasswordReset.php
+++ b/src/app/Mail/PasswordReset.php
@@ -40,7 +40,6 @@
public function build()
{
$appName = Tenant::getConfig($this->code->user->tenant_id, 'app.name');
- $supportUrl = Tenant::getConfig($this->code->user->tenant_id, 'app.support_url');
$href = Utils::serviceUrl(
sprintf('/password-reset/%s-%s', $this->code->short_code, $this->code->code),
diff --git a/src/app/Mail/PaymentFailure.php b/src/app/Mail/PaymentFailure.php
--- a/src/app/Mail/PaymentFailure.php
+++ b/src/app/Mail/PaymentFailure.php
@@ -56,7 +56,7 @@
'subject' => $subject,
'username' => $this->user->name(true),
'walletUrl' => Utils::serviceUrl('/wallet', $this->user->tenant_id),
- 'supportUrl' => $supportUrl,
+ 'supportUrl' => Utils::serviceUrl($supportUrl, $this->user->tenant_id),
]);
return $this;
diff --git a/src/app/Mail/PaymentMandateDisabled.php b/src/app/Mail/PaymentMandateDisabled.php
--- a/src/app/Mail/PaymentMandateDisabled.php
+++ b/src/app/Mail/PaymentMandateDisabled.php
@@ -56,7 +56,7 @@
'subject' => $subject,
'username' => $this->user->name(true),
'walletUrl' => Utils::serviceUrl('/wallet', $this->user->tenant_id),
- 'supportUrl' => $supportUrl,
+ 'supportUrl' => Utils::serviceUrl($supportUrl, $this->user->tenant_id),
]);
return $this;
diff --git a/src/app/Mail/PaymentSuccess.php b/src/app/Mail/PaymentSuccess.php
--- a/src/app/Mail/PaymentSuccess.php
+++ b/src/app/Mail/PaymentSuccess.php
@@ -56,7 +56,7 @@
'subject' => $subject,
'username' => $this->user->name(true),
'walletUrl' => Utils::serviceUrl('/wallet', $this->user->tenant_id),
- 'supportUrl' => $supportUrl,
+ 'supportUrl' => Utils::serviceUrl($supportUrl, $this->user->tenant_id),
]);
return $this;
diff --git a/src/app/Mail/SuspendedDebtor.php b/src/app/Mail/SuspendedDebtor.php
--- a/src/app/Mail/SuspendedDebtor.php
+++ b/src/app/Mail/SuspendedDebtor.php
@@ -58,7 +58,7 @@
'subject' => $subject,
'username' => $this->account->name(true),
'cancelUrl' => $cancelUrl,
- 'supportUrl' => $supportUrl,
+ 'supportUrl' => Utils::serviceUrl($supportUrl, $this->account->tenant_id),
'walletUrl' => Utils::serviceUrl('/wallet', $this->account->tenant_id),
'moreInfoHtml' => $moreInfoHtml,
'moreInfoText' => $moreInfoText,
diff --git a/src/app/Mail/SuspendedDebtor.php b/src/app/Mail/TrialEnd.php
copy from src/app/Mail/SuspendedDebtor.php
copy to src/app/Mail/TrialEnd.php
--- a/src/app/Mail/SuspendedDebtor.php
+++ b/src/app/Mail/TrialEnd.php
@@ -9,19 +9,19 @@
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
-class SuspendedDebtor extends Mailable
+class TrialEnd extends Mailable
{
use Queueable;
use SerializesModels;
- /** @var \App\User A suspended user (account) */
+ /** @var \App\User An account owner (account) */
protected $account;
/**
* Create a new message instance.
*
- * @param \App\User $account A suspended user (account)
+ * @param \App\User $account An account owner (account)
*
* @return void
*/
@@ -38,31 +38,20 @@
public function build()
{
$appName = Tenant::getConfig($this->account->tenant_id, 'app.name');
+ $paymentUrl = Tenant::getConfig($this->account->tenant_id, 'app.kb.payment_system');
$supportUrl = Tenant::getConfig($this->account->tenant_id, 'app.support_url');
- $cancelUrl = Tenant::getConfig($this->account->tenant_id, 'app.kb.account_delete');
- $subject = \trans('mail.suspendeddebtor-subject', ['site' => $appName]);
+ $subject = \trans('mail.trialend-subject', ['site' => $appName]);
- $moreInfoHtml = null;
- $moreInfoText = null;
- if ($moreInfoUrl = Tenant::getConfig($this->account->tenant_id, 'app.kb.account_suspended')) {
- $moreInfoHtml = \trans('mail.more-info-html', ['href' => $moreInfoUrl]);
- $moreInfoText = \trans('mail.more-info-text', ['href' => $moreInfoUrl]);
- }
-
- $this->view('emails.html.suspended_debtor')
- ->text('emails.plain.suspended_debtor')
+ $this->view('emails.html.trial_end')
+ ->text('emails.plain.trial_end')
->subject($subject)
->with([
'site' => $appName,
'subject' => $subject,
'username' => $this->account->name(true),
- 'cancelUrl' => $cancelUrl,
- 'supportUrl' => $supportUrl,
- 'walletUrl' => Utils::serviceUrl('/wallet', $this->account->tenant_id),
- 'moreInfoHtml' => $moreInfoHtml,
- 'moreInfoText' => $moreInfoText,
- 'days' => 14 // TODO: Configurable
+ 'paymentUrl' => $paymentUrl,
+ 'supportUrl' => Utils::serviceUrl($supportUrl, $this->account->tenant_id),
]);
return $this;
diff --git a/src/app/Utils.php b/src/app/Utils.php
--- a/src/app/Utils.php
+++ b/src/app/Utils.php
@@ -460,7 +460,7 @@
/**
* Create self URL
*
- * @param string $route Route/Path
+ * @param string $route Route/Path/URL
* @param int|null $tenantId Current tenant
*
* @todo Move this to App\Http\Controllers\Controller
@@ -469,6 +469,10 @@
*/
public static function serviceUrl(string $route, $tenantId = null): string
{
+ if (preg_match('|^https?://|i', $route)) {
+ return $route;
+ }
+
$url = \App\Tenant::getConfig($tenantId, 'app.public_url');
if (!$url) {
diff --git a/src/config/app.php b/src/config/app.php
--- a/src/config/app.php
+++ b/src/config/app.php
@@ -230,6 +230,8 @@
'account_suspended' => env('KB_ACCOUNT_SUSPENDED'),
// An article about a way to delete an owned account
'account_delete' => env('KB_ACCOUNT_DELETE'),
+ // An article about the payment system
+ 'payment_system' => env('KB_PAYMENT_SYSTEM'),
],
'company' => [
diff --git a/src/resources/lang/en/mail.php b/src/resources/lang/en/mail.php
--- a/src/resources/lang/en/mail.php
+++ b/src/resources/lang/en/mail.php
@@ -107,4 +107,17 @@
'suspendeddebtor-middle' => "Settle up now to reactivate your account.",
'suspendeddebtor-cancel' => "Don't want to be our customer anymore? "
. "Here is how you can cancel your account:",
+
+ 'trialend-subject' => ":site: Your trial phase has ended",
+ 'trialend-intro' => "We hope you enjoyed the 30 days of free :site trial."
+ . " Your subscriptions become active after the first month of use and the fee is due after another month.",
+ 'trialend-kb' => "You can read about how to pay the subscription fee in this knowledge base article:",
+ 'trialend-body1' => "You can leave :site at any time, there is no contractual minimum period"
+ . " and your account will NOT be deleted automatically."
+ . " You can delete your account via the red [Delete account] button in your profile."
+ . " This will end your subscription and delete all relevant data.",
+ 'trialend-body2' => "THIS OPERATION IS IRREVERSIBLE!",
+ 'trialend-body3' => "When data is deleted it can not be recovered."
+ . " Please make sure that you have saved all data that you need before pressing the red button."
+ . " Do not hesitate to contact Support with any questions or concerns.",
];
diff --git a/src/resources/views/emails/html/trial_end.blade.php b/src/resources/views/emails/html/trial_end.blade.php
new file mode 100644
--- /dev/null
+++ b/src/resources/views/emails/html/trial_end.blade.php
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
+ <head>
+ <meta charset="utf-8">
+ </head>
+ <body>
+ <p>{{ __('mail.header', ['name' => $username]) }}</p>
+ <p>{{ __('mail.trialend-intro', ['site' => $site]) }}</p>
+@if ($paymentUrl)
+ <p>{{ __('mail.trialend-kb', ['site' => $site]) }}</p>
+ <p><a href="{{ $paymentUrl }}">{{ $paymentUrl }}</a></p>
+@endif
+ <p>{{ __('mail.trialend-body1', ['site' => $site]) }}</p>
+ <p>{{ __('mail.trialend-body2', ['site' => $site]) }}</p>
+ <p>{{ __('mail.trialend-body3', ['site' => $site]) }}</p>
+ <p><a href="{{ $supportUrl }}">{{ $supportUrl }}</a></p>
+
+ <p>{{ __('mail.footer1') }}</p>
+ <p>{{ __('mail.footer2', ['site' => $site]) }}</p>
+ </body>
+</html>
diff --git a/src/resources/views/emails/plain/trial_end.blade.php b/src/resources/views/emails/plain/trial_end.blade.php
new file mode 100644
--- /dev/null
+++ b/src/resources/views/emails/plain/trial_end.blade.php
@@ -0,0 +1,19 @@
+{!! __('mail.header', ['name' => $username]) !!}
+
+{!! __('mail.trialend-intro', ['site' => $site]) !!}
+@if ($paymentUrl)
+
+{!! __('mail.trialend-kb', ['site' => $site]) !!} {!! $paymentUrl !!}
+@endif
+
+{!! __('mail.trialend-body1', ['site' => $site]) !!}
+
+{!! __('mail.trialend-body2', ['site' => $site]) !!}
+
+{!! __('mail.trialend-body3', ['site' => $site]) !!}
+
+{!! $supportUrl !!}
+
+--
+{!! __('mail.footer1') !!}
+{!! __('mail.footer2', ['site' => $site]) !!}
diff --git a/src/tests/Feature/Console/Wallet/TrialEndTest.php b/src/tests/Feature/Console/Wallet/TrialEndTest.php
new file mode 100644
--- /dev/null
+++ b/src/tests/Feature/Console/Wallet/TrialEndTest.php
@@ -0,0 +1,91 @@
+<?php
+
+namespace Tests\Feature\Console\Wallet;
+
+use App\User;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Queue;
+use Tests\TestCase;
+
+class TrialEndTest extends TestCase
+{
+ /**
+ * {@inheritDoc}
+ */
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ $this->deleteTestUser('wallets-controller@kolabnow.com');
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function tearDown(): void
+ {
+ $this->deleteTestUser('wallets-controller@kolabnow.com');
+
+ parent::tearDown();
+ }
+
+ /**
+ * Test command run
+ */
+ public function testHandle(): void
+ {
+ Queue::fake();
+
+ $user = $this->getTestUser('wallets-controller@kolabnow.com', [
+ 'status' => User::STATUS_IMAP_READY | User::STATUS_LDAP_READY | User::STATUS_ACTIVE,
+ ]);
+ $wallet = $user->wallets()->first();
+
+ DB::table('users')->update(['created_at' => \now()->clone()->subMonthsNoOverflow(2)->subHours(1)]);
+
+ // Expect no wallets in after-trial state
+ Queue::fake();
+ $code = \Artisan::call("wallet:trial-end");
+ Queue::assertNothingPushed();
+
+ // Test an email sent
+ $user->created_at = \now()->clone()->subMonthNoOverflow();
+ $user->save();
+
+ Queue::fake();
+ $code = \Artisan::call("wallet:trial-end");
+ Queue::assertPushed(\App\Jobs\TrialEndEmail::class, 1);
+ Queue::assertPushed(\App\Jobs\TrialEndEmail::class, function ($job) use ($user) {
+ $job_user = TestCase::getObjectProperty($job, 'account');
+ return $job_user->id === $user->id;
+ });
+
+ $dt = $wallet->getSetting('trial_end_notice');
+ $this->assertMatchesRegularExpression('/^' . date('Y-m-d') . ' [0-9]{2}:[0-9]{2}:[0-9]{2}$/', $dt);
+
+ // Test no duplicate email sent for the same wallet
+ Queue::fake();
+ $code = \Artisan::call("wallet:trial-end");
+ Queue::assertNothingPushed();
+
+ // Test not imap ready user - no email sent
+ $wallet->setSetting('trial_end_notice', null);
+ $user->status = User::STATUS_NEW | User::STATUS_LDAP_READY | User::STATUS_ACTIVE;
+ $user->save();
+
+ Queue::fake();
+ $code = \Artisan::call("wallet:trial-end");
+ Queue::assertNothingPushed();
+
+ // Test deleted user - no email sent
+ $user->status = User::STATUS_NEW | User::STATUS_LDAP_READY | User::STATUS_ACTIVE | User::STATUS_IMAP_READY;
+ $user->save();
+ $user->delete();
+
+ Queue::fake();
+ $code = \Artisan::call("wallet:trial-end");
+ Queue::assertNothingPushed();
+
+ $this->assertNull($wallet->getSetting('trial_end_notice'));
+ }
+}
diff --git a/src/tests/Feature/Jobs/TrialEndEmailTest.php b/src/tests/Feature/Jobs/TrialEndEmailTest.php
new file mode 100644
--- /dev/null
+++ b/src/tests/Feature/Jobs/TrialEndEmailTest.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace Tests\Feature\Jobs;
+
+use App\Jobs\TrialEndEmail;
+use App\Mail\TrialEnd;
+use Illuminate\Support\Facades\Mail;
+use Tests\TestCase;
+
+class TrialEndEmailTest extends TestCase
+{
+ /**
+ * {@inheritDoc}
+ *
+ * @return void
+ */
+ public function setUp(): void
+ {
+ parent::setUp();
+
+ $this->deleteTestUser('PaymentEmail@UserAccount.com');
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return void
+ */
+ public function tearDown(): void
+ {
+ $this->deleteTestUser('PaymentEmail@UserAccount.com');
+
+ parent::tearDown();
+ }
+
+ /**
+ * Test job handle
+ *
+ * @return void
+ */
+ public function testHandle()
+ {
+ $user = $this->getTestUser('PaymentEmail@UserAccount.com');
+ $user->setSetting('external_email', 'ext@email.tld');
+
+ Mail::fake();
+
+ // Assert that no jobs were pushed...
+ Mail::assertNothingSent();
+
+ $job = new TrialEndEmail($user);
+ $job->handle();
+
+ // Assert the email sending job was pushed once
+ Mail::assertSent(TrialEnd::class, 1);
+
+ // Assert the mail was sent to the user's email
+ Mail::assertSent(TrialEnd::class, function ($mail) {
+ return $mail->hasTo('paymentemail@useraccount.com') && !$mail->hasCc('ext@email.tld');
+ });
+ }
+}
diff --git a/src/tests/Unit/Mail/TrialEndTest.php b/src/tests/Unit/Mail/TrialEndTest.php
new file mode 100644
--- /dev/null
+++ b/src/tests/Unit/Mail/TrialEndTest.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Tests\Unit\Mail;
+
+use App\Mail\TrialEnd;
+use App\User;
+use Tests\TestCase;
+
+class TrialEndTest extends TestCase
+{
+ /**
+ * Test email content
+ */
+ public function testBuild(): void
+ {
+ $user = new User();
+
+ \config([
+ 'app.support_url' => 'https://kolab.org/support',
+ 'app.kb.payment_system' => 'https://kb.kolab.org/payment-system',
+ ]);
+
+ $mail = $this->renderMail(new TrialEnd($user));
+
+ $html = $mail['html'];
+ $plain = $mail['plain'];
+
+ $supportUrl = \config('app.support_url');
+ $supportLink = sprintf('<a href="%s">%s</a>', $supportUrl, $supportUrl);
+ $paymentUrl = \config('app.kb.payment_system');
+ $paymentLink = sprintf('<a href="%s">%s</a>', $paymentUrl, $paymentUrl);
+ $appName = \config('app.name');
+
+ $this->assertSame("$appName: Your trial phase has ended", $mail['subject']);
+
+ $this->assertStringStartsWith('<!DOCTYPE html>', $html);
+ $this->assertTrue(strpos($html, $user->name(true)) > 0);
+ $this->assertTrue(strpos($html, $supportLink) > 0);
+ $this->assertTrue(strpos($html, $paymentLink) > 0);
+ $this->assertTrue(strpos($html, "30 days of free $appName trial") > 0);
+ $this->assertTrue(strpos($html, "$appName Team") > 0);
+
+ $this->assertStringStartsWith('Dear ' . $user->name(true), $plain);
+ $this->assertTrue(strpos($plain, $supportUrl) > 0);
+ $this->assertTrue(strpos($plain, $paymentUrl) > 0);
+ $this->assertTrue(strpos($plain, "30 days of free $appName trial") > 0);
+ $this->assertTrue(strpos($plain, "$appName Team") > 0);
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 4, 8:01 PM (4 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18830998
Default Alt Text
D3590.1775332865.diff (26 KB)

Event Timeline