Instantly share code, notes, and snippets.

Embed
What would you like to do?
Laravel - Testing - Base class to extend basic API tests
<?php
namespace Tests\Traits;
use KushyApi\User;
trait AttachJwtToken
{
/**
* @var User
*/
protected $loginUser;
/**
* @param User $user
* @return $this
*/
public function loginAs(User $user)
{
$this->loginUser = $user;
return $this;
}
/**
* @return string
*/
protected function getJwtToken()
{
$user = $this->loginUser ?: factory(User::class)->create([
'type' => 'admin',
]);
return $user->createToken('Kushy Test API', [])->accessToken;
}
/**
* @param string $method
* @param string $uri
* @param array $parameters
* @param array $cookies
* @param array $files
* @param array $server
* @param string $content
* @return \Illuminate\Http\Response
*/
public function call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
{
if ($this->requestNeedsToken($method, $uri)) {
$server = $this->attachToken($server);
}
return parent::call($method, $uri, $parameters, $cookies, $files, $server, $content);
}
/**
* @param string $method
* @param string $uri
* @return bool
*/
protected function requestNeedsToken($method, $uri)
{
return !('/auth/login' === $uri && 'POST' === $method);
}
/**
* @param array $server
* @return string
*/
protected function attachToken(array $server)
{
return array_merge($server, $this->transformHeadersToServerVars([
'Authorization' => 'Bearer ' . $this->getJwtToken(),
]));
}
}
<?php
namespace Tests\Feature\Controllers;
use Tests\CrudTest;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class StrainsControllerTest extends CrudTest
{
/**
* The model to use when creating dummy data
*
* @var class
*/
protected $model = \KushyApi\Posts::class;
/**
* The endpoint to query in the API
* e.g = /api/v1/<endpoint>
*
* @var string
*/
protected $endpoint = 'strains';
/**
* Any additional "states" to add to factory
*
* @var string
*/
protected $states = 'strains';
/**
* Extra data to pass to POST endpoint
* aka the (store() method)
*
* Must be array (ends up merged with another)
*
* @var array
*/
protected $store = [
'category' => '1'
];
}
<?php
namespace Tests;
use Tests\TestCase;
use Tests\Traits\AttachJwtToken;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
abstract class CrudTest extends TestCase
{
use AttachJwtToken;
public function createPost()
{
if($this->states)
{
return factory($this->model)->states($this->states)->create();
}
return factory($this->model)->create();
}
/**
* GET /endpoint/
* Should return 201 with data array
*
* @return void
*/
public function testIndex()
{
$response = $this->json('GET', "api/v1/{$this->endpoint}");
$response
->assertStatus(201)
->assertJson([
'data' => true
]);
}
/**
* GET /endpoint/<id>
* Should return 201 with data array
*
* @return void
*/
public function testShow()
{
// Create a test shop with filled out fields
$activity = $this->createPost();
// Check the API for the new entry
$response = $this->json('GET', "api/v1/{$this->endpoint}/{$activity->id}");
// Delete the test shop
$activity->delete();
$response
->assertStatus(201)
->assertJson([
'data' => true
]);
}
/**
* POST /endpoint/
*
* @return void
*/
public function testStore()
{
$activity = $this->createPost();
$activity = $activity->toArray();
/**
* Pass in any extra data
*/
if($this->store)
{
$activity = array_merge($activity, $this->store);
}
$response = $this->json('POST', "api/v1/{$this->endpoint}/", $activity);
($this->model)::destroy($activity['id']);
$response
->assertStatus(201)
->assertJson([
'data' => true
]);
}
/**
* DELETE /endpoint/<id>
* Tests the destroy() method that deletes the shop
*
* @return void
*/
public function testDestroy()
{
$activity = $this->createPost();
$response = $this->json('DELETE', "api/v1/{$this->endpoint}/{$activity->id}");
$response
->assertStatus(200);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment