Skip to content

[Bug]: Fakeable trait incorrectly merges array properties causing contaminated test responses #581

Open
@bartsome

Description

@bartsome

Description

When I was using CreateResponse::fake() to create test fixtures for response api, I've noticed the Fakeable trait's buildAttributes method improperly merges indexed arrays like output from the default fixtures with the provided override data, resulting in unexpected content in test responses.

Steps To Reproduce

// Create a fake response with specific output
$response = CreateResponse::fake([
    'output' => [
        [
            'type' => 'message',
            'id' => 'msg_1',
            'role' => 'assistant',
            'status' => 'completed',
            'content' => [
                [
                    'type' => 'output_text',
                    'text' => 'This is a test response',
                    'annotations' => [],
                ],
            ],
        ],
    ],
]);

// Actual output contains both the test data AND data from CreateResponseFixture.php
// Unexpected output like: "This is a test responseAs of today, March 9, 2025, one notable positive news story..."

OpenAI PHP Client Version

v0.13.0

PHP Version

8.4.0

Notes

Cursor suggested solution:

private static function buildAttributes(array $original, array $override): array
{
    $new = [];

    foreach ($original as $key => $entry) {
        // Check if this is an array that should be replaced entirely rather than merged
        if (isset($override[$key]) && is_array($entry) && is_array($override[$key]) && 
            (in_array($key, ['output', 'tools', 'annotations']) || isset($override[$key][0]))) {
            // For arrays of objects (indexed arrays), replace entirely instead of merging
            $new[$key] = $override[$key];
        } else {
            // For other arrays, continue with recursive merging
            $new[$key] = is_array($entry) ?
                self::buildAttributes($entry, $override[$key] ?? []) :
                $override[$key] ?? $entry;
        }
        unset($override[$key]);
    }

    // Add any remaining overrides
    foreach ($override as $key => $value) {
        $new[$key] = $value;
    }

    return $new;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions