Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[9.x] Adds assertJsonIsArray and assertJsonIsObject for TestResponse #45731

Merged
merged 3 commits into from
Jan 23, 2023
Merged

[9.x] Adds assertJsonIsArray and assertJsonIsObject for TestResponse #45731

merged 3 commits into from
Jan 23, 2023

Conversation

sethsandaru
Copy link
Contributor

@sethsandaru sethsandaru commented Jan 20, 2023

Hi team,

When interacting with Collection, after several actions (like sort or filter,...), the array won't be an indexed array like before (I think most of us here would probably encounter this at least once).

And if we return the Collection immediately, it will result in a JS Object { ... }. For listing endpoints, it would be wrong and result in an error from the API consumers (frontend, mobile,...)

So to ensure we won't return the wrong data structure to the consumers, I added 2 assert methods to validate the data:

  • assertJsonIsArray
  • assertJsonIsObject

FYA: from 10.x we can use array_is_list (PHP 8.1) to check against the data since it requires PHP 8.2 and above.

Usage

$this->json('GET', 'countries')
    ->assertOk()
    ->assertJsonIsArray(); // [ {..}, {...}, ....]

$this->json('GET', 'users')
    ->assertOk()
    ->assertJsonIsArray('data'); // {'data': [...]}

$this->json('GET', 'countries/US')
    ->assertOk()
    ->assertJsonIsObject(); // {id: '...', name: '..'}

$this->json('GET', 'users/1')
    ->assertOk()
    ->assertJsonIsObject('data'); // {'data': {id: '..', name: '...'}}

PR Information

  • Implemented the methods
  • Added tests and cover all cases
  • No breaking changes - only introduces new methods

Additional information

assertJsonStructure won't help us to validate that (check TestResponseTest@testAssertJsonStructure)

The wildcard * only validates the repeating structure. It doesn't care whether our data is a JS array or JS object.

Screenshot 2023-01-20 at 10 14 01

assertJson or assertExactJson might be a good alternative, but for listing endpoints, preparing a big list of data to assert would not so fun, right?

Thanks all!

@timacdonald
Copy link
Member

I don't think this would handle empty objects / arrays well. It would just assume they are all arrays.

If the payload was...

{ "users": {} }

When you json encode that in PHP it is going to have to cast it to an object or an array based on flags.vvfg

@sethsandaru
Copy link
Contributor Author

@timacdonald Not sure if I understand you correctly.

So for Laravel Response, by default, if you pass an empty array response()->json([]) or new JsonResponse([]) => [] will be rendered => assertJsonIsArray is working correctly?

But for some cases, you wanted the users to be an object, then in your controller, you would do something like response()->json(new YourObject()); (if the object is empty => {} => assertJsonIsObject is working correctly?

@timacdonald timacdonald self-requested a review January 23, 2023 03:24
@timacdonald
Copy link
Member

@sethsandaru I was concerned about how an empty hash in PHP is JSON encoded as an empty array, but I don't think that impacts this feature, and if anything this feature actually forces users to consider that.

Sorry for my rushed comment without further testing.

@timacdonald timacdonald removed their request for review January 23, 2023 03:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants