Reputation: 2827
In my application I have a response like this:
{
"items": [
{
"id": 10,
"field": "foo"
},
{
"id": 20,
"field": "bar"
}
]
}
I need to test the content of items
and validate each id
.
I've tried many solutions but no one works, for example (this is just a kind of pseudo-code):
assertJson(fn (AssertableJson $json) =>
$json->where('items.*.id', [10, 20])
)
Is there a way to use a wildcard to pick every ID and validate using an array?
Upvotes: 1
Views: 1372
Reputation: 42725
The lack of support for testing an array of randomly ordered elements is pretty frustrating. I just came across this problem and solved it by looping over the array of things I was looking for and making sure they're all in the response data. Fortunately there's an AssertableJson::toArray()
method which allows access to the JSON directly.
<?php
namespace Tests\Feature;
use Illuminate\Testing\Fluent\AssertableJson;
use Symfony\Component\HttpFoundation\Response;
use Tests\TestCase;
class ReportingTest extends TestCase
{
public function testReportData(): void
{
$expected_ids = [10, 20];
$this->getJson(route("report.view"))
->assertStatus(Response::HTTP_OK)
->assertJsonIsObject()
->assertJson(function (AssertableJson $response) use ($expected_ids) {
$response
->has("items", 2)
->has("items", function (AssertableJson $items) use ($expected_ids) {
$item_ids = array_column($items->toArray(), "id");
foreach ($expected_ids as $id) {
$this->assertContains($id, $item_ids);
}
});
});
}
}
Upvotes: 2
Reputation: 7594
You can use array_filter
:
$idArray = [10, 20];
$myObj = json_decode($json); // Turn JSON to obj
$items = $myObj["items"]; // Get items from object
// Filter the items for items that aren't in the ID list
$invalidItems = array_filter($items, function ($el) {
// If the item has an id which isn't in the array, return true
return !in_array($el["id"], $idArray);
});
// This returns true if we found 0 items with IDs not in the ID list
return $invalidItems == [];
You can similarly use array_map
to simplify your array, then compare it to your ID array:
$myObj = json_decode($json); // Turn JSON to obj
$items = $myObj["items"]; // Get items from object
$outIdArray = array_map(function($el) {
return $el["id"];
}, $items);
// Compare $outIdArray to [10, 20]
Upvotes: 0