Neue aufklappbare "Erste Schritte"-Card als erste Card im Kunden-Dashboard, die neue Nutzer durch Profil, Rechnungsadresse, Firma und erste PM führt und sich ausblendet, sobald alle Schritte erledigt sind. Zusätzlich die gemeinsame Fehlerseiten-Vorlage (404/403/419/500/503) an das Hub-Design angepasst (Palette, Gold-Akzent, Hub-Blau-Button), weiterhin self-contained ohne Vite-Assets. Co-authored-by: Cursor <cursoragent@cursor.com>
273 lines
8.8 KiB
PHP
273 lines
8.8 KiB
PHP
<?php
|
|
|
|
use App\Enums\PressReleaseStatus;
|
|
use App\Enums\UserPaymentOptionStatus;
|
|
use App\Models\BillingAddress;
|
|
use App\Models\Company;
|
|
use App\Models\PressRelease;
|
|
use App\Models\Profile;
|
|
use App\Models\User;
|
|
use App\Models\UserPaymentOption;
|
|
use Database\Seeders\RolesAndPermissionsSeeder;
|
|
use Livewire\Volt\Volt as LivewireVolt;
|
|
use Tests\TestCase;
|
|
|
|
beforeEach(function (): void {
|
|
/** @var TestCase $this */
|
|
$this->seed(RolesAndPermissionsSeeder::class);
|
|
});
|
|
|
|
test('customer dashboard renders core sections without errors', function () {
|
|
/** @var TestCase $this */
|
|
$customer = User::factory()->create(['is_active' => true]);
|
|
$customer->assignRole('customer');
|
|
|
|
$this->actingAs($customer);
|
|
|
|
LivewireVolt::test('customer.dashboard')
|
|
->assertSee('Mein Dashboard')
|
|
->assertSee(__('Gesamt'))
|
|
->assertSee(__('Veröffentlicht'))
|
|
->assertSee(__('In Prüfung'))
|
|
->assertSee(__('Entwürfe'))
|
|
->assertSee(__('Meine letzten Pressemitteilungen'))
|
|
->assertSee(__('Datenqualität'))
|
|
->assertSee(__('Brand-Bridge'));
|
|
});
|
|
|
|
test('empty-state with three-step intro shows when no press releases exist', function () {
|
|
/** @var TestCase $this */
|
|
$customer = User::factory()->create(['is_active' => true]);
|
|
$customer->assignRole('customer');
|
|
|
|
$this->actingAs($customer);
|
|
|
|
LivewireVolt::test('customer.dashboard')
|
|
->assertSee(__('Noch keine Pressemitteilungen'))
|
|
->assertSee(__('Erste Pressemitteilung erstellen'))
|
|
->assertSee(__('Firma zuordnen'))
|
|
->assertSee(__('Mitteilung verfassen'))
|
|
->assertSee(__('Zur Prüfung senden'));
|
|
});
|
|
|
|
test('the first-steps onboarding card appears for a fresh customer with all steps open', function () {
|
|
/** @var TestCase $this */
|
|
$customer = User::factory()->create(['is_active' => true]);
|
|
$customer->assignRole('customer');
|
|
|
|
$this->actingAs($customer);
|
|
|
|
LivewireVolt::test('customer.dashboard')
|
|
->assertSee(__('Erste Schritte'))
|
|
->assertSee('0/4 '.__('erledigt'))
|
|
->assertSee(__('Profil vervollständigen'))
|
|
->assertSee(__('Rechnungsadresse hinterlegen'))
|
|
->assertSee(__('Firma zuordnen'))
|
|
->assertSee(__('Erste Pressemitteilung erstellen'));
|
|
});
|
|
|
|
test('the first-steps onboarding card reflects completed steps in the counter', function () {
|
|
/** @var TestCase $this */
|
|
$customer = User::factory()->create(['is_active' => true]);
|
|
$customer->assignRole('customer');
|
|
|
|
Company::factory()->create(['owner_user_id' => $customer->id]);
|
|
|
|
$this->actingAs($customer);
|
|
|
|
LivewireVolt::test('customer.dashboard')
|
|
->assertSee(__('Erste Schritte'))
|
|
->assertSee('1/4 '.__('erledigt'))
|
|
->assertSee(__('Erledigt'));
|
|
});
|
|
|
|
test('the first-steps onboarding card disappears once every step is complete', function () {
|
|
/** @var TestCase $this */
|
|
$customer = User::factory()->create(['is_active' => true]);
|
|
$customer->assignRole('customer');
|
|
|
|
Profile::factory()->create([
|
|
'user_id' => $customer->id,
|
|
'salutation_key' => 'mr',
|
|
'first_name' => 'Test',
|
|
'last_name' => 'Customer',
|
|
'phone' => '+49 30 1234567',
|
|
'address' => 'Teststr. 1',
|
|
'country_code' => 'DE',
|
|
]);
|
|
|
|
BillingAddress::query()->create([
|
|
'user_id' => $customer->id,
|
|
'name' => 'Test Customer GmbH',
|
|
'address1' => 'Teststr. 1',
|
|
'postal_code' => '10115',
|
|
'city' => 'Berlin',
|
|
'country_code' => 'DE',
|
|
]);
|
|
|
|
$company = Company::factory()->create(['owner_user_id' => $customer->id]);
|
|
|
|
PressRelease::factory()->create([
|
|
'user_id' => $customer->id,
|
|
'company_id' => $company->id,
|
|
]);
|
|
|
|
$this->actingAs($customer);
|
|
|
|
LivewireVolt::test('customer.dashboard')
|
|
->assertDontSee(__('Erste Schritte'));
|
|
});
|
|
|
|
test('press release list and KPI counts render when data exists', function () {
|
|
/** @var TestCase $this */
|
|
$customer = User::factory()->create(['is_active' => true]);
|
|
$customer->assignRole('customer');
|
|
$company = Company::factory()->create(['owner_user_id' => $customer->id]);
|
|
|
|
PressRelease::factory()
|
|
->published()
|
|
->create([
|
|
'user_id' => $customer->id,
|
|
'company_id' => $company->id,
|
|
'title' => 'Phase 2 Demo Release',
|
|
]);
|
|
|
|
PressRelease::factory()->create([
|
|
'user_id' => $customer->id,
|
|
'company_id' => $company->id,
|
|
'status' => PressReleaseStatus::Draft->value,
|
|
]);
|
|
|
|
$this->actingAs($customer);
|
|
|
|
LivewireVolt::test('customer.dashboard')
|
|
->assertSee('Phase 2 Demo Release')
|
|
->assertDontSee(__('Noch keine Pressemitteilungen'))
|
|
->assertSee('Alle anzeigen');
|
|
});
|
|
|
|
test('company dashboard preview is limited to the ten newest companies', function () {
|
|
/** @var TestCase $this */
|
|
$customer = User::factory()->create(['is_active' => true]);
|
|
$customer->assignRole('customer');
|
|
|
|
for ($i = 1; $i <= 12; $i++) {
|
|
Company::factory()->create([
|
|
'owner_user_id' => $customer->id,
|
|
'name' => sprintf('Dashboard Firma %02d', $i),
|
|
'created_at' => now()->subDays(13 - $i),
|
|
]);
|
|
}
|
|
|
|
$this->actingAs($customer);
|
|
|
|
LivewireVolt::test('customer.dashboard')
|
|
->assertSee('12 zugeordnet')
|
|
->assertSee('Dashboard Firma 12')
|
|
->assertSee('Dashboard Firma 03')
|
|
->assertDontSee('Dashboard Firma 02')
|
|
->assertDontSee('Dashboard Firma 01')
|
|
->assertSee('Die zehn neuesten Firmen werden hier als Vorschau angezeigt.')
|
|
->assertSee(route('me.press-kits.index'), false);
|
|
});
|
|
|
|
test('profile completeness hint with percentage appears for partial profiles', function () {
|
|
/** @var TestCase $this */
|
|
$customer = User::factory()->create(['is_active' => true]);
|
|
$customer->assignRole('customer');
|
|
|
|
Profile::factory()->create([
|
|
'user_id' => $customer->id,
|
|
'first_name' => 'Test',
|
|
'last_name' => 'Customer',
|
|
'phone' => null,
|
|
'address' => null,
|
|
'country_code' => null,
|
|
'salutation_key' => null,
|
|
]);
|
|
|
|
$this->actingAs($customer);
|
|
|
|
LivewireVolt::test('customer.dashboard')
|
|
->assertSee(__('Profil unvollständig'))
|
|
->assertSee('33');
|
|
});
|
|
|
|
test('the booking-required banner stays hidden while the gate is open', function () {
|
|
/** @var TestCase $this */
|
|
config()->set('billing.enforce_booking', false);
|
|
|
|
$customer = User::factory()->create(['is_active' => true]);
|
|
$customer->assignRole('customer');
|
|
|
|
$this->actingAs($customer);
|
|
|
|
LivewireVolt::test('customer.dashboard')
|
|
->assertDontSee(__('Buchung erforderlich, um zu veröffentlichen'));
|
|
});
|
|
|
|
test('the booking-required banner appears when the gate is enforced and no booking exists', function () {
|
|
/** @var TestCase $this */
|
|
config()->set('billing.enforce_booking', true);
|
|
|
|
$customer = User::factory()->create(['is_active' => true]);
|
|
$customer->assignRole('customer');
|
|
|
|
$this->actingAs($customer);
|
|
|
|
LivewireVolt::test('customer.dashboard')
|
|
->assertSee(__('Buchung erforderlich, um zu veröffentlichen'))
|
|
->assertSee(route('me.bookings.index'), false);
|
|
});
|
|
|
|
test('a grandfathered bestandskunde does not see the booking-required banner', function () {
|
|
/** @var TestCase $this */
|
|
config()->set('billing.enforce_booking', true);
|
|
|
|
$customer = User::factory()->create(['is_active' => true]);
|
|
$customer->assignRole('customer');
|
|
|
|
UserPaymentOption::factory()->create([
|
|
'user_id' => $customer->id,
|
|
'status' => UserPaymentOptionStatus::Grandfathered->value,
|
|
'grandfathered_until' => now()->addYear(),
|
|
'stripe_subscription_id' => null,
|
|
]);
|
|
|
|
$this->actingAs($customer);
|
|
|
|
LivewireVolt::test('customer.dashboard')
|
|
->assertDontSee(__('Buchung erforderlich, um zu veröffentlichen'));
|
|
});
|
|
|
|
test('billing address hint disappears once address is complete', function () {
|
|
/** @var TestCase $this */
|
|
$customer = User::factory()->create(['is_active' => true]);
|
|
$customer->assignRole('customer');
|
|
|
|
Profile::factory()->create([
|
|
'user_id' => $customer->id,
|
|
'salutation_key' => 'mr',
|
|
'first_name' => 'Test',
|
|
'last_name' => 'Customer',
|
|
'phone' => '+49 30 1234567',
|
|
'address' => 'Teststr. 1',
|
|
'country_code' => 'DE',
|
|
]);
|
|
|
|
BillingAddress::query()->create([
|
|
'user_id' => $customer->id,
|
|
'name' => 'Test Customer GmbH',
|
|
'address1' => 'Teststr. 1',
|
|
'postal_code' => '10115',
|
|
'city' => 'Berlin',
|
|
'country_code' => 'DE',
|
|
]);
|
|
|
|
$this->actingAs($customer);
|
|
|
|
LivewireVolt::test('customer.dashboard')
|
|
->assertDontSee(__('Profil unvollständig'))
|
|
->assertDontSee(__('Rechnungsadresse fehlt'))
|
|
->assertSee(__('Alles im grünen Bereich'));
|
|
});
|