mirror of
https://github.com/AnimeThemes/animethemes-server.git
synced 2026-07-11 01:24:46 +02:00
tests: add mutation tests (#1100)
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\GraphQL\Middleware;
|
||||
|
||||
use Closure;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Rebing\GraphQL\Error\AuthorizationError;
|
||||
use Rebing\GraphQL\Support\Middleware;
|
||||
|
||||
class AuthMutation extends Middleware
|
||||
{
|
||||
/**
|
||||
* @param array<string, mixed> $args
|
||||
*/
|
||||
public function handle($root, array $args, $context, ResolveInfo $resolveInfo, Closure $next)
|
||||
{
|
||||
throw_unless(Auth::check(), AuthorizationError::class, 'Unauthenticated.');
|
||||
|
||||
return $next($root, $args, $context, $resolveInfo);
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ class AnimeYearsResolver extends BaseResolver
|
||||
|
||||
$fieldSelection = $resolveInfo->getFieldSelection(1);
|
||||
|
||||
Validator::make(['year' => $year], [new AnimeYearRule($fieldSelection)])
|
||||
Validator::make(['year' => $year], ['year' => new AnimeYearRule($fieldSelection)])
|
||||
->validate();
|
||||
|
||||
return Anime::query()
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace App\GraphQL\Schema\Mutations;
|
||||
|
||||
use App\Concerns\GraphQL\ResolvesArguments;
|
||||
use App\GraphQL\Argument\Argument;
|
||||
use App\GraphQL\Middleware\AuthMutation;
|
||||
use App\GraphQL\Middleware\ResolveBindableArgs;
|
||||
use App\GraphQL\Schema\Types\BaseType;
|
||||
use App\GraphQL\Schema\Unions\BaseUnion;
|
||||
@@ -27,6 +28,7 @@ abstract class BaseMutation extends Mutation
|
||||
$this->middleware = array_merge(
|
||||
$this->middleware,
|
||||
[
|
||||
AuthMutation::class,
|
||||
ResolveBindableArgs::class,
|
||||
],
|
||||
);
|
||||
|
||||
-18
@@ -5,37 +5,19 @@ declare(strict_types=1);
|
||||
namespace App\GraphQL\Schema\Mutations\Models\List\ExternalProfile;
|
||||
|
||||
use App\Contracts\GraphQL\Fields\BindableField;
|
||||
use App\Features\AllowExternalProfileManagement;
|
||||
use App\GraphQL\Argument\Argument;
|
||||
use App\GraphQL\Resolvers\List\SyncExternalProfileResolver;
|
||||
use App\GraphQL\Schema\Fields\Field;
|
||||
use App\GraphQL\Schema\Mutations\BaseMutation;
|
||||
use App\GraphQL\Schema\Types\List\ExternalProfileType;
|
||||
use App\Http\Middleware\Api\EnabledOnlyOnLocalhost;
|
||||
use GraphQL\Type\Definition\ResolveInfo;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Pennant\Middleware\EnsureFeaturesAreActive;
|
||||
|
||||
class SyncExternalProfileMutation extends BaseMutation
|
||||
{
|
||||
protected $middleware = [
|
||||
EnabledOnlyOnLocalhost::class,
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware = array_merge(
|
||||
$this->middleware,
|
||||
[
|
||||
Str::of(EnsureFeaturesAreActive::class)
|
||||
->append(':')
|
||||
->append(AllowExternalProfileManagement::class)
|
||||
->__toString(),
|
||||
]
|
||||
);
|
||||
|
||||
parent::__construct('SyncExternalProfile');
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ class PlaylistTrackPolicy extends BasePolicy
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Playlist $playlist
|
||||
* @param Playlist|null $playlist
|
||||
*/
|
||||
public function create(User $user, $playlist = null): Response
|
||||
{
|
||||
@@ -87,8 +87,9 @@ class PlaylistTrackPolicy extends BasePolicy
|
||||
|
||||
/**
|
||||
* @param PlaylistTrack $track
|
||||
* @param Playlist|null $playlist
|
||||
*/
|
||||
public function update(User $user, Model $track): Response
|
||||
public function update(User $user, Model $track, $playlist = null): Response
|
||||
{
|
||||
if (Filament::isServing()) {
|
||||
return $user->hasRole(RoleEnum::ADMIN->value)
|
||||
@@ -97,7 +98,7 @@ class PlaylistTrackPolicy extends BasePolicy
|
||||
}
|
||||
|
||||
/** @var Playlist|null $playlist */
|
||||
$playlist = request()->route('playlist');
|
||||
$playlist ??= request()->route('playlist');
|
||||
|
||||
return $playlist?->user()->is($user) && parent::update($user, $track)->allowed()
|
||||
? Response::allow()
|
||||
@@ -106,8 +107,9 @@ class PlaylistTrackPolicy extends BasePolicy
|
||||
|
||||
/**
|
||||
* @param PlaylistTrack $track
|
||||
* @param Playlist|null $playlist
|
||||
*/
|
||||
public function delete(User $user, Model $track): Response
|
||||
public function delete(User $user, Model $track, $playlist = null): Response
|
||||
{
|
||||
if (Filament::isServing()) {
|
||||
return $user->hasRole(RoleEnum::ADMIN->value)
|
||||
@@ -116,7 +118,7 @@ class PlaylistTrackPolicy extends BasePolicy
|
||||
}
|
||||
|
||||
/** @var Playlist|null $playlist */
|
||||
$playlist = request()->route('playlist');
|
||||
$playlist ??= request()->route('playlist');
|
||||
|
||||
return $playlist?->user()->is($user) && parent::delete($user, $track)->allowed()
|
||||
? Response::allow()
|
||||
|
||||
@@ -54,3 +54,6 @@ parameters:
|
||||
-
|
||||
message: '#Call to method assertActionDoesNotExist\(\) on an unknown class static.#'
|
||||
path: tests/Unit/Filament/*
|
||||
-
|
||||
message: '#Access to an undefined property PHPUnit\\Framework\\TestCase::\$mutation.#'
|
||||
path: tests/Feature/GraphQL/*
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Enums\Auth\CrudPermission;
|
||||
use App\Enums\Models\List\PlaylistVisibility;
|
||||
use App\Events\List\Playlist\PlaylistCreated;
|
||||
use App\Models\Auth\User;
|
||||
use App\Models\List\Playlist;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
beforeEach(function () {
|
||||
$this->mutation = '
|
||||
mutation($name: String!, $visibility: PlaylistVisibility!, $description: String) {
|
||||
CreatePlaylist(name: $name, visibility: $visibility, description: $description) {
|
||||
name
|
||||
visibility
|
||||
description
|
||||
}
|
||||
}
|
||||
';
|
||||
});
|
||||
|
||||
test('protected', function () {
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'name' => fake()->word(),
|
||||
'visibility' => Arr::random(PlaylistVisibility::cases())->name,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
test('forbidden', function () {
|
||||
actingAs(User::factory()->createOne());
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'name' => fake()->word(),
|
||||
'visibility' => Arr::random(PlaylistVisibility::cases())->name,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
it('creates', function () {
|
||||
Event::fakeExcept(PlaylistCreated::class);
|
||||
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::CREATE->format(Playlist::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$playlist = Playlist::factory()->makeOne();
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'name' => $playlist->name,
|
||||
'visibility' => $playlist->visibility->name,
|
||||
'description' => $playlist->description,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertDatabaseCount(Playlist::class, 1);
|
||||
$response->assertOk();
|
||||
$response->assertJsonIsObject('data.CreatePlaylist');
|
||||
});
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Enums\Auth\CrudPermission;
|
||||
use App\Events\List\Playlist\PlaylistCreated;
|
||||
use App\Models\Auth\User;
|
||||
use App\Models\List\Playlist;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
beforeEach(function () {
|
||||
$this->mutation = '
|
||||
mutation($id: String!) {
|
||||
DeletePlaylist(id: $id) {
|
||||
message
|
||||
}
|
||||
}
|
||||
';
|
||||
});
|
||||
|
||||
test('protected', function () {
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'id' => fake()->word(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
test('forbidden', function () {
|
||||
Event::fakeExcept(PlaylistCreated::class);
|
||||
|
||||
actingAs(User::factory()->createOne());
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
// Needed for the bind resolver.
|
||||
'id' => Playlist::factory()->createOne()->hashid,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
test('forbidden if not owner', function () {
|
||||
Event::fakeExcept(PlaylistCreated::class);
|
||||
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::DELETE->format(Playlist::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'id' => Playlist::factory()->createOne()->hashid,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
it('deletes', function () {
|
||||
Event::fakeExcept(PlaylistCreated::class);
|
||||
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::DELETE->format(Playlist::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$playlist = Playlist::factory()
|
||||
->for($user)
|
||||
->createOne();
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'id' => $playlist->hashid,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertDatabaseCount(Playlist::class, 0);
|
||||
$response->assertOk();
|
||||
$this->assertIsString($response->json('data.DeletePlaylist.message'));
|
||||
});
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Enums\Auth\CrudPermission;
|
||||
use App\Events\List\Playlist\PlaylistCreated;
|
||||
use App\Events\List\Playlist\Track\TrackCreated;
|
||||
use App\Models\Auth\User;
|
||||
use App\Models\List\Playlist;
|
||||
use App\Models\List\Playlist\PlaylistTrack;
|
||||
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
|
||||
use App\Models\Wiki\Video;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
beforeEach(function () {
|
||||
$this->mutation = '
|
||||
mutation($playlist: String!, $entryId: Int!, $videoId: Int!) {
|
||||
CreatePlaylistTrack(playlist: $playlist, entryId: $entryId, videoId: $videoId) {
|
||||
id
|
||||
}
|
||||
}
|
||||
';
|
||||
});
|
||||
|
||||
test('protected', function () {
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'playlist' => fake()->word(),
|
||||
'entryId' => fake()->randomDigitNotNull(),
|
||||
'videoId' => fake()->randomDigitNotNull(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
test('forbidden', function () {
|
||||
Event::fakeExcept(PlaylistCreated::class);
|
||||
|
||||
actingAs(User::factory()->createOne());
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
// Needed for the bind resolver.
|
||||
'playlist' => Playlist::factory()->createOne()->hashid,
|
||||
'entryId' => AnimeThemeEntry::factory()->createOne()->getKey(),
|
||||
'videoId' => Video::factory()->createOne()->getKey(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
it('fails if no entry video link', function () {
|
||||
Event::fakeExcept([PlaylistCreated::class, TrackCreated::class]);
|
||||
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::CREATE->format(PlaylistTrack::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$entry = AnimeThemeEntry::factory()->createOne();
|
||||
$video = Video::factory()->createOne();
|
||||
|
||||
$playlist = Playlist::factory()
|
||||
->for($user)
|
||||
->createOne();
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'playlist' => $playlist->hashid,
|
||||
'entryId' => $entry->getKey(),
|
||||
'videoId' => $video->getKey(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'validation');
|
||||
$this->assertArrayHasKey('entryId', $response->json('errors.0.extensions.validation'));
|
||||
$this->assertArrayHasKey('videoId', $response->json('errors.0.extensions.validation'));
|
||||
});
|
||||
|
||||
it('creates', function () {
|
||||
Event::fakeExcept([PlaylistCreated::class, TrackCreated::class]);
|
||||
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::CREATE->format(PlaylistTrack::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$entry = AnimeThemeEntry::factory()->createOne();
|
||||
$video = Video::factory()->createOne();
|
||||
|
||||
$entry->videos()->attach($video);
|
||||
|
||||
$playlist = Playlist::factory()
|
||||
->for($user)
|
||||
->createOne();
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'playlist' => $playlist->hashid,
|
||||
'entryId' => $entry->getKey(),
|
||||
'videoId' => $video->getKey(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertDatabaseCount(PlaylistTrack::class, 1);
|
||||
$response->assertOk();
|
||||
$response->assertJsonIsObject('data.CreatePlaylistTrack');
|
||||
});
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Enums\Auth\CrudPermission;
|
||||
use App\Events\List\Playlist\PlaylistCreated;
|
||||
use App\Events\List\Playlist\Track\TrackCreated;
|
||||
use App\Models\Auth\User;
|
||||
use App\Models\List\Playlist;
|
||||
use App\Models\List\Playlist\PlaylistTrack;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
beforeEach(function () {
|
||||
$this->mutation = '
|
||||
mutation($playlist: String!, $id: String!) {
|
||||
DeletePlaylistTrack(playlist: $playlist, id: $id) {
|
||||
message
|
||||
}
|
||||
}
|
||||
';
|
||||
});
|
||||
|
||||
test('protected', function () {
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'playlist' => fake()->word(),
|
||||
'id' => fake()->word(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
test('forbidden', function () {
|
||||
Event::fakeExcept([PlaylistCreated::class, TrackCreated::class]);
|
||||
|
||||
actingAs(User::factory()->createOne());
|
||||
|
||||
$playlist = Playlist::factory()->createOne();
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
// Needed for the bind resolver.
|
||||
'playlist' => $playlist->hashid,
|
||||
'id' => PlaylistTrack::factory()->for($playlist)->createOne()->hashid,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
test('forbidden if not owner', function () {
|
||||
Event::fakeExcept([PlaylistCreated::class, TrackCreated::class]);
|
||||
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::DELETE->format(PlaylistTrack::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$track = PlaylistTrack::factory()
|
||||
->for(Playlist::factory())
|
||||
->createOne();
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'playlist' => $track->playlist->hashid,
|
||||
'id' => $track->hashid,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
it('deletes', function () {
|
||||
Event::fakeExcept([PlaylistCreated::class, TrackCreated::class]);
|
||||
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::DELETE->format(PlaylistTrack::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$track = PlaylistTrack::factory()
|
||||
->for(Playlist::factory()->for($user))
|
||||
->createOne();
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'playlist' => $track->playlist->hashid,
|
||||
'id' => $track->hashid,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertDatabaseCount(PlaylistTrack::class, 0);
|
||||
$response->assertOk();
|
||||
$this->assertIsString($response->json('data.DeletePlaylistTrack.message'));
|
||||
});
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Enums\Auth\CrudPermission;
|
||||
use App\Events\List\Playlist\PlaylistCreated;
|
||||
use App\Events\List\Playlist\Track\TrackCreated;
|
||||
use App\Models\Auth\User;
|
||||
use App\Models\List\Playlist;
|
||||
use App\Models\List\Playlist\PlaylistTrack;
|
||||
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
|
||||
use App\Models\Wiki\Video;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
beforeEach(function () {
|
||||
$this->mutation = '
|
||||
mutation($playlist: String!, $id: String!, $entryId: Int, $videoId: Int) {
|
||||
UpdatePlaylistTrack(playlist: $playlist, id: $id, entryId: $entryId, videoId: $videoId) {
|
||||
animethemeentry {
|
||||
id
|
||||
}
|
||||
video {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
';
|
||||
});
|
||||
|
||||
test('protected', function () {
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'playlist' => fake()->word(),
|
||||
'id' => fake()->word(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
test('forbidden', function () {
|
||||
Event::fakeExcept([PlaylistCreated::class, TrackCreated::class]);
|
||||
|
||||
actingAs(User::factory()->createOne());
|
||||
|
||||
$playlist = Playlist::factory()->createOne();
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
// Needed for the bind resolver.
|
||||
'playlist' => $playlist->hashid,
|
||||
'id' => PlaylistTrack::factory()->for($playlist)->createOne()->hashid,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
test('forbidden if not owner', function () {
|
||||
Event::fakeExcept([PlaylistCreated::class, TrackCreated::class]);
|
||||
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::UPDATE->format(PlaylistTrack::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$track = PlaylistTrack::factory()
|
||||
->for(Playlist::factory())
|
||||
->createOne();
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'playlist' => $track->playlist->hashid,
|
||||
'id' => $track->hashid,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
it('updates', function () {
|
||||
Event::fakeExcept([PlaylistCreated::class, TrackCreated::class]);
|
||||
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::UPDATE->format(PlaylistTrack::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$track = PlaylistTrack::factory()
|
||||
->for(Playlist::factory()->for($user))
|
||||
->createOne();
|
||||
|
||||
$entry = AnimeThemeEntry::factory()->createOne();
|
||||
$video = Video::factory()->createOne();
|
||||
|
||||
$entry->videos()->attach($video);
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'playlist' => $track->playlist->hashid,
|
||||
'id' => $track->hashid,
|
||||
'entryId' => $entry->getKey(),
|
||||
'videoId' => $video->getKey(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJson([
|
||||
'data' => [
|
||||
'UpdatePlaylistTrack' => [
|
||||
'animethemeentry' => [
|
||||
'id' => $entry->getKey(),
|
||||
],
|
||||
'video' => [
|
||||
'id' => $video->getKey(),
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
});
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Enums\Auth\CrudPermission;
|
||||
use App\Events\List\Playlist\PlaylistCreated;
|
||||
use App\Models\Auth\User;
|
||||
use App\Models\List\Playlist;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
beforeEach(function () {
|
||||
$this->mutation = '
|
||||
mutation($id: String!, $name: String, $visibility: PlaylistVisibility, $description: String) {
|
||||
UpdatePlaylist(id: $id, name: $name, visibility: $visibility, description: $description) {
|
||||
name
|
||||
visibility
|
||||
description
|
||||
}
|
||||
}
|
||||
';
|
||||
});
|
||||
|
||||
test('protected', function () {
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'id' => fake()->word(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
test('forbidden', function () {
|
||||
Event::fakeExcept(PlaylistCreated::class);
|
||||
|
||||
actingAs(User::factory()->createOne());
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
// Needed for the bind resolver.
|
||||
'id' => Playlist::factory()->createOne()->hashid,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
test('forbidden if not owner', function () {
|
||||
Event::fakeExcept(PlaylistCreated::class);
|
||||
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::UPDATE->format(Playlist::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'id' => Playlist::factory()->createOne()->hashid,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
it('updates', function () {
|
||||
Event::fakeExcept(PlaylistCreated::class);
|
||||
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::UPDATE->format(Playlist::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$playlist = Playlist::factory()
|
||||
->for($user)
|
||||
->createOne();
|
||||
|
||||
$newPlaylist = Playlist::factory()->makeOne();
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'id' => $playlist->hashid,
|
||||
'name' => $newPlaylist->name,
|
||||
'visibility' => $newPlaylist->visibility->name,
|
||||
'description' => $newPlaylist->description,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJson([
|
||||
'data' => [
|
||||
'UpdatePlaylist' => [
|
||||
'name' => $newPlaylist->name,
|
||||
'visibility' => $newPlaylist->visibility->name,
|
||||
'description' => $newPlaylist->description,
|
||||
],
|
||||
],
|
||||
]);
|
||||
});
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Enums\Auth\CrudPermission;
|
||||
use App\Models\Auth\User;
|
||||
use App\Models\List\Playlist;
|
||||
use App\Models\User\Like;
|
||||
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
beforeEach(function () {
|
||||
$this->mutation = '
|
||||
mutation($entryId: Int, $playlistId: String) {
|
||||
ToggleLike(entry: $entryId, playlist: $playlistId) {
|
||||
animethemeentry: likeable {
|
||||
... on AnimeThemeEntry {
|
||||
id
|
||||
}
|
||||
}
|
||||
playlist: likeable {
|
||||
... on Playlist {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
';
|
||||
});
|
||||
|
||||
test('protected', function () {
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'entryId' => fake()->randomDigitNotNull(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
test('forbidden', function () {
|
||||
actingAs(User::factory()->createOne());
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
// Needed for the bind resolver.
|
||||
'entryId' => AnimeThemeEntry::factory()->createOne()->getKey(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
it('fails if more than one resource is passed', function () {
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::CREATE->format(Like::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$entry = AnimeThemeEntry::factory()->createOne();
|
||||
$playlist = Playlist::factory()->createOne();
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'entryId' => $entry->getKey(),
|
||||
'playlistId' => $playlist->hashid,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'validation');
|
||||
$this->assertArrayHasKey('entry', $response->json('errors.0.extensions.validation'));
|
||||
$this->assertArrayHasKey('playlist', $response->json('errors.0.extensions.validation'));
|
||||
});
|
||||
|
||||
it('likes entry', function () {
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::CREATE->format(Like::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$entry = AnimeThemeEntry::factory()->createOne();
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'entryId' => $entry->getKey(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertDatabaseCount(Like::class, 1);
|
||||
$response->assertOk();
|
||||
$response->assertJson([
|
||||
'data' => [
|
||||
'ToggleLike' => [
|
||||
'animethemeentry' => [
|
||||
'id' => $entry->getKey(),
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
||||
it('likes playlist', function () {
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::CREATE->format(Like::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$playlist = Playlist::factory()->createOne([
|
||||
Playlist::ATTRIBUTE_HASHID => fake()->word(),
|
||||
]);
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'playlistId' => $playlist->hashid,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertDatabaseCount(Like::class, 1);
|
||||
$response->assertOk();
|
||||
$response->assertJson([
|
||||
'data' => [
|
||||
'ToggleLike' => [
|
||||
'playlist' => [
|
||||
'id' => $playlist->hashid,
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
});
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Enums\Auth\CrudPermission;
|
||||
use App\Models\Auth\User;
|
||||
use App\Models\User\WatchHistory;
|
||||
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
|
||||
use App\Models\Wiki\Video;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
beforeEach(function () {
|
||||
$this->mutation = '
|
||||
mutation($entryId: Int!, $videoId: Int!) {
|
||||
Watch(entryId: $entryId, videoId: $videoId) {
|
||||
animethemeentry {
|
||||
id
|
||||
}
|
||||
video {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
';
|
||||
});
|
||||
|
||||
test('protected', function () {
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'entryId' => fake()->randomDigitNotNull(),
|
||||
'videoId' => fake()->randomDigitNotNull(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
test('forbidden', function () {
|
||||
actingAs(User::factory()->createOne());
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'entryId' => fake()->randomDigitNotNull(),
|
||||
'videoId' => fake()->randomDigitNotNull(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'authorization');
|
||||
});
|
||||
|
||||
test('invalid entry id or video id', function () {
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::CREATE->format(WatchHistory::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$entry = AnimeThemeEntry::factory()->createOne();
|
||||
$video = Video::factory()->createOne();
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'entryId' => $entry->getKey(),
|
||||
'videoId' => $video->getKey(),
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'validation');
|
||||
$this->assertArrayHasKey('entryId', $response->json('errors.0.extensions.validation'));
|
||||
$this->assertArrayHasKey('videoId', $response->json('errors.0.extensions.validation'));
|
||||
});
|
||||
|
||||
test('mark as watched', function () {
|
||||
$user = User::factory()
|
||||
->withPermissions(CrudPermission::CREATE->format(WatchHistory::class))
|
||||
->createOne();
|
||||
|
||||
actingAs($user);
|
||||
|
||||
$entry = AnimeThemeEntry::factory()->createOne();
|
||||
$video = Video::factory()->createOne();
|
||||
|
||||
$entry->videos()->attach($video);
|
||||
|
||||
$response = graphql([
|
||||
'query' => $this->mutation,
|
||||
'variables' => [
|
||||
'entryId' => $entry->getKey(),
|
||||
'videoId' => $video->getKey(),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertDatabaseCount(WatchHistory::class, 1);
|
||||
$response->assertOk();
|
||||
$response->assertJson([
|
||||
'data' => [
|
||||
'Watch' => [
|
||||
'animethemeentry' => [
|
||||
'id' => $entry->getKey(),
|
||||
],
|
||||
'video' => [
|
||||
'id' => $video->getKey(),
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
});
|
||||
@@ -4,6 +4,45 @@ declare(strict_types=1);
|
||||
|
||||
use App\Models\Wiki\Anime;
|
||||
|
||||
test('fails query season anime field without year', function () {
|
||||
$animes = Anime::factory()
|
||||
->count(fake()->randomDigitNotNull())
|
||||
->create();
|
||||
|
||||
$response = graphql([
|
||||
'query' => '
|
||||
query($season: AnimeSeason!) {
|
||||
animeyears {
|
||||
year
|
||||
season(season: $season) {
|
||||
season
|
||||
anime {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
seasons {
|
||||
season
|
||||
anime {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
',
|
||||
'variables' => [
|
||||
'season' => $animes->random()->getAttribute(Anime::ATTRIBUTE_SEASON)->name,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'validation');
|
||||
$this->assertArrayHasKey('year', $response->json('errors.0.extensions.validation'));
|
||||
});
|
||||
|
||||
test('query season & seasons field', function () {
|
||||
$animes = Anime::factory()
|
||||
->count(fake()->randomDigitNotNull())
|
||||
@@ -29,7 +68,6 @@ test('query season & seasons field', function () {
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
|
||||
$response->assertJsonStructure([
|
||||
'data' => [
|
||||
'animeyears' => [[
|
||||
@@ -42,48 +80,6 @@ test('query season & seasons field', function () {
|
||||
]);
|
||||
});
|
||||
|
||||
test('fails query season anime field without year', function () {
|
||||
$animes = Anime::factory()
|
||||
->count(fake()->randomDigitNotNull())
|
||||
->create();
|
||||
|
||||
$response = graphql([
|
||||
'query' => '
|
||||
query($season: AnimeSeason!) {
|
||||
animeyears {
|
||||
year
|
||||
season(season: $season) {
|
||||
season
|
||||
anime {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
seasons {
|
||||
season {
|
||||
anime {
|
||||
data {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
',
|
||||
'variables' => [
|
||||
'season' => $animes->random()->getAttribute(Anime::ATTRIBUTE_SEASON)->name,
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonCount(1, 'errors');
|
||||
$response->assertJsonStructure([
|
||||
'errors' => [['message']],
|
||||
]);
|
||||
});
|
||||
|
||||
test('query season anime field with year', function () {
|
||||
$animes = Anime::factory()
|
||||
->count(fake()->randomDigitNotNull())
|
||||
|
||||
@@ -25,9 +25,9 @@ test('fails without id or link', function () {
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonStructure([
|
||||
'errors' => [['message']],
|
||||
]);
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'validation');
|
||||
$this->assertArrayHasKey('id', $response->json('errors.0.extensions.validation'));
|
||||
$this->assertArrayHasKey('link', $response->json('errors.0.extensions.validation'));
|
||||
});
|
||||
|
||||
test('fails with for than 100 ids', function () {
|
||||
@@ -35,7 +35,7 @@ test('fails with for than 100 ids', function () {
|
||||
|
||||
$response = graphql([
|
||||
'query' => '
|
||||
query($site: ResourceSite!, ids: [Int!]) {
|
||||
query($site: ResourceSite!, $ids: [Int!]) {
|
||||
findAnimeByExternalSite(site: $site, id: $ids) {
|
||||
id
|
||||
}
|
||||
@@ -48,9 +48,8 @@ test('fails with for than 100 ids', function () {
|
||||
]);
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertJsonStructure([
|
||||
'errors' => [['message']],
|
||||
]);
|
||||
$response->assertJsonPath('errors.0.extensions.category', 'validation');
|
||||
$this->assertArrayHasKey('id', $response->json('errors.0.extensions.validation'));
|
||||
});
|
||||
|
||||
test('passes with id', function () {
|
||||
|
||||
Reference in New Issue
Block a user