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>
140 lines
5.0 KiB
PHP
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}');
|
|
}
|
|
}
|