feat(graphql): made animethemeShuffle.spoiler optional (#1093)

This commit is contained in:
Kyrch
2026-02-10 02:10:56 -03:00
committed by GitHub
parent 747d1d8fc3
commit 5e7b03b167
5 changed files with 209 additions and 6 deletions
@@ -64,9 +64,7 @@ class AnimeThemeShuffleQuery extends BaseQuery
new Argument(self::ATTRIBUTE_YEAR_GTE, Type::int()),
new Argument(self::ATTRIBUTE_SPOILER, Type::boolean())
->required()
->withDefaultValue(false),
new Argument(self::ATTRIBUTE_SPOILER, Type::boolean()),
];
}
@@ -100,7 +98,11 @@ class AnimeThemeShuffleQuery extends BaseQuery
}
});
$builder->whereRelation(AnimeTheme::RELATION_ENTRIES, AnimeThemeEntry::ATTRIBUTE_SPOILER, Arr::boolean($args, self::ATTRIBUTE_SPOILER));
$builder->whereHas(AnimeTheme::RELATION_VIDEOS);
if (is_bool($spoiler = Arr::get($args, self::ATTRIBUTE_SPOILER))) {
$builder->whereRelation(AnimeTheme::RELATION_ENTRIES, AnimeThemeEntry::ATTRIBUTE_SPOILER, $spoiler);
}
$builder->inRandomOrder();
+2
View File
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace App\Http;
use App\Http\Middleware\Api\SetAcceptJsonHeader;
use App\Http\Middleware\Api\SetServingJsonApi;
use App\Http\Middleware\Auth\Authenticate;
use App\Http\Middleware\Auth\RedirectIfAuthenticated;
use App\Http\Middleware\GraphQL\RateLimitPerQuery;
@@ -90,6 +91,7 @@ class Kernel extends HttpKernel
'throttle:api',
SubstituteBindings::class,
LogRequest::class,
SetServingJsonApi::class,
],
'graphql' => [
@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace App\Http\Middleware\Api;
use Closure;
use Illuminate\Http\Request;
class SetServingJsonApi
{
public static bool $isServing = false;
/**
* @param Closure(Request): mixed $next
*/
public function handle(Request $request, Closure $next): mixed
{
static::$isServing = true;
return $next($request);
}
}
+2 -2
View File
@@ -15,7 +15,7 @@ use App\Events\Wiki\Anime\Theme\ThemeDeleting;
use App\Events\Wiki\Anime\Theme\ThemeRestored;
use App\Events\Wiki\Anime\Theme\ThemeUpdated;
use App\Http\Api\Schema\Wiki\Anime\ThemeSchema;
use App\Http\Middleware\GraphQL\SetServingGraphQL;
use App\Http\Middleware\Api\SetServingJsonApi;
use App\Models\BaseModel;
use App\Models\Wiki\Anime;
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
@@ -89,7 +89,7 @@ class AnimeTheme extends BaseModel implements Auditable, InteractsWithSchema, So
{
parent::boot();
if (! SetServingGraphQL::$isServing) {
if (SetServingJsonApi::$isServing) {
static::addGlobalScope(new WithoutInsertSongScope);
}
}
@@ -0,0 +1,176 @@
<?php
declare(strict_types=1);
use App\Enums\Models\Wiki\AnimeMediaFormat;
use App\Enums\Models\Wiki\ThemeType;
use App\Models\Wiki\Anime;
use App\Models\Wiki\Anime\AnimeTheme;
use App\Models\Wiki\Anime\Theme\AnimeThemeEntry;
use App\Models\Wiki\Video;
use Illuminate\Support\Arr;
use Illuminate\Testing\Fluent\AssertableJson;
test('filter by theme type', function () {
$type = Arr::random(ThemeType::cases());
AnimeTheme::factory()
->state([AnimeTheme::ATTRIBUTE_TYPE => $type->value])
->has(AnimeThemeEntry::factory()->has(Video::factory()))
->count(fake()->randomDigitNotNull())
->create();
AnimeTheme::factory()
->has(AnimeThemeEntry::factory()->has(Video::factory()))
->count(fake()->randomDigitNotNull())
->create();
$response = graphql([
'query' => '
query($type: [ThemeType!]) {
animethemeShuffle(type: $type) {
type
}
}
',
'variables' => [
'type' => [$type->name],
],
]);
$response->assertOk();
$response->assertJsonCount(1);
$response->assertJson(
fn (AssertableJson $json) => $json->has(
'data.animethemeShuffle',
fn (AssertableJson $themes) => $themes->each(fn (AssertableJson $theme) => $theme->where(AnimeTheme::ATTRIBUTE_TYPE, $type->name))
)
);
});
test('filter by anime media format', function () {
$format = Arr::random(AnimeMediaFormat::cases());
AnimeTheme::factory()
->for(Anime::factory()->state([Anime::ATTRIBUTE_MEDIA_FORMAT => $format->value]))
->has(AnimeThemeEntry::factory()->has(Video::factory()))
->count(fake()->randomDigitNotNull())
->create();
AnimeTheme::factory()
->has(AnimeThemeEntry::factory()->has(Video::factory()))
->count(fake()->randomDigitNotNull())
->create();
$response = graphql([
'query' => '
query($format: [AnimeMediaFormat!]) {
animethemeShuffle(mediaFormat: $format) {
anime {
mediaFormat
}
}
}
',
'variables' => [
'format' => [$format->name],
],
]);
$response->assertOk();
$response->assertJsonCount(1);
$response->assertJson(
fn (AssertableJson $json) => $json->has(
'data.animethemeShuffle',
fn (AssertableJson $themes) => $themes->each(fn (AssertableJson $theme) => $theme->where('anime.mediaFormat', $format->name))
)
);
});
test('filter by year', function () {
$yearGte = fake()->numberBetween(1964, date('Y') - 1);
$yearLte = fake()->numberBetween($yearGte, date('Y'));
AnimeTheme::factory()
->for(Anime::factory()->state([Anime::ATTRIBUTE_YEAR => fake()->numberBetween($yearLte, $yearGte)]))
->has(AnimeThemeEntry::factory()->has(Video::factory()))
->count(fake()->randomDigitNotNull())
->create();
AnimeTheme::factory()
->has(AnimeThemeEntry::factory()->has(Video::factory()))
->count(fake()->randomDigitNotNull())
->create();
$response = graphql([
'query' => '
query($yearLte: Int, $yearGte: Int) {
animethemeShuffle(year_lte: $yearLte, year_gte: $yearGte) {
anime {
year
}
}
}
',
'variables' => [
'yearLte' => $yearLte,
'yearGte' => $yearGte,
],
]);
$response->assertOk();
$response->assertJsonCount(1);
$response->assertJson(
fn (AssertableJson $json) => $json->has(
'data.animethemeShuffle',
fn (AssertableJson $themes) => $themes->each(fn (AssertableJson $theme) => $theme->where('anime.year', fn (int $year) => $year <= $yearLte)
->where('anime.year', fn (int $year) => $year >= $yearGte))
)
);
});
test('filter by entry spoiler', function () {
$spoiler = fake()->boolean();
AnimeTheme::factory()
->for(Anime::factory())
->has(AnimeThemeEntry::factory()->state([AnimeThemeEntry::ATTRIBUTE_SPOILER => $spoiler])->has(Video::factory()))
->count(fake()->randomDigitNotNull())
->create();
AnimeTheme::factory()
->has(AnimeThemeEntry::factory()->has(Video::factory()))
->count(fake()->randomDigitNotNull())
->create();
$response = graphql([
'query' => '
query($spoiler: Boolean) {
animethemeShuffle(spoiler: $spoiler) {
animethemeentries {
spoiler
}
}
}
',
'variables' => [
'spoiler' => $spoiler,
],
]);
$response->assertOk();
$response->assertJsonCount(1);
$response->assertJson(
fn (AssertableJson $json) => $json->has(
'data.animethemeShuffle',
fn (AssertableJson $themes) => $themes->each(
fn (AssertableJson $theme) => $theme->has(
AnimeTheme::RELATION_ENTRIES,
fn (AssertableJson $entries) => $entries->each(
fn (AssertableJson $entry) => $entry->where(AnimeThemeEntry::ATTRIBUTE_SPOILER, $spoiler)
)
)
)
)
);
});