92 lines
3.3 KiB
PHP
92 lines
3.3 KiB
PHP
<?php
|
|
|
|
use App\Enums\SubscriptionPlan;
|
|
use App\Enums\SubscriptionStatus;
|
|
use App\Models\Subscription;
|
|
use App\Models\SubscriptionInvoice;
|
|
use App\Models\User;
|
|
use App\Notifications\SubscriptionDowngradedNotification;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Notification;
|
|
|
|
beforeEach(function () {
|
|
config([
|
|
'services.moneybird.api_token' => 'test-token',
|
|
'services.moneybird.administration_id' => '123456',
|
|
'services.moneybird.grace_days' => 14,
|
|
]);
|
|
});
|
|
|
|
test('an overdue awaiting-payment subscription is marked past due with a grace period', function () {
|
|
$user = User::factory()->create();
|
|
$subscription = Subscription::factory()->for($user)->starter()->create([
|
|
'status' => SubscriptionStatus::AwaitingPayment,
|
|
]);
|
|
|
|
SubscriptionInvoice::factory()->for($subscription)->create([
|
|
'state' => 'open',
|
|
'due_date' => today()->subDay(),
|
|
]);
|
|
|
|
$this->artisan('app:sync-subscriptions')->assertSuccessful();
|
|
|
|
$subscription->refresh();
|
|
expect($subscription->status)->toBe(SubscriptionStatus::PastDue)
|
|
->and($subscription->grace_ends_at?->toDateString())->toBe(today()->addDays(14)->toDateString());
|
|
});
|
|
|
|
test('a past-due subscription is downgraded to free once its grace period lapses', function () {
|
|
Notification::fake();
|
|
Http::fake([
|
|
'*/recurring_sales_invoices/recurring-1.json' => Http::response('', 204),
|
|
]);
|
|
|
|
$user = User::factory()->create();
|
|
$subscription = Subscription::factory()->for($user)->starter()->pastDue()->create([
|
|
'moneybird_recurring_invoice_id' => 'recurring-1',
|
|
]);
|
|
|
|
$this->artisan('app:sync-subscriptions')->assertSuccessful();
|
|
|
|
expect($subscription->refresh()->plan)->toBe(SubscriptionPlan::Free)
|
|
->and($subscription->status)->toBe(SubscriptionStatus::Active)
|
|
->and($subscription->moneybird_recurring_invoice_id)->toBeNull();
|
|
|
|
Http::assertSent(fn ($request) => str_contains((string) $request->url(), '/recurring_sales_invoices/recurring-1.json')
|
|
&& $request->method() === 'DELETE');
|
|
Notification::assertSentTo($user, SubscriptionDowngradedNotification::class);
|
|
});
|
|
|
|
test('a cancelled subscription is downgraded to free once the current period ends', function () {
|
|
Notification::fake();
|
|
Http::fake([
|
|
'*/recurring_sales_invoices/*' => Http::response('', 404),
|
|
]);
|
|
|
|
$user = User::factory()->create();
|
|
$subscription = Subscription::factory()->for($user)->starter()->create([
|
|
'cancel_at_period_end' => true,
|
|
'current_period_ends_at' => today()->subDay(),
|
|
]);
|
|
|
|
$this->artisan('app:sync-subscriptions')->assertSuccessful();
|
|
|
|
expect($subscription->refresh()->plan)->toBe(SubscriptionPlan::Free)
|
|
->and($subscription->cancel_at_period_end)->toBeFalse();
|
|
|
|
Notification::assertSentTo($user, SubscriptionDowngradedNotification::class);
|
|
});
|
|
|
|
test('subscriptions in good standing are left untouched', function () {
|
|
Notification::fake();
|
|
|
|
$user = User::factory()->create();
|
|
$subscription = Subscription::factory()->for($user)->starter()->create();
|
|
|
|
$this->artisan('app:sync-subscriptions')->assertSuccessful();
|
|
|
|
expect($subscription->refresh()->status)->toBe(SubscriptionStatus::Active)
|
|
->and($subscription->plan)->toBe(SubscriptionPlan::Starter);
|
|
|
|
Notification::assertNothingSent();
|
|
});
|