Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<?php
namespace Tests\Asserts;
use App\Domain\Stock\Enum\StocktakingStatus;
use App\Domain\Stock\Resource\StorageBatchResource;
use Carbon\Carbon;
use DateTimeInterface;
use Illuminate\Testing\Fluent\AssertableJson;
use OutOfBoundsException;
class AssertableJsonResourceAssertions
{
protected const RESOURCES = [
StorageBatchResource::class => 'assertStorageBatchResource',
];
public static function assertResource(AssertableJson $json, string $resource): void
{
if (!array_key_exists($resource, self::RESOURCES)) {
throw new OutOfBoundsException();
}
call_user_func(
self::class.'::'.self::RESOURCES[$resource],
$json
);
}
public static function assertResourceCollection(AssertableJson $json, string $resource): void
{
if (!array_key_exists($resource, self::RESOURCES)) {
throw new OutOfBoundsException();
}
$json->each(static function (AssertableJson $json) use ($resource): void {
self::assertResource($json, $resource);
});
}
protected static function assertStorageBatchResource(AssertableJson $json): bool
{
$json
->whereType('sku', 'string')
->whereType('best_before_date', ['string', 'null'])
->where('best_before_date', static function (?string $date): bool {
return $date === null || Carbon::canBeCreatedFromFormat($date, DateTimeInterface::RFC3339);
})
->whereType('stock', 'integer')
->where('stock', static function (int $stock): bool {
return $stock >= 0;
})
->whereType('packing_position_name', 'string')
->whereType('approved_by', ['integer', 'null'])
->whereType('approved_at', ['string', 'null'])
->where('approved_at', static function (?string $date): bool {
return $date === null || Carbon::canBeCreatedFromFormat($date, DateTimeInterface::RFC3339);
})
->whereType('stocktaking_requested_at', ['string', 'null'])
->where('stocktaking_requested_at', static function (?string $date): bool {
return $date === null || Carbon::canBeCreatedFromFormat($date, DateTimeInterface::RFC3339);
})
->whereType('stocktaking_status', 'string')
->where('stocktaking_status', static function (string $status): bool {
return in_array($status, StocktakingStatus::toValues(), true);
});
return true;
}
}
<?php
namespace Tests\Providers;
use Closure;
use Illuminate\Support\ServiceProvider;
use Illuminate\Testing\Fluent\AssertableJson;
use PHPUnit\Framework\Assert as PHPUnit;
use Tests\Asserts\AssertableJsonResourceAssertions;
class AssertableJsonResourceProvider extends ServiceProvider
{
public function boot(): void
{
/**
* @link https://github.com/laravel/framework/releases/tag/v8.59.0
* @link https://github.com/laravel/framework/commit/389cd2b9a4075750661d37a1691ecb074c7cfdae
*/
AssertableJson::macro('each', function (Closure $callback): AssertableJson {
/** @var AssertableJson $this */
$props = $this->prop();
$path = $this->dotPath();
PHPUnit::assertNotEmpty($props, $path === ''
? 'Cannot scope directly onto each element of the root level because it is empty.'
: sprintf('Cannot scope directly onto each element of property [%s] because it is empty.', $path)
);
foreach (array_keys($props) as $key) {
$this->interactsWith($key);
$this->scope($key, $callback);
}
return $this;
});
AssertableJson::macro('assertResource', function (string $resource): AssertableJson {
/* @var AssertableJson $this */
AssertableJsonResourceAssertions::assertResource($this, $resource);
return $this;
});
AssertableJson::macro('assertResourceCollection', function (string $resource): AssertableJson {
/* @var AssertableJson $this */
AssertableJsonResourceAssertions::assertResourceCollection($this, $resource);
return $this;
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment