Files
City10/tests/Feature/CitySocialTest.php
T
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

132 lines
4.2 KiB
PHP
Executable File

<?php
namespace Tests\Feature;
use App\Models\Character;
use App\Models\CharacterMessage;
use App\Models\Relationship;
use App\Models\User;
use Database\Seeders\CityWorldSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
/**
* Social graph and character chat coverage.
*/
class CitySocialTest extends TestCase
{
use RefreshDatabase;
/**
* Seed world fixtures.
*/
protected function setUp(): void
{
parent::setUp();
$this->seed(CityWorldSeeder::class);
}
/**
* Friendship request flows from pending to accepted.
*/
public function test_friend_request_and_accept(): void
{
$a = Character::factory()->create();
$b = Character::factory()->create();
$userA = User::factory()->create(['status' => User::STATUS_ACTIVE, 'is_active' => true]);
$a->user_id = $userA->id;
$a->save();
$this->actingAs($userA)
->postJson('/city/social/friend', ['character_id' => $b->id])
->assertOk();
$rel = Relationship::where('type', Relationship::TYPE_FRIEND)
->where('character_a_id', $a->id)
->where('character_b_id', $b->id)
->first();
$this->assertNotNull($rel);
$this->assertSame(Relationship::STATUS_PENDING, $rel->status);
$userB = User::factory()->create(['status' => User::STATUS_ACTIVE, 'is_active' => true]);
$b->user_id = $userB->id;
$b->save();
$this->actingAs($userB)
->postJson('/city/social/accept-friend', ['relationship_id' => $rel->id])
->assertOk();
$this->assertSame(Relationship::STATUS_ACCEPTED, $rel->fresh()->status);
}
/**
* Marriage requires an accepted friendship.
*/
public function test_marry_requires_friendship(): void
{
$userA = User::factory()->create(['status' => User::STATUS_ACTIVE, 'is_active' => true]);
$a = Character::ensureForUser($userA);
$b = Character::factory()->create(['city_id' => $a->city_id]);
$this->actingAs($userA)
->postJson('/city/social/marry', ['character_id' => $b->id])
->assertStatus(422);
}
/**
* Spouses can have an NPC child linked to both parents.
*/
public function test_child_creates_npc_character(): void
{
$userA = User::factory()->create(['status' => User::STATUS_ACTIVE, 'is_active' => true]);
$a = Character::ensureForUser($userA);
$b = Character::factory()->create(['city_id' => $a->city_id, 'name' => 'Parceiro']);
Relationship::create([
'character_a_id' => $a->id,
'character_b_id' => $b->id,
'type' => Relationship::TYPE_FRIEND,
'status' => Relationship::STATUS_ACCEPTED,
]);
Relationship::create([
'character_a_id' => $a->id,
'character_b_id' => $b->id,
'type' => Relationship::TYPE_SPOUSE,
'status' => Relationship::STATUS_ACCEPTED,
]);
$before = Character::count();
$this->actingAs($userA)
->postJson('/city/social/child', ['character_id' => $b->id])
->assertOk();
$this->assertSame($before + 1, Character::count());
$child = Character::orderByDesc('id')->first();
$this->assertNull($child->user_id);
$this->assertSame(2, Relationship::where('type', Relationship::TYPE_PARENT_CHILD)
->where('character_a_id', $child->id)->count());
}
/**
* Messages persist between characters.
*/
public function test_character_chat_persists(): void
{
$userA = User::factory()->create(['status' => User::STATUS_ACTIVE, 'is_active' => true]);
$a = Character::ensureForUser($userA);
$b = Character::factory()->create(['city_id' => $a->city_id]);
$this->actingAs($userA)
->postJson("/city/messages/{$b->id}", ['body' => 'Olá vizinho!'])
->assertOk();
$this->assertSame(1, CharacterMessage::count());
$this->actingAs($userA)
->getJson("/city/messages/{$b->id}")
->assertOk()
->assertJsonPath('me', $a->id)
->assertJsonPath('messages.0.body', 'Olá vizinho!');
}
}