resolveApiUser('api-company-settings-' . uniqid() . '@example.com', true); $this->authenticateApiUser($user); CompanySettings::set('S_COMPANY_NAME', 'ACME Corp API', $user->company_id); CompanySettings::set(SettingsHelper::S_COMPANY_SOFTPHONE_AUTO_ANSWER_TIMEOUT, '3', $user->company_id); CompanySettings::set(SettingsHelper::S_COMPANY_WHATSAPP_COUNTRY_CODE, '968', $user->company_id); $this->seedCountries($user->company_id); $response = $this->get('/api/settings/company-data'); $response->assertStatus(200); $payload = json_decode($response->getContent(), true); $this->assertTrue($payload['status']); $settings = $payload['data']['settings'] ?? null; $this->assertTrue(is_array($settings)); $expectedKeys = [ 'company_name', 'address', 'city', 'state', 'postal_code', 'country_id', 'phone', 'fax', 'website', 'vat_id', 'companyDomain', 'userLimit', 'multiCompany', 's3Storage', 'autoAnswer', 'autoAnswerTimeout', 'whatsAppCountryCode', 'softphoneAutoHold', 'softphonePauseEnableDnd', 'softphoneSurveyTransfer', 'dndEnabledForAll', 'companyServerType', 'smsApiLink', 'smsSender', 'smsUser', 'smsPass', 'pbxWssUrl', 'pbxWssPort', 'externalProfileUrl', 'missedCallsAlertEmail', 'missedCallsAlertMinutes', 'web_hook_link', 'call_throw_did', ]; $this->assertCount(count($expectedKeys), $settings); $byKey = []; foreach ($settings as $entry) { $this->assertArrayHasKey('key', $entry); $this->assertArrayHasKey('value', $entry); $this->assertArrayNotHasKey('label', $entry); $this->assertArrayNotHasKey('type', $entry); $byKey[$entry['key']] = $entry; } foreach ($expectedKeys as $key) { $this->assertArrayHasKey($key, $byKey, "Setting '{$key}' missing from response"); } $this->assertSame('ACME Corp API', $byKey['company_name']['value']); $this->assertIsBool($byKey['multiCompany']['value']); $this->assertIsBool($byKey['dndEnabledForAll']['value']); $this->assertIsBool($byKey['softphonePauseEnableDnd']['value']); $this->assertSame(3, $byKey['autoAnswerTimeout']['value']); $this->assertSame('968', $byKey['whatsAppCountryCode']['value']); $this->assertArrayHasKey('options', $byKey['country_id']); $this->assertNotEmpty($byKey['country_id']['options']); $this->assertSame('Egypt', $byKey['country_id']['options'][0]['name']); $this->assertArrayHasKey('options', $byKey['whatsAppCountryCode']); $this->assertNotEmpty($byKey['whatsAppCountryCode']['options']); $this->assertArrayNotHasKey('options', $byKey['company_name']); } public function test_company_data_settings_endpoint_requires_admin_settings_permission() { $user = $this->resolveApiUser('api-company-settings-no-perm-' . uniqid() . '@example.com', false); $this->authenticateApiUser($user); $response = $this->get('/api/settings/company-data'); $response->assertStatus(403); } public function test_login_response_includes_company_data_settings() { $user = $this->resolveApiUser('api-login-settings-' . uniqid() . '@example.com', false); CompanySettings::set('S_COMPANY_NAME', 'ACME Corp API', $user->company_id); CompanySettings::set(SettingsHelper::S_COMPANY_SOFTPHONE_AUTO_ANSWER_TIMEOUT, '3', $user->company_id); CompanySettings::set(SettingsHelper::S_COMPANY_WHATSAPP_COUNTRY_CODE, '968', $user->company_id); $this->seedCountries($user->company_id); $response = $this->post('/api/login', [ 'email' => $user->email, 'password' => 'secret', ]); $response->assertStatus(200); $payload = json_decode($response->getContent(), true); $this->assertTrue($payload['status']); $this->assertArrayHasKey('access_token', $payload['data']); $settings = $payload['data']['settings'] ?? null; $this->assertTrue(is_array($settings)); $this->assertNotEmpty($settings); $byKey = []; foreach ($settings as $entry) { $this->assertArrayHasKey('key', $entry); $this->assertArrayHasKey('value', $entry); $this->assertArrayNotHasKey('label', $entry); $this->assertArrayNotHasKey('type', $entry); $byKey[$entry['key']] = $entry; } $this->assertSame('ACME Corp API', $byKey['company_name']['value']); $this->assertSame(3, $byKey['autoAnswerTimeout']['value']); $this->assertSame('968', $byKey['whatsAppCountryCode']['value']); $this->assertIsBool($byKey['dndEnabledForAll']['value']); $this->assertNotEmpty($byKey['country_id']['options']); $this->assertSame('Egypt', $byKey['country_id']['options'][0]['name']); } private function seedCountries(int $companyId): void { if (!Schema::hasTable('bap_country')) { return; } DB::table('bap_country')->insert([ [ 'name' => 'Egypt', 'alpha2' => 'EG', 'is_active' => 1, 'company_id' => $companyId, 'created_at' => now(), 'updated_at' => now(), ], [ 'name' => 'Oman', 'alpha2' => 'OM', 'is_active' => 1, 'company_id' => $companyId, 'created_at' => now(), 'updated_at' => now(), ], ]); } private function resolveCompanyId() { if (!Schema::hasTable('bap_companies')) { return null; } return DB::table('bap_companies')->insertGetId([ 'name' => 'API Test Company ' . uniqid(), 'is_enabled' => 1, 'created_at' => now(), 'updated_at' => now(), ]); } private function resolveApiUser(string $email, bool $grantPermission): User { $payload = [ 'name' => 'API Company Settings User', 'email' => $email, 'password' => bcrypt('secret'), 'created_at' => now(), 'updated_at' => now(), ]; if (Schema::hasColumn('users', 'company_id')) { $payload['company_id'] = $this->resolveCompanyId(); } if (Schema::hasColumn('users', 'is_active')) { $payload['is_active'] = 1; } $userId = DB::table('users')->insertGetId($payload); $user = User::query()->findOrFail($userId); if ($grantPermission) { Permission::findOrCreate('admin.settings'); $user->givePermissionTo('admin.settings'); } return $user; } private function authenticateApiUser(User $user): void { $token = \JWTAuth::fromUser($user); if (Schema::hasColumn('users', 'jwt_token')) { DB::table('users')->where('id', $user->id)->update(['jwt_token' => $token]); $user->jwt_token = $token; } $this->withHeader('Authorization', 'Bearer ' . $token); } }