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

API Response Assertion Macros (for ya'll) #87

Open
zlanich opened this issue Apr 29, 2018 · 0 comments
Open

API Response Assertion Macros (for ya'll) #87

zlanich opened this issue Apr 29, 2018 · 0 comments

Comments

@zlanich
Copy link
Collaborator

zlanich commented Apr 29, 2018

Hey all! After going through this course, I still had issues with asserting API JSON responses in an expressive way given the way Laravel's TestResponse helpers work, so I created a few macros that helped, so I'm posting them here if anyone wants to use them. Feel free to suggest improvements 😄

My main issues where:

  1. $this->assertJsonMissing(), etc doesn't work with nested keys - ie. Laravel's ['data' => '...'] convention using Resource classes. There are some issues on this, but Taylor chose to leave this out of core.
  2. Asserting sort orders, etc in an expressive way, especially given # 1 above

Example Usage for a Geo-Location App:

// Not Nearby
factory(Some::class)->create(['location' => '40,-80.1111', 'some-identifier' => 1003]);

// Nearby - But created out of order distance wise (intentionally)
factory(Some::class)->create(['location' => '40,-80.0002', 'some-identifier' => 1001]);
factory(Some::class)->create(['location' => '40,-80.0003', 'some-identifier' => 1002]);
factory(Some::class)->create(['location' => '40,-80.0001', 'some-identifier' => 1000]);
$userLocation = '40,-80.0000'; // lat, long

$response = $this->json('GET', "/locations?near={$userLocation}");

$response->assertHasWhere('some-identifier', [1000, 1001, 1002]);
$response->assertMissingWhere('some-identifier', [1003]);
$response->assertSort('some-identifier', [1000, 1001, 1002]);

Macros:

/**
 * Asserts response has objects with the given key/value(s)
 */
TestResponse::macro('assertHasWhere', function (string $key, $values, bool $strict = false)
{
    $content = $this->decodeResponseJson();
    $content = $content['data'] ?? $content;

    $values = is_array($values) ? $values : [$values];

    $method = $strict ? 'whereInStrict' : 'whereIn';
    PHPUnit::assertTrue((collect($content)->$method($key, $values)->count() === sizeof($values)), 'Failed to assert json response contained all values');

    return $this;
});

/**
 * Asserts response has objects sorted in the specified order by key
 */
TestResponse::macro('assertSort', function (string $key, array $values, bool $strict = false)
{
    $content = $this->decodeResponseJson();
    $content = $content['data'] ?? $content;

    $method = $strict ? 'whereInStrict' : 'whereIn';
    $contentSubset = collect($content)->$method($key, $values)->pluck($key)->all();
    PHPUnit::assertEquals($values, $contentSubset, 'Failed to assert sorted');

    return $this;
});

/**
 * Asserts response is missing objects with the given key/value(s)
 */
TestResponse::macro('assertMissingWhere', function (string $key, $values, bool $strict = false)
{
    $content = $this->decodeResponseJson();
    $content = $content['data'] ?? $content;

    $values = is_array($values) ? $values : [$values];

    $method = $strict ? 'whereInStrict' : 'whereIn';
    PHPUnit::assertTrue((collect($content)->$method($key, $values)->count() === 0), 'Failed to assert json response was missing all values');

    return $this;
});

I toyed with just added an $assertSort flag to assertHasWhere, along with a few other approaches, but the error messages were a bit convoluted, so I split them out into separate macros.

Enjoy!

P.S. I couldn't find a better place to post these, so if an Issue isn't the best place, let me know.

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

No branches or pull requests

1 participant