144 lines
7.9 KiB
PHP
144 lines
7.9 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Models\InterestRequest;
|
|
use App\Models\LandAssistanceCase;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Inertia\Testing\AssertableInertia as Assert;
|
|
use Tests\TestCase;
|
|
|
|
class LandAssistanceTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
public function test_filled_print_preserves_country_origin_and_private_ownership(): void
|
|
{
|
|
$owner = User::factory()->create(['email_verified_at' => now()]);
|
|
$this->actingAs($owner)->postJson('/investidor/terra-duat', ['payload' => ['full_name' => 'Pessoa sintética QA', 'country' => 'MZ', 'declared_origin_country_code' => 'PT']])->assertCreated();
|
|
$case = LandAssistanceCase::firstOrFail();
|
|
$this->actingAs($owner)->get('/investidor/terra-duat/'.$case->id.'/imprimir')
|
|
->assertOk()->assertInertia(fn (Assert $page) => $page->component('land-assistance/print')
|
|
->where('country.code', 'MZ')->where('declaredOrigin.code', 'PT')
|
|
->where('case.version', 1)->where('case.payload.country', 'MZ')->where('case.payload.declared_origin_country_code', 'PT'));
|
|
$this->actingAs(User::factory()->create(['email_verified_at' => now()]))
|
|
->get('/investidor/terra-duat/'.$case->id.'/imprimir')->assertNotFound();
|
|
$this->assertSame(1, $case->fresh()->version);
|
|
}
|
|
|
|
public function test_public_guide_and_blank_form_are_available_without_claiming_official_status(): void
|
|
{
|
|
$this->get('/terra-duat')->assertOk()->assertInertia(fn (Assert $page) => $page->component('land-assistance/guide'));
|
|
$this->get('/terra-duat/formulario-em-branco')->assertOk()->assertInertia(fn (Assert $page) => $page->component('land-assistance/blank'));
|
|
}
|
|
|
|
public function test_private_draft_and_support_are_versioned_and_create_one_crm_receipt(): void
|
|
{
|
|
$owner = User::factory()->create(['email_verified_at' => now()]);
|
|
$payload = [
|
|
'support_kind' => 'investment', 'request_description' => 'Preciso de orientação para preparar um pedido de apoio sobre um terreno.',
|
|
'applicant_category' => 'individual', 'full_name' => 'Pessoa de Teste', 'email' => 'terra@example.test',
|
|
'phone' => null, 'preferred_contact' => 'email', 'country' => 'Moçambique', 'area_status' => 'identified',
|
|
'purpose' => 'Projecto agrícola exploratório', 'parcels' => [], 'contact_consent' => true,
|
|
'truth_declaration' => true,
|
|
];
|
|
|
|
$this->actingAs($owner)->postJson('/investidor/terra-duat', ['payload' => $payload])->assertCreated();
|
|
$case = LandAssistanceCase::firstOrFail();
|
|
$this->assertSame(1, $case->version);
|
|
$this->assertSame('draft', $case->status);
|
|
$this->assertDatabaseCount('land_assistance_revisions', 1);
|
|
|
|
$this->postJson("/investidor/terra-duat/{$case->id}/solicitar-apoio", ['version' => 1, 'payload' => $payload])->assertAccepted();
|
|
$case->refresh();
|
|
$this->assertSame('support_requested', $case->status);
|
|
$this->assertSame(2, $case->version);
|
|
$this->assertNotNull($case->interest_request_id);
|
|
$this->assertDatabaseCount('interest_requests', 1);
|
|
$this->assertDatabaseCount('interest_submission_receipts', 1);
|
|
$this->assertDatabaseCount('outbox_events', 1);
|
|
$this->assertDatabaseCount('consents', 1);
|
|
$this->assertSame('Terra e DUAT', InterestRequest::firstOrFail()->sector_interest);
|
|
|
|
$this->actingAs(User::factory()->create(['email_verified_at' => now()]))
|
|
->getJson("/investidor/terra-duat/{$case->id}")->assertNotFound();
|
|
$this->actingAs($owner)->postJson("/investidor/terra-duat/{$case->id}/solicitar-apoio", ['version' => 2, 'payload' => $payload])->assertStatus(409);
|
|
$this->assertDatabaseCount('interest_requests', 1);
|
|
}
|
|
|
|
public function test_phone_only_support_still_requires_contact_consent(): void
|
|
{
|
|
$owner = User::factory()->create(['email_verified_at' => now()]);
|
|
$payload = [
|
|
'support_kind' => 'investment', 'request_description' => 'Preciso de orientação sobre os passos de preparação do pedido.',
|
|
'applicant_category' => 'individual', 'full_name' => 'Pessoa de Teste', 'phone' => '840000000',
|
|
'preferred_contact' => 'phone', 'area_status' => 'identified', 'purpose' => 'Projecto exploratório',
|
|
'contact_consent' => false, 'truth_declaration' => true,
|
|
];
|
|
$this->actingAs($owner)->postJson('/investidor/terra-duat', ['payload' => $payload])->assertCreated();
|
|
$case = LandAssistanceCase::firstOrFail();
|
|
$this->postJson("/investidor/terra-duat/{$case->id}/solicitar-apoio", ['version' => 1, 'payload' => $payload])
|
|
->assertUnprocessable()->assertJsonValidationErrors(['payload.contact_consent']);
|
|
$this->assertDatabaseCount('interest_requests', 0);
|
|
}
|
|
|
|
public function test_phone_only_support_is_saved_without_a_synthetic_email(): void
|
|
{
|
|
$owner = User::factory()->create(['email_verified_at' => now()]);
|
|
$payload = [
|
|
'support_kind' => 'investment', 'request_description' => 'Preciso de orientação sobre a preparação do pedido.',
|
|
'applicant_category' => 'individual', 'full_name' => 'Pessoa de Teste', 'email' => '', 'phone' => '840000000',
|
|
'preferred_contact' => 'phone', 'area_status' => 'identified', 'purpose' => 'Projecto exploratório',
|
|
'contact_consent' => true, 'truth_declaration' => true,
|
|
];
|
|
$this->actingAs($owner)->postJson('/investidor/terra-duat', ['payload' => $payload])->assertCreated();
|
|
$case = LandAssistanceCase::firstOrFail();
|
|
|
|
$this->postJson("/investidor/terra-duat/{$case->id}/solicitar-apoio", ['version' => 1, 'payload' => $payload])
|
|
->assertAccepted();
|
|
$interest = InterestRequest::firstOrFail();
|
|
$this->assertNull($interest->email);
|
|
$this->assertSame('840000000', $interest->phone);
|
|
$this->assertSame('support_requested', $case->fresh()->status);
|
|
}
|
|
|
|
public function test_email_nullable_migration_can_be_reversed_when_no_email_is_missing(): void
|
|
{
|
|
$migration = require base_path('database/migrations/2026_10_03_210000_make_interest_request_email_nullable.php');
|
|
|
|
$migration->down();
|
|
$this->assertSame('NO', DB::table('information_schema.columns')
|
|
->where('table_schema', 'public')->where('table_name', 'interest_requests')->where('column_name', 'email')
|
|
->value('is_nullable'));
|
|
|
|
$migration->up();
|
|
$this->assertSame('YES', DB::table('information_schema.columns')
|
|
->where('table_schema', 'public')->where('table_name', 'interest_requests')->where('column_name', 'email')
|
|
->value('is_nullable'));
|
|
}
|
|
|
|
public function test_email_nullable_migration_refuses_rollback_with_phone_only_requests(): void
|
|
{
|
|
DB::table('interest_requests')->insert([
|
|
'reference' => 'AP-QA-PHONE-ONLY-ROLLBACK', 'full_name' => 'Pessoa de Teste', 'email' => null,
|
|
'phone' => '840000000', 'investor_type' => 'individual', 'country' => 'MZ',
|
|
'sector_interest' => 'Terra e DUAT', 'message' => 'Pedido sintético de teste.',
|
|
'privacy_consent' => true, 'status' => 'received', 'created_at' => now(), 'updated_at' => now(),
|
|
]);
|
|
$migration = require base_path('database/migrations/2026_10_03_210000_make_interest_request_email_nullable.php');
|
|
|
|
try {
|
|
$migration->down();
|
|
$this->fail('Rollback must preserve phone-only requests.');
|
|
} catch (\RuntimeException $exception) {
|
|
$this->assertStringContainsString('phone-only', $exception->getMessage());
|
|
}
|
|
|
|
$this->assertSame('YES', DB::table('information_schema.columns')
|
|
->where('table_schema', 'public')->where('table_name', 'interest_requests')->where('column_name', 'email')
|
|
->value('is_nullable'));
|
|
}
|
|
}
|