assertArrayHasKey('name', $result); $this->assertArrayHasKey('available', $result); $this->assertArrayHasKey('reserved', $result); $this->assertArrayHasKey('fqdn', $result); $this->assertEquals('testname123.lthn', $result['fqdn']); } public function test_invalid_name_returns_unavailable(): void { $result = CheckAvailability::run('AB'); $this->assertFalse($result['available']); } public function test_submit_claim_creates_record(): void { $claim = SubmitClaim::run([ 'name' => 'claimtest', 'email' => 'test@example.com', ]); $this->assertInstanceOf(NameClaim::class, $claim); $this->assertEquals('claimtest', $claim->name); $this->assertEquals('pending', $claim->status); $this->assertNotEmpty($claim->claim_id); $this->assertEquals(12, strlen($claim->claim_id)); $this->assertDatabaseHas('name_claims', [ 'name' => 'claimtest', 'email' => 'test@example.com', 'status' => 'pending', ]); } public function test_submit_claim_logs_activity(): void { SubmitClaim::run([ 'name' => 'actlogtest', 'email' => 'log@example.com', ]); $this->assertDatabaseHas('name_activity', [ 'name' => 'actlogtest', 'event' => 'claimed', ]); } public function test_duplicate_claim_rejected(): void { SubmitClaim::run([ 'name' => 'dupetest1', 'email' => 'first@example.com', ]); $this->expectException(\Illuminate\Validation\ValidationException::class); SubmitClaim::run([ 'name' => 'dupetest1', 'email' => 'second@example.com', ]); } public function test_claim_with_invalid_email_rejected(): void { $this->expectException(\Illuminate\Validation\ValidationException::class); SubmitClaim::run([ 'name' => 'emailtest', 'email' => 'not-an-email', ]); } public function test_claim_with_short_name_rejected(): void { $this->expectException(\Illuminate\Validation\ValidationException::class); SubmitClaim::run([ 'name' => 'abc', 'email' => 'test@example.com', ]); } public function test_name_claim_model_scopes(): void { $pending = NameClaim::create(['name' => 'scopep1', 'email' => 'a@b.com', 'status' => 'pending', 'claim_id' => 'scpaaa']); $approved = NameClaim::create(['name' => 'scopea1', 'email' => 'a@b.com', 'status' => 'approved', 'claim_id' => 'scpbbb']); $this->assertTrue(NameClaim::pending()->where('id', $pending->id)->exists()); $this->assertTrue(NameClaim::approved()->where('id', $approved->id)->exists()); $this->assertFalse(NameClaim::pending()->where('id', $approved->id)->exists()); } public function test_name_activity_log(): void { $activity = NameActivity::log('testlog', 'registered', [ 'address' => 'iTHN...', ], '1.2.3.4'); $this->assertEquals('testlog', $activity->name); $this->assertEquals('registered', $activity->event); $this->assertNotNull($activity->ip_hash); $this->assertNotEquals('1.2.3.4', $activity->ip_hash); // Hashed $this->assertEquals(['address' => 'iTHN...'], $activity->properties); } public function test_available_endpoint_returns_json(): void { $response = $this->getJson('/v1/names/available/apiendtest'); $response->assertOk() ->assertJsonStructure(['name', 'available', 'reserved', 'fqdn']); } public function test_claim_endpoint_returns_201(): void { $response = $this->postJson('/v1/names/claim', [ 'name' => 'endpointtest', 'email' => 'endpoint@test.com', ]); $response->assertStatus(201) ->assertJsonStructure(['data' => ['claim_id', 'name', 'fqdn', 'status']]); } public function test_claim_endpoint_validates_input(): void { $response = $this->postJson('/v1/names/claim', [ 'name' => 'ab', 'email' => 'bad', ]); $response->assertStatus(422); } }