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

[WIP] Feature | V3 - Request validator #291

Closed
14 changes: 14 additions & 0 deletions src/Contracts/Testing/ValidatorCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Saloon\Contracts\Testing;

interface ValidatorCheck
{

public function valid(): bool;

public function message(): string;

}
36 changes: 36 additions & 0 deletions src/Helpers/Testing/Checks/BodyEqualsCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Saloon\Helpers\Testing\Checks;

use Closure;
use Illuminate\Support\Arr;
use Saloon\Traits\Makeable;
use Saloon\Http\PendingRequest;
use Saloon\Contracts\Testing\ValidatorCheck;

class BodyEqualsCheck implements ValidatorCheck
{
use Makeable;

public function __construct(protected PendingRequest $actual, protected string| Closure $path, protected mixed $expected = null)
{
}

public function valid(): bool
{
$body = json_decode((string) $this->actual->body(), true);

Check failure on line 23 in src/Helpers/Testing/Checks/BodyEqualsCheck.php

View workflow job for this annotation

GitHub Actions / phpstan

Cannot cast Saloon\Contracts\Body\BodyRepository|null to string.

if ($this->path instanceof Closure) {
return ($this->path)($body);
}

return Arr::get($body, $this->path) === $this->expected;
}

public function message(): string
{
return 'The body did not contain the expected value';
}
}
36 changes: 36 additions & 0 deletions src/Helpers/Testing/Checks/EndpointContainsCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Saloon\Helpers\Testing\Checks;

use Closure;
use Saloon\Traits\Makeable;
use Saloon\Http\PendingRequest;
use Saloon\Contracts\Testing\ValidatorCheck;

class EndpointContainsCheck implements ValidatorCheck
{
use Makeable;

public function __construct(protected PendingRequest $actual, protected Closure|string $expected)
{

}

public function valid(): bool
{
$path = $this->actual->createPsrRequest()->getUri()->getPath();

if ($this->expected instanceof Closure) {
return ($this->expected)($path);
}

return str_contains($path, $this->expected);
}

public function message(): string
{
return "The url did not contain '{$this->expected}'";

Check failure on line 34 in src/Helpers/Testing/Checks/EndpointContainsCheck.php

View workflow job for this annotation

GitHub Actions / phpstan

Part $this->expected (Closure|string) of encapsed string cannot be cast to string.
}
}
29 changes: 29 additions & 0 deletions src/Helpers/Testing/Checks/EndpointEndsWithCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Saloon\Helpers\Testing\Checks;

use Saloon\Traits\Makeable;
use Saloon\Http\PendingRequest;
use Saloon\Contracts\Testing\ValidatorCheck;

class EndpointEndsWithCheck implements ValidatorCheck
{
use Makeable;

public function __construct(protected PendingRequest $actual, protected string $expected)
{

}

public function valid(): bool
{
return str_ends_with($this->actual->createPsrRequest()->getUri()->getPath(), $this->expected);
}

public function message(): string
{
return "The url did not end with '{$this->expected}'";
}
}
29 changes: 29 additions & 0 deletions src/Helpers/Testing/Checks/EndpointStartsWithCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Saloon\Helpers\Testing\Checks;

use Saloon\Traits\Makeable;
use Saloon\Http\PendingRequest;
use Saloon\Contracts\Testing\ValidatorCheck;

class EndpointStartsWithCheck implements ValidatorCheck
{
use Makeable;

public function __construct(protected PendingRequest $actual, protected string $expected)
{

}

public function valid(): bool
{
return str_starts_with($this->actual->createPsrRequest()->getUri()->getPath(), $this->expected);
}

public function message(): string
{
return "The url did not start with '{$this->expected}'";
}
}
29 changes: 29 additions & 0 deletions src/Helpers/Testing/Checks/InstanceOfCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Saloon\Helpers\Testing\Checks;

use Saloon\Traits\Makeable;
use Saloon\Http\PendingRequest;
use Saloon\Contracts\Testing\ValidatorCheck;

class InstanceOfCheck implements ValidatorCheck
{
use Makeable;

public function __construct(protected PendingRequest $actual, protected string $expected)
{

}

public function valid(): bool
{
return $this->actual->getRequest() instanceof $this->expected;
}

public function message(): string
{
return "The request is not an instance of {$this->expected}";
}
}
36 changes: 36 additions & 0 deletions src/Helpers/Testing/Checks/QueryEqualsCheck.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Saloon\Helpers\Testing\Checks;

use Closure;
use Illuminate\Support\Arr;
use Saloon\Traits\Makeable;
use Saloon\Http\PendingRequest;
use Saloon\Contracts\Testing\ValidatorCheck;

class QueryEqualsCheck implements ValidatorCheck
{
use Makeable;

public function __construct(protected PendingRequest $actual, protected string| Closure $path, protected mixed $expected = null)
{
}

public function valid(): bool
{
$query = $this->actual->query();

if ($this->path instanceof Closure) {
return ($this->path)($query);
}

return Arr::get($query->all(), $this->path) === $this->expected;
}

public function message(): string
{
return 'The query parameters did not contain the expected value';
}
}
123 changes: 123 additions & 0 deletions src/Helpers/Testing/RequestValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?php

declare(strict_types=1);

namespace Saloon\Helpers\Testing;

use Closure;
use Saloon\Http\PendingRequest;
use Saloon\Contracts\Testing\ValidatorCheck;
use Saloon\Helpers\Testing\Checks\BodyEqualsCheck;
use Saloon\Helpers\Testing\Checks\InstanceOfCheck;
use Saloon\Helpers\Testing\Checks\QueryEqualsCheck;
use Saloon\Helpers\Testing\Checks\EndpointContainsCheck;
use Saloon\Helpers\Testing\Checks\EndpointEndsWithCheck;
use Saloon\Helpers\Testing\Checks\EndpointStartsWithCheck;

class RequestValidator
{

/**
* @var array<ValidatorCheck>
*/
protected array $checks = [];

public function __construct(protected PendingRequest $request)
{

}

public static function for(PendingRequest $request): self
{
return new static($request);
}

public function instanceOf(string $expected): self
{
$check = InstanceOfCheck::make(
$this->request,
$expected
);

$this->checks[] = $check;

return $this;
}

public function endpointStartsWith(string $expected): self
{
$check = EndpointStartsWithCheck::make(
$this->request,
$expected
);

$this->checks[] = $check;

return $this;
}

public function endpointEndsWith(string $expected): self
{
$check = EndpointEndsWithCheck::make(
$this->request,
$expected
);

$this->checks[] = $check;

return $this;
}

public function endpointContains(Closure|string $expected): self
{
$check = EndpointContainsCheck::make(
$this->request,
$expected
);

$this->checks[] = $check;

return $this;
}

public function bodyEquals(string|Closure $path, mixed $expected = null): self
{
$check = BodyEqualsCheck::make(
$this->request,
$path,
$expected
);

$this->checks[] = $check;

return $this;
}

public function queryEquals(string|Closure $path, mixed $expected = null): self
{
$check = QueryEqualsCheck::make(
$this->request,
$path,
$expected
);

$this->checks[] = $check;

return $this;
}

public function validate(): bool
{
return collect($this->checks)
->every(fn (ValidatorCheck $check) => $check->valid());
}

public function errors(): array

Check failure on line 115 in src/Helpers/Testing/RequestValidator.php

View workflow job for this annotation

GitHub Actions / phpstan

Method Saloon\Helpers\Testing\RequestValidator::errors() return type has no value type specified in iterable type array.
{
return collect($this->checks)
->filter(fn (ValidatorCheck $check) => ! $check->valid())
->map(fn (ValidatorCheck $check) => $check->message())
->toArray();
}

}