CluPilotCloud/tests/Feature/SupportRequestTest.php

165 lines
5.4 KiB
PHP

<?php
use App\Livewire\NewSupportRequest;
use App\Livewire\Support;
use App\Models\Customer;
use App\Models\Instance;
use App\Models\SupportRequest;
use App\Models\User;
use Livewire\Livewire;
/**
* Asking for help, and being able to see that you did.
*
* The page used to be a decorated placeholder: a button that raised a toast
* saying the form was "only hinted at in the prototype", three invented ticket
* titles sitting in the translation file, and no way to check what had become
* of anything. It looked thin because nothing on it was real.
*/
function supportCustomer(): array
{
$user = User::factory()->create(['name' => 'Dr. S. Berger']);
$customer = Customer::factory()->create(['user_id' => $user->id, 'email' => $user->email]);
return [$user, $customer];
}
it('records a request and shows it back to the customer', function () {
[$user, $customer] = supportCustomer();
Livewire::actingAs($user)
->test(NewSupportRequest::class)
->set('category', 'technical')
->set('subject', 'Kalendersynchronisation mit Outlook')
->set('body', 'Termine werden bei zwei Mitarbeitern nicht mehr übernommen.')
->call('save')
->assertHasNoErrors();
$request = SupportRequest::query()->where('customer_id', $customer->id)->sole();
expect($request->status)->toBe('open')
// The person, not the account: on a shared login the account name says
// nothing about who is actually asking.
->and($request->reported_by)->toBe('Dr. S. Berger');
Livewire::actingAs($user)
->test(Support::class)
->assertSee('Kalendersynchronisation mit Outlook')
->assertSee(__('support.status_open'));
});
it('attaches the instance so nobody has to ask which server', function () {
[$user, $customer] = supportCustomer();
$instance = Instance::factory()->create(['customer_id' => $customer->id, 'status' => 'active']);
Livewire::actingAs($user)
->test(NewSupportRequest::class)
->set('subject', 'Ein Betreff')
->set('body', 'Eine Nachricht, die lang genug ist.')
->call('save');
expect(SupportRequest::query()->sole()->instance_id)->toBe($instance->id);
});
it('still takes a request from somebody whose cloud is not built yet', function () {
// A question can arrive before provisioning finishes, and that is exactly
// when somebody is most likely to have one.
[$user] = supportCustomer();
Livewire::actingAs($user)
->test(NewSupportRequest::class)
->set('subject', 'Wann geht es los?')
->set('body', 'Wir haben gestern bestellt und würden gerne planen.')
->call('save')
->assertHasNoErrors();
expect(SupportRequest::query()->sole()->instance_id)->toBeNull();
});
it('refuses an empty or barely-written request', function () {
[$user] = supportCustomer();
Livewire::actingAs($user)
->test(NewSupportRequest::class)
->set('subject', '')
->set('body', 'kurz')
->call('save')
->assertHasErrors(['subject', 'body']);
expect(SupportRequest::query()->count())->toBe(0);
});
it('refuses a category that is not on the form', function () {
[$user] = supportCustomer();
Livewire::actingAs($user)
->test(NewSupportRequest::class)
->set('category', 'urgent-vip')
->set('subject', 'Ein Betreff')
->set('body', 'Eine Nachricht, die lang genug ist.')
->call('save')
->assertHasErrors('category');
});
it('shows a customer only their own requests', function () {
[$user] = supportCustomer();
[, $other] = supportCustomer();
SupportRequest::create([
'customer_id' => $other->id,
'subject' => 'Fremde Anfrage',
'category' => 'billing',
'body' => 'Gehört jemand anderem.',
'status' => 'open',
]);
Livewire::actingAs($user)
->test(Support::class)
->assertDontSee('Fremde Anfrage')
->assertSee(__('support.empty_title'));
});
it('counts only what is still open', function () {
[$user, $customer] = supportCustomer();
foreach (['open', 'in_progress', 'answered', 'closed'] as $status) {
SupportRequest::create([
'customer_id' => $customer->id,
'subject' => 'Anfrage '.$status,
'category' => 'other',
'body' => 'Eine Nachricht, die lang genug ist.',
'status' => $status,
]);
}
Livewire::actingAs($user)
->test(Support::class)
// open + in_progress. Answered and closed are done with.
->assertViewHas('openCount', 2);
});
it('says something useful when there is nothing to show', function () {
// An empty state that names the next step, rather than "no data".
[$user] = supportCustomer();
Livewire::actingAs($user)
->test(Support::class)
->assertSee(__('support.empty_title'))
->assertSee(__('support.empty_body'))
->assertSee(__('support.new'));
});
it('carries no invented ticket titles', function () {
// Three fictional tickets used to live in the translation file and render
// as though they were the customer's own.
foreach (['de', 'en'] as $locale) {
$keys = array_keys(include base_path("lang/{$locale}/support.php"));
expect($keys)->not->toContain('ticket_migration')
->and($keys)->not->toContain('ticket_training')
->and($keys)->not->toContain('ticket_smtp')
->and($keys)->not->toContain('new_toast');
}
});