-
-
Save sidigi/34c67a75b139949656ba55d8557530a9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Tests; | |
use Illuminate\Contracts\Auth\Authenticatable; | |
use Illuminate\Foundation\Http\FormRequest; | |
use Illuminate\Validation\ValidationException; | |
use Illuminate\Validation\Validator; | |
use Symfony\Component\HttpFoundation\ParameterBag; | |
use function PHPUnit\Framework\assertFalse; | |
use function PHPUnit\Framework\assertTrue; | |
class TestFormRequest | |
{ | |
private FormRequest $request; | |
public function __construct(FormRequest $request) | |
{ | |
$this->request = $request; | |
} | |
public function validate(array $data) | |
{ | |
$this->request->request = new ParameterBag($data); | |
/** @var Validator $validator */ | |
$validator = \Closure::fromCallable(function () { | |
return $this->getValidatorInstance(); | |
})->call($this->request); | |
try { | |
$validator->validate(); | |
} catch (ValidationException $e) { | |
return new TestValidationResult($validator, $e); | |
} | |
return new TestValidationResult($validator); | |
} | |
public function by(Authenticatable $user = null) | |
{ | |
$this->request->setUserResolver(fn() => $user); | |
return $this; | |
} | |
public function withParams(array $params) | |
{ | |
foreach($params as $param => $value) { | |
$this->withParam($param, $value); | |
} | |
return $this; | |
} | |
public function withParam(string $param, $value) | |
{ | |
$this->request->route()->setParameter($param, $value); | |
return $this; | |
} | |
public function assertAuthorized() | |
{ | |
assertTrue( | |
$this->bully(fn() => $this->passesAuthorization(), $this->request), | |
'The provided user is not authorized by this request' | |
); | |
} | |
public function assertNotAuthorized() | |
{ | |
assertFalse( | |
$this->bully(fn() => $this->passesAuthorization(), $this->request), | |
'The provided user is authorized by this request' | |
); | |
} | |
private function bully(\Closure $elevatedFunction, object $targetObject) | |
{ | |
return \Closure::fromCallable($elevatedFunction)->call($targetObject); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Tests; | |
use Illuminate\Support\Arr; | |
use Illuminate\Support\Str; | |
use Illuminate\Validation\ValidationException; | |
use Illuminate\Validation\Validator; | |
use function PHPUnit\Framework\assertArrayHasKey; | |
use function PHPUnit\Framework\assertContains; | |
use function PHPUnit\Framework\assertStringContainsString; | |
use function PHPUnit\Framework\assertTrue; | |
class TestValidationResult | |
{ | |
private Validator $validator; | |
private ?ValidationException $failed; | |
public function __construct(Validator $validator, ?ValidationException $failed = null) | |
{ | |
$this->validator = $validator; | |
$this->failed = $failed; | |
} | |
public function assertPassesValidation() | |
{ | |
assertTrue($this->validator->passes(), | |
sprintf("Validation of the payload:\n%s\ndid not pass validation rules\n%s\n", | |
json_encode($this->validator->getData(), JSON_PRETTY_PRINT), | |
json_encode($this->getFailedRules(), JSON_PRETTY_PRINT) | |
) | |
); | |
return $this; | |
} | |
public function assertFailsValidation($expectedFailedRules = []) | |
{ | |
assertTrue($this->validator->fails()); | |
if (empty($expectedFailedRules)) { | |
return $this; | |
} | |
$failedRules = $this->getFailedRules(); | |
foreach ($expectedFailedRules as $expectedFailedRule => $constraints) { | |
assertArrayHasKey($expectedFailedRule, $failedRules); | |
assertStringContainsString($constraints, $failedRules[$expectedFailedRule]); | |
} | |
return $this; | |
} | |
public function assertHasMessage($message, $rule = null) | |
{ | |
$validationMessages = $this->getValidationMessages($rule); | |
assertContains($message, $validationMessages, | |
sprintf("\"%s\" was not contained in the failed%s validation messages\n%s", | |
$message, $rule ? ' '.$rule : '', json_encode($validationMessages, JSON_PRETTY_PRINT) | |
) | |
); | |
return $this; | |
} | |
public function getFailedRules() | |
{ | |
if (!$this->failed) { | |
return []; | |
} | |
$failedRules = collect($this->validator->failed()) | |
->map(function ($details) { | |
return collect($details)->reduce(function ($aggregateRule, $constraints, $ruleName) { | |
$failedRule = Str::lower($ruleName); | |
if (count($constraints)) { | |
$failedRule .= ':'.implode(',', $constraints); | |
} | |
return $aggregateRule.$failedRule; | |
}); | |
}); | |
return $failedRules; | |
} | |
private function getValidationMessages($rule = null) | |
{ | |
$messages = $this->validator->messages()->getMessages(); | |
if ($rule) { | |
return $messages[$rule] ?? []; | |
} | |
return Arr::flatten($messages); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Tests; | |
use Illuminate\Foundation\Http\FormRequest; | |
use Illuminate\Http\Request; | |
use Illuminate\Routing\Route; | |
use Symfony\Component\HttpFoundation\Request as SymfonyRequest; | |
trait ValidatesRequests | |
{ | |
protected function createRequest(string $requestClass, $headers = []) | |
{ | |
$symfonyRequest = SymfonyRequest::create( | |
$this->prepareUrlForRequest('/test/route'), | |
'POST', | |
[], | |
$this->prepareCookiesForRequest(), | |
[], | |
array_replace($this->serverVariables, $this->transformHeadersToServerVars($headers)) | |
); | |
$formRequest = FormRequest::createFrom( | |
Request::createFromBase($symfonyRequest), | |
new $requestClass | |
)->setContainer($this->app); | |
$route = new Route('POST', '/test/route', fn() => null); | |
$route->parameters = []; | |
$formRequest->setRouteResolver(fn() => $route); | |
return new TestFormRequest($formRequest); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment