Files
ladill-frontdesk/tests/Feature/FrontdeskProTest.php
T
isaaccladandCursor 6bc52d9ef3
Deploy Ladill Frontdesk / deploy (push) Successful in 1m13s
Add dashboard upgrade banner for free Frontdesk plans.
Show the Pro upsell CTA on the reception dashboard so free orgs can discover plans without opening the sidebar.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-30 18:13:18 +00:00

208 lines
6.5 KiB
PHP

<?php
namespace Tests\Feature;
use App\Http\Middleware\EnsurePlatformSession;
use App\Models\Branch;
use App\Models\Member;
use App\Models\Organization;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;
class FrontdeskProTest extends TestCase
{
use RefreshDatabase;
protected User $owner;
protected Organization $organization;
protected function setUp(): void
{
parent::setUp();
$this->withoutMiddleware(EnsurePlatformSession::class);
config(['billing.api_url' => 'https://billing.test']);
$this->owner = User::create([
'public_id' => 'pro-owner-001',
'name' => 'Owner',
'email' => 'owner@example.com',
]);
$this->organization = Organization::create([
'owner_ref' => $this->owner->public_id,
'name' => 'Pro Org',
'slug' => 'pro-org',
'settings' => ['onboarded' => true, 'badge_expiry_hours' => 8],
]);
Member::create([
'owner_ref' => $this->owner->public_id,
'organization_id' => $this->organization->id,
'user_ref' => $this->owner->public_id,
'role' => 'org_admin',
]);
Branch::create([
'owner_ref' => $this->owner->public_id,
'organization_id' => $this->organization->id,
'name' => 'HQ',
'is_active' => true,
]);
}
public function test_pro_page_renders_three_tier_pricing(): void
{
$this->actingAs($this->owner)
->get(route('frontdesk.pro.index'))
->assertOk()
->assertSee('Choose your Frontdesk plan')
->assertSee('GHS 79')
->assertSee('Custom')
->assertSee('Upgrade to Pro')
->assertSee('Enterprise')
->assertSee('Contact sales');
}
public function test_sidebar_shows_upgrade_to_pro_on_dashboard(): void
{
$this->actingAs($this->owner)
->get(route('frontdesk.dashboard'))
->assertOk()
->assertSee('Upgrade to Pro')
->assertSee('Unlock Frontdesk Pro or Enterprise')
->assertSee('View plans');
}
public function test_subscribe_upgrades_organization(): void
{
Http::fake([
'billing.test/can-afford*' => Http::response(['affordable' => true]),
'billing.test/debit' => Http::response(['ok' => true]),
]);
$this->actingAs($this->owner)
->post(route('frontdesk.pro.subscribe'))
->assertRedirect(route('frontdesk.pro.index'))
->assertSessionHas('success');
$settings = $this->organization->fresh()->settings;
$this->assertSame('pro', $settings['plan']);
$this->assertSame('wallet_monthly', $settings['billing_method']);
}
public function test_subscribe_prepaid_redirects_to_paystack(): void
{
Http::fake([
'billing.test/plan-checkout' => Http::response([
'checkout_url' => 'https://checkout.paystack.com/test',
'reference' => 'ref-123',
]),
]);
$this->actingAs($this->owner)
->post(route('frontdesk.pro.subscribe-prepaid'), [
'plan' => 'pro',
'months' => 12,
])
->assertRedirect('https://checkout.paystack.com/test');
}
public function test_paystack_callback_activates_prepaid_pro(): void
{
Http::fake([
'billing.test/plan-checkout/verify' => Http::response([
'paid' => true,
'plan' => 'pro',
'months' => 12,
'metadata' => ['organization_id' => $this->organization->id],
]),
]);
$this->actingAs($this->owner)
->get(route('frontdesk.pro.paystack.callback', ['reference' => 'ref-123']))
->assertRedirect(route('frontdesk.pro.index'))
->assertSessionHas('success');
$settings = $this->organization->fresh()->settings;
$this->assertSame('pro', $settings['plan']);
$this->assertFalse($settings['auto_renew']);
$this->assertSame('paystack_prepaid', $settings['billing_method']);
}
public function test_pro_renew_extends_subscription_when_wallet_charges(): void
{
$this->organization->update([
'settings' => [
'onboarded' => true,
'plan' => 'pro',
'auto_renew' => true,
'plan_expires_at' => now()->subDay()->toIso8601String(),
],
]);
Http::fake([
'billing.test/debit' => Http::response(['ok' => true]),
]);
$this->artisan('frontdesk:pro-renew')->assertSuccessful();
$settings = $this->organization->fresh()->settings;
$this->assertSame('pro', $settings['plan']);
$this->assertTrue(now()->parse($settings['plan_expires_at'])->isFuture());
}
public function test_prepaid_pro_skipped_by_renewal_command(): void
{
$this->organization->update([
'settings' => [
'onboarded' => true,
'plan' => 'pro',
'auto_renew' => false,
'billing_method' => 'paystack_prepaid',
'plan_expires_at' => now()->subDay()->toIso8601String(),
],
]);
Http::fake();
$this->artisan('frontdesk:pro-renew')->assertSuccessful();
Http::assertNothingSent();
}
public function test_pro_sidebar_shows_active_label_after_upgrade(): void
{
$this->organization->update([
'settings' => array_merge($this->organization->settings ?? [], [
'plan' => 'pro',
'plan_expires_at' => now()->addMonth()->toIso8601String(),
]),
]);
$this->actingAs($this->owner)
->get(route('frontdesk.dashboard'))
->assertOk()
->assertSee('Frontdesk Pro')
->assertDontSee('Upgrade to Pro');
}
public function test_enterprise_sidebar_shows_enterprise_label(): void
{
$this->organization->update([
'settings' => array_merge($this->organization->settings ?? [], [
'plan' => 'enterprise',
'plan_expires_at' => now()->addYear()->toIso8601String(),
]),
]);
$this->actingAs($this->owner)
->get(route('frontdesk.dashboard'))
->assertOk()
->assertSee('Frontdesk Enterprise')
->assertDontSee('Upgrade to Pro');
}
}