Merge pull request #549 from jikan-me/bugfix/548

🐛 Fixed an issue with casting query string params on `/top/reviews` endpoint
This commit is contained in:
pushrbx 2024-10-15 19:01:45 +01:00 committed by GitHub
commit 744bd69aea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 56 additions and 19 deletions

View File

@ -4,7 +4,6 @@ namespace App\Dto;
use App\Concerns\HasRequestFingerprint; use App\Concerns\HasRequestFingerprint;
use App\Contracts\DataRequest; use App\Contracts\DataRequest;
use App\DataPipes\MapRouteParametersDataPipe;
use App\Dto\Concerns\MapsRouteParameters; use App\Dto\Concerns\MapsRouteParameters;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection; use Illuminate\Http\Resources\Json\ResourceCollection;
@ -13,12 +12,6 @@ use Spatie\LaravelData\Attributes\Validation\Min;
use Spatie\LaravelData\Attributes\Validation\Numeric; use Spatie\LaravelData\Attributes\Validation\Numeric;
use Spatie\LaravelData\Attributes\Validation\Required; use Spatie\LaravelData\Attributes\Validation\Required;
use Spatie\LaravelData\Data; use Spatie\LaravelData\Data;
use Spatie\LaravelData\DataPipeline;
use Spatie\LaravelData\DataPipes\AuthorizedDataPipe;
use Spatie\LaravelData\DataPipes\CastPropertiesDataPipe;
use Spatie\LaravelData\DataPipes\DefaultValuesDataPipe;
use Spatie\LaravelData\DataPipes\MapPropertiesDataPipe;
use Spatie\LaravelData\DataPipes\ValidatePropertiesDataPipe;
/** /**
* Base class for all requests/commands which are for looking up things by id. * Base class for all requests/commands which are for looking up things by id.

View File

@ -2,14 +2,12 @@
namespace App\Dto; namespace App\Dto;
use App\Casts\ContextualBooleanCast;
use App\Casts\EnumCast; use App\Casts\EnumCast;
use App\Concerns\HasRequestFingerprint; use App\Concerns\HasRequestFingerprint;
use App\Contracts\DataRequest; use App\Contracts\DataRequest;
use App\Dto\Concerns\HasPreliminaryParameter; use App\Dto\Concerns\HasPreliminaryParameter;
use App\Dto\Concerns\HasSpoilersParameter; use App\Dto\Concerns\HasSpoilersParameter;
use App\Dto\Concerns\PreparesData; use App\Dto\Concerns\PreparesData;
use App\Enums\TopAnimeFilterEnum;
use App\Enums\TopReviewsTypeEnum; use App\Enums\TopReviewsTypeEnum;
use App\Rules\Attributes\EnumValidation; use App\Rules\Attributes\EnumValidation;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@ -23,6 +21,6 @@ final class QueryTopReviewsCommand extends QueryTopItemsCommand implements DataR
{ {
use HasRequestFingerprint, HasPreliminaryParameter, HasSpoilersParameter, PreparesData; use HasRequestFingerprint, HasPreliminaryParameter, HasSpoilersParameter, PreparesData;
#[WithCast(EnumCast::class, TopAnimeFilterEnum::class), EnumValidation(TopReviewsTypeEnum::class)] #[WithCast(EnumCast::class, TopReviewsTypeEnum::class), EnumValidation(TopReviewsTypeEnum::class)]
public TopReviewsTypeEnum|Optional $type; public TopReviewsTypeEnum|Optional $type;
} }

View File

@ -7,7 +7,6 @@ use App\Enums\TopReviewsTypeEnum;
use App\Support\CachedData; use App\Support\CachedData;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Jikan\Helper\Constants;
use Jikan\MyAnimeList\MalClient; use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Reviews\ReviewsRequest; use Jikan\Request\Reviews\ReviewsRequest;
@ -31,7 +30,7 @@ final class QueryTopReviewsHandler extends RequestHandlerWithScraperCache
$preliminary = $requestParams->get("preliminary", true); $preliminary = $requestParams->get("preliminary", true);
return $this->scraperService->findList( return $this->scraperService->findList(
$requestFingerPrint, $requestFingerPrint,
fn (MalClient $jikan, ?int $page = null) => $jikan->getReviews(new ReviewsRequest($type, $page, $spoilers, $preliminary)), fn (MalClient $jikan, ?int $page = null) => $jikan->getReviews(new ReviewsRequest(ensureEnumPrimitiveValue($type), $page, $spoilers, $preliminary)),
$requestParams->get("page")); $requestParams->get("page"));
} }
} }

View File

@ -3,6 +3,7 @@
namespace App\Http\Resources\V4; namespace App\Http\Resources\V4;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use OpenApi\Annotations as OA;
class ReviewsResource extends JsonResource class ReviewsResource extends JsonResource
{ {

View File

@ -114,3 +114,12 @@ if (! function_exists('cache')) {
return app('cache')->put(key($arguments[0]), reset($arguments[0]), $arguments[1] ?? null); return app('cache')->put(key($arguments[0]), reset($arguments[0]), $arguments[1] ?? null);
} }
} }
if (!function_exists("ensureEnumPrimitiveValue")) {
function ensureEnumPrimitiveValue(int|string|bool|float|null|\Spatie\Enum\Laravel\Enum $value): mixed {
if ($value instanceof \Spatie\Enum\Laravel\Enum) {
return $value->value;
}
return $value;
}
}

14
composer.lock generated
View File

@ -4554,16 +4554,16 @@
}, },
{ {
"name": "jikan-me/jikan", "name": "jikan-me/jikan",
"version": "v4.0.11", "version": "v4.0.12",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/jikan-me/jikan.git", "url": "https://github.com/jikan-me/jikan.git",
"reference": "fcc8d20817ce29332b496a21652b9965c6c8196c" "reference": "dcb47237a9407473f484bd28a5e44479cdd916fc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/jikan-me/jikan/zipball/fcc8d20817ce29332b496a21652b9965c6c8196c", "url": "https://api.github.com/repos/jikan-me/jikan/zipball/dcb47237a9407473f484bd28a5e44479cdd916fc",
"reference": "fcc8d20817ce29332b496a21652b9965c6c8196c", "reference": "dcb47237a9407473f484bd28a5e44479cdd916fc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4602,7 +4602,7 @@
"description": "Jikan is an unofficial MyAnimeList API", "description": "Jikan is an unofficial MyAnimeList API",
"support": { "support": {
"issues": "https://github.com/jikan-me/jikan/issues", "issues": "https://github.com/jikan-me/jikan/issues",
"source": "https://github.com/jikan-me/jikan/tree/v4.0.11" "source": "https://github.com/jikan-me/jikan/tree/v4.0.12"
}, },
"funding": [ "funding": [
{ {
@ -4610,7 +4610,7 @@
"type": "patreon" "type": "patreon"
} }
], ],
"time": "2024-05-30T08:15:50+00:00" "time": "2024-09-20T22:15:42+00:00"
}, },
{ {
"name": "jms/metadata", "name": "jms/metadata",
@ -13591,5 +13591,5 @@
"ext-mongodb": "*" "ext-mongodb": "*"
}, },
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "2.6.0" "plugin-api-version": "2.3.0"
} }

View File

@ -7,6 +7,11 @@ use App\Person;
use App\Testing\ScoutFlush; use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction; use App\Testing\SyntheticMongoDbTransaction;
use Illuminate\Database\Eloquent\Factories\Sequence; use Illuminate\Database\Eloquent\Factories\Sequence;
use Jikan\Exception\BadResponseException;
use Jikan\Exception\ParserException;
use Jikan\Model\Reviews\Reviews;
use Jikan\MyAnimeList\MalClient;
use Jikan\Parser\Reviews\ReviewsParser;
use Tests\TestCase; use Tests\TestCase;
class TopControllerTest extends TestCase class TopControllerTest extends TestCase
@ -14,6 +19,15 @@ class TopControllerTest extends TestCase
use SyntheticMongoDbTransaction; use SyntheticMongoDbTransaction;
use ScoutFlush; use ScoutFlush;
public function topReviewTypeParametersProvider(): array
{
return [
"empty query string" => [[]],
"query string = `?type=anime`" => [["type" => "anime"]],
"query string = `?type=manga`" => [["type" => "manga"]],
];
}
public function testTopAnime() public function testTopAnime()
{ {
Anime::factory(3)->state(new Sequence( Anime::factory(3)->state(new Sequence(
@ -290,4 +304,27 @@ class TopControllerTest extends TestCase
$this->get('/v4/top/anime/999') $this->get('/v4/top/anime/999')
->seeStatusCode(404); ->seeStatusCode(404);
} }
/**
* @dataProvider topReviewTypeParametersProvider
* @param $params
* @return void
* @throws BadResponseException
* @throws ParserException
*/
public function testTopReviews($params)
{
$jikanParser = \Mockery::mock(MalClient::class)->makePartial();
$reviewsParser = \Mockery::mock(ReviewsParser::class)->makePartial();
$reviewsParser->allows()->getReviews()->andReturn([]);
$reviewsParser->allows()->hasNextPage()->andReturn(false);
$reviewsFacade = Reviews::fromParser($reviewsParser);
/** @noinspection PhpParamsInspection */
$jikanParser->allows()->getReviews(\Mockery::any())->andReturn($reviewsFacade);
$this->app->instance('JikanParser', $jikanParser);
$this->getJsonResponse($params,"/v4/top/reviews");
$this->seeStatusCode(200);
}
} }