- Tenant-Admin-PWA: Neues /event-admin/welcome Onboarding mit WelcomeHero, Packages-, Order-Summary- und Event-Setup-Pages, Zustandsspeicher, Routing-Guard und Dashboard-CTA für Erstnutzer; Filament-/admin-Login via Custom-View behoben.
- Brand/Theming: Marketing-Farb- und Typographievariablen in `resources/css/app.css` eingeführt, AdminLayout, Dashboardkarten und Onboarding-Komponenten entsprechend angepasst; Dokumentation (`docs/todo/tenant-admin-onboarding-fusion.md`, `docs/changes/...`) aktualisiert. - Checkout & Payments: Checkout-, PayPal-Controller und Tests für integrierte Stripe/PayPal-Flows sowie Paket-Billing-Abläufe überarbeitet; neue PayPal SDK-Factory und Admin-API-Helper (`resources/js/admin/api.ts`) schaffen Grundlage für Billing/Members/Tasks-Seiten. - DX & Tests: Neue Playwright/E2E-Struktur (docs/testing/e2e.md, `tests/e2e/tenant-onboarding-flow.test.ts`, Utilities), E2E-Tenant-Seeder und zusätzliche Übersetzungen/Factories zur Unterstützung der neuen Flows. - Marketing-Kommunikation: Automatische Kontakt-Bestätigungsmail (`ContactConfirmation` + Blade-Template) implementiert; Guest-PWA unter `/event` erreichbar. - Nebensitzung: Blogsystem gefixt und umfassenden BlogPostSeeder für Beispielinhalte angelegt.
This commit is contained in:
@@ -3,9 +3,11 @@
|
||||
namespace Tests\Unit;
|
||||
|
||||
use App\Models\Event;
|
||||
use App\Models\Package;
|
||||
use App\Models\PackagePurchase;
|
||||
use App\Models\Photo;
|
||||
use App\Models\PurchaseHistory;
|
||||
use App\Models\Tenant;
|
||||
use App\Models\TenantPackage;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
@@ -13,120 +15,96 @@ class TenantModelTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
/** @test */
|
||||
public function tenant_has_many_events()
|
||||
public function testTenantHasManyEvents(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create();
|
||||
Event::factory(3)->create(['tenant_id' => $tenant->id]);
|
||||
Event::factory()->count(3)->create(['tenant_id' => $tenant->id]);
|
||||
|
||||
$this->assertCount(3, $tenant->events);
|
||||
$this->assertCount(3, $tenant->events()->get());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function tenant_has_photos_through_events()
|
||||
public function testTenantHasPhotosThroughEvents(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create();
|
||||
$event = Event::factory()->create(['tenant_id' => $tenant->id]);
|
||||
Photo::factory(2)->create(['event_id' => $event->id]);
|
||||
Photo::factory()->count(2)->create(['event_id' => $event->id]);
|
||||
|
||||
$this->assertCount(2, $tenant->photos);
|
||||
$this->assertCount(2, $tenant->photos()->get());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function tenant_has_many_purchases()
|
||||
public function testTenantHasManyPackagePurchases(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create();
|
||||
PurchaseHistory::factory(2)->create(['tenant_id' => $tenant->id]);
|
||||
|
||||
$this->assertCount(2, $tenant->purchases);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function active_subscription_returns_true_if_not_expired()
|
||||
{
|
||||
$tenant = Tenant::factory()->create([
|
||||
'subscription_tier' => 'pro',
|
||||
'subscription_expires_at' => now()->addDays(30),
|
||||
$package = Package::factory()->create();
|
||||
PackagePurchase::factory()->count(2)->create([
|
||||
'tenant_id' => $tenant->id,
|
||||
'package_id' => $package->id,
|
||||
]);
|
||||
|
||||
$this->assertTrue($tenant->active_subscription);
|
||||
$this->assertCount(2, $tenant->purchases()->get());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function active_subscription_returns_false_if_expired()
|
||||
public function testActiveSubscriptionAccessorReturnsTrueWhenActivePackageExists(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create([
|
||||
'subscription_tier' => 'pro',
|
||||
'subscription_expires_at' => now()->subDays(1),
|
||||
$tenant = Tenant::factory()->create();
|
||||
$package = Package::factory()->create(['type' => 'reseller']);
|
||||
|
||||
TenantPackage::factory()->create([
|
||||
'tenant_id' => $tenant->id,
|
||||
'package_id' => $package->id,
|
||||
'active' => true,
|
||||
]);
|
||||
|
||||
$this->assertFalse($tenant->active_subscription);
|
||||
$this->assertTrue($tenant->fresh()->active_subscription);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function active_subscription_returns_false_if_no_subscription()
|
||||
public function testActiveSubscriptionAccessorReturnsFalseWithoutActivePackage(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create([
|
||||
'subscription_tier' => 'free',
|
||||
'subscription_expires_at' => null,
|
||||
$tenant = Tenant::factory()->create();
|
||||
|
||||
$this->assertFalse($tenant->fresh()->active_subscription);
|
||||
}
|
||||
|
||||
public function testIncrementUsedEventsReturnsFalseWithoutActivePackage(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create();
|
||||
|
||||
$this->assertFalse($tenant->incrementUsedEvents());
|
||||
}
|
||||
|
||||
public function testIncrementUsedEventsUpdatesActivePackage(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create();
|
||||
$package = Package::factory()->create(['type' => 'reseller']);
|
||||
$tenantPackage = TenantPackage::factory()->create([
|
||||
'tenant_id' => $tenant->id,
|
||||
'package_id' => $package->id,
|
||||
'active' => true,
|
||||
'used_events' => 1,
|
||||
]);
|
||||
|
||||
$this->assertFalse($tenant->active_subscription);
|
||||
$this->assertTrue($tenant->incrementUsedEvents(2));
|
||||
$this->assertEquals(3, $tenantPackage->fresh()->used_events);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function can_decrement_credits()
|
||||
{
|
||||
$tenant = Tenant::factory()->create(['event_credits_balance' => 10]);
|
||||
|
||||
$result = $tenant->decrementCredits(3);
|
||||
|
||||
$this->assertTrue($result);
|
||||
$this->assertEquals(7, $tenant->fresh()->event_credits_balance);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function can_increment_credits()
|
||||
{
|
||||
$tenant = Tenant::factory()->create(['event_credits_balance' => 10]);
|
||||
|
||||
$result = $tenant->incrementCredits(5);
|
||||
|
||||
$this->assertTrue($result);
|
||||
$this->assertEquals(15, $tenant->fresh()->event_credits_balance);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function decrementing_credits_does_not_go_negative()
|
||||
{
|
||||
$tenant = Tenant::factory()->create(['event_credits_balance' => 2]);
|
||||
|
||||
$result = $tenant->decrementCredits(5);
|
||||
|
||||
$this->assertFalse($result);
|
||||
$this->assertEquals(2, $tenant->fresh()->event_credits_balance);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function settings_are_properly_cast_as_json()
|
||||
public function testSettingsCastToArray(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create([
|
||||
'settings' => json_encode(['theme' => 'dark', 'logo' => 'logo.png'])
|
||||
'settings' => ['theme' => 'dark', 'logo' => 'logo.png'],
|
||||
]);
|
||||
|
||||
$this->assertIsArray($tenant->settings);
|
||||
$this->assertEquals('dark', $tenant->settings['theme']);
|
||||
$this->assertSame('dark', $tenant->settings['theme']);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function features_are_cast_as_array()
|
||||
public function testFeaturesCastToArray(): void
|
||||
{
|
||||
$tenant = Tenant::factory()->create([
|
||||
'features' => ['photo_likes' => true, 'analytics' => false]
|
||||
'features' => ['photo_likes' => true, 'analytics' => false],
|
||||
]);
|
||||
|
||||
$this->assertIsArray($tenant->features);
|
||||
$this->assertTrue($tenant->features['photo_likes']);
|
||||
$this->assertFalse($tenant->features['analytics']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user