refactored tests and fixed test runner issues

- additionally fixed some bugs with schedule endpoint
This commit is contained in:
pushrbx 2023-02-05 00:55:11 +00:00
parent a530e9f5d6
commit baa5e9c557
44 changed files with 2971 additions and 970 deletions

View File

@ -8,7 +8,6 @@ use App\Enums\AnimeRatingEnum;
use App\Enums\AnimeStatusEnum;
use App\Http\Resources\V4\AnimeCollection;
use App\Rules\Attributes\EnumValidation;
use Spatie\Enum\Laravel\Rules\EnumRule;
use Spatie\LaravelData\Attributes\MapInputName;
use Spatie\LaravelData\Attributes\MapOutputName;
use Spatie\LaravelData\Attributes\Validation\IntegerType;

View File

@ -10,11 +10,11 @@ use App\Contracts\DataRequest;
use App\Dto\Concerns\HasLimitParameter;
use App\Dto\Concerns\HasPageParameter;
use App\Dto\Concerns\HasSfwParameter;
use App\Dto\Concerns\MapsRouteParameters;
use App\Dto\Concerns\PreparesData;
use App\Enums\AnimeScheduleFilterEnum;
use App\Rules\Attributes\EnumValidation;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Spatie\LaravelData\Attributes\Validation\BooleanType;
use Spatie\LaravelData\Attributes\WithCast;
use Spatie\LaravelData\Data;
@ -25,26 +25,11 @@ use Spatie\LaravelData\Optional;
*/
final class QueryAnimeSchedulesCommand extends Data implements DataRequest
{
use HasLimitParameter, HasRequestFingerprint, HasPageParameter, PreparesData, HasSfwParameter;
use HasLimitParameter, HasRequestFingerprint, HasPageParameter, PreparesData, HasSfwParameter, MapsRouteParameters;
#[BooleanType, WithCast(ContextualBooleanCast::class)]
public bool|Optional $kids = false;
#[WithCast(EnumCast::class, AnimeScheduleFilterEnum::class), EnumValidation(AnimeScheduleFilterEnum::class)]
public ?AnimeScheduleFilterEnum $filter;
/** @noinspection PhpUnused */
public static function fromRequestAndDay(Request $request, ?string $day): self
{
/**
* @var QueryAnimeSchedulesCommand $data
*/
$data = self::fromRequest($request);
if (!is_null($day)) {
$data->filter = AnimeScheduleFilterEnum::from($day);
}
return $data;
}
public ?AnimeScheduleFilterEnum $dayFilter;
}

View File

@ -0,0 +1,7 @@
<?php
namespace App\Exceptions;
class CustomTestException extends \Exception
{
}

View File

@ -24,7 +24,7 @@ final class QueryAnimeSchedulesHandler implements RequestHandler
public function handle($request)
{
$limit = intval($request->limit ?? Env::get("MAX_RESULTS_PER_PAGE", 25));
$results = $this->repository->getCurrentlyAiring($request->filter, $request->kids, $request->sfw);
$results = $this->repository->getCurrentlyAiring($request->dayFilter, $request->kids, $request->sfw);
$results = $results->paginate(
$limit,
["*"],

View File

@ -3,7 +3,6 @@
namespace App\Http\Controllers\V4DB;
use App\Dto\QueryAnimeSchedulesCommand;
use Illuminate\Http\Request;
class ScheduleController extends Controller
{
@ -74,9 +73,13 @@ class ScheduleController extends Controller
* }
* )
*/
public function main(Request $request, ?string $day = null)
public function main(QueryAnimeSchedulesCommand $command)
{
$command = QueryAnimeSchedulesCommand::from($request, $day);
return $this->mediator->send($command);
}
// public function byDay(QueryAnimeSchedulesByDayCommand $command)
// {
// return $this->mediator->send($command);
// }
}

View File

@ -3,11 +3,12 @@
namespace App;
use App\Concerns\FilteredByLetter;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Jikan\Request\Producer\ProducerRequest;
class Producers extends JikanApiSearchableModel
{
use FilteredByLetter;
use FilteredByLetter, HasFactory;
protected array $filters = ["order_by", "sort", "letter"];
/**

View File

@ -3,11 +3,12 @@
namespace App;
use App\Concerns\FilteredByLetter;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Jikan\Request\User\UserProfileRequest;
class Profile extends JikanApiSearchableModel
{
use FilteredByLetter;
use FilteredByLetter, HasFactory;
protected array $filters = [];
/**

View File

@ -280,8 +280,8 @@ class AppServiceProvider extends ServiceProvider
];
foreach ($requestHandlersWithScraperService as $handlerClass => $repositoryInstance) {
$jikan = $app->make(MalClient::class);
$serializer = $app->make("SerializerV4");
$jikan = $app->get("JikanParser");
$serializer = $app->get("SerializerV4");
$scraperService = $app->make(DefaultCachedScraperService::class,
["repository" => $repositoryInstance, "jikan" => $jikan, "serializer" => $serializer]);
$requestHandlers[] = $app->make($handlerClass, [

View File

@ -52,7 +52,16 @@ trait SyntheticMongoDbTransaction
"manga_reviews",
"manga_stats",
"manga_userupdates",
"people_pictures"
"people_pictures",
"reviews",
"recommendations",
"themes_anime",
"themes_manga",
"users_history",
"users_friends",
"users_recommendations",
"users_reviews",
"users_clubs"
];
foreach ($jikanModels as $jikanModel)

View File

@ -0,0 +1,32 @@
<?php
namespace App\Testing;
use App\Exceptions\CustomTestException;
use App\Exceptions\Handler;
use Illuminate\Http\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use TypeError;
/**
* An exception handler class which helps to highlight errors during tests.
*/
class TestExceptionsHandler extends Handler
{
/**
* @throws \Throwable
* @throws CustomTestException
*/
public function render($request, \Throwable $e): JsonResponse|Response
{
if ($e instanceof CustomTestException) {
throw $e;
}
if ($e instanceof TypeError) {
throw $e;
}
return parent::render($request, $e);
}
}

View File

@ -137,7 +137,7 @@ $httpClient = \Symfony\Component\HttpClient\HttpClient::create(
);
$app->instance('HttpClient', $httpClient);
$jikan = new \Jikan\MyAnimeList\MalClient(app('HttpClient'));
$jikan = new \Jikan\MyAnimeList\MalClient($httpClient);
$app->instance('JikanParser', $jikan);
$app->instance('SerializerV4', SerializerFactory::createV4());

View File

@ -29,6 +29,18 @@ class AnimeFactory extends JikanMediaModelFactory
return [
"mal_id" => $mal_id,
"url" => $this->createMalUrl($mal_id, "anime"),
"images" => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644.jpg',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644t.jpg',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644l.jpg',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644.webp',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644t.webp',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644l.webp',
],
],
"titles" => [
[
"type" => "Default",
@ -48,11 +60,11 @@ class AnimeFactory extends JikanMediaModelFactory
"duration" => "",
"rating" => $this->getRandomRating(),
"score" => $this->faker->randomFloat(2, 1.00, 9.99),
"scored_by" => $this->faker->randomDigitNotNull(),
"rank" => $this->faker->randomDigitNotNull(),
"popularity" => $this->faker->randomDigitNotNull(),
"members" => $this->faker->randomDigitNotNull(),
"favorites" => $this->faker->randomDigitNotNull(),
"scored_by" => $this->faker->randomDigitNotnull(),
"rank" => $this->faker->randomDigitNotnull(),
"popularity" => $this->faker->randomDigitNotnull(),
"members" => $this->faker->randomDigitNotnull(),
"favorites" => $this->faker->randomDigitNotnull(),
"synopsis" => "test",
"background" => "test",
"premiered" => $this->faker->randomElement(["Winter", "Spring", "Fall", "Summer"]),
@ -62,6 +74,18 @@ class AnimeFactory extends JikanMediaModelFactory
"timezone" => "Asia/Tokyo",
"string" => "Tuesdays at 00:00 (JST)"
],
'trailer' => [
'youtube_id' => null,
'url' => null,
'embed_url' => null,
'images' => [
'image_url' => null,
'small_image_url' => null,
'medium_image_url' => null,
'large_image_url' => null,
'maximum_image_url' => null,
],
],
"producers" => [
[
"mal_id" => 16,
@ -70,7 +94,7 @@ class AnimeFactory extends JikanMediaModelFactory
"url" => "https://myanimelist.net/anime/producer/16/TV_Tokyo"
]
],
"lincesors" => [
"licensors" => [
[
"mal_id" => 119,
"type" => "anime",
@ -78,7 +102,14 @@ class AnimeFactory extends JikanMediaModelFactory
"url" => "https://myanimelist.net/anime/producer/119/VIZ_Media"
]
],
"studios" => [],
"studios" => [
[
'mal_id' => 14,
'type' => 'anime',
'name' => 'Sunrise',
'url' => 'https://myanimelist.net/anime/producer/14/Sunrise',
]
],
"genres" => [
[
"mal_id" => 1,

View File

@ -33,11 +33,11 @@ class CharacterFactory extends JikanModelFactory
"name" => $this->faker->name(),
"name_kanji" => "",
"nicknames" => [],
"favorites" => $this->faker->randomDigitNotNull(),
"member_favorites" => $this->faker->randomDigitNotNull(),
"about" => "test",
"createdAt" => new UTCDateTime(),
"modifiedAt" => new UTCDateTime(),
"request_hash" => sprintf("request:%s:%s", "v4", $this->getItemTestUrl("character", $mal_id)),
"request_hash" => sprintf("request:%s:%s", "characters", $this->getItemTestUrl("character", $mal_id)),
"animeography" => [],
"mangaography" => [],
"voice_actors" => [
@ -45,7 +45,11 @@ class CharacterFactory extends JikanModelFactory
"person" => [
"mal_id" => 11,
"url" => "https://myanimelist.net/people/11/Kouichi_Yamadera",
"images" => [],
"images" => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/voiceactors/1/16847.jpg',
],
],
"name" => "Yamadera, Kouichi"
],
"language" => "Japanese"

View File

@ -201,8 +201,10 @@ abstract class JikanMediaModelFactory extends JikanModelFactory implements Media
}
if ($this->descriptor->hasRatingParam() && $additionalParams->has("rating")) {
$overrides["rating"] = AnimeRatingEnum::from(strtolower($additionalParams["rating"]))->label;
$v = AnimeRatingEnum::tryFrom(strtolower($additionalParams["rating"]));
if (!is_null($v)) {
$overrides["rating"] = $v->value;
}
}
if ($additionalParams->has("genres")) {

View File

@ -22,6 +22,18 @@ class MangaFactory extends JikanMediaModelFactory
return [
"mal_id" => $mal_id,
"url" => $this->createMalUrl($mal_id, "manga"),
"images" => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644.jpg',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644t.jpg',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644l.jpg',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644.webp',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644t.webp',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644l.webp',
],
],
"titles" => [
[
"type" => "Default",

View File

@ -27,17 +27,26 @@ class PersonFactory extends JikanModelFactory
"mal_id" => $mal_id,
"url" => $this->createMalUrl($mal_id, "people"),
"website_url" => "https://webiste.example",
"images" => [],
"images" => [
"jpg" => [
"image_url" => "https://cdn.myanimelist.net/images/voiceactors/1/55486.jpg"
]
],
"name" => $name,
"given_name" => $given_name,
"family_name" => $family_name,
"alternate_names" => [],
"alternate_names" => [
$this->faker->name()
],
"birthday" => $this->createRandomDateTime("-80 years")->toAtomString(),
"favorites" => $this->faker->randomDigitNotNull(),
"member_favorites" => $this->faker->randomDigitNotNull(),
"about" => "test",
"createdAt" => new UTCDateTime(),
"modifiedAt" => new UTCDateTime(),
"request_hash" => sprintf("request:%s:%s", "v4", $this->getItemTestUrl("people", $mal_id))
"request_hash" => sprintf("request:%s:%s", "v4", $this->getItemTestUrl("people", $mal_id)),
"published_manga" => [],
"voice_acting_roles" => [],
"anime_staff_positions" => []
];
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace Database\Factories;
use App\Producers;
use App\Testing\JikanDataGenerator;
use Carbon\Carbon;
use MongoDB\BSON\UTCDateTime;
class ProducersFactory extends JikanModelFactory
{
use JikanDataGenerator;
protected $model = Producers::class;
protected function definitionInternal(): array
{
$mal_id = $this->createMalId();
$url = $this->createMalUrl($mal_id, "anime/producer");
return [
"mal_id" => $mal_id,
"url" => $url,
"request_hash" => sprintf("request:%s:%s", "producers", $this->getItemTestUrl("producers", $mal_id)),
"images" => [
"jpg" => [
"image_url" => "https://cdn.myanimelist.net/images/company/441.png"
]
],
"name" => $this->faker->name(),
"titles" => [
[
"type" => "Default",
"title" => $this->faker->name()
]
],
"createdAt" => new UTCDateTime(),
"modifiedAt" => new UTCDateTime(),
"favorites" => 535,
"established" => new UTCDateTime(Carbon::now()->sub($this->faker->randomNumber(2, true) . " days")->getPreciseTimestamp(3)),
"about" => "",
"external_links" => [
[
"name" => $this->faker->name(),
"url" => $this->faker->url()
]
],
"count" => $this->faker->randomNumber()
];
}
}

View File

@ -0,0 +1,170 @@
<?php
namespace Database\Factories;
use App\Profile;
use App\Testing\JikanDataGenerator;
use MongoDB\BSON\UTCDateTime;
final class ProfileFactory extends JikanModelFactory
{
use JikanDataGenerator;
protected $model = Profile::class;
protected function definitionInternal(): array
{
$mal_id = $this->createMalId();
$username = $this->faker->userName();
$url = $this->createMalUrl($username, "profile");
return [
"mal_id" => $mal_id,
"username" => $username,
"url" => $url,
"request_hash" => sprintf("request:%s:%s", "users", $this->getItemTestUrl("users", $username)),
"images" => [
"jpg" => [
"image_url" => $this->faker->url()
],
"webp" => [
"image_url" => $this->faker->url()
]
],
"last_online" => new UTCDateTime($this->faker->dateTimeBetween('-5 years')->format('Uv')),
"gender" => $this->faker->randomElement(["Male", "Female", "Other"]),
"birthday" => new UTCDateTime($this->faker->dateTimeBetween('-60 years')->format('Uv')),
"location" => $this->faker->country(),
"joined" => new UTCDateTime($this->faker->dateTimeBetween('-5 years')->format('Uv')),
"createdAt" => new UTCDateTime(),
"modifiedAt" => new UTCDateTime(),
"anime_stats" => [
'days_watched' => 106.8,
'mean_score' => 8.21,
'watching' => 44,
'completed' => 449,
'on_hold' => 15,
'dropped' => 3,
'plan_to_watch' => 426,
'total_entries' => 937,
'rewatched' => 22,
'episodes_watched' => 6305,
],
"manga_stats" => [
'days_read' => 91,
'mean_score' => 8.45,
'reading' => 380,
'completed' => 145,
'on_hold' => 3,
'dropped' => 1,
'plan_to_read' => 58,
'total_entries' => 587,
'reread' => 1,
'chapters_read' => 16263,
'volumes_read' => 777,
],
"favorites" => [
"anime" => [
[
'mal_id' => 9253,
'url' => 'https://myanimelist.net/anime/9253/Steins_Gate',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/5/73199.jpg?s=bd7fc157718660193b28926006b3fd1c',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/5/73199t.jpg?s=bd7fc157718660193b28926006b3fd1c',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/5/73199l.jpg?s=bd7fc157718660193b28926006b3fd1c',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/5/73199.webp?s=bd7fc157718660193b28926006b3fd1c',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/5/73199t.webp?s=bd7fc157718660193b28926006b3fd1c',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/5/73199l.webp?s=bd7fc157718660193b28926006b3fd1c',
],
],
'title' => 'Steins;Gate',
'type' => 'TV',
'start_year' => 2011,
]
],
"manga" => [
[
'mal_id' => 642,
'url' => 'https://myanimelist.net/manga/642/Vinland_Saga',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/manga/2/188925.jpg?s=967b5e2908beae63c5c22e61176ef728',
'small_image_url' => 'https://cdn.myanimelist.net/images/manga/2/188925t.jpg?s=967b5e2908beae63c5c22e61176ef728',
'large_image_url' => 'https://cdn.myanimelist.net/images/manga/2/188925l.jpg?s=967b5e2908beae63c5c22e61176ef728',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/manga/2/188925.webp?s=967b5e2908beae63c5c22e61176ef728',
'small_image_url' => 'https://cdn.myanimelist.net/images/manga/2/188925t.webp?s=967b5e2908beae63c5c22e61176ef728',
'large_image_url' => 'https://cdn.myanimelist.net/images/manga/2/188925l.webp?s=967b5e2908beae63c5c22e61176ef728',
],
],
'title' => 'Vinland Saga',
'type' => 'Manga',
'start_year' => 2005,
]
],
"characters" => [
[
'mal_id' => 34470,
'url' => 'https://myanimelist.net/character/34470/Kurisu_Makise',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/characters/10/114399.jpg?s=f259c43bfc8346dad813e9491d507165',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/characters/10/114399.webp?s=f259c43bfc8346dad813e9491d507165',
'small_image_url' => 'https://cdn.myanimelist.net/images/characters/10/114399t.webp?s=f259c43bfc8346dad813e9491d507165',
],
],
'name' => 'Makise, Kurisu',
]
],
"people" => [
[
'mal_id' => 39950,
'url' => 'https://myanimelist.net/people/39950/Sayuri',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/voiceactors/1/57707.jpg?s=2998fa772aea87259bbf3855e6c52043',
],
],
'name' => 'Sayuri',
]
]
],
"last_updates" => [
"anime" => [
[
'entry' => [
'mal_id' => 15227,
'url' => 'https://myanimelist.net/anime/15227/Kono_Sekai_no_Katasumi_ni',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/2/87704.jpg?s=222f784bad4c7505ec2761715f585cc9',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/2/87704t.jpg?s=222f784bad4c7505ec2761715f585cc9',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/2/87704l.jpg?s=222f784bad4c7505ec2761715f585cc9',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/2/87704.webp?s=222f784bad4c7505ec2761715f585cc9',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/2/87704t.webp?s=222f784bad4c7505ec2761715f585cc9',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/2/87704l.webp?s=222f784bad4c7505ec2761715f585cc9',
],
],
'title' => 'Kono Sekai no Katasumi ni',
],
'score' => 0,
'status' => 'Plan to Watch',
'episodes_seen' => NULL,
'episodes_total' => NULL,
'date' => '2022-05-19T23:38:00+00:00',
]
],
"manga" => []
],
"about" => "",
];
}
}

View File

@ -6,9 +6,6 @@
verbose="true"
>
<testsuites>
<testsuite name="http-integration">
<directory>./tests/HttpV4/</directory>
</testsuite>
<testsuite name="integration">
<directory>./tests/Integration/</directory>
</testsuite>

View File

@ -269,7 +269,7 @@ $router->group(
}
);
$router->get('schedules[/{day:[A-Za-z]+}]', [
$router->get('schedules[/{dayFilter:[A-Za-z]+}]', [
'uses' => 'ScheduleController@main'
]);

View File

@ -1,261 +0,0 @@
<?php
/** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\Integration;
use App\Anime;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Illuminate\Support\Facades\DB;
use MongoDB\BSON\UTCDateTime;
use Tests\TestCase;
class AnimeControllerTest extends TestCase
{
use SyntheticMongoDbTransaction;
use ScoutFlush;
public function __construct($name = null, array $data = [], $dataName = '')
{
parent::__construct($name, $data, $dataName);
$this->searchIndexModelCleanupList = ["App\\Anime"];
}
private function givenDummyCharactersStaffData($uri)
{
DB::table("anime_characters_staff")->insert([
"createdAt" => new UTCDateTime(),
"modifiedAt" => new UTCDateTime(),
"request_hash" => "request:anime:" . sha1($uri),
"characters" => [
[
"character" => [
"mal_id" => 3,
"url" => "https://myanimelist.net/character/3/Jet_Black",
"images" => [
"jpg" => [
"image_url" => "https://cdn.myanimelist.net/images/characters/11/253723.jpg?s=6c8a19a79a88c46ae15f30e3ef5fd839",
"small_image_url" => "https://cdn.myanimelist.net/images/characters/11/253723t.jpg?s=6c8a19a79a88c46ae15f30e3ef5fd839"
],
"webp" => [
"image_url" => "https://cdn.myanimelist.net/images/characters/11/253723.webp?s=6c8a19a79a88c46ae15f30e3ef5fd839",
"small_image_url" => "https://cdn.myanimelist.net/images/characters/11/253723t.webp?s=6c8a19a79a88c46ae15f30e3ef5fd839"
]
],
"name" => "Black, Jet"
],
"role" => "Main",
"favorites" => 1,
"voice_actors" => [
[
"person" => [
"mal_id" => 357,
"url" => "https://myanimelist.net/people/357/Unshou_Ishizuk",
"images" => [
"jpg" => [
"image_url" => "https://cdn.myanimelist.net/images/voiceactors/2/17135.jpg?s=5925123b8a7cf9b51a445c225442f0ef"
]
],
"name" => "Ishizuka, Unshou"
],
"language" => "Japanese"
]
]
]
],
"staff" => [
[
"person" => [
"mal_id" => 40009,
"url" => "https://myanimelist.net/people/40009/Yutaka_Maseba",
"images" => [
"jpg" => [
"image_url" => "https://cdn.myanimelist.net/images/voiceactors/3/40216.jpg?s=d9fb7a625868ec7d9cd3804fa0da3fd6"
]
],
"name" => "Maseba, Yutaka"
],
"positions" => [
"Producer"
]
]
]
]);
}
public function testMain()
{
Anime::factory(1)->create([
"mal_id" => 1
]);
$this->getJson('/v4/anime/1')
->seeStatusCode(200)
->seeJsonStructure(['data' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'trailer' => [
'youtube_id',
'url',
'embed_url',
'images' => [
'image_url',
'small_image_url',
'medium_image_url',
'large_image_url',
'maximum_image_url',
]
],
'title',
'title_english',
'title_japanese',
'title_synonyms',
'type',
'source',
'episodes',
'status',
'airing',
'aired' => [
'from',
'to',
'prop' => [
'from' => [
'day',
'month',
'year'
],
'to' => [
'day',
'month',
'year'
]
],
'string'
],
'duration',
'rating',
'score',
'scored_by',
'rank',
'popularity',
'members',
'favorites',
'synopsis',
'background',
'season',
'year',
'broadcast' => [
'day',
'time',
'timezone',
'string'
],
'producers' => [
[
'mal_id',
'type',
'name',
'url'
]
],
'licensors' => [
[
'mal_id',
'type',
'name',
'url'
]
],
'studios' => [
[
'mal_id',
'type',
'name',
'url'
]
],
'genres' => [
[
'mal_id',
'type',
'name',
'url'
]
],
]]);
}
public function testCharacters()
{
// let's avoid sending request to MAL in tests
$this->givenDummyCharactersStaffData("/v4/anime/1/characters");
$this->getJson('/v4/anime/1/characters')
->seeStatusCode(200)
->seeJsonStructure(['data' => [
[
'character' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
],
'webp' => [
'image_url',
'small_image_url',
],
],
'name',
],
'role',
'voice_actors' => [
[
'person' => [
'mal_id',
'images' => [
'jpg' => [
'image_url',
],
],
'name'
],
'language'
]
]
]
]]);
}
public function testStaff()
{
$this->givenDummyCharactersStaffData('/v4/anime/1/staff');
$this->getJson('/v4/anime/1/staff')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
[
'person' => [
'mal_id',
'images' => [
'jpg' => [
'image_url',
],
],
'name'
],
'positions'
]
]]);
}
}

View File

@ -1,154 +0,0 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Tests\TestCase;
class PersonControllerTest extends TestCase
{
use SyntheticMongoDbTransaction;
use ScoutFlush;
public function testMain()
{
$this->get('/v4/people/1')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
'mal_id',
'url',
'website_url',
'images' => [
'jpg' => [
'image_url',
],
],
'name',
'given_name',
'family_name',
'alternate_names',
'birthday',
'favorites',
'about',
]]);
}
public function testAnimeography()
{
$this->get('/v4/people/1/anime')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
[
'position',
'anime' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
]
]
]]);
}
public function testMangaography()
{
$this->get('/v4/characters/1/manga')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
[
'role',
'manga' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
]
]
]]);
}
public function testVoices()
{
$this->get('/v4/people/1/voices')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
[
'role',
'anime' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'character' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
],
'webp' => [
'image_url',
'small_image_url',
],
],
'name'
]
]
]]);
}
public function testPictures()
{
$this->get('/v4/people/1/pictures')
->seeStatusCode(200)
->seeJsonStructure([
'data' => [
[
'jpg' => [
'image_url'
]
]
]
]);
}
public function test404()
{
$this->get('/v4/people/1000000')
->seeStatusCode(404);
}
}

View File

@ -1,55 +0,0 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Tests\TestCase;
class RecommendationsControllerTest extends TestCase
{
use SyntheticMongoDbTransaction;
use ScoutFlush;
public function testAnimeRecommendations()
{
$this->get('/v4/recommendations/anime')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'mal_id',
'entry' => [
[
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
]
],
'content',
'date',
'user' => [
'username',
'url',
],
]
]
]);
}
}

View File

@ -1,123 +0,0 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Tests\TestCase;
class ReviewsControllerTest extends TestCase
{
use SyntheticMongoDbTransaction;
use ScoutFlush;
public function testAnimeReviews()
{
$this->get('/v4/reviews/anime')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'mal_id',
'url',
'type',
'reactions',
'date',
'review',
'score',
'tags',
'is_spoiler',
'is_preliminary',
'episodes_watched',
'entry' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'user' => [
'username',
'url',
'images' => [
'jpg' => [
'image_url'
],
'webp' => [
'image_url'
]
]
],
]
]
]);
}
public function testMangaReviews()
{
$this->get('/v4/reviews/manga')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'mal_id',
'url',
'type',
'reactions',
'date',
'review',
'score',
'tags',
'is_spoiler',
'is_preliminary',
'chapters_read',
'entry' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'user' => [
'username',
'url',
'images' => [
'jpg' => [
'image_url'
],
'webp' => [
'image_url'
]
]
],
]
]
]);
}
}

View File

@ -1,99 +0,0 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Tests\TestCase;
class ScheduleControllerTest extends TestCase
{
use SyntheticMongoDbTransaction;
use ScoutFlush;
public function testSchedule()
{
$this->get('/v4/schedules')
->seeStatusCode(200)
->seeJsonStructure(['data' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'trailer' => [
'youtube_id',
'url',
'embed_url',
'images' => [
'image_url',
'small_image_url',
'medium_image_url',
'large_image_url',
'maximum_image_url',
]
],
'title',
'title_english',
'title_japanese',
'title_synonyms',
'type',
'source',
'episodes',
'status',
'airing',
'aired' => [
'from',
'to',
'prop' => [
'from' => [
'day',
'month',
'year'
],
'to' => [
'day',
'month',
'year'
]
],
'string'
],
'duration',
'rating',
'score',
'scored_by',
'rank',
'popularity',
'members',
'favorites',
'synopsis',
'background',
'season',
'year',
'broadcast' => [
'day',
'time',
'timezone',
'string'
],
'producers',
'licensors',
'studios',
'genres',
]]);
}
public function test400()
{
$this->get('/v4/schedules/asdjkhas')
->seeStatusCode(400);
}
}

View File

@ -1,180 +0,0 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Tests\TestCase;
class WatchControllerTest extends TestCase
{
use SyntheticMongoDbTransaction;
use ScoutFlush;
public function testWatchEpisodes()
{
$this->get('/v4/watch/episodes')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'entry' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'episodes' => [
[
'mal_id',
'url',
'title',
'premium'
]
],
]
]
]);
$this->get('/v4/watch/episodes/popular')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'entry' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'episodes' => [
[
'mal_id',
'url',
'title',
'premium'
]
],
]
]
]);
}
public function testWatchPromos()
{
$this->get('/v4/watch/promos')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'title',
'entry' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'trailer' => [
'youtube_id',
'url',
'embed_url',
'images' => [
'image_url',
'small_image_url',
'medium_image_url',
'large_image_url',
'maximum_image_url',
]
],
]
]
]);
$this->get('/v4/watch/promos/popular')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'title',
'entry' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'trailer' => [
'youtube_id',
'url',
'embed_url',
'images' => [
'image_url',
'small_image_url',
'medium_image_url',
'large_image_url',
'maximum_image_url',
]
],
]
]
]);
}
}

View File

@ -0,0 +1,924 @@
<?php
/** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\Integration;
use App\Anime;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Illuminate\Support\Facades\DB;
use MongoDB\BSON\UTCDateTime;
use Tests\TestCase;
class AnimeControllerTest extends TestCase
{
use SyntheticMongoDbTransaction;
use ScoutFlush;
public function __construct($name = null, array $data = [], $dataName = '')
{
parent::__construct($name, $data, $dataName);
$this->searchIndexModelCleanupList = ["App\\Anime"];
}
public function testMain()
{
Anime::factory(1)->createOne([
"mal_id" => 1,
"studios" => [
[
'mal_id' => 18,
'type' => 'anime',
'name' => 'Toei Animation',
'url' => 'https://myanimelist.net/anime/producer/18/Toei_Animation',
]
],
"producers" => [
[
'mal_id' => 16,
'type' => 'anime',
'name' => 'TV Tokyo',
'url' => 'https://myanimelist.net/anime/producer/16/TV_Tokyo',
]
],
"licensors" => [
[
'mal_id' => 102,
'type' => 'anime',
'name' => 'Funimation',
'url' => 'https://myanimelist.net/anime/producer/102/Funimation',
]
]
]);
$this->getJson('/v4/anime/1')
->seeStatusCode(200)
->seeJsonStructure(['data' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'trailer' => [
'youtube_id',
'url',
'embed_url',
'images' => [
'image_url',
'small_image_url',
'medium_image_url',
'large_image_url',
'maximum_image_url',
]
],
'title',
'title_english',
'title_japanese',
'title_synonyms',
'type',
'source',
'episodes',
'status',
'airing',
'aired' => [
'from',
'to',
'prop' => [
'from' => [
'day',
'month',
'year'
],
'to' => [
'day',
'month',
'year'
]
],
'string'
],
'duration',
'rating',
'score',
'scored_by',
'rank',
'popularity',
'members',
'favorites',
'synopsis',
'background',
'season',
'year',
'broadcast' => [
'day',
'time',
'timezone',
'string'
],
'producers' => [
[
'mal_id',
'type',
'name',
'url'
]
],
'licensors' => [
[
'mal_id',
'type',
'name',
'url'
]
],
'studios' => [
[
'mal_id',
'type',
'name',
'url'
]
],
'genres' => [
[
'mal_id',
'type',
'name',
'url'
]
],
]]);
}
public function testCharacters()
{
// let's avoid sending request to MAL in tests
$this->givenDummyCharactersStaffData("/v4/anime/1/characters", "anime");
$this->getJson('/v4/anime/1/characters')
->seeStatusCode(200)
->seeJsonStructure(['data' => [
[
'character' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
],
'webp' => [
'image_url',
'small_image_url',
],
],
'name',
],
'role',
'voice_actors' => [
[
'person' => [
'mal_id',
'images' => [
'jpg' => [
'image_url',
],
],
'name'
],
'language'
]
]
]
]]);
}
public function testStaff()
{
$this->givenDummyCharactersStaffData('/v4/anime/1/staff', "anime");
$this->getJson('/v4/anime/1/staff')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
[
'person' => [
'mal_id',
'images' => [
'jpg' => [
'image_url',
],
],
'name'
],
'positions'
]
]]);
}
private function dummyEpisode(): array
{
return [
"mal_id" => 301,
"url" => "https://myanimelist.net/anime/516/Keroro_Gunsou/episode/301",
"title" => "Tamama, Exiled from the Nishizawa House, Sir? / Momoka: A Chocolate ",
"title_japanese" => null,
"title_romanji" => null,
"aired" => null,
"filler" => false,
"recap" => false,
"score" => 4.5,
"forum_url" => null
];
}
public function testEpisodesOne()
{
DB::table("anime_episodes")->insert(
$this->dummyResultsDocument("/v4/anime/1/episodes", "anime", [
$this->dummyEpisode()
])
);
$this->get('/v4/anime/1/episodes')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'mal_id',
'url',
'title',
'title_japanese',
'title_romanji',
'aired',
'score',
'filler',
'recap',
'forum_url'
]
]
]);
}
public function testEpisodesTwo()
{
DB::table("anime_episodes")->insert(
$this->dummyResultsDocument(
"/v4/anime/21/episodes?page=2",
"anime",
array_fill(0, 24, $this->dummyEpisode()),
true,
2
)
);
$this->get('/v4/anime/21/episodes?page=2')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'mal_id',
'url',
'title',
'title_japanese',
'title_romanji',
'aired',
'score',
'filler',
'recap',
'forum_url'
]
]
]);
}
public function testEpisode()
{
$document = $this->dummyScraperResultDocument('/v4/anime/21/episodes/1', "anime", [
'mal_id' => 1,
'url' => 'https://myanimelist.net/anime/21/One_Piece/episode/1',
'title' => 'I\'m Luffy! The Man Who\'s Gonna Be King of the Pirates!',
'title_japanese' => '俺はルフィ!海賊王になる男だ!',
'title_romanji' => 'Ore wa Luffy! Kaizoku Ou ni Naru Otoko Da!',
'duration' => 1475,
'aired' => '1999-10-20T00:00:00+09:00',
'filler' => false,
'recap' => false,
'synopsis' => 'The series begins with an attack'
]);
DB::table("anime_episode")->insert($document);
$this->get('/v4/anime/21/episodes/1')
->seeStatusCode(200)
->seeJsonStructure([
'data' => [
'mal_id',
'url',
'title',
'title_japanese',
'title_romanji',
'duration',
'aired',
'aired',
'filler',
'recap',
'synopsis',
]
]);
}
public function testNews()
{
$document = $this->dummyResultsDocument('/v4/anime/1/news', 'anime', [[
'mal_id' => 60609964,
'url' => 'https://myanimelist.net/news/60609964',
'title' => 'North American Anime & Manga Releases for September',
'date' => '2020-08-31T14:34:00+00:00',
'author_username' => 'ImperfectBlue',
'author_url' => 'https://myanimelist.net/profile/ImperfectBlue',
'forum_url' => 'https://myanimelist.net/forum/?topicid=1862079',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/s/common/uploaded_files/1598909553-a6f9acc1b6c36cd7b792e5bd67321c13.png?s=3b52b4fe7a2670d33b32d8397d2776bb',
],
],
'comments' => 0,
'excerpt' => 'Here are the North American anime & manga releases for September Week 1: September 1 - 7 Anime Releases Africa no Salaryman (TV) (Africa Salaryman) Complete Coll...',
]]);
DB::table("anime_news")->insert($document);
$this->get('/v4/anime/1/news')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'mal_id',
'url',
'title',
'date',
'author_username',
'author_url',
'forum_url',
'images' => [
'jpg' => [
'image_url',
],
],
'comments',
'excerpt'
]
]
]);
}
public function testPictures()
{
$document = $this->dummyScraperResultDocument(
'/v4/anime/1/pictures',
'anime',
[[
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/7/3791.jpg',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/7/3791t.jpg',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/7/3791l.jpg',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/7/3791.webp',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/7/3791t.webp',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/7/3791l.webp',
],
]],
'pictures'
);
DB::table("anime_pictures")->insert($document);
$this->get('/v4/anime/1/pictures')
->seeStatusCode(200)
->seeJsonStructure([
'data' => [
[
'jpg' => [
'image_url',
'large_image_url',
'small_image_url',
],
'webp' => [
'image_url',
'large_image_url',
'small_image_url',
]
]
]
]);
}
public function testVideos()
{
$document = $this->dummyScraperResultDocument(
'/v4/anime/1/videos',
'anime',
[
'promo' => [
[
'title' => 'PV Blu-ray Box version',
'trailer' => [
'youtube_id' => 'qig4KOK2R2g',
'url' => 'https://www.youtube.com/watch?v=qig4KOK2R2g',
'embed_url' => 'https://www.youtube.com/embed/qig4KOK2R2g?enablejsapi=1&wmode=opaque&autoplay=1',
'images' => [
'image_url' => 'https://img.youtube.com/vi/qig4KOK2R2g/default.jpg',
'small_image_url' => 'https://img.youtube.com/vi/qig4KOK2R2g/sddefault.jpg',
'medium_image_url' => 'https://img.youtube.com/vi/qig4KOK2R2g/mqdefault.jpg',
'large_image_url' => 'https://img.youtube.com/vi/qig4KOK2R2g/hqdefault.jpg',
'maximum_image_url' => 'https://img.youtube.com/vi/qig4KOK2R2g/maxresdefault.jpg',
],
],
]
],
'episodes' => [
[
'mal_id' => 26,
'title' => 'The Real Folk Blues (part 2)',
'episode' => 'Episode 26',
'url' => 'https://myanimelist.net/anime/1/Cowboy_Bebop/episode/26',
'images' => [
'jpg' => [
'image_url' => 'https://img1.ak.crunchyroll.com/i/spire1-tmb/191b230426f0b0e6568b4ca6edab47321473136587_large.jpg',
],
],
]
],
'music_videos' => [
[
'title' => 'OP 1 (Artist ver.)',
'video' => [
'youtube_id' => 'wbaILDE7Dco',
'url' => 'https://www.youtube.com/watch?v=wbaILDE7Dco',
'embed_url' => 'https://www.youtube.com/embed/wbaILDE7Dco?enablejsapi=1&wmode=opaque&autoplay=1',
'images' => [
'image_url' => 'https://img.youtube.com/vi/wbaILDE7Dco/default.jpg',
'small_image_url' => 'https://img.youtube.com/vi/wbaILDE7Dco/sddefault.jpg',
'medium_image_url' => 'https://img.youtube.com/vi/wbaILDE7Dco/mqdefault.jpg',
'large_image_url' => 'https://img.youtube.com/vi/wbaILDE7Dco/hqdefault.jpg',
'maximum_image_url' => 'https://img.youtube.com/vi/wbaILDE7Dco/maxresdefault.jpg',
],
],
'meta' => [
'title' => '"heavenly blue"',
'author' => 'Kalafina',
],
]
]
]
);
DB::table('anime_videos')->insert($document);
$this->get('/v4/anime/1/videos')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
'promo' => [
[
'title',
'trailer' => [
'youtube_id',
'url',
'embed_url',
'images' => [
'image_url',
'small_image_url',
'medium_image_url',
'large_image_url',
'maximum_image_url',
]
],
]
],
'episodes' => [
[
'mal_id',
'title',
'episode',
'url',
'images' => [
'jpg' => [
'image_url',
],
],
]
],
'music_videos' => [
[
'title',
'video' => [
'youtube_id',
'url',
'embed_url',
'images' => [
'image_url',
'small_image_url',
'medium_image_url',
'large_image_url',
'maximum_image_url',
],
],
'meta' => [
'title',
'author',
],
]
]
]]);
}
public function testStats()
{
$document = $this->dummyScraperResultDocument('/v4/anime/21/statistics', "anime",
[
'watching' => 1293641,
'completed' => 37,
'on_hold' => 239382,
'dropped' => 164598,
'plan_to_watch' => 195375,
'total' => 1893033,
'scores' => [
[
'score' => 1,
'votes' => 9470,
'percentage' => 0.9,
],
[
'score' => 2,
'votes' => 3363,
'percentage' => 0.3,
],
],
]
);
DB::table("anime_stats")->insert($document);
$this->get('/v4/anime/21/statistics')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
'watching',
'completed',
'on_hold',
'dropped',
'plan_to_watch',
'total',
'scores' => [
[
'score',
'votes',
'percentage'
]
]
]]);
}
public function testForum()
{
$document = $this->dummyScraperResultDocument('/v4/anime/1/forum', "anime", [
[
'mal_id' => 2022869,
'url' => 'https://myanimelist.net/forum/?topicid=2022869',
'title' => 'What was the reception like when this first came out?',
'date' => '2022-06-15T00:00:00+00:00',
'author_username' => 'NextUniverse',
'author_url' => 'https://myanimelist.net/profile/NextUniverse',
'comments' => 7,
'last_comment' => [
'url' => 'https://myanimelist.net/forum/?topicid=2022869&goto=lastpost',
'author_username' => 'Bacon_and_Eggs',
'author_url' => 'https://myanimelist.net/profile/Bacon_and_Eggs',
'date' => '2022-06-19T06:26:00+00:00',
],
]
], "topics");
DB::table("anime_forum")->insert($document);
$this->get('/v4/anime/1/forum')
->seeStatusCode(200)
->seeJsonStructure([
'data' => [
[
'mal_id',
'url',
'title',
'date',
'author_username',
'author_url',
'comments',
'last_comment' => [
'url',
'author_username',
'author_url',
'date'
]
]
]
]);
}
public function testMoreInfo()
{
$document = $this->dummyScraperResultDocument('/v4/anime/1/moreinfo', "anime", ["moreinfo" => "asd"]);
DB::table("anime_moreinfo")->insert($document);
$this->get('/v4/anime/1/moreinfo')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
'moreinfo'
]]);
}
public function testReviewsOne()
{
$document = $this->dummyResultsDocument('/v4/anime/1/reviews', "anime", [
[
'mal_id' => 7406,
'url' => 'https://myanimelist.net/reviews.php?id=7406',
'type' => 'anime',
'reactions' => [
'overall' => 2112,
'nice' => 2105,
'love_it' => 3,
'funny' => 1,
'confusing' => 0,
'informative' => 2,
'well_written' => 1,
'creative' => 0,
],
'date' => '2008-08-24T05:46:00+00:00',
'review' => 'People who know me dd',
'score' => 10,
'tags' => [
0 => 'Recommended',
],
'is_spoiler' => false,
'is_preliminary' => false,
'episodes_watched' => NULL,
'user' => [
'url' => 'https://myanimelist.net/profile/TheLlama',
'username' => 'TheLlama',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/userimages/11081.jpg?t=1666216200',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/userimages/11081.webp?t=1666216200',
],
],
],
]
]);
DB::table("anime_reviews")->insert($document);
$this->get('/v4/anime/1/reviews')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'mal_id',
'url',
'type',
'reactions',
'date',
'review',
'score',
'tags',
'is_spoiler',
'is_preliminary',
'episodes_watched',
'user' => [
'url',
'username',
'images' => [
'jpg' => [
'image_url',
],
'webp' => [
'image_url',
],
],
]
]
]
]);
}
public function testReviewsTwo()
{
$this->mockJikanParserWith404RespondingUpstream();
$this->get('/v4/anime/1/reviews?page=100')
->seeStatusCode(404)
->seeJsonStructure([
'status',
'type',
'message',
'error'
]);
}
public function testRecommendations()
{
$document = $this->dummyScraperResultDocument('/v4/anime/1/recommendations', 'anime', [
'recommendations' => [
[
'entry' => [
'mal_id' => 205,
'url' => 'https://myanimelist.net/anime/205/Samurai_Champloo',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/1375/121599.jpg?s=690d61d9517bcc79a007c21f1e9b58e8',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/1375/121599t.jpg?s=690d61d9517bcc79a007c21f1e9b58e8',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/1375/121599l.jpg?s=690d61d9517bcc79a007c21f1e9b58e8',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/1375/121599.webp?s=690d61d9517bcc79a007c21f1e9b58e8',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/1375/121599t.webp?s=690d61d9517bcc79a007c21f1e9b58e8',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/1375/121599l.webp?s=690d61d9517bcc79a007c21f1e9b58e8',
],
],
'title' => 'Samurai Champloo',
],
'url' => 'https://myanimelist.net/recommendations/anime/1-205',
'votes' => 118,
]
]
]);
DB::table('anime_recommendations')->insert($document);
$this->get('/v4/anime/1/recommendations')
->seeStatusCode(200)
->seeJsonStructure([
'data' => [
[
'entry' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'url',
'votes',
]
]
]);
}
public function testAnimeUserUpdates()
{
$document = $this->dummyResultsDocument('/v4/anime/1/userupdates', 'anime', [
[
'user' => [
'username' => 'Mar-E',
'url' => 'https://myanimelist.net/profile/Mar-E',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/userimages/12234611.jpg?t=1675204800',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/userimages/12234611.webp?t=1675204800',
],
],
],
'score' => NULL,
'status' => 'Watching',
'episodes_seen' => 16,
'episodes_total' => 26,
'date' => '2023-01-31T22:34:00+00:00',
]
]);
DB::table("anime_userupdates")->insert($document);
$this->get('/v4/anime/1/userupdates')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'user' => [
'username',
'url',
'images' => [
'jpg' => [
'image_url',
],
'webp' => [
'image_url',
],
],
],
'score',
'status',
'episodes_seen',
'episodes_total',
'date'
]
]
]);
}
public function testAnimeUserUpdatesNotFound()
{
$this->mockJikanParserWith404RespondingUpstream();
$this->get('/v4/anime/1/userupdates?page=200')
->seeStatusCode(404);
}
public function testAnimeRelations()
{
Anime::factory()->createOne([
"mal_id" => 1,
"related" => [
[
'relation' => 'Adaptation',
'entry' => [
0 => [
'mal_id' => 173,
'type' => 'manga',
'name' => 'Cowboy Bebop',
'url' => 'https://myanimelist.net/manga/173/Cowboy_Bebop',
],
1 => [
'mal_id' => 174,
'type' => 'manga',
'name' => 'Shooting Star Bebop: Cowboy Bebop',
'url' => 'https://myanimelist.net/manga/174/Shooting_Star_Bebop__Cowboy_Bebop',
],
],
]
]
]);
$this->get('/v4/anime/1/relations')
->seeStatusCode(200)
->seeJsonStructure([
'data' => [
[
'relation',
'entry' => [
[
'mal_id',
'type',
'name',
'url'
]
],
]
]
]);
}
public function testAnimeThemes()
{
Anime::factory()->createOne([
"mal_id" => 1,
"themes" => [
[
'mal_id' => 50,
'type' => 'anime',
'name' => 'Adult Cast',
'url' => 'https://myanimelist.net/anime/genre/50/Adult_Cast',
]
]
]);
$this->get('/v4/anime/1/themes')
->seeStatusCode(200)
->seeJsonStructure([
'data' => [
'openings',
'endings',
]
]);
}
public function test404()
{
$this->mockJikanParserWith404RespondingUpstream();
$this->get('/v4/anime/2')
->seeStatusCode(404);
}
}

View File

@ -3,6 +3,7 @@ namespace Tests\HttpV4\Controllers;
use App\Character;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
@ -46,7 +47,18 @@ class CharacterControllerTest extends TestCase
"anime" => [
"mal_id" => 1,
"url" => "https://myanimelist.net/anime/1/Cowboy_Bebop",
"images" => [],
"images" => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644.jpg?s=42d7666179a2851c99fada2e0ceb5da1',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644t.jpg?s=42d7666179a2851c99fada2e0ceb5da1',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644l.jpg?s=42d7666179a2851c99fada2e0ceb5da1',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644.webp?s=42d7666179a2851c99fada2e0ceb5da1',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644t.webp?s=42d7666179a2851c99fada2e0ceb5da1',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644l.webp?s=42d7666179a2851c99fada2e0ceb5da1',
],
],
"title" => "Cowboy Bebop"
]
]
@ -88,7 +100,18 @@ class CharacterControllerTest extends TestCase
"manga" => [
"mal_id" => 1,
"url" => "https://myanimelist.net/anime/1/Cowboy_Bebop",
"images" => [],
"images" => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644.jpg?s=42d7666179a2851c99fada2e0ceb5da1',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644t.jpg?s=42d7666179a2851c99fada2e0ceb5da1',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644l.jpg?s=42d7666179a2851c99fada2e0ceb5da1',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644.webp?s=42d7666179a2851c99fada2e0ceb5da1',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644t.webp?s=42d7666179a2851c99fada2e0ceb5da1',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/4/19644l.webp?s=42d7666179a2851c99fada2e0ceb5da1',
],
],
"title" => "Cowboy Bebop"
]
]
@ -146,9 +169,16 @@ class CharacterControllerTest extends TestCase
public function testPictures()
{
Character::factory()->createOne([
"mal_id" => 1
$document = $this->dummyScraperResultDocument('/v4/characters/1/pictures', 'characters', [
'pictures' => [
[
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/characters/10/34138.jpg',
],
]
]
]);
DB::table("characters_pictures")->insert($document);
$this->get('/v4/characters/1/pictures')
->seeStatusCode(200)
->seeJsonStructure([

View File

@ -16,8 +16,8 @@ class ClubControllerTest extends TestCase
Club::factory()->createOne([
"mal_id" => 1
]);
$t = $this->get('/v4/clubs/1');
$t->seeStatusCode(200)
$this->get('/v4/clubs/1')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
'mal_id',
'name',
@ -36,32 +36,22 @@ class ClubControllerTest extends TestCase
public function testMembers()
{
$m = Club::factory()->createOne([
"mal_id" => 1
]);
$dummyUsername = $this->faker->userName();
DB::table("clubs_members")->insert([
// we are just copying the data from the manufactured model out of convenience
"createdAt" => $m->createdAt,
"modifiedAt" => $m->modifiedAt,
"has_next_page" => false,
"last_visible_page" => 1,
"request_hash" => "request:clubs:".sha1("/v4/clubs/1/members"),
"results" => [
[
"username" => $this->faker->userName(),
"url" => "https://myanimelist.net/profile/".$dummyUsername,
"images" => [
"jpg" => [
"image_url" => "http://httpbin.org/get"
],
"webp" => [
"image_url" => "http://httpbin.org/get"
]
$document = $this->dummyResultsDocument('/v4/clubs/1/members', 'clubs', [
[
"username" => $this->faker->userName(),
"url" => "https://myanimelist.net/profile/".$dummyUsername,
"images" => [
"jpg" => [
"image_url" => "http://httpbin.org/get"
],
"webp" => [
"image_url" => "http://httpbin.org/get"
]
]
]
]);
DB::table("clubs_members")->insert($document);
$this->get('/v4/clubs/1/members')
->seeStatusCode(200)
->seeJsonStructure([
@ -84,9 +74,6 @@ class ClubControllerTest extends TestCase
]
]
]);
$this->get('/v4/clubs/1000000/members')
->seeStatusCode(404);
}
public function test404()

View File

@ -1,5 +1,7 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\GenreAnime;
use App\GenreManga;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Tests\TestCase;
@ -11,6 +13,7 @@ class GenreControllerTest extends TestCase
public function testAnimeGenre()
{
GenreAnime::factory()->createOne();
$this->get('/v4/genres/anime')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
@ -25,6 +28,7 @@ class GenreControllerTest extends TestCase
public function testMangaGenre()
{
GenreManga::factory()->createOne();
$this->get('/v4/genres/manga')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[

View File

@ -13,8 +13,8 @@ class MagazineControllerTest extends TestCase
public function testMagazinesListing()
{
Magazine::factory(1)->create();
$test = $this->get('/v4/magazines');
$test->seeStatusCode(200)
$this->get('/v4/magazines')
->seeStatusCode(200)
->seeJsonStructure(['data' => [
[
'mal_id',

View File

@ -1,7 +1,9 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Manga;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
class MangaControllerTest extends TestCase
@ -11,6 +13,9 @@ class MangaControllerTest extends TestCase
public function testMain()
{
Manga::factory()->createOne([
"mal_id" => 1
]);
$this->get('/v4/manga/1')
->seeStatusCode(200)
->seeJsonStructure(['data' => [
@ -91,6 +96,8 @@ class MangaControllerTest extends TestCase
public function testCharacters()
{
$this->givenDummyCharactersStaffData("/v4/manga/1/characters", "manga");
$this->get('/v4/manga/1/characters')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
@ -116,6 +123,23 @@ class MangaControllerTest extends TestCase
public function testNews()
{
$document = $this->dummyResultsDocument('/v4/manga/1/news', 'manga', [[
'mal_id' => 60609964,
'url' => 'https://myanimelist.net/news/60609964',
'title' => 'North American Anime & Manga Releases for September',
'date' => '2020-08-31T14:34:00+00:00',
'author_username' => 'ImperfectBlue',
'author_url' => 'https://myanimelist.net/profile/ImperfectBlue',
'forum_url' => 'https://myanimelist.net/forum/?topicid=1862079',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/s/common/uploaded_files/1598909553-a6f9acc1b6c36cd7b792e5bd67321c13.png?s=3b52b4fe7a2670d33b32d8397d2776bb',
],
],
'comments' => 0,
'excerpt' => 'Here are the North American anime & manga releases for September Week 1: September 1 - 7 Anime Releases Africa no Salaryman (TV) (Africa Salaryman) Complete Coll...',
]]);
DB::table("manga_news")->insert($document);
$this->get('/v4/manga/1/news')
->seeStatusCode(200)
->seeJsonStructure([
@ -146,6 +170,24 @@ class MangaControllerTest extends TestCase
public function testPictures()
{
$document = $this->dummyScraperResultDocument(
'/v4/manga/1/pictures',
'manga',
[[
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/manga/7/3791.jpg',
'small_image_url' => 'https://cdn.myanimelist.net/images/manga/7/3791t.jpg',
'large_image_url' => 'https://cdn.myanimelist.net/images/manga/7/3791l.jpg',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/manga/7/3791.webp',
'small_image_url' => 'https://cdn.myanimelist.net/images/manga/7/3791t.webp',
'large_image_url' => 'https://cdn.myanimelist.net/images/manga/7/3791l.webp',
],
]],
'pictures'
);
DB::table("manga_pictures")->insert($document);
$this->get('/v4/manga/1/pictures')
->seeStatusCode(200)
->seeJsonStructure([
@ -168,6 +210,29 @@ class MangaControllerTest extends TestCase
public function testStats()
{
$document = $this->dummyScraperResultDocument('/v4/manga/1/statistics', "manga",
[
'reading' => 1293641,
'completed' => 37,
'on_hold' => 239382,
'dropped' => 164598,
'plan_to_read' => 195375,
'total' => 1893033,
'scores' => [
[
'score' => 1,
'votes' => 9470,
'percentage' => 0.9,
],
[
'score' => 2,
'votes' => 3363,
'percentage' => 0.3,
],
],
]
);
DB::table("manga_stats")->insert($document);
$this->get('/v4/manga/1/statistics')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
@ -189,6 +254,24 @@ class MangaControllerTest extends TestCase
public function testForum()
{
$document = $this->dummyScraperResultDocument('/v4/manga/1/forum', "manga", [
[
'mal_id' => 2022869,
'url' => 'https://myanimelist.net/forum/?topicid=2022869',
'title' => 'What was the reception like when this first came out?',
'date' => '2022-06-15T00:00:00+00:00',
'author_username' => 'NextUniverse',
'author_url' => 'https://myanimelist.net/profile/NextUniverse',
'comments' => 7,
'last_comment' => [
'url' => 'https://myanimelist.net/forum/?topicid=2022869&goto=lastpost',
'author_username' => 'Bacon_and_Eggs',
'author_url' => 'https://myanimelist.net/profile/Bacon_and_Eggs',
'date' => '2022-06-19T06:26:00+00:00',
],
]
], "topics");
DB::table("manga_forum")->insert($document);
$this->get('/v4/manga/1/forum')
->seeStatusCode(200)
->seeJsonStructure([
@ -214,6 +297,8 @@ class MangaControllerTest extends TestCase
public function testMoreInfo()
{
$document = $this->dummyScraperResultDocument('/v4/manga/1/moreinfo', "manga", ["moreinfo" => "asd"]);
DB::table("manga_moreinfo")->insert($document);
$this->get('/v4/manga/1/moreinfo')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
@ -223,6 +308,45 @@ class MangaControllerTest extends TestCase
public function testReviews()
{
$document = $this->dummyResultsDocument('/v4/manga/1/reviews', "manga", [
[
'mal_id' => 7406,
'url' => 'https://myanimelist.net/reviews.php?id=7406',
'type' => 'manga',
'reactions' => [
'overall' => 2112,
'nice' => 2105,
'love_it' => 3,
'funny' => 1,
'confusing' => 0,
'informative' => 2,
'well_written' => 1,
'creative' => 0,
],
'date' => '2008-08-24T05:46:00+00:00',
'review' => 'People who know me dd',
'score' => 10,
'tags' => [
0 => 'Recommended',
],
'is_spoiler' => false,
'is_preliminary' => false,
'chapters_read' => null,
'user' => [
'url' => 'https://myanimelist.net/profile/TheLlama',
'username' => 'TheLlama',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/userimages/11081.jpg?t=1666216200',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/userimages/11081.webp?t=1666216200',
],
],
],
]
]);
DB::table("manga_reviews")->insert($document);
$this->get('/v4/manga/1/reviews')
->seeStatusCode(200)
->seeJsonStructure([
@ -258,20 +382,49 @@ class MangaControllerTest extends TestCase
]
]
]);
}
public function testReviewsTwo()
{
$this->mockJikanParserWith404RespondingUpstream();
$this->get('/v4/manga/1/reviews?page=100')
->seeStatusCode(404)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => []
'status',
'type',
'message',
'error'
]);
}
public function testRecommendations()
{
$document = $this->dummyScraperResultDocument('/v4/manga/1/recommendations', 'manga', [
'recommendations' => [
[
'entry' => [
'mal_id' => 205,
'url' => 'https://myanimelist.net/anime/205/Samurai_Champloo',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/1375/121599.jpg?s=690d61d9517bcc79a007c21f1e9b58e8',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/1375/121599t.jpg?s=690d61d9517bcc79a007c21f1e9b58e8',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/1375/121599l.jpg?s=690d61d9517bcc79a007c21f1e9b58e8',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/1375/121599.webp?s=690d61d9517bcc79a007c21f1e9b58e8',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/1375/121599t.webp?s=690d61d9517bcc79a007c21f1e9b58e8',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/1375/121599l.webp?s=690d61d9517bcc79a007c21f1e9b58e8',
],
],
'title' => 'Samurai Champloo',
],
'url' => 'https://myanimelist.net/recommendations/anime/1-205',
'votes' => 118,
]
]
]);
DB::table('manga_recommendations')->insert($document);
$this->get('/v4/manga/1/recommendations')
->seeStatusCode(200)
->seeJsonStructure([
@ -303,6 +456,30 @@ class MangaControllerTest extends TestCase
public function testUserUpdates()
{
$document = $this->dummyResultsDocument('/v4/manga/1/userupdates', 'manga', [
[
'user' => [
'username' => 'Mar-E',
'url' => 'https://myanimelist.net/profile/Mar-E',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/userimages/12234611.jpg?t=1675204800',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/userimages/12234611.webp?t=1675204800',
],
],
],
'score' => NULL,
'status' => 'Watching',
'volumes_read' => 16,
'volumes_total' => 26,
'chapters_read' => 22,
'chapters_total' => 22,
'date' => '2023-01-31T22:34:00+00:00',
]
]);
DB::table("manga_userupdates")->insert($document);
$this->get('/v4/manga/1/userupdates')
->seeStatusCode(200)
->seeJsonStructure([
@ -334,13 +511,39 @@ class MangaControllerTest extends TestCase
]
]
]);
}
public function testUserUpdatesNotFound()
{
$this->mockJikanParserWith404RespondingUpstream();
$this->get('/v4/manga/1/userupdates?page=200')
->seeStatusCode(404);
}
public function testMangaRelations()
{
Manga::factory()->createOne([
"mal_id" => 1,
"related" => [
[
'relation' => 'Other',
'entry' => [
[
'mal_id' => 793,
'type' => 'manga',
'name' => 'Wanted!',
'url' => 'https://myanimelist.net/manga/793/Wanted',
],
[
'mal_id' => 25146,
'type' => 'manga',
'name' => 'One Piece x Toriko',
'url' => 'https://myanimelist.net/manga/25146/One_Piece_x_Toriko',
],
],
]
]
]);
$this->get('/v4/manga/1/relations')
->seeStatusCode(200)
->seeJsonStructure([
@ -362,6 +565,7 @@ class MangaControllerTest extends TestCase
public function test404()
{
$this->mockJikanParserWith404RespondingUpstream();
$this->get('/v4/manga/1000000')
->seeStatusCode(404);
}

View File

@ -0,0 +1,259 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Person;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
class PersonControllerTest extends TestCase
{
use SyntheticMongoDbTransaction;
use ScoutFlush;
public function testMain()
{
Person::factory()->createOne([
"mal_id" => 1
]);
$this->get('/v4/people/1')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
'mal_id',
'url',
'website_url',
'images' => [
'jpg' => [
'image_url',
],
],
'name',
'given_name',
'family_name',
'alternate_names',
'birthday',
'favorites',
'about',
]]);
}
public function testAnimeography()
{
Person::factory()->createOne([
"mal_id" => 1,
"anime_staff_positions" => [
[
'position' => 'Theme Song Performance',
'anime' => [
'mal_id' => 3080,
'url' => 'https://myanimelist.net/anime/3080/Anime_Tenchou',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/9/4635.jpg?s=ad3dd02ed42bccbc84e0bde5c9e4ac7d',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/9/4635t.jpg?s=ad3dd02ed42bccbc84e0bde5c9e4ac7d',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/9/4635l.jpg?s=ad3dd02ed42bccbc84e0bde5c9e4ac7d',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/9/4635.webp?s=ad3dd02ed42bccbc84e0bde5c9e4ac7d',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/9/4635t.webp?s=ad3dd02ed42bccbc84e0bde5c9e4ac7d',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/9/4635l.webp?s=ad3dd02ed42bccbc84e0bde5c9e4ac7d',
],
],
'title' => 'Anime Tenchou',
],
]
]
]);
$this->get('/v4/people/1/anime')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
[
'position',
'anime' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
]
]
]]);
}
public function testMangaography()
{
Person::factory()->createOne([
"mal_id" => 1,
"published_manga" => [
[
'position' => 'Art',
'manga' => [
'mal_id' => 3080,
'url' => 'https://myanimelist.net/manga/3080/x',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/9/4635.jpg?s=ad3dd02ed42bccbc84e0bde5c9e4ac7d',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/9/4635t.jpg?s=ad3dd02ed42bccbc84e0bde5c9e4ac7d',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/9/4635l.jpg?s=ad3dd02ed42bccbc84e0bde5c9e4ac7d',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/9/4635.webp?s=ad3dd02ed42bccbc84e0bde5c9e4ac7d',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/9/4635t.webp?s=ad3dd02ed42bccbc84e0bde5c9e4ac7d',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/9/4635l.webp?s=ad3dd02ed42bccbc84e0bde5c9e4ac7d',
],
],
'title' => 'Anime Tenchou',
],
]
]
]);
$this->get('/v4/people/1/manga')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
[
'position',
'manga' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
]
]
]]);
}
public function testVoices()
{
Person::factory()->createOne([
"mal_id" => 1,
"voice_acting_roles" => [
[
'role' => 'Main',
'anime' => [
'mal_id' => 53127,
'url' => 'https://myanimelist.net/anime/53127/Fate_strange_Fake__Whispers_of_Dawn',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/1502/128320.jpg?s=6b3f95b29d8156f15851f720f06c42ca',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/1502/128320t.jpg?s=6b3f95b29d8156f15851f720f06c42ca',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/1502/128320l.jpg?s=6b3f95b29d8156f15851f720f06c42ca',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/1502/128320.webp?s=6b3f95b29d8156f15851f720f06c42ca',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/1502/128320t.webp?s=6b3f95b29d8156f15851f720f06c42ca',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/1502/128320l.webp?s=6b3f95b29d8156f15851f720f06c42ca',
],
],
'title' => 'Fate/strange Fake: Whispers of Dawn',
],
'character' => [
'mal_id' => 2514,
'url' => 'https://myanimelist.net/character/2514/Gilgamesh',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/r/84x124/images/characters/12/338672.jpg?s=45f9ea76970db587f1ab490b1a3573a1',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/r/84x124/images/characters/12/338672.webp?s=45f9ea76970db587f1ab490b1a3573a1',
'small_image_url' => 'https://cdn.myanimelist.net/r/84x124/images/characters/12/338672t.webp?s=45f9ea76970db587f1ab490b1a3573a1',
],
],
'name' => 'Gilgamesh',
],
]
]
]);
$this->get('/v4/people/1/voices')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
[
'role',
'anime' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'character' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
],
'webp' => [
'image_url',
'small_image_url',
],
],
'name'
]
]
]]);
}
public function testPictures()
{
$document = $this->dummyScraperResultDocument('/v4/people/1/pictures', 'people', [
'pictures' => [
[
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/voiceactors/10/34138.jpg',
],
]
]
]);
DB::table("people_pictures")->insert($document);
$this->get('/v4/people/1/pictures')
->seeStatusCode(200)
->seeJsonStructure([
'data' => [
[
'jpg' => [
'image_url'
]
]
]
]);
}
public function test404()
{
$this->mockJikanParserWith404RespondingUpstream();
$this->get('/v4/people/1000000')
->seeStatusCode(404);
}
}

View File

@ -1,5 +1,6 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Producers;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Tests\TestCase;
@ -11,6 +12,7 @@ class ProducerControllerTest extends TestCase
public function testProducersListing()
{
Producers::factory()->createOne();
$this->get('/v4/producers')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[

View File

@ -0,0 +1,102 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
class RecommendationsControllerTest extends TestCase
{
use SyntheticMongoDbTransaction;
use ScoutFlush;
public function testAnimeRecommendations()
{
$document = $this->dummyResultsDocument('/v4/recommendations/anime', 'recommendations', [[
'mal_id' => '4103-6675',
'entry' => [
[
'mal_id' => 4103,
'url' => 'https://myanimelist.net/anime/4103/Oval_x_Over',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/5/29979.jpg',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/5/29979t.jpg',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/5/29979l.jpg',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/5/29979.webp',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/5/29979t.webp',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/5/29979l.webp',
],
],
'title' => 'Oval x Over',
],
[
'mal_id' => 6675,
'url' => 'https://myanimelist.net/anime/6675/Redline',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/12/28553.jpg',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/12/28553t.jpg',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/12/28553l.jpg',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/12/28553.webp',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/12/28553t.webp',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/12/28553l.webp',
],
],
'title' => 'Redline',
],
],
'content' => 'Oval x Over looks like a prototype version of Redline....',
'date' => '2022-06-20T17:21:22+00:00',
'user' => [
'url' => 'https://myanimelist.net/profile/VBayer',
'username' => 'VBayer',
],
]]);
DB::table("recommendations")->insert($document);
$this->get('/v4/recommendations/anime')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'mal_id',
'entry' => [
[
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
]
],
'content',
'date',
'user' => [
'username',
'url',
],
]
]
]);
}
}

View File

@ -0,0 +1,242 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
class ReviewsControllerTest extends TestCase
{
use SyntheticMongoDbTransaction;
use ScoutFlush;
public function testAnimeReviews()
{
$document = $this->dummyResultsDocument('/v4/reviews/anime', 'reviews', [
[
'mal_id' => 448579,
'url' => 'https://myanimelist.net/reviews.php?id=448579',
'type' => 'anime',
'reactions' => [
'overall' => 0,
'nice' => 0,
'love_it' => 0,
'funny' => 0,
'confusing' => 0,
'informative' => 0,
'well_written' => 0,
'creative' => 0,
],
'votes' => 0,
'score' => 4,
'tags' => ['Recommended'],
'is_spoiler' => false,
'is_preliminary' => false,
'date' => '2022-06-20T12:13:00+00:00',
'review' => 'Its good and enjoyable until Kanade drama kick in and it goes downhill since then. The drama is irritating to watch...',
'episodes_watched' => 12,
'scores' => [
'overall' => 5,
'story' => 3,
'animation' => 7,
'sound' => 5,
'character' => 5,
'enjoyment' => 4,
],
'entry' => [
'mal_id' => 43470,
'url' => 'https://myanimelist.net/anime/43470/Rikei_ga_Koi_ni_Ochita_no_de_Shoumei_shitemita_Heart',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/1109/118948.jpg?s=22c36e71a40927d69da106c932bda628',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/1109/118948t.jpg?s=22c36e71a40927d69da106c932bda628',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/1109/118948l.jpg?s=22c36e71a40927d69da106c932bda628',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/1109/118948.webp?s=22c36e71a40927d69da106c932bda628',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/1109/118948t.webp?s=22c36e71a40927d69da106c932bda628',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/1109/118948l.webp?s=22c36e71a40927d69da106c932bda628',
],
],
'title' => 'Rikei ga Koi ni Ochita no de Shoumei shitemita. Heart',
],
'user' => [
'url' => 'https://myanimelist.net/profile/helmy47',
'username' => 'helmy47',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/userimages/9023550.jpg?t=1655753400',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/userimages/9023550.webp?t=1655753400',
],
],
],
]
]);
DB::table("reviews")->insert($document);
$this->get('/v4/reviews/anime')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'mal_id',
'url',
'type',
'reactions',
'date',
'review',
'score',
'tags',
'is_spoiler',
'is_preliminary',
'episodes_watched',
'entry' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'user' => [
'username',
'url',
'images' => [
'jpg' => [
'image_url'
],
'webp' => [
'image_url'
]
]
],
]
]
]);
}
public function testMangaReviews()
{
$document = $this->dummyResultsDocument('/v4/reviews/manga', 'reviews', [
[
'mal_id' => 448579,
'url' => 'https://myanimelist.net/reviews.php?id=448579',
'type' => 'manga',
'reactions' => [
'overall' => 0,
'nice' => 0,
'love_it' => 0,
'funny' => 0,
'confusing' => 0,
'informative' => 0,
'well_written' => 0,
'creative' => 0,
],
'votes' => 0,
'date' => '2022-06-20T12:13:00+00:00',
'review' => 'Its good and enjoyable until Kanade drama kick in and it goes downhill since then. The drama is irritating to watch...',
'chapters_read' => 75,
'score' => 5,
'is_spoiler' => false,
'is_preliminary' => false,
'tags' => ['Recommended'],
'entry' => [
'mal_id' => 43470,
'url' => 'https://myanimelist.net/anime/43470/Rikei_ga_Koi_ni_Ochita_no_de_Shoumei_shitemita_Heart',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/1109/118948.jpg?s=22c36e71a40927d69da106c932bda628',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/1109/118948t.jpg?s=22c36e71a40927d69da106c932bda628',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/1109/118948l.jpg?s=22c36e71a40927d69da106c932bda628',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/1109/118948.webp?s=22c36e71a40927d69da106c932bda628',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/1109/118948t.webp?s=22c36e71a40927d69da106c932bda628',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/1109/118948l.webp?s=22c36e71a40927d69da106c932bda628',
],
],
'title' => 'Rikei ga Koi ni Ochita no de Shoumei shitemita. Heart',
],
'user' => [
'url' => 'https://myanimelist.net/profile/helmy47',
'username' => 'helmy47',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/userimages/9023550.jpg?t=1655753400',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/userimages/9023550.webp?t=1655753400',
],
],
],
]
]);
DB::table("reviews")->insert($document);
$this->get('/v4/reviews/manga')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'mal_id',
'url',
'type',
'reactions',
'date',
'review',
'score',
'tags',
'is_spoiler',
'is_preliminary',
'chapters_read',
'entry' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'user' => [
'username',
'url',
'images' => [
'jpg' => [
'image_url'
],
'webp' => [
'image_url'
]
]
],
]
]
]);
}
}

View File

@ -0,0 +1,116 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Anime;
use App\Enums\AnimeStatusEnum;
use App\Enums\AnimeTypeEnum;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Tests\TestCase;
class ScheduleControllerTest extends TestCase
{
use SyntheticMongoDbTransaction;
use ScoutFlush;
public function testSchedule()
{
Anime::factory(3)->state(new Sequence(
["members" => 100],
["members" => 50],
["members" => 10]
))->state([
"type" => AnimeTypeEnum::tv()->label,
"status" => AnimeStatusEnum::airing()->label,
"airing" => true,
])->create();
$this->get('/v4/schedules')
->seeStatusCode(200)
->seeJsonStructure([
'data' => [
[
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'trailer' => [
'youtube_id',
'url',
'embed_url',
'images' => [
'image_url',
'small_image_url',
'medium_image_url',
'large_image_url',
'maximum_image_url',
]
],
'title',
'title_english',
'title_japanese',
'title_synonyms',
'type',
'source',
'episodes',
'status',
'airing',
'aired' => [
'from',
'to',
'prop' => [
'from' => [
'day',
'month',
'year'
],
'to' => [
'day',
'month',
'year'
]
],
'string'
],
'duration',
'rating',
'score',
'scored_by',
'rank',
'popularity',
'members',
'favorites',
'synopsis',
'background',
'season',
'year',
'broadcast' => [
'day',
'time',
'timezone',
'string'
],
'producers',
'licensors',
'studios',
'genres',
]
]
]);
}
public function test400()
{
$this->get('/v4/schedules/asdjkhas')
->seeStatusCode(400);
}
}

View File

@ -1,5 +1,9 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Anime;
use App\Character;
use App\Manga;
use App\Person;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Tests\TestCase;
@ -11,7 +15,8 @@ class SearchControllerTest extends TestCase
public function testAnimeSearch()
{
$this->get('/v4/anime?order_by=id&sort=asc')
Anime::factory(3)->create();
$this->get('/v4/anime?order_by=mal_id&sort=asc')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
@ -89,6 +94,7 @@ class SearchControllerTest extends TestCase
'background',
'season',
'year',
'themes',
'broadcast' => [
'day',
'time',
@ -135,7 +141,8 @@ class SearchControllerTest extends TestCase
public function testMangaSearch()
{
$this->get('/v4/manga?order_by=id&sort=asc')
Manga::factory(3)->create();
$this->get('/v4/manga?order_by=mal_id&sort=asc')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
@ -229,6 +236,10 @@ class SearchControllerTest extends TestCase
public function testPeopleSearch()
{
Person::factory(2)->create();
Person::factory()->createOne([
"name" => "Sawano Kuma"
]);
$this->get('/v4/people?q=Sawano')
->seeStatusCode(200)
->seeJsonStructure([
@ -266,7 +277,11 @@ class SearchControllerTest extends TestCase
public function testCharacterSearch()
{
$this->get('/v4/characters?q=Okabe,%20Rintarou')
Character::factory(2)->create();
Character::factory()->createOne([
"name" => "Okabe"
]);
$this->get('/v4/characters?q=Okabe')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [

View File

@ -1,7 +1,12 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Anime;
use App\Character;
use App\Manga;
use App\Person;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Illuminate\Database\Eloquent\Factories\Sequence;
use Tests\TestCase;
class TopControllerTest extends TestCase
@ -11,6 +16,11 @@ class TopControllerTest extends TestCase
public function testTopAnime()
{
Anime::factory(3)->state(new Sequence(
["rank" => 54],
["rank" => 22],
["rank" => 12]
))->create();
$this->get('/v4/top/anime')
->seeStatusCode(200)
->seeJsonStructure([
@ -125,6 +135,11 @@ class TopControllerTest extends TestCase
public function testTopManga()
{
Manga::factory(3)->state(new Sequence(
["rank" => 54],
["rank" => 22],
["rank" => 12]
))->create();
$this->get('/v4/top/manga')
->seeStatusCode(200)
->seeJsonStructure([
@ -209,6 +224,11 @@ class TopControllerTest extends TestCase
public function testTopPeople()
{
Person::factory(3)->state(new Sequence(
["member_favorites" => 524],
["member_favorites" => 323],
["member_favorites" => 224],
))->create();
$this->get('/v4/top/people')
->seeStatusCode(200)
->seeJsonStructure([
@ -236,6 +256,11 @@ class TopControllerTest extends TestCase
public function testTopCharacters()
{
Character::factory(3)->state(new Sequence(
["member_favorites" => 524],
["member_favorites" => 323],
["member_favorites" => 224],
))->create();
$this->get('/v4/top/characters')
->seeStatusCode(200)
->seeJsonStructure([

View File

@ -1,7 +1,15 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Profile;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Jikan\Model\Recommendations\UserRecommendations;
use Jikan\Model\User\Friends;
use Jikan\Model\User\Reviews\UserReviews;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\User\UserRecommendationsRequest;
use Tests\TestCase;
class UserControllerTest extends TestCase
@ -11,6 +19,9 @@ class UserControllerTest extends TestCase
public function testUserProfile()
{
Profile::factory()->createOne([
"username" => "nekomata1037"
]);
$this->get('/v4/users/nekomata1037')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
@ -35,6 +46,9 @@ class UserControllerTest extends TestCase
public function testUserStatistics()
{
Profile::factory()->createOne([
"username" => "nekomata1037"
]);
$this->get('/v4/users/nekomata1037/statistics')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
@ -69,6 +83,9 @@ class UserControllerTest extends TestCase
public function testUserAbout()
{
Profile::factory()->createOne([
"username" => "nekomata1037"
]);
$this->get('/v4/users/nekomata1037/about')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
@ -78,6 +95,9 @@ class UserControllerTest extends TestCase
public function testUserFavorites()
{
Profile::factory()->createOne([
"username" => "nekomata1037"
]);
$this->get('/v4/users/nekomata1037/favorites')
->seeStatusCode(200)
->seeJsonStructure(['data'=>[
@ -156,8 +176,23 @@ class UserControllerTest extends TestCase
public function testUserHistory()
public function testUserAnimeHistory()
{
$document = $this->dummyScraperResultDocument('/v4/users/purplepinapples/history/anime', 'users', [
'history' => [
[
'entry' => [
'mal_id' => $this->faker->numberBetween(2, 9999),
'type' => 'anime',
'name' => $this->faker->name(),
'url' => $this->faker->url()
],
'increment' => 1,
'date' => Carbon::now()->toAtomString()
]
]
]);
DB::table("users_history")->insert($document);
$this->get('/v4/users/purplepinapples/history/anime')
->seeStatusCode(200)
->seeJsonStructure([
@ -174,7 +209,25 @@ class UserControllerTest extends TestCase
]
]
]);
}
public function testUserMangaHistory()
{
$document = $this->dummyScraperResultDocument('/v4/users/nekomata1037/history/manga', 'users', [
'history' => [
[
'entry' => [
'mal_id' => $this->faker->numberBetween(2, 9999),
'type' => 'manga',
'name' => $this->faker->name(),
'url' => $this->faker->url()
],
'increment' => 1,
'date' => Carbon::now()->toAtomString()
]
]
]);
DB::table("users_history")->insert($document);
$this->get('/v4/users/nekomata1037/history/manga')
->seeStatusCode(200)
->seeJsonStructure([
@ -186,6 +239,23 @@ class UserControllerTest extends TestCase
public function testUserFriends()
{
$document = $this->dummyResultsDocument('/v4/users/nekomata1037/friends', 'users', [[
'user' => [
'username' => $this->faker->userName(),
'url' => $this->faker->url(),
"images" => [
"jpg" => [
"image_url" => $this->faker->url()
],
"webp" => [
"image_url" => $this->faker->url()
]
],
],
'last_online' => Carbon::now()->toAtomString(),
'friends_since' => Carbon::now()->toAtomString()
]]);
DB::table("users_friends")->insert($document);
$this->get('/v4/users/nekomata1037/friends')
->seeStatusCode(200)
->seeJsonStructure([
@ -212,6 +282,16 @@ class UserControllerTest extends TestCase
]
]
]);
}
public function testInvalidUserFriendsRequest()
{
$jikanParser = \Mockery::mock(MalClient::class)->makePartial();
/** @noinspection PhpParamsInspection */
$jikanParser->allows()
->getUserFriends(\Mockery::any())
->andReturn(new Friends());
$this->app->instance('JikanParser', $jikanParser);
$this->get('/v4/users/nekomata1037/friends?page=200')
->seeStatusCode(200);
@ -219,6 +299,37 @@ class UserControllerTest extends TestCase
public function testUserRecommendations()
{
$document = $this->dummyResultsDocument('/v4/users/xinil/recommendations', 'users', [
[
'mal_id' => '263-1559',
'entry' => [
[
'mal_id' => 263,
'url' => 'https://myanimelist.net/anime/263/Hajime_no_Ippo',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/4/86334.jpg?s=20b66bb8d0eb0af0a1810eb8717ec44f',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/4/86334t.jpg?s=20b66bb8d0eb0af0a1810eb8717ec44f',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/4/86334l.jpg?s=20b66bb8d0eb0af0a1810eb8717ec44f',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/4/86334.webp?s=20b66bb8d0eb0af0a1810eb8717ec44f',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/4/86334t.webp?s=20b66bb8d0eb0af0a1810eb8717ec44f',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/4/86334l.webp?s=20b66bb8d0eb0af0a1810eb8717ec44f',
],
],
'title' => 'Hajime no Ippo',
]
],
'content' => 'Hajime no Ippo and Kenichi are very similar, mostly by looking at the main characters. Makunouchi is a weakling, Kenichi is a weakling. However, they both train hard and become stronger in order to achieve their goals. Makounouchi wants to know what it means to be "strong", and Kenichi wants to become stronger to protect his friends from harm.',
'date' => '2008-01-20T00:00:00+00:00',
'user' => [
'url' => 'https://myanimelist.net/profile/Xinil',
'username' => 'Xinil',
],
]
]);
DB::table("users_recommendations")->insert($document);
$this->get('/v4/users/xinil/recommendations')
->seeStatusCode(200)
->seeJsonStructure([
@ -254,6 +365,17 @@ class UserControllerTest extends TestCase
]
]
]);
}
public function testInvalidUserRecommendationsRequest()
{
// let's add a parser which returns nothing all the time for user recommendations request
$jikanParser = \Mockery::mock(MalClient::class)->makePartial();
/** @noinspection PhpParamsInspection */
$jikanParser->allows()
->getUserRecommendations(\Mockery::type(UserRecommendationsRequest::class))
->andReturn(new UserRecommendations());
$this->app->instance('JikanParser', $jikanParser);
$this->get('/v4/users/xinil/recommendations?page=200')
->seeStatusCode(200)
@ -269,6 +391,54 @@ class UserControllerTest extends TestCase
public function testUserReviews()
{
$document = $this->dummyResultsDocument('/v4/users/xinil/reviews', 'users', [[
'mal_id' => 829,
'url' => 'https://myanimelist.net/reviews.php?id=829',
'type' => 'manga',
'votes' => 78,
'date' => '2007-09-09T16:43:00+00:00',
'review' => 'Just an all around &quot;fun&quot;',
'chapters_read' => 89,
'is_spoiler' => false,
'is_preliminary' => false,
'tags' => [],
'score' => 1,
'reactions' => [
'overall' => 2112,
'nice' => 2105,
'love_it' => 3,
'funny' => 1,
'confusing' => 0,
'informative' => 2,
'well_written' => 1,
'creative' => 0,
],
'scores' => [
'overall' => 7,
'story' => 8,
'art' => 6,
'character' => 7,
'enjoyment' => 8,
],
'entry' => [
'mal_id' => 1190,
'url' => 'https://myanimelist.net/manga/1190/Asatte_Dance',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/manga/5/202582.jpg?s=3035988a19db4f7223de8b0168bdae30',
'small_image_url' => 'https://cdn.myanimelist.net/images/manga/5/202582t.jpg?s=3035988a19db4f7223de8b0168bdae30',
'large_image_url' => 'https://cdn.myanimelist.net/images/manga/5/202582l.jpg?s=3035988a19db4f7223de8b0168bdae30',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/manga/5/202582.webp?s=3035988a19db4f7223de8b0168bdae30',
'small_image_url' => 'https://cdn.myanimelist.net/images/manga/5/202582t.webp?s=3035988a19db4f7223de8b0168bdae30',
'large_image_url' => 'https://cdn.myanimelist.net/images/manga/5/202582l.webp?s=3035988a19db4f7223de8b0168bdae30',
],
],
'title' => 'Asatte Dance',
],
]]);
DB::table("users_reviews")->insert($document);
$this->get('/v4/users/xinil/reviews')
->seeStatusCode(200)
->seeJsonStructure([
@ -308,6 +478,16 @@ class UserControllerTest extends TestCase
]
]
]);
}
public function testInvalidUserReviewsRequest()
{
$jikanParser = \Mockery::mock(MalClient::class)->makePartial();
/** @noinspection PhpParamsInspection */
$jikanParser->allows()
->getUserReviews(\Mockery::any())
->andReturn(new UserReviews());
$this->app->instance('JikanParser', $jikanParser);
$this->get('/v4/users/xinil/reviews?page=200')
->seeStatusCode(200);
@ -315,6 +495,12 @@ class UserControllerTest extends TestCase
public function testUserClubs()
{
$document = $this->dummyResultsDocument('/v4/users/nekomata1037/clubs', 'users', [[
'mal_id' => 1,
'name' => 'a',
'url' => $this->faker->url()
]]);
DB::table('users_clubs')->insert($document);
$this->get('/v4/users/nekomata1037/clubs')
->seeStatusCode(200)
->seeJsonStructure([

View File

@ -0,0 +1,334 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests\HttpV4\Controllers;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
class WatchControllerTest extends TestCase
{
use SyntheticMongoDbTransaction;
use ScoutFlush;
public function testWatchEpisodes()
{
$document = $this->dummyResultsDocument('/v4/watch/episodes', 'watch', [
[
'entry' => [
'mal_id' => 21,
'url' => 'https://myanimelist.net/anime/21/One_Piece',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/6/73245.jpg',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/6/73245t.jpg',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/6/73245l.jpg',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/6/73245.webp',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/6/73245t.webp',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/6/73245l.webp',
],
],
'title' => 'One Piece',
],
'episodes' => [
[
'mal_id' => 1022,
'url' => 'https://myanimelist.net/anime/21/One_Piece/episode/1022',
'title' => 'Episode 1022',
'premium' => false,
],
[
'mal_id' => 1021,
'url' => 'https://myanimelist.net/anime/21/One_Piece/episode/1021',
'title' => 'Episode 1021',
'premium' => false,
],
],
'region_locked' => false,
]
]);
DB::table("watch")->insert($document);
$this->get('/v4/watch/episodes')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'entry' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'episodes' => [
[
'mal_id',
'url',
'title',
'premium'
]
],
]
]
]);
}
public function testWatchEpisodesPopular()
{
$document = $this->dummyResultsDocument('/v4/watch/episodes/popular', 'watch', [
[
'entry' => [
'mal_id' => 21,
'url' => 'https://myanimelist.net/anime/21/One_Piece',
'images' => [
'jpg' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/6/73245.jpg',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/6/73245t.jpg',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/6/73245l.jpg',
],
'webp' => [
'image_url' => 'https://cdn.myanimelist.net/images/anime/6/73245.webp',
'small_image_url' => 'https://cdn.myanimelist.net/images/anime/6/73245t.webp',
'large_image_url' => 'https://cdn.myanimelist.net/images/anime/6/73245l.webp',
],
],
'title' => 'One Piece',
],
'episodes' => [
[
'mal_id' => 1022,
'url' => 'https://myanimelist.net/anime/21/One_Piece/episode/1022',
'title' => 'Episode 1022',
'premium' => false,
],
[
'mal_id' => 1021,
'url' => 'https://myanimelist.net/anime/21/One_Piece/episode/1021',
'title' => 'Episode 1021',
'premium' => false,
],
],
'region_locked' => false,
]
]);
DB::table("watch")->insert($document);
$this->get('/v4/watch/episodes/popular')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'entry' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'episodes' => [
[
'mal_id',
'url',
'title',
'premium'
]
],
]
]
]);
}
public function testWatchPromos()
{
$document = $this->dummyResultsDocument('/v4/watch/promos', 'watch', [
[
'title' => 'Character PV',
'entry' => [
'mal_id' => 51019,
'url' => 'https:\\/\\/myanimelist.net\\/anime\\/51019\\/Kimetsu_no_Yaiba__Katanakaji_no_Sato-hen',
'images' => [
'jpg' => [
'image_url' => 'https:\\/\\/cdn.myanimelist.net\\/images\\/anime\\/1499\\/121027.jpg',
'small_image_url' => 'https:\\/\\/cdn.myanimelist.net\\/images\\/anime\\/1499\\/121027t.jpg',
'large_image_url' => 'https:\\/\\/cdn.myanimelist.net\\/images\\/anime\\/1499\\/121027l.jpg',
],
'webp' => [
'image_url' => 'https:\\/\\/cdn.myanimelist.net\\/images\\/anime\\/1499\\/121027.webp',
'small_image_url' => 'https:\\/\\/cdn.myanimelist.net\\/images\\/anime\\/1499\\/121027t.webp',
'large_image_url' => 'https:\\/\\/cdn.myanimelist.net\\/images\\/anime\\/1499\\/121027l.webp',
],
],
'title' => 'Kimetsu no Yaiba: Katanakaji no Sato-hen',
],
'trailer' => [
'youtube_id' => 't0d7_6WCls8',
'url' => 'https:\\/\\/www.youtube.com\\/watch?v=t0d7_6WCls8',
'embed_url' => 'https:\\/\\/www.youtube.com\\/embed\\/t0d7_6WCls8?enablejsapi=1&wmode=opaque&autoplay=1',
'images' => [
'image_url' => 'https:\\/\\/img.youtube.com\\/vi\\/t0d7_6WCls8\\/default.jpg',
'small_image_url' => 'https:\\/\\/img.youtube.com\\/vi\\/t0d7_6WCls8\\/sddefault.jpg',
'medium_image_url' => 'https:\\/\\/img.youtube.com\\/vi\\/t0d7_6WCls8\\/mqdefault.jpg',
'large_image_url' => 'https:\\/\\/img.youtube.com\\/vi\\/t0d7_6WCls8\\/hqdefault.jpg',
'maximum_image_url' => 'https:\\/\\/img.youtube.com\\/vi\\/t0d7_6WCls8\\/maxresdefault.jpg',
],
],
]
]);
DB::table("watch")->insert($document);
$this->get('/v4/watch/promos')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'title',
'entry' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'trailer' => [
'youtube_id',
'url',
'embed_url',
'images' => [
'image_url',
'small_image_url',
'medium_image_url',
'large_image_url',
'maximum_image_url',
]
],
]
]
]);
}
public function testWatchPopularPromos()
{
$document = $this->dummyResultsDocument('/v4/watch/promos/popular', 'watch', [
[
'title' => 'Character PV',
'entry' => [
'mal_id' => 51019,
'url' => 'https:\\/\\/myanimelist.net\\/anime\\/51019\\/Kimetsu_no_Yaiba__Katanakaji_no_Sato-hen',
'images' => [
'jpg' => [
'image_url' => 'https:\\/\\/cdn.myanimelist.net\\/images\\/anime\\/1499\\/121027.jpg',
'small_image_url' => 'https:\\/\\/cdn.myanimelist.net\\/images\\/anime\\/1499\\/121027t.jpg',
'large_image_url' => 'https:\\/\\/cdn.myanimelist.net\\/images\\/anime\\/1499\\/121027l.jpg',
],
'webp' => [
'image_url' => 'https:\\/\\/cdn.myanimelist.net\\/images\\/anime\\/1499\\/121027.webp',
'small_image_url' => 'https:\\/\\/cdn.myanimelist.net\\/images\\/anime\\/1499\\/121027t.webp',
'large_image_url' => 'https:\\/\\/cdn.myanimelist.net\\/images\\/anime\\/1499\\/121027l.webp',
],
],
'title' => 'Kimetsu no Yaiba: Katanakaji no Sato-hen',
],
'trailer' => [
'youtube_id' => 't0d7_6WCls8',
'url' => 'https:\\/\\/www.youtube.com\\/watch?v=t0d7_6WCls8',
'embed_url' => 'https:\\/\\/www.youtube.com\\/embed\\/t0d7_6WCls8?enablejsapi=1&wmode=opaque&autoplay=1',
'images' => [
'image_url' => 'https:\\/\\/img.youtube.com\\/vi\\/t0d7_6WCls8\\/default.jpg',
'small_image_url' => 'https:\\/\\/img.youtube.com\\/vi\\/t0d7_6WCls8\\/sddefault.jpg',
'medium_image_url' => 'https:\\/\\/img.youtube.com\\/vi\\/t0d7_6WCls8\\/mqdefault.jpg',
'large_image_url' => 'https:\\/\\/img.youtube.com\\/vi\\/t0d7_6WCls8\\/hqdefault.jpg',
'maximum_image_url' => 'https:\\/\\/img.youtube.com\\/vi\\/t0d7_6WCls8\\/maxresdefault.jpg',
],
],
]
]);
DB::table("watch")->insert($document);
$this->get('/v4/watch/promos/popular')
->seeStatusCode(200)
->seeJsonStructure([
'pagination' => [
'last_visible_page',
'has_next_page',
],
'data' => [
[
'title',
'entry' => [
'mal_id',
'url',
'images' => [
'jpg' => [
'image_url',
'small_image_url',
'large_image_url'
],
'webp' => [
'image_url',
'small_image_url',
'large_image_url'
],
],
'title'
],
'trailer' => [
'youtube_id',
'url',
'embed_url',
'images' => [
'image_url',
'small_image_url',
'medium_image_url',
'large_image_url',
'maximum_image_url',
]
],
]
]
]);
}
}

View File

@ -1,7 +1,10 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests;
use Illuminate\Support\Str;
use Illuminate\Console\OutputStyle;
use Illuminate\Container\Container;
use Illuminate\Database\Migrations\Migrator;
use Illuminate\Support\Facades\Facade;
use \Throwable;
use PHPUnit\Framework\TestListener;
@ -47,8 +50,7 @@ class IntegrationTestListener implements TestListener
{
$suiteName = $suite->getName();
return in_array($suiteName, [
"integration", "http-integration", "Tests\HttpV4\Controllers", "Tests\Integration",
"Integration"
"integration", "Tests\Integration", "Integration"
]);
}
@ -56,6 +58,8 @@ class IntegrationTestListener implements TestListener
{
if ($this->isIntegrationTest($suite)) {
$app = $this->app;
Container::setInstance($app);
Facade::setFacadeApplication($app);
$kernel = $app->make(
'Illuminate\Contracts\Console\Kernel'
);
@ -63,6 +67,7 @@ class IntegrationTestListener implements TestListener
$kernel->call('migrate:fresh', []);
} catch (\Exception $ex) {
print_r($ex->getMessage());
print_r($ex);
throw $ex;
}
}
@ -71,11 +76,20 @@ class IntegrationTestListener implements TestListener
public function endTestSuite(\PHPUnit\Framework\TestSuite $suite): void
{
if ($this->isIntegrationTest($suite)) {
$app = $this->app;
Container::setInstance($app);
Facade::setFacadeApplication($app);
$kernel = $app->make(
'Illuminate\Contracts\Console\Kernel'
);
$kernel->call('migrate:rollback');
try {
$kernel->call('migrate:rollback');
} catch (\Exception $ex) {
print_r($ex->getMessage());
print_r($ex);
throw $ex;
}
}
}

View File

@ -1,14 +1,22 @@
<?php /** @noinspection PhpIllegalPsrClassPathInspection */
namespace Tests;
use App\Exceptions\CustomTestException;
use App\Testing\Concerns\MakesHttpRequestsEx;
use App\Testing\ScoutFlush;
use App\Testing\SyntheticMongoDbTransaction;
use App\Testing\TestExceptionsHandler;
use Faker\Factory as FakerFactory;
use Faker\Generator;
use Illuminate\Container\Container;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Facade;
use Illuminate\Testing\TestResponse;
use Jikan\MyAnimeList\MalClient;
use Laravel\Lumen\Application;
use Laravel\Lumen\Testing\TestCase as LumenTestCase;
use MongoDB\BSON\UTCDateTime;
use Spatie\Enum\Faker\FakerEnumProvider;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;
@ -19,6 +27,97 @@ abstract class TestCase extends LumenTestCase
protected Generator $faker;
protected int $maxResultsPerPage;
protected function dummyScraperResultDocument(string $uri, string $mediaType, array $content, ?string $wrapKey = null): array
{
return [
"createdAt" => new UTCDateTime(),
"modifiedAt" => new UTCDateTime(),
"request_hash" => "request:$mediaType:" . sha1($uri),
...($wrapKey !== null ? [$wrapKey => $content] : $content)
];
}
protected function dummyResultsDocument(string $uri, string $mediaType, array $resultsContent, $hasNextPage = false, $lastVisiblePage = 1): array
{
return $this->dummyScraperResultDocument(
$uri,
$mediaType,
[
"results" => $resultsContent,
"has_next_page" => $hasNextPage,
"last_visible_page" => $lastVisiblePage
]
);
}
protected function givenDummyCharactersStaffData($uri, $mediaType)
{
DB::table($mediaType === "anime" ? $mediaType."_characters_staff" : $mediaType."_characters")->insert([
"createdAt" => new UTCDateTime(),
"modifiedAt" => new UTCDateTime(),
"request_hash" => "request:$mediaType:" . sha1($uri),
"characters" => [
[
"character" => [
"mal_id" => 3,
"url" => "https://myanimelist.net/character/3/Jet_Black",
"images" => [
"jpg" => [
"image_url" => "https://cdn.myanimelist.net/images/characters/11/253723.jpg?s=6c8a19a79a88c46ae15f30e3ef5fd839",
"small_image_url" => "https://cdn.myanimelist.net/images/characters/11/253723t.jpg?s=6c8a19a79a88c46ae15f30e3ef5fd839"
],
"webp" => [
"image_url" => "https://cdn.myanimelist.net/images/characters/11/253723.webp?s=6c8a19a79a88c46ae15f30e3ef5fd839",
"small_image_url" => "https://cdn.myanimelist.net/images/characters/11/253723t.webp?s=6c8a19a79a88c46ae15f30e3ef5fd839"
]
],
"name" => "Black, Jet"
],
"role" => "Main",
"favorites" => 1,
...($mediaType === "anime" ? [
"voice_actors" => [
[
"person" => [
"mal_id" => 357,
"url" => "https://myanimelist.net/people/357/Unshou_Ishizuk",
"images" => [
"jpg" => [
"image_url" => "https://cdn.myanimelist.net/images/voiceactors/2/17135.jpg?s=5925123b8a7cf9b51a445c225442f0ef"
]
],
"name" => "Ishizuka, Unshou"
],
"language" => "Japanese"
]
]
] : [])
]
],
...(
$mediaType === "anime" ? [
"staff" => [
[
"person" => [
"mal_id" => 40009,
"url" => "https://myanimelist.net/people/40009/Yutaka_Maseba",
"images" => [
"jpg" => [
"image_url" => "https://cdn.myanimelist.net/images/voiceactors/3/40216.jpg?s=d9fb7a625868ec7d9cd3804fa0da3fd6"
]
],
"name" => "Maseba, Yutaka"
],
"positions" => [
"Producer"
]
]
]
] : []
)
]);
}
protected function setUp(): void
{
parent::setUp();
@ -34,11 +133,26 @@ abstract class TestCase extends LumenTestCase
*/
public function createApplication()
{
/**
* @var Application $app
*/
$app = require __DIR__.'/../bootstrap/app.php';
// a http client which fails the tests if requests are leaking to MAL.
$mockHttpClient = \Mockery::mock(HttpClientInterface::class);
/** @noinspection PhpParamsInspection */
$mockHttpClient->allows()
->request(\Mockery::any(), \Mockery::any(), \Mockery::any())
->andThrow(new CustomTestException("Http Request to MAL server was attempted during testing. By default we throw this exception to indicate a buggy test."));
$jikan = new \Jikan\MyAnimeList\MalClient($mockHttpClient);
$app->instance('JikanParser', $jikan);
$app->singleton(ExceptionHandler::class, TestExceptionsHandler::class);
$database = env('DB_DATABASE', 'jikan_tests');
$app['config']->set('database.connections.mongodb.database', $database === 'jikan' ? 'jikan_tests' : $database);
$app['config']->set('jikan.micro_caching_enabled', false);
$app->register(TestServiceProvider::class);
Container::setInstance($app);
/** @noinspection PhpParamsInspection */
Facade::setFacadeApplication($app);
return $app;
}
@ -94,6 +208,7 @@ abstract class TestCase extends LumenTestCase
"getHeaders" => [],
"getContent" => ""
]);
$this->app->instance("HttpClient", $httpClient);
$this->app->instance("JikanParser", new MalClient($httpClient));
}
}

View File

@ -5,6 +5,7 @@ namespace Unit;
use App\Contracts\Repository;
use App\Services\DefaultCachedScraperService;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Jenssegers\Mongodb\Eloquent\Builder;
use Jikan\MyAnimeList\MalClient;
use JMS\Serializer\SerializerInterface;
@ -70,8 +71,8 @@ final class DefaultCachedScraperServiceTest extends TestCase
// the cached data in the database
$dummyResults = collect([
["dummy" => "dummy1", "modifiedAt" => new UTCDateTime($now->sub("2 days")->timestamp)],
["dummy" => "dummy2", "modifiedAt" => new UTCDateTime($now->sub("2 days")->timestamp)]
["dummy" => "dummy1", "modifiedAt" => new UTCDateTime($now->sub("2 days")->getPreciseTimestamp(3))],
["dummy" => "dummy2", "modifiedAt" => new UTCDateTime($now->sub("2 days")->getPreciseTimestamp(3))]
]);
// the data returned by the scraper
@ -93,8 +94,8 @@ final class DefaultCachedScraperServiceTest extends TestCase
$result = $target->findList($testRequestHash, fn() => []);
$this->assertEquals([
["dummy" => "dummy1", "modifiedAt" => new UTCDateTime($now->getPreciseTimestamp(3))],
["dummy" => "dummy2", "modifiedAt" => new UTCDateTime($now->getPreciseTimestamp(3))]
["dummy" => "dummy1", "modifiedAt" => $dummyResults->toArray()[0]["modifiedAt"]],
["dummy" => "dummy2", "modifiedAt" => $dummyResults->toArray()[1]["modifiedAt"]]
], $result->toArray());
}