CluPilotCloud/tests/Feature/SettingsTest.php

110 lines
4.0 KiB
PHP

<?php
use App\Livewire\ConfirmCancelPackage;
use App\Livewire\ConfirmCloseAccount;
use App\Livewire\Settings;
use App\Models\Customer;
use App\Models\Instance;
use App\Models\Order;
use App\Models\User;
use Livewire\Livewire;
function settingsSetup(bool $withInstance = true): array
{
$user = User::factory()->create(['email' => 's@set.test', 'is_admin' => false]);
$customer = Customer::factory()->create(['email' => 's@set.test', 'user_id' => $user->id, 'name' => 'Acme', 'status' => 'active']);
if ($withInstance) {
$order = Order::factory()->create(['customer_id' => $customer->id, 'plan' => 'team']);
Instance::factory()->create(['customer_id' => $customer->id, 'order_id' => $order->id, 'plan' => 'team', 'status' => 'active', 'subdomain' => 'acme']);
}
return compact('user', 'customer');
}
it('gates settings to authenticated users', function () {
$this->get(route('settings'))->assertRedirect('/login');
});
it('saves the company profile', function () {
['user' => $user, 'customer' => $customer] = settingsSetup();
Livewire::actingAs($user)->test(Settings::class)
->set('companyName', 'Acme GmbH')
->set('vatId', 'ATU12345678')
->set('billingAddress', "Hauptstraße 1\n1010 Wien")
->call('saveProfile')
->assertHasNoErrors();
$customer->refresh();
expect($customer->name)->toBe('Acme GmbH')
->and($customer->vat_id)->toBe('ATU12345678')
->and($customer->billing_address)->toContain('Wien');
});
it('saves branding and resolves defaults when unset', function () {
['user' => $user, 'customer' => $customer] = settingsSetup();
// Unset → resolver reports defaults.
expect($customer->brandingResolved()['is_default'])->toBeTrue();
Livewire::actingAs($user)->test(Settings::class)
->set('brandDisplayName', 'Acme Cloud')
->set('brandPrimary', '#123456')
->call('saveBranding')
->assertHasNoErrors();
$customer->refresh();
expect($customer->brand_display_name)->toBe('Acme Cloud')
->and($customer->brandingResolved()['primary_color'])->toBe('#123456')
->and($customer->brandingResolved()['is_default'])->toBeFalse();
});
it('rejects an invalid brand colour', function () {
['user' => $user] = settingsSetup();
Livewire::actingAs($user)->test(Settings::class)
->set('brandPrimary', 'notacolor')
->call('saveBranding')
->assertHasErrors(['brandPrimary']);
});
it('schedules package cancellation only with the correct typed confirmation', function () {
['user' => $user, 'customer' => $customer] = settingsSetup();
$instance = $customer->instances()->first();
// Wrong confirmation → no change.
Livewire::actingAs($user)->test(ConfirmCancelPackage::class)
->set('confirmName', 'wrong')
->call('cancelPackage')
->assertHasErrors(['confirmName']);
expect($instance->fresh()->status)->toBe('active');
// Correct confirmation → scheduled.
Livewire::actingAs($user)->test(ConfirmCancelPackage::class)
->set('confirmName', 'acme')
->call('cancelPackage');
$instance->refresh();
expect($instance->status)->toBe('cancellation_scheduled')
->and($instance->service_ends_at)->not->toBeNull();
});
it('blocks closing the account while a package is active', function () {
['user' => $user, 'customer' => $customer] = settingsSetup();
Livewire::actingAs($user)->test(ConfirmCloseAccount::class)
->set('confirmWord', __('settings.close_keyword'))
->call('closeAccount')
->assertHasErrors(['confirmWord']);
expect($customer->fresh()->closed_at)->toBeNull();
});
it('closes the account when no package is active', function () {
['user' => $user, 'customer' => $customer] = settingsSetup(withInstance: false);
Livewire::actingAs($user)->test(ConfirmCloseAccount::class)
->set('confirmWord', __('settings.close_keyword'))
->call('closeAccount');
expect($customer->fresh()->closed_at)->not->toBeNull();
});