laravel-json-api / testing Goto Github PK
View Code? Open in Web Editor NEWTest helpers for JSON API compliant APIs.
License: MIT License
Test helpers for JSON API compliant APIs.
License: MIT License
Hi, thanks for your great work.
I'm trying to create a Feature test for some routes:
I've defined this one in my api.php
route file:
JsonApiRoute::server('v1')
->middleware('auth:api')
->prefix($api_prefix)
->namespace('Api\V1')
->resources(function ($server) {
$server->resource('users')->actions('-actions', function ($actions) {
$actions->get('profile');
})->only('profile');
});
Making the request with a restful client I get a successful answer, but when I'm going to test it following the steps from documentation, I get the No bound JSON API server - your application may not be handling an HTTP request.
.
This is my TestCase.php
file:
And my test file is this:
BTW. I had to bind $this->app->bind(Server::class, ServerServer::class);
because I was getting this error:
I'm using a fresh installation of Laravel v8.27 and Pest v1.0.
Thanks.
/**
* Add query parameters to the request.
*
* @param iterable $query
* @return $this
*/
public function query(iterable $query): self
{
$this->query = collect($query)->merge($query);
return $this;
}
should't it be...
/**
* Add query parameters to the request.
*
* @param iterable $query
* @return $this
*/
public function query(iterable $query): self
{
$this->query = $this->query->merge($query);
return $this;
}
response from my PHPunit command:
$ php -dxdebug.mode=coverage ./vendor/phpunit/phpunit/phpunit tests/Feature --coverage-filter app --coverage-text --colors=never
PHPUnit 10.4.1 by Sebastian Bergmann and contributors.
Runtime: PHP 8.2.12 with Xdebug 3.2.2
Configuration: /builds/application-projects/skeleton/skeleton-project/laravel/phpunit.xml
EEEEEEEEEEEEE 13 / 13 (100%)
Time: 00:01.562, Memory: 52.50 MB
There was 1 PHPUnit test runner deprecation:
1) Your XML configuration validates against a deprecated schema. Migrate your XML configuration using "--migrate-configuration"!
--
There were 13 errors:
1) Tests\Feature\FilesTest::testIndexWithPermission
LogicException: No bound JSON:API server - your application may not be handling an HTTP request.
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php:1126
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php:921
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php:795
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:937
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php:731
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:922
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel-json-api/core/src/Core/JsonApiService.php:81
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:353
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel-json-api/core/src/Core/Server/Concerns/ServerAware.php:53
/builds/application-projects/skeleton/skeleton-project/laravel/app/Traits/Publishable.php:16
/builds/application-projects/skeleton/skeleton-project/laravel/app/Observers/UserObserver.php:14
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:4[41](https://gitlab.beech.it/application-projects/skeleton/skeleton-project/-/jobs/415812#L41)
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:249
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php:188
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1319
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1137
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:338
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php:238
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:333
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:287
/builds/application-projects/skeleton/skeleton-project/laravel/tests/Feature/FilesTest.php:36
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:174
Caused by
Illuminate\Contracts\Container\BindingResolutionException: Target [LaravelJsonApi\Contracts\Server\Server] is not instantiable.
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php:1126
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php:921
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php:795
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:937
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Container/Container.php:731
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:922
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel-json-api/core/src/Core/JsonApiService.php:81
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:353
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel-json-api/core/src/Core/Server/Concerns/ServerAware.php:53
/builds/application-projects/skeleton/skeleton-project/laravel/app/Traits/Publishable.php:16
/builds/application-projects/skeleton/skeleton-project/laravel/app/Observers/UserObserver.php:14
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:[44](https://gitlab.beech.it/application-projects/skeleton/skeleton-project/-/jobs/415812#L44)1
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php:249
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php:188
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1319
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1137
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:338
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php:238
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:333
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:287
/builds/application-projects/skeleton/skeleton-project/laravel/tests/Feature/FilesTest.php:36
/builds/application-projects/skeleton/skeleton-project/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:174
I have currently made a trait which uses the server to send a message with the json api format via the Redis pub/sub system instead of HTTP.
<?php
declare(strict_types=1);
namespace App\Traits;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redis;
use LaravelJsonApi\Core\Server\Concerns\ServerAware;
trait Publishable
{
use ServerAware;
public function publish(): void
{
// retrieve the resources which are registered inside the server.
$resources = $this->server()->resources();
// check if the model exists and exists inside the resources.
if (! is_object($this) || ! $resources->exists($this)) {
return;
}
// Create the resource from model
$model = $resources->create($this);
// Create response from the resource and get the content to send through Redis.P
$message = $model->toResponse(new Request())->content();
// Publish the serialized model to the default Redis channel
Redis::publish('default', $message);
}
}
My user is currently added as publishable and the error is formed because in my example tests I use the user as acting user.
<?php
declare(strict_types=1);
namespace Tests\Feature;
use App\Http\Middleware\Keycloak\CheckRoles;
use App\Http\Middleware\Keycloak\CheckSession;
use App\Models\File;
use App\Models\Permission;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use LaravelJsonApi\Core\Server\Concerns\ServerAware;
use LaravelJsonApi\Testing\MakesJsonApiRequests;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;
use Tests\TestCase;
class FilesTest extends TestCase
{
use DatabaseTransactions;
use MakesJsonApiRequests;
use ServerAware;
public const BASEURL = '/api/v1/'.File::JSON_API_TYPE;
public function setUp(): void
{
parent::setUp();
$this->withoutMiddleware(CheckSession::class);
$this->withoutMiddleware(CheckRoles::class);
}
public function testIndexWithPermission(): void
{
// GIVEN
File::factory()->count(10)->create();
$user = User::factory()->create();
$user->givePermissionTo(Permission::PERMISSION_FILE_INDEX);
// WHEN
$response = $this->actingAs($user, 'api')->jsonApi()->get(self::BASEURL);
// THEN
$response->assertJsonStructure([
'data' => [
[
'type',
'id',
'attributes' => [
'name',
'path',
'mime_type',
'createdAt',
'updatedAt',
],
],
],
]);
$response->assertJsonCount(10, 'data');
}
public function testIndexWithoutPermission(): void
{
// GIVEN
File::factory()->count(10)->create();
$user = User::factory()->create();
// WHEN
$response = $this->actingAs($user, 'api')->jsonApi()->get(self::BASEURL);
// THEN
$response->assertStatus(ResponseAlias::HTTP_FORBIDDEN);
}
public function testCreateWithPermission(): void
{
// GIVEN
$user = User::factory()->create();
$user->givePermissionTo(Permission::PERMISSION_FILE_CREATE);
$file = File::factory()->make();
// WHEN
$response = $this->actingAs($user, 'api')->jsonApi()->withData([
'type' => File::JSON_API_TYPE,
'attributes' => [
'name' => $file->name,
'mime_type' => $file->mime_type,
],
])->post(self::BASEURL);
// THEN
$response->assertStatus(ResponseAlias::HTTP_CREATED);
$response->assertSessionHasNoErrors();
$response->assertJsonStructure([
'data' => [
'type',
'id',
'attributes' => [
'name',
'path',
'mime_type',
'createdAt',
'updatedAt',
],
],
]);
}
public function testCreateWithInvalidData(): void
{
// GIVEN
$user = User::factory()->create();
$user->givePermissionTo(Permission::PERMISSION_FILE_CREATE);
// WHEN
$response = $this->actingAs($user, 'api')->jsonApi()->withData([
'type' => File::JSON_API_TYPE,
'attributes' => [
'name' => null,
'mime_type' => null,
],
])->post(self::BASEURL);
// THEN
$response->assertStatusCode(ResponseAlias::HTTP_UNPROCESSABLE_ENTITY);
}
public function testCreateWithoutPermission(): void
{
// GIVEN
$user = User::factory()->create();
// WHEN
$response = $this->actingAs($user, 'api')->jsonApi()->withData([
'type' => File::JSON_API_TYPE,
'attributes' => [
'name' => 'test',
'mime_type' => 'txt',
],
])->post(self::BASEURL);
// THEN
$response->assertStatus(ResponseAlias::HTTP_FORBIDDEN);
}
public function testShowWithPermission(): void
{
// GIVEN
$user = User::factory()->create();
$user->givePermissionTo(Permission::PERMISSION_FILE_SHOW);
$user->givePermissionTo(Permission::PERMISSION_FILE_CREATE);
$file = File::factory()->create(
[
'id' => 1,
'name' => 'test',
'mime_type' => 'txt',
]
);
$this->actingAs($user, 'api')->jsonApi()->withData([
'type' => File::JSON_API_TYPE,
'attributes' => [
'name' => $file->name,
'mime_type' => $file->mime_type,
],
])->post(self::BASEURL);
// WHEN
$response = $this->actingAs($user, 'api')->jsonApi()->get(self::BASEURL.'/1');
// THEN
$response->assertStatus(ResponseAlias::HTTP_OK);
$response->assertJsonStructure([
'data' => [
'type',
'id',
'attributes' => [
'name',
'path',
'mime_type',
'createdAt',
'updatedAt',
],
],
]);
}
public function testShowWithoutPermission(): void
{
// GIVEN
$user = User::factory()->create();
$file = File::factory()->create();
// WHEN
$response = $this->actingAs($user, 'api')->jsonApi()->get(self::BASEURL.'/'.$file->id);
// THEN
$response->assertStatus(ResponseAlias::HTTP_FORBIDDEN);
}
public function testUpdateWithPermission(): void
{
// GIVEN
$user = User::factory()->create();
$user->givePermissionTo(Permission::PERMISSION_FILE_UPDATE);
$file = File::factory()->create();
// WHEN
$response = $this->actingAs($user, 'api')->jsonApi()->withData([
'type' => File::JSON_API_TYPE,
'id' => (string) $file->id,
'attributes' => [
'name' => 'file',
'mime_type' => 'txt',
],
])->patch(self::BASEURL.'/'.$file->id);
// THEN
$response->assertStatus(ResponseAlias::HTTP_OK);
$response->assertSessionHasNoErrors();
$response->assertJsonStructure([
'data' => [
'type',
'id',
'attributes' => [
'name',
'path',
'mime_type',
'createdAt',
'updatedAt',
],
],
]);
}
public function testUpdateWithInvalidData(): void
{
// GIVEN
$user = User::factory()->create();
$user->givePermissionTo(Permission::PERMISSION_FILE_UPDATE);
$file = File::factory()->create();
// WHEN
$response = $this->actingAs($user, 'api')->jsonApi()->withData([
'type' => File::JSON_API_TYPE,
'id' => (string) $file->id,
'attributes' => [
'name' => null,
'mime_type' => null,
],
])->patch(self::BASEURL.'/'.$file->id);
// THEN
$response->assertStatusCode(ResponseAlias::HTTP_UNPROCESSABLE_ENTITY);
}
public function testUpdateWithoutPermission(): void
{
// GIVEN
$user = User::factory()->create();
$file = File::factory()->create();
// WHEN
$response = $this->actingAs($user, 'api')->jsonApi()->withData([
'type' => File::JSON_API_TYPE,
'id' => (string) $file->id,
'attributes' => [
'name' => 'test',
'mime_type' => 'txt',
],
])->patch(self::BASEURL.'/'.$file->id);
// THEN
$response->assertStatus(ResponseAlias::HTTP_FORBIDDEN);
}
public function testDeleteWithPermission(): void
{
// GIVEN
$user = User::factory()->create();
$user->givePermissionTo(Permission::PERMISSION_FILE_DELETE);
$file = File::factory()->create();
// WHEN
$response = $this->actingAs($user, 'api')->jsonApi()->delete(self::BASEURL.'/'.$file->id);
// THEN
$response->assertStatus(ResponseAlias::HTTP_NO_CONTENT);
}
public function testDeleteWithoutPermission(): void
{
// GIVEN
$user = User::factory()->create();
$file = File::factory()->create();
// WHEN
$response = $this->actingAs($user, 'api')->jsonApi()->delete(self::BASEURL.'/'.$file->id);
// THEN
$response->assertStatus(ResponseAlias::HTTP_FORBIDDEN);
}
public function testUpdateObjectThatDoesntExist(): void
{
// GIVEN
$user = User::factory()->create();
$user->givePermissionTo(Permission::PERMISSION_FILE_UPDATE);
// WHEN
$response = $this->actingAs($user, 'api')->jsonApi()->withData([
'type' => File::JSON_API_TYPE,
'id' => '1',
'attributes' => [
'name' => 'test',
'mime_type' => 'txt',
],
])->patch(self::BASEURL.'/1');
// THEN
$response->assertStatus(ResponseAlias::HTTP_NOT_FOUND);
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.