['id' => 1, 'description' => 'A']]; $this->assertSame(['id' => 1, 'description' => 'A'], RepositoryArrayHelper::unwrap($row, 'tenants')); } public function testUnwrapReturnsNullForMissingKey(): void { $row = ['other' => ['id' => 1]]; $this->assertNull(RepositoryArrayHelper::unwrap($row, 'tenants')); } public function testUnwrapReturnsNullForNullInput(): void { $this->assertNull(RepositoryArrayHelper::unwrap(null, 'tenants')); } public function testUnwrapReturnsNullForEmptyArray(): void { $this->assertNull(RepositoryArrayHelper::unwrap([], 'tenants')); } // --- unwrapList --- public function testUnwrapListExtractsRows(): void { $rows = [ ['roles' => ['id' => 1, 'description' => 'Admin']], ['roles' => ['id' => 2, 'description' => 'User']], ]; $result = RepositoryArrayHelper::unwrapList($rows, 'roles'); $this->assertCount(2, $result); $this->assertSame(1, $result[0]['id']); $this->assertSame(2, $result[1]['id']); } public function testUnwrapListSkipsNonArrayEntries(): void { $rows = [ ['roles' => ['id' => 1]], ['roles' => null], ['other' => ['id' => 3]], ]; $result = RepositoryArrayHelper::unwrapList($rows, 'roles'); $this->assertCount(1, $result); $this->assertSame(1, $result[0]['id']); } public function testUnwrapListReturnsEmptyForNonArray(): void { $this->assertSame([], RepositoryArrayHelper::unwrapList(null, 'roles')); $this->assertSame([], RepositoryArrayHelper::unwrapList(false, 'roles')); } public function testUnwrapListReturnsEmptyForEmptyArray(): void { $this->assertSame([], RepositoryArrayHelper::unwrapList([], 'roles')); } // --- extractIds --- public function testExtractIdsFromWrappedRows(): void { $rows = [ ['tenants' => ['id' => 1]], ['tenants' => ['id' => 2]], ['tenants' => ['id' => 3]], ]; $this->assertSame([1, 2, 3], RepositoryArrayHelper::extractIds($rows, 'tenants')); } public function testExtractIdsDeduplicates(): void { $rows = [ ['tenants' => ['id' => 1]], ['tenants' => ['id' => 1]], ['tenants' => ['id' => 2]], ]; $this->assertSame([1, 2], RepositoryArrayHelper::extractIds($rows, 'tenants')); } public function testExtractIdsFallsBackToRowItself(): void { $rows = [ ['id' => 5], ['id' => 6], ]; $this->assertSame([5, 6], RepositoryArrayHelper::extractIds($rows, 'missing_key')); } public function testExtractIdsWithCustomIdField(): void { $rows = [ ['user_roles' => ['role_id' => 10]], ['user_roles' => ['role_id' => 20]], ]; $this->assertSame([10, 20], RepositoryArrayHelper::extractIds($rows, 'user_roles', 'role_id')); } public function testExtractIdsSkipsMissingIdField(): void { $rows = [ ['tenants' => ['id' => 1]], ['tenants' => ['name' => 'no id']], ]; $this->assertSame([1], RepositoryArrayHelper::extractIds($rows, 'tenants')); } public function testExtractIdsReturnsEmptyForNonArray(): void { $this->assertSame([], RepositoryArrayHelper::extractIds(null, 'tenants')); $this->assertSame([], RepositoryArrayHelper::extractIds(false, 'tenants')); } public function testExtractIdsReturnsEmptyForEmptyArray(): void { $this->assertSame([], RepositoryArrayHelper::extractIds([], 'tenants')); } // --- sanitizePositiveIds --- public function testSanitizePositiveIdsFiltersAndDeduplicates(): void { $this->assertSame([1, 3, 5], RepositoryArrayHelper::sanitizePositiveIds([1, 3, 5, 1, 3])); } public function testSanitizePositiveIdsRemovesZeroAndNegative(): void { $this->assertSame([2, 4], RepositoryArrayHelper::sanitizePositiveIds([0, -1, 2, -3, 4])); } public function testSanitizePositiveIdsCastsToInt(): void { $this->assertSame([1, 2, 3], RepositoryArrayHelper::sanitizePositiveIds(['1', '2', '3'])); } public function testSanitizePositiveIdsReturnsEmptyForEmpty(): void { $this->assertSame([], RepositoryArrayHelper::sanitizePositiveIds([])); } public function testSanitizePositiveIdsReturnsEmptyForAllInvalid(): void { $this->assertSame([], RepositoryArrayHelper::sanitizePositiveIds([0, -1, -2])); } public function testSanitizePositiveIdsReindexes(): void { $result = RepositoryArrayHelper::sanitizePositiveIds([0, 0, 5]); $this->assertSame([5], $result); $this->assertSame(0, array_key_first($result)); } // --- flattenRow --- public function testFlattenRowMergesNestedTableArrays(): void { $row = [ 'api_audit_log' => ['id' => 1, 'request_id' => 'abc'], 'users' => ['display_name' => 'Alice'], 'tenants' => ['description' => 'Tenant A'], ]; $this->assertSame( [ 'id' => 1, 'request_id' => 'abc', 'display_name' => 'Alice', 'description' => 'Tenant A', ], RepositoryArrayHelper::flattenRow($row) ); } public function testFlattenRowKeepsTopLevelScalarValues(): void { $row = [ 'status' => 'ok', 'count' => 3, ]; $this->assertSame(['status' => 'ok', 'count' => 3], RepositoryArrayHelper::flattenRow($row)); } public function testFlattenRowReturnsEmptyForNonArray(): void { $this->assertSame([], RepositoryArrayHelper::flattenRow(null)); $this->assertSame([], RepositoryArrayHelper::flattenRow(false)); $this->assertSame([], RepositoryArrayHelper::flattenRow('text')); } }