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

Improvements to the AssertStatusToAssertMethodRector #255

Merged
merged 2 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 10 additions & 86 deletions docs/rector_rules_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,103 +273,27 @@ Replace `(new \Illuminate\Testing\TestResponse)->assertStatus(200)` with `(new \
```diff
class ExampleTest extends \Illuminate\Foundation\Testing\TestCase
{
public function testOk()
public function testFoo()
{
- $this->get('/')->assertStatus(200);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_OK);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_OK);
+ $this->get('/')->assertOk();
+ $this->get('/')->assertOk();
+ $this->get('/')->assertOk();
}

public function testNoContent()
{
- $this->get('/')->assertStatus(204);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_NO_CONTENT);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_NO_CONTENT);
+ $this->get('/')->assertNoContent();
+ $this->get('/')->assertNoContent();
+ $this->get('/')->assertNoContent();
}

public function testUnauthorized()
{
- $this->get('/')->assertStatus(401);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_UNAUTHORIZED);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_UNAUTHORIZED);
+ $this->get('/')->assertUnauthorized();
+ $this->get('/')->assertUnauthorized();
+ $this->get('/')->assertUnauthorized();
}

public function testForbidden()
{
- $this->get('/')->assertStatus(403);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_FORBIDDEN);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_FORBIDDEN);
+ $this->get('/')->assertForbidden();
+ $this->get('/')->assertForbidden();
+ $this->get('/')->assertForbidden();
}

public function testNotFound()
{
- $this->get('/')->assertStatus(404);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_NOT_FOUND);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_NOT_FOUND);
+ $this->get('/')->assertNotFound();
+ $this->get('/')->assertNotFound();
+ $this->get('/')->assertNotFound();
}

public function testMethodNotAllowed()
{
- $this->get('/')->assertStatus(405);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_METHOD_NOT_ALLOWED);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_METHOD_NOT_ALLOWED);
+ $this->get('/')->assertMethodNotAllowed();
+ $this->get('/')->assertMethodNotAllowed();
+ $this->get('/')->assertMethodNotAllowed();
}

public function testUnprocessableEntity()
{
- $this->get('/')->assertStatus(422);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_UNPROCESSABLE_ENTITY);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_UNPROCESSABLE_ENTITY);
+ $this->get('/')->assertUnprocessable();
+ $this->get('/')->assertUnprocessable();
+ $this->get('/')->assertUnprocessable();
}

public function testGone()
{
- $this->get('/')->assertStatus(410);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_GONE);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_GONE);
+ $this->get('/')->assertGone();
+ $this->get('/')->assertGone();
+ $this->get('/')->assertGone();
}

public function testInternalServerError()
{
- $this->get('/')->assertStatus(500);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_INTERNAL_SERVER_ERROR);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_INTERNAL_SERVER_ERROR);
+ $this->get('/')->assertInternalServerError();
+ $this->get('/')->assertInternalServerError();
+ $this->get('/')->assertInternalServerError();
}

public function testServiceUnavailable()
{
- $this->get('/')->assertStatus(503);
- $this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_SERVICE_UNAVAILABLE);
- $this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_SERVICE_UNAVAILABLE);
+ $this->get('/')->assertServiceUnavailable();
+ $this->get('/')->assertServiceUnavailable();
+ $this->get('/')->assertOk();
+ $this->get('/')->assertNoContent();
+ $this->get('/')->assertUnauthorized();
+ $this->get('/')->assertForbidden();
+ $this->get('/')->assertNotFound();
+ $this->get('/')->assertMethodNotAllowed();
+ $this->get('/')->assertUnprocessable();
+ $this->get('/')->assertGone();
+ $this->get('/')->assertInternalServerError();
+ $this->get('/')->assertServiceUnavailable();
}
}
Expand Down
175 changes: 24 additions & 151 deletions src/Rector/MethodCall/AssertStatusToAssertMethodRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@
namespace RectorLaravel\Rector\MethodCall;

use PhpParser\Node;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Scalar\LNumber;
use PHPStan\Type\ObjectType;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
Expand All @@ -28,148 +26,36 @@ public function getRuleDefinition(): RuleDefinition
<<<'CODE_SAMPLE'
class ExampleTest extends \Illuminate\Foundation\Testing\TestCase
{
public function testOk()
public function testFoo()
{
$this->get('/')->assertStatus(200);
$this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_OK);
$this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_OK);
}

public function testNoContent()
{
$this->get('/')->assertStatus(204);
$this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_NO_CONTENT);
$this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_NO_CONTENT);
}

public function testUnauthorized()
{
$this->get('/')->assertStatus(401);
$this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_UNAUTHORIZED);
$this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_UNAUTHORIZED);
}

public function testForbidden()
{
$this->get('/')->assertStatus(403);
$this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_FORBIDDEN);
$this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_FORBIDDEN);
}

public function testNotFound()
{
$this->get('/')->assertStatus(404);
$this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_NOT_FOUND);
$this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_NOT_FOUND);
}

public function testMethodNotAllowed()
{
$this->get('/')->assertStatus(405);
$this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_METHOD_NOT_ALLOWED);
$this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_METHOD_NOT_ALLOWED);
}

public function testUnprocessableEntity()
{
$this->get('/')->assertStatus(422);
$this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_UNPROCESSABLE_ENTITY);
$this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_UNPROCESSABLE_ENTITY);
}

public function testGone()
{
$this->get('/')->assertStatus(410);
$this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_GONE);
$this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_GONE);
}

public function testInternalServerError()
{
$this->get('/')->assertStatus(500);
$this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_INTERNAL_SERVER_ERROR);
$this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_INTERNAL_SERVER_ERROR);
}

public function testServiceUnavailable()
{
$this->get('/')->assertStatus(503);
$this->get('/')->assertStatus(\Illuminate\Http\Response::HTTP_SERVICE_UNAVAILABLE);
$this->get('/')->assertStatus(\Symfony\Component\HttpFoundation\Response::HTTP_SERVICE_UNAVAILABLE);
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class ExampleTest extends \Illuminate\Foundation\Testing\TestCase
{
public function testOk()
public function testFoo()
{
$this->get('/')->assertOk();
$this->get('/')->assertOk();
$this->get('/')->assertOk();
}

public function testNoContent()
{
$this->get('/')->assertNoContent();
$this->get('/')->assertNoContent();
$this->get('/')->assertNoContent();
}

public function testUnauthorized()
{
$this->get('/')->assertUnauthorized();
$this->get('/')->assertUnauthorized();
$this->get('/')->assertUnauthorized();
}

public function testForbidden()
{
$this->get('/')->assertForbidden();
$this->get('/')->assertForbidden();
$this->get('/')->assertForbidden();
}

public function testNotFound()
{
$this->get('/')->assertNotFound();
$this->get('/')->assertNotFound();
$this->get('/')->assertNotFound();
}

public function testMethodNotAllowed()
{
$this->get('/')->assertMethodNotAllowed();
$this->get('/')->assertMethodNotAllowed();
$this->get('/')->assertMethodNotAllowed();
}

public function testUnprocessableEntity()
{
$this->get('/')->assertUnprocessable();
$this->get('/')->assertUnprocessable();
$this->get('/')->assertUnprocessable();
}

public function testGone()
{
$this->get('/')->assertGone();
$this->get('/')->assertGone();
$this->get('/')->assertGone();
}

public function testInternalServerError()
{
$this->get('/')->assertInternalServerError();
$this->get('/')->assertInternalServerError();
$this->get('/')->assertInternalServerError();
}

public function testServiceUnavailable()
{
$this->get('/')->assertServiceUnavailable();
$this->get('/')->assertServiceUnavailable();
$this->get('/')->assertServiceUnavailable();
}
}
Expand Down Expand Up @@ -212,47 +98,34 @@ private function updateAssertStatusCall(MethodCall $methodCall): ?MethodCall
$arg = $methodCall->getArgs()[0];
$argValue = $arg->value;

if (! $argValue instanceof LNumber && ! $argValue instanceof ClassConstFetch) {
// we can check if the arg is an integer even if it comes from a constant
$type = $this->getType($argValue);

if (! $type->isInteger()->yes()) {
return null;
}

if ($argValue instanceof LNumber) {
$replacementMethod = match ($argValue->value) {
200 => 'assertOk',
204 => 'assertNoContent',
401 => 'assertUnauthorized',
403 => 'assertForbidden',
404 => 'assertNotFound',
405 => 'assertMethodNotAllowed',
410 => 'assertGone',
422 => 'assertUnprocessable',
500 => 'assertInternalServerError',
503 => 'assertServiceUnavailable',
default => null
};
} else {
if (! in_array($this->getName($argValue->class), [
'Illuminate\Http\Response',
'Symfony\Component\HttpFoundation\Response',
], true)) {
return null;
}
// we want the value of the integer if it's known
$value = ($type->getConstantScalarValues()[0] ?? null);

$replacementMethod = match ($this->getName($argValue->name)) {
'HTTP_OK' => 'assertOk',
'HTTP_NO_CONTENT' => 'assertNoContent',
'HTTP_UNAUTHORIZED' => 'assertUnauthorized',
'HTTP_FORBIDDEN' => 'assertForbidden',
'HTTP_NOT_FOUND' => 'assertNotFound',
'HTTP_METHOD_NOT_ALLOWED' => 'assertMethodNotAllowed',
'HTTP_GONE' => 'assertGone',
'HTTP_UNPROCESSABLE_ENTITY' => 'assertUnprocessable',
'HTTP_INTERNAL_SERVER_ERROR' => 'assertInternalServerError',
'HTTP_SERVICE_UNAVAILABLE' => 'assertServiceUnavailable',
default => null
};
if ($value === null) {
return null;
}

$replacementMethod = match ($value) {
200 => 'assertOk',
204 => 'assertNoContent',
401 => 'assertUnauthorized',
403 => 'assertForbidden',
404 => 'assertNotFound',
405 => 'assertMethodNotAllowed',
410 => 'assertGone',
422 => 'assertUnprocessable',
500 => 'assertInternalServerError',
503 => 'assertServiceUnavailable',
default => null
};

if ($replacementMethod === null) {
return null;
}
Expand Down
13 changes: 13 additions & 0 deletions stubs/Illuminate/Http/Response.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Illuminate\Http;

use Symfony\Component\HttpFoundation\Response as SymfonyResponse;

if (class_exists('Illuminate\Http\Response')) {
return;
}

class Response extends SymfonyResponse
{
}
Loading
Loading