Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚑 Fixed issues around the season endpoint #515

Merged
merged 2 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions app/Repositories/DefaultAnimeRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@
use App\Anime;
use App\Contracts\AnimeRepository;
use App\Contracts\Repository;
use App\Enums\AnimeRatingEnum;
use App\Enums\AnimeScheduleFilterEnum;
use App\Enums\AnimeSeasonEnum;
use App\Enums\AnimeStatusEnum;
use App\Enums\AnimeTypeEnum;
use Illuminate\Contracts\Database\Query\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Carbon;
use Jikan\Helper\Constants;
use Laravel\Scout\Builder as ScoutBuilder;

/**
Expand Down Expand Up @@ -120,44 +117,49 @@
?string $premiered = null
): EloquentBuilder
{
/** @noinspection PhpParamsInspection */
$queryable = $this->queryable(true);

$airedFilter = ["aired.from" => [
$airedFilter = ['aired.from' => [
'$gte' => $from->toAtomString(),
'$lte' => $to->modify("last day of this month")->toAtomString()
'$lte' => $to->modify('last day of this month')->toAtomString()
]];

$finalFilter = [];

// if the premiered parameter for the filter is not null, look for those items which have a premiered attribute set,
// and equals to the parameter value, OR look for those items which doesn't have premired attribute set,
// they don't have a garbled aired string and their aired.from date is within the from-to parameters range
// they don't have a garbled aired string and their aired.from date is within the from-to parameters range.
// Additionally, we want to include all those items which are carry overs from previous seasons.
if ($premiered !== null) {
$finalFilter['$or'] = [
["premiered" => $premiered],
['premiered' => $premiered],
[
"premiered" => null,
"aired.string" => [
'$not' => ['$regex' => "{$from->year} to ?"]
'premiered' => null,
'aired.string' => [
'$nin' => ["{$from->year} to ?"]
],
...$airedFilter
],
// this condition will include "continuing" items from previous seasons
[
'aired.from' => ['$lte' => $from->toAtomString()],
'airing' => true
]
];
} else {
$finalFilter = array_merge($finalFilter, $airedFilter);
$finalFilter["aired.string"] = [
'$not' => ['$regex' => "{$from->year} to ?"]
$finalFilter['aired.string'] = [
'$nin' => ["{$from->year} to ?"]

Check warning on line 152 in app/Repositories/DefaultAnimeRepository.php

View check run for this annotation

Codecov / codecov/patch

app/Repositories/DefaultAnimeRepository.php#L151-L152

Added lines #L151 - L152 were not covered by tests
];
}

if (!is_null($type)) {
$finalFilter["type"] = $type->label;
$finalFilter['type'] = $type->label;

Check warning on line 157 in app/Repositories/DefaultAnimeRepository.php

View check run for this annotation

Codecov / codecov/patch

app/Repositories/DefaultAnimeRepository.php#L157

Added line #L157 was not covered by tests
}

$queryable = $queryable->whereRaw($finalFilter);

return $queryable->orderBy("members", "desc");
return $queryable->orderBy('members', 'desc');
}

public function getUpcomingSeasonItems(
Expand Down
2 changes: 1 addition & 1 deletion app/Support/CachedData.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public function isExpired(): bool

$expiry = $this->expiry();

return time() > $expiry;
return Carbon::now()->unix() > $expiry;
}

public function toArray(): array
Expand Down
3 changes: 2 additions & 1 deletion app/Support/RepositoryQueryBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Support;
use Laravel\Scout\Builder as ScoutBuilder;
use Illuminate\Contracts\Database\Query\Builder;
use Jenssegers\Mongodb\Eloquent\Builder as MongoDbBuilder;

class RepositoryQueryBase
{
Expand All @@ -15,7 +16,7 @@ public function __construct(
{
}

protected function queryable(bool $createNew = false): Builder
protected function queryable(bool $createNew = false): Builder|MongoDbBuilder
{
if ($createNew) {
$callback = $this->getQueryable;
Expand Down
89 changes: 88 additions & 1 deletion tests/Integration/SeasonControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function testShouldFilterOutAnimeWithGarbledAiredString()
$state = $f->serializeStateDefinition([
"aired" => new CarbonDateRange($carbonStartDate, null)
]);
$state["aired"]["string"] = "Jan 1, 2024 to ?";
$state["aired"]["string"] = "2024 to ?";
$state["premiered"] = null;
$state["status"] = "Not yet aired";
$state["airing"] = false;
Expand All @@ -49,4 +49,91 @@ public function testShouldFilterOutAnimeWithGarbledAiredString()
$this->assertIsArray($content["data"]);
$this->assertCount(1, $content["data"]);
}

public function testShouldNotFilterOutFutureAiringDates()
{
Carbon::setTestNow(Carbon::parse("2024-01-11"));
// an item in the future airing
$f = Anime::factory(1);
$startDate = "2024-02-24";
$carbonStartDate = Carbon::parse($startDate);
$state = $f->serializeStateDefinition([
"aired" => new CarbonDateRange($carbonStartDate, null)
]);
$state["aired"]["string"] = "Feb 24, 2024 to ?";
$state["premiered"] = null;
$state["status"] = "Not yet aired";
$state["airing"] = false;
$f->create($state);

// the "garbled" wrong item
$f = Anime::factory(1);
$startDate = "2024-01-01";
$carbonStartDate = Carbon::parse($startDate);
$state = $f->serializeStateDefinition([
"aired" => new CarbonDateRange($carbonStartDate, null)
]);
$state["aired"]["string"] = "2024 to ?";
$state["premiered"] = null;
$state["status"] = "Not yet aired";
$state["airing"] = false;
$f->create($state);

// the absolutely correct item
$f = Anime::factory(1);
$state = $f->serializeStateDefinition([
"aired" => new CarbonDateRange(Carbon::parse("2024-01-10"), Carbon::parse("2024-02-15"))
]);
$state["premiered"] = "Winter 2024";
$state["status"] = "Currently Airing";
$state["airing"] = true;
$f->create($state);

$content = $this->getJsonResponse([], "/v4/seasons/2024/winter");
$this->seeStatusCode(200);
$this->assertIsArray($content["data"]);
$this->assertCount(2, $content["data"]);
}

public function testShouldNotFilterOutContinuingItemsFromPreviousSeasons()
{
Carbon::setTestNow(Carbon::parse("2024-01-11"));
// an item in the future airing
$f = Anime::factory(1);
$startDate = "2024-02-24";
$carbonStartDate = Carbon::parse($startDate);
$state = $f->serializeStateDefinition([
"aired" => new CarbonDateRange($carbonStartDate, null)
]);
$state["aired"]["string"] = "Feb 24, 2024 to ?";
$state["premiered"] = null;
$state["status"] = "Not yet aired";
$state["airing"] = false;
$f->create($state);

// the absolutely correct item
$f = Anime::factory(1);
$state = $f->serializeStateDefinition([
"aired" => new CarbonDateRange(Carbon::parse("2024-01-10"), Carbon::parse("2024-02-15"))
]);
$state["premiered"] = "Winter 2024";
$state["status"] = "Currently Airing";
$state["airing"] = true;
$f->create($state);

// the continuing item
$f = Anime::factory(1);
$state = $f->serializeStateDefinition([
"aired" => new CarbonDateRange(Carbon::parse("2023-10-10"), null)
]);
$state["premiered"] = "Fall 2023";
$state["status"] = "Currently Airing";
$state["airing"] = true;
$f->create($state);

$content = $this->getJsonResponse([], "/v4/seasons/2024/winter");
$this->seeStatusCode(200);
$this->assertIsArray($content["data"]);
$this->assertCount(3, $content["data"]);
}
}
28 changes: 14 additions & 14 deletions tests/Unit/DefaultCachedScraperServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ private function makeCtorArgMocks(int $repositoryWhereCallCount = 1): array
public function testIfFindListReturnsNotExpiredItems()
{
$testRequestHash = $this->requestHash();
$now = Carbon::now();
$now = Carbon::createFromDate(2022, 1, 11, "UTC")->addHours(8)->addMinutes(12);
Carbon::setTestNow($now);
// the cached data in the database
// this should be an array of arrays as builder->get() returns multiple items
Expand All @@ -76,14 +76,14 @@ public function testIfFindListReturnsNotExpiredItems()
public function testIfFindListUpdatesCacheIfItemsExpired()
{
$testRequestHash = $this->requestHash();
$now = Carbon::now();
$now = Carbon::createFromDate(2022, 1, 11, "UTC")->addHours(8)->addMinutes(12);
Carbon::setTestNow($now);

// the cached data in the database
// this should be an array of arrays as builder->get() returns multiple items
$dummyResults = collect([[
"request_hash" => $testRequestHash,
"modifiedAt" => new UTCDateTime($now->sub("2 days")->getPreciseTimestamp(3)),
"modifiedAt" => new UTCDateTime($now->copy()->subDays(2)->getPreciseTimestamp(3)),
"results" => [
["dummy" => "dummy1"],
["dummy" => "dummy2"]
Expand Down Expand Up @@ -128,7 +128,7 @@ function () use (&$updatedData) {
public function testIfFindListUpdatesCacheIfCacheIsEmpty()
{
$testRequestHash = $this->requestHash();
$now = Carbon::now();
$now = Carbon::createFromDate(2022, 1, 11, "UTC")->addHours(8)->addMinutes(12);
Carbon::setTestNow($now);

// the data returned by the scraper
Expand Down Expand Up @@ -175,7 +175,7 @@ public function testIfFindReturnsNotExpiredItems()
{
$malId = 1;
$testRequestHash = $this->requestHash();
$now = Carbon::now();
$now = Carbon::createFromDate(2022, 1, 11, "UTC")->addHours(8)->addMinutes(12);
Carbon::setTestNow($now);
$mockModel = Anime::factory()->makeOne([
"mal_id" => $malId,
Expand All @@ -197,7 +197,7 @@ public function testIfFindScrapesNotFoundKey()
{
$malId = 1;
$testRequestHash = $this->requestHash();
$now = Carbon::now();
$now = Carbon::createFromDate(2022, 1, 11, "UTC")->addHours(8)->addMinutes(12);
Carbon::setTestNow($now);
$mockModel = Anime::factory()->makeOne([
"mal_id" => $malId,
Expand All @@ -224,11 +224,11 @@ public function testIfFindUpdatesExpiredDbItem()
{
$malId = 1;
$testRequestHash = $this->requestHash();
$now = Carbon::now();
$now = Carbon::createFromDate(2022, 1, 11, "UTC")->addHours(8)->addMinutes(12);
$mockModel = Anime::factory()->makeOne([
"mal_id" => $malId,
"modifiedAt" => new UTCDateTime($now->sub("3 days")->getPreciseTimestamp(3)),
"createdAt" => new UTCDateTime($now->sub("3 days")->getPreciseTimestamp(3))
"modifiedAt" => new UTCDateTime($now->copy()->sub("3 days")->getPreciseTimestamp(3)),
"createdAt" => new UTCDateTime($now->copy()->sub("3 days")->getPreciseTimestamp(3))
]);
$now = Carbon::now();
Carbon::setTestNow($now);
Expand Down Expand Up @@ -264,7 +264,7 @@ public function testIfFindByKeyReturnsNotExpiredItems()
{
$username = "kompot";
$testRequestHash = $this->requestHash();
$now = Carbon::now();
$now = Carbon::createFromDate(2022, 1, 11, "UTC")->addHours(8)->addMinutes(12);
Carbon::setTestNow($now);
$mockModel = Profile::factory()->makeOne([
"username" => $username,
Expand All @@ -287,7 +287,7 @@ public function testIfFindByKeyScrapesNotFoundKey()
{
$username = "kompot";
$testRequestHash = $this->requestHash();
$now = Carbon::now();
$now = Carbon::createFromDate(2022, 1, 11, "UTC")->addHours(8)->addMinutes(12);
Carbon::setTestNow($now);
$mockModel = Profile::factory()->makeOne([
"username" => $username,
Expand Down Expand Up @@ -319,12 +319,12 @@ public function testIfFindByKeyUpdatesCache()
$malId = 1;
$username = "kompot";
$testRequestHash = $this->requestHash();
$now = Carbon::now();
$now = Carbon::createFromDate(2022, 1, 11, "UTC")->addHours(8)->addMinutes(12);
$mockModel = Profile::factory()->makeOne([
"mal_id" => $malId,
"username" => $username,
"modifiedAt" => new UTCDateTime($now->sub("3 days")->getPreciseTimestamp(3)),
"createdAt" => new UTCDateTime($now->sub("3 days")->getPreciseTimestamp(3))
"modifiedAt" => new UTCDateTime($now->copy()->sub("3 days")->getPreciseTimestamp(3)),
"createdAt" => new UTCDateTime($now->copy()->sub("3 days")->getPreciseTimestamp(3))
]);
$now = Carbon::now();
Carbon::setTestNow($now);
Expand Down