Files
City10/tests/Feature/CityExpansionTest.php
marcocosta10000 79ce2a1825 feat(world): add persistent citizen simulation with needs, jobs, and social features
- Adds Character model with survival needs (hunger, thirst, energy) and state machine
- Implements city:tick world ticker for offline progression every minute
- Adds city territory expansion and building construction system
- Introduces job economy, inventory, and transaction audit trail
- Adds social graph (friends, marriage, children) and character chat
- Implements admin approval workflow for new registrations
- Adds hospital admission system for traffic accidents
- Includes comprehensive feature tests and world seeders
2026-10-17 21:46:23 -03:00

110 lines
3.2 KiB
PHP
Executable File

<?php
namespace Tests\Feature;
use App\Models\City;
use App\Models\LegalDocument;
use App\Models\User;
use App\Models\UserConsent;
use Database\Seeders\CityWorldSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
/**
* Admin territory expansion and multi-city creation.
*/
class CityExpansionTest extends TestCase
{
use RefreshDatabase;
/**
* Seed world fixtures.
*/
protected function setUp(): void
{
parent::setUp();
$this->seed(CityWorldSeeder::class);
$this->admin = User::factory()->admin()->create();
foreach (LegalDocument::where('is_current', true)->pluck('id') as $docId) {
UserConsent::create([
'user_id' => $this->admin->id,
'legal_document_id' => $docId,
'accepted_at' => now(),
'ip_address' => '127.0.0.1',
'user_agent' => 'phpunit',
'source' => 'web_form',
]);
}
$this->actingAs($this->admin);
}
protected User $admin;
/**
* Admin can create a new city with its own bounds.
*/
public function test_create_city(): void
{
$before = City::count();
$this->post(route('admin.cities.store'), ['name' => 'Nova Cidade'])
->assertRedirect(route('admin.cities.index'));
$this->assertSame($before + 1, City::count());
$city = City::where('name', 'Nova Cidade')->first();
$this->assertNotNull($city);
$this->assertFalse($city->is_active);
$this->assertSame(-80.0, $city->bounds_min_x);
$this->assertSame(80.0, $city->bounds_max_x);
}
/**
* Expanding a city grows its maximum bounds by one grid step.
*/
public function test_expand_city_bounds(): void
{
$city = City::where('slug', 'city10')->firstOrFail();
$beforeMax = $city->bounds_max_x;
$this->post(route('admin.cities.expand', $city))
->assertRedirect(route('admin.cities.index'));
$city->refresh();
$this->assertSame($beforeMax + 40, $city->bounds_max_x);
$this->assertSame(1, $city->expansions);
}
/**
* Expansion is capped to protect map generation.
*/
public function test_expand_capped(): void
{
$city = City::where('slug', 'city10')->firstOrFail();
$city->forceFill(['expansions' => City::MAX_EXPANSIONS])->save();
$this->from(route('admin.cities.index'))
->post(route('admin.cities.expand', $city))
->assertSessionHasErrors('city');
}
/**
* City layout for a second city uses its own bounds.
*/
public function test_city_data_for_second_city(): void
{
$other = City::create([
'name' => 'Cidade B',
'slug' => 'cidade-b',
'bounds_min_x' => 0,
'bounds_max_x' => 120,
'bounds_min_z' => 0,
'bounds_max_z' => 80,
'is_active' => false,
'expansions' => 0,
]);
$response = $this->getJson('/city/data?city=cidade-b');
$response->assertOk()->assertJsonPath('city.slug', 'cidade-b');
$this->assertNotEmpty($response->json('layout.roads'));
}
}