Files
landing-api/tests/Feature/Panel/InboxRepliesTest.php
Josep Piguillem 76d022053b Answer the inbox from the panel, with templates
A reply starts from a template filled in the language the person wrote in,
is sent by the application when it has a mailer that delivers or handed to
the replier's mail program otherwise, and is recorded on the submission.
The same is available through the API.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 10:45:47 +02:00

140 lines
5.0 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Feature\Panel;
use App\Enums\ApplicationStatus;
use App\Filament\Resources\Applications\Pages\ViewApplication;
use App\Filament\Resources\ReplyTemplates\Pages\CreateReplyTemplate;
use App\Filament\Resources\ReplyTemplates\ReplyTemplateResource;
use App\Mail\ApplicationReplyMail;
use App\Models\Application;
use App\Models\ApplicationReply;
use App\Models\ReplyTemplate;
use Database\Seeders\RolePermissionSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Mail;
use Livewire\Livewire;
use PHPUnit\Framework\Attributes\Test;
use Tests\FakesPireon;
use Tests\TestCase;
/**
* Answering the inbox from the panel and the API, with templates.
*/
class InboxRepliesTest extends TestCase
{
use FakesPireon, RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
$this->seed(RolePermissionSeeder::class);
Mail::fake();
}
#[Test]
public function a_template_is_filled_in_the_language_they_wrote_in(): void
{
$template = ReplyTemplate::factory()->create();
$application = Application::factory()->create(['name' => 'Ada', 'locale' => 'en']);
$text = $template->renderFor($application, $this->userWithRoles('editor', ['name' => 'Linus']));
$this->assertSame('Thank you, Ada', $text['subject']);
$this->assertStringContainsString('Linus', $text['body']);
}
#[Test]
public function with_a_real_mailer_the_reply_is_sent_and_recorded(): void
{
config(['mail.default' => 'smtp']);
$this->actingAs($editor = $this->userWithRoles('editor'));
$template = ReplyTemplate::factory()->create();
$application = Application::factory()->create(['name' => 'Ada', 'locale' => 'es', 'email' => 'ada@example.org']);
Livewire::test(ViewApplication::class, ['record' => $application->getRouteKey()])
->callAction('reply', ['template_id' => $template->id, 'subject' => 'Gracias, Ada', 'body' => 'Hola Ada'])
->assertHasNoActionErrors();
Mail::assertSent(ApplicationReplyMail::class, fn (ApplicationReplyMail $mail) => $mail->hasTo('ada@example.org'));
$reply = $application->replies()->sole();
$this->assertSame(ApplicationReply::MAIL, $reply->channel);
$this->assertSame($editor->id, $reply->user_id);
$this->assertSame(ApplicationStatus::Contacted, $application->fresh()->status);
}
#[Test]
public function without_one_it_is_recorded_and_handed_to_the_mail_program(): void
{
config(['mail.default' => 'log']);
$this->actingAs($this->userWithRoles('editor'));
$application = Application::factory()->create();
Livewire::test(ViewApplication::class, ['record' => $application->getRouteKey()])
->callAction('reply', ['subject' => 'Re', 'body' => 'Gracias'])
->assertHasNoActionErrors();
Mail::assertNothingSent();
$this->assertSame(ApplicationReply::MAILTO, $application->replies()->sole()->channel);
}
#[Test]
public function a_decision_already_taken_is_not_undone_by_replying(): void
{
config(['mail.default' => 'smtp']);
$this->actingAs($this->userWithRoles('editor'));
$application = Application::factory()->create(['status' => ApplicationStatus::Accepted]);
Livewire::test(ViewApplication::class, ['record' => $application->getRouteKey()])
->callAction('reply', ['subject' => 'Bienvenida', 'body' => '¡Adelante!']);
$this->assertSame(ApplicationStatus::Accepted, $application->fresh()->status);
}
#[Test]
public function templates_are_written_by_whoever_answers_the_inbox(): void
{
$this->actingAs($this->userWithRoles('editor'));
Livewire::test(CreateReplyTemplate::class)
->fillForm(['name' => 'Gracias', 'subject' => ['es' => 'Gracias'], 'body' => ['es' => 'Hola {name}']])
->call('create')
->assertHasNoFormErrors();
$this->assertSame(1, ReplyTemplate::query()->count());
$this->actingAs($this->userWithRoles('writer'));
$this->get(ReplyTemplateResource::getUrl('index'))->assertForbidden();
}
#[Test]
public function the_api_replies_from_a_template_and_lists_replies(): void
{
config(['mail.default' => 'log']);
$this->withHeaders($this->apiHeadersFor($this->userWithRoles('editor')));
$template = ReplyTemplate::factory()->create();
$application = Application::factory()->create(['name' => 'Ada', 'locale' => 'ca']);
$this->postJson("/api/v1/applications/{$application->id}/reply", ['template_id' => $template->id])
->assertCreated()
->assertJsonPath('data.subject', 'Gràcies, Ada')
->assertJsonPath('data.channel', 'mailto');
$this->getJson("/api/v1/applications/{$application->id}/replies")->assertJsonCount(1, 'data');
$this->getJson('/api/v1/reply-templates')->assertJsonPath('data.0.subject.en', 'Thank you, {name}');
}
}