public async Task HandleAsync_GivenNotExistingSeiyuuNullFromJikan_ShouldSkipAndNotInsert()
        {
            // Given
            var       dbContext           = InMemoryDbProvider.GetDbContext();
            var       jikanServiceBuilder = new JikanServiceBuilder().WithPersonReturned(null, null);
            const int startingMalId       = 1;
            var       s3Service           = new S3ServiceStub(startingMalId);

            var anime = new SeiyuuBuilder()
                        .WithMalId(startingMalId)
                        .Build();

            await dbContext.AddAsync(anime);

            await dbContext.SaveChangesAsync();

            var handler = CreateHandler(dbContext, jikanServiceBuilder.Build(), s3Service, 1);

            // When
            await handler.HandleAsync();

            // Then
            jikanServiceBuilder.JikanClient.Verify(x => x.GetPersonAsync(startingMalId + 1), Times.Once);
            dbContext.Seiyuus.Should().ContainSingle();
        }
        public async Task HandleAsync_GivenNotExistingSeiyuuExceptionFromJikan_ShouldSkipAndNotInsert()
        {
            // Given
            var       dbContext           = InMemoryDbProvider.GetDbContext();
            var       jikanServiceBuilder = new JikanServiceBuilder().WithGetPersonThrowing();
            const int startingMalId       = 1;
            var       s3Service           = new S3ServiceStub(startingMalId);

            var anime = new SeiyuuBuilder()
                        .WithMalId(startingMalId)
                        .Build();

            await dbContext.AddAsync(anime);

            await dbContext.SaveChangesAsync();

            var handler = CreateHandler(dbContext, jikanServiceBuilder.Build(), s3Service, 1);

            // When
            var action = handler.Awaiting(x => x.HandleAsync());

            // Then
            using (new AssertionScope())
            {
                await action.Should().ThrowExactlyAsync <JikanRequestException>();

                dbContext.Seiyuus.Should().ContainSingle();
            }
            jikanServiceBuilder.JikanClient.Verify(x => x.GetPersonAsync(startingMalId + 1), Times.Once);
        }
        public async Task HandleAsync_GivenExistingSeiyuu_ShouldSkipAndNotCallJikan()
        {
            // Given
            var       dbContext           = InMemoryDbProvider.GetDbContext();
            var       jikanServiceBuilder = new JikanServiceBuilder();
            const int startingMalId       = 1;
            var       s3Service           = new S3ServiceStub(startingMalId);

            var anime = new SeiyuuBuilder()
                        .WithMalId(startingMalId + 1)
                        .Build();

            await dbContext.AddAsync(anime);

            await dbContext.SaveChangesAsync();

            var handler = CreateHandler(dbContext, jikanServiceBuilder.Build(), s3Service, 5);

            // When
            await handler.HandleAsync();

            // Then
            jikanServiceBuilder.JikanClient.Verify(x => x.GetPersonAsync(It.IsAny <int>()), Times.Never);
            dbContext.Seiyuus.Should().ContainSingle();
        }
        public async Task HandleAsync_GivenNotExistingNonJapanesePersonWithoutRoles_ShouldSkipAndNotInsert()
        {
            // Given
            var       dbContext     = InMemoryDbProvider.GetDbContext();
            const int startingMalId = 1;
            var       s3Service     = new S3ServiceStub(startingMalId);

            const string returnedSeiyuuName           = "PostUpdateSeiyuuName";
            const string returnedSeiyuuAbout          = "PostUpdateSeiyuuAbout";
            const string returnedSeiyuuGivenName      = "John";
            const string returnedSeiyuuFamilyNameName = "Doe";
            const string returnedSeiyuuImageUrl       = "PostUpdateSeiyuuImageUrl";
            const int    returnedSeiyuuPopularity     = 1;
            var          returnedBirthdate            = new DateTime(1990, 1, 1);

            var returnedSeiyuu = new Person
            {
                Name       = returnedSeiyuuName,
                About      = returnedSeiyuuAbout,
                GivenName  = returnedSeiyuuGivenName,
                FamilyName = returnedSeiyuuFamilyNameName,
                Images     = new ImagesSet
                {
                    JPG = new Image {
                        ImageUrl = returnedSeiyuuImageUrl
                    }
                },
                MemberFavorites = returnedSeiyuuPopularity,
                Birthday        = returnedBirthdate
            };

            var jikanServiceBuilder = new JikanServiceBuilder().WithPersonReturned(returnedSeiyuu, null);

            var anime = new SeiyuuBuilder()
                        .WithMalId(startingMalId)
                        .Build();

            await dbContext.AddAsync(anime);

            await dbContext.SaveChangesAsync();

            var handler = CreateHandler(dbContext, jikanServiceBuilder.Build(), s3Service, 5);

            // When
            await handler.HandleAsync();

            // Then
            jikanServiceBuilder.JikanClient.Verify(x => x.GetPersonAsync(startingMalId + 1), Times.Once);
            dbContext.Seiyuus.Should().ContainSingle();
        }
        public async Task HandleAsync_GivenEmptyDatabaseAndBatchSizeOne_LastInsertedSeiyuuIdShouldBeBiggerByOne()
        {
            // Given
            var dbContext           = InMemoryDbProvider.GetDbContext();
            var jikanServiceBuilder = new JikanServiceBuilder();
            var s3Service           = new S3ServiceStub(1);

            var handler = CreateHandler(dbContext, jikanServiceBuilder.Build(), s3Service, 1);

            // When
            await handler.HandleAsync();

            // Then
            var state = await s3Service.GetBgJobsStateAsync(It.IsAny <string>());

            state.LastCheckedSeiyuuMalId.Should().Be(2);
        }
        public async Task HandleAsync_GivenNotExistingJapanesePersonWithSingleRoles_ShouldInsertNewSeiyuuWithRole()
        {
            // Given
            const long animeMalId          = 100;
            const long characterMalId      = 1000;
            var        dbContext           = InMemoryDbProvider.GetDbContext();
            const int  startingSeiyuuMalId = 1;
            var        s3Service           = new S3ServiceStub(startingSeiyuuMalId);

            const string returnedSeiyuuName           = "PostUpdateSeiyuuName";
            const string returnedSeiyuuAbout          = "PostUpdateSeiyuuAbout";
            const string returnedSeiyuuGivenName      = "花澤";
            const string returnedSeiyuuFamilyNameName = "香菜";
            const string returnedSeiyuuImageUrl       = "PostUpdateSeiyuuImageUrl";
            const int    returnedSeiyuuPopularity     = 1;
            var          returnedBirthdate            = new DateTime(1990, 1, 1);

            const string returnedCharacterName         = "PostUpdateName";
            const string returnedCharacterAbout        = "PostUpdateAbout";
            const string returnedCharacterJapaneseName = "PostUpdateJapanese";
            const string returnedCharacterImageUrl     = "PostUpdateImageUrl";
            const int    returnedCharacterPopularity   = 1;

            const string returnedAnimeTitle         = "PostUpdateTitle";
            const string returnedAnimeAbout         = "PostUpdateAbout";
            const string returnedAnimeEnglishTitle  = "PostUpdateEnglish";
            const string returnedAnimeJapaneseTitle = "PostUpdateJapanese";
            const string returnedAnimeImageUrl      = "PostUpdateImageUrl";
            const int    returnedAnimePopularity    = 3;

            var returnedSeiyuu = new Person
            {
                Name       = returnedSeiyuuName,
                About      = returnedSeiyuuAbout,
                GivenName  = returnedSeiyuuGivenName,
                FamilyName = returnedSeiyuuFamilyNameName,
                Images     = new ImagesSet
                {
                    JPG = new Image {
                        ImageUrl = returnedSeiyuuImageUrl
                    }
                },
                MemberFavorites = returnedSeiyuuPopularity,
                Birthday        = returnedBirthdate
            };
            var returnedRoles = new List <VoiceActingRole>
            {
                new VoiceActingRole
                {
                    Role  = "Main",
                    Anime = new MalImageSubItem
                    {
                        MalId = animeMalId
                    },
                    Character = new MalImageSubItem()
                    {
                        MalId = characterMalId
                    }
                }
            };

            var returnedCharacter = new Character
            {
                MalId     = characterMalId,
                Name      = returnedCharacterName,
                About     = returnedCharacterAbout,
                NameKanji = returnedCharacterJapaneseName,
                Images    = new ImagesSet
                {
                    JPG = new Image {
                        ImageUrl = returnedCharacterImageUrl
                    }
                },
                Nicknames = new List <string>(),
                Favorites = returnedCharacterPopularity
            };

            var returnedAnime = new Anime
            {
                MalId         = animeMalId,
                Title         = returnedAnimeTitle,
                Synopsis      = returnedAnimeAbout,
                TitleEnglish  = returnedAnimeEnglishTitle,
                TitleJapanese = returnedAnimeJapaneseTitle,
                Images        = new ImagesSet
                {
                    JPG = new Image {
                        ImageUrl = returnedAnimeImageUrl
                    }
                },
                TitleSynonyms = new List <string>(),
                Members       = returnedAnimePopularity
            };

            var jikanServiceBuilder = new JikanServiceBuilder()
                                      .WithPersonReturned(returnedSeiyuu, returnedRoles)
                                      .WithCharacterReturned(returnedCharacter)
                                      .WithAnimeReturned(returnedAnime);

            var anime = new SeiyuuBuilder()
                        .WithMalId(startingSeiyuuMalId)
                        .Build();

            await dbContext.AddAsync(anime);

            await dbContext.SaveChangesAsync();

            var handler = CreateHandler(dbContext, jikanServiceBuilder.Build(), s3Service, 1);

            // When
            await handler.HandleAsync();

            // Then
            jikanServiceBuilder.JikanClient.Verify(x => x.GetPersonAsync(startingSeiyuuMalId + 1), Times.Once);
            jikanServiceBuilder.JikanClient.Verify(x => x.GetAnimeAsync(animeMalId), Times.Once);
            jikanServiceBuilder.JikanClient.Verify(x => x.GetCharacterAsync(characterMalId), Times.Once);
            using (new AssertionScope())
            {
                dbContext.Seiyuus.Should().HaveCount(2);
                dbContext.Animes.Should().ContainSingle();
                dbContext.AnimeCharacters.Should().ContainSingle();
                dbContext.AnimeRoles.Should().ContainSingle();
            }
        }
        public async Task HandleAsync_GivenNotExistingJapanesePersonWithRolesAndNullResponsesFromCharacterAndAnimeRequests_ShouldInsertNewSeiyuuWithoutroles()
        {
            // Given
            const long animeMalId          = 100;
            const long characterMalId      = 1000;
            var        dbContext           = InMemoryDbProvider.GetDbContext();
            const int  startingSeiyuuMalId = 1;
            var        s3Service           = new S3ServiceStub(startingSeiyuuMalId);

            const string returnedSeiyuuName           = "PostUpdateSeiyuuName";
            const string returnedSeiyuuAbout          = "PostUpdateSeiyuuAbout";
            const string returnedSeiyuuGivenName      = "花澤";
            const string returnedSeiyuuFamilyNameName = "香菜";
            const string returnedSeiyuuImageUrl       = "PostUpdateSeiyuuImageUrl";
            const int    returnedSeiyuuPopularity     = 1;
            var          returnedBirthdate            = new DateTime(1990, 1, 1);

            var returnedSeiyuu = new Person
            {
                Name       = returnedSeiyuuName,
                About      = returnedSeiyuuAbout,
                GivenName  = returnedSeiyuuGivenName,
                FamilyName = returnedSeiyuuFamilyNameName,
                Images     = new ImagesSet
                {
                    JPG = new Image {
                        ImageUrl = returnedSeiyuuImageUrl
                    }
                },
                MemberFavorites = returnedSeiyuuPopularity,
                Birthday        = returnedBirthdate
            };
            var returnedRoles = new List <VoiceActingRole>
            {
                new VoiceActingRole
                {
                    Role  = "Main",
                    Anime = new MalImageSubItem
                    {
                        MalId = animeMalId
                    },
                    Character = new MalImageSubItem()
                    {
                        MalId = characterMalId
                    }
                }
            };

            var jikanServiceBuilder = new JikanServiceBuilder()
                                      .WithPersonReturned(returnedSeiyuu, returnedRoles)
                                      .WithCharacterReturned(null)
                                      .WithAnimeReturned(null);

            var anime = new SeiyuuBuilder()
                        .WithMalId(startingSeiyuuMalId)
                        .Build();

            await dbContext.AddAsync(anime);

            await dbContext.SaveChangesAsync();

            var handler = CreateHandler(dbContext, jikanServiceBuilder.Build(), s3Service, 1);

            // When
            await handler.HandleAsync();

            // Then
            jikanServiceBuilder.JikanClient.Verify(x => x.GetPersonAsync(startingSeiyuuMalId + 1), Times.Once);
            jikanServiceBuilder.JikanClient.Verify(x => x.GetAnimeAsync(animeMalId), Times.Once);
            jikanServiceBuilder.JikanClient.Verify(x => x.GetCharacterAsync(characterMalId), Times.Once);
            dbContext.Seiyuus.Should().HaveCount(2);
            dbContext.AnimeRoles.Should().BeEmpty();
        }
        public async Task HandleAsync_GivenNotExistingNonJapanesePersonWithRoles_ShouldSkipAndNotInsert()
        {
            // Given
            const long animeMalId          = 100;
            const long characterMalId      = 1000;
            var        dbContext           = InMemoryDbProvider.GetDbContext();
            const int  startingSeiyuuMalId = 1;
            var        s3Service           = new S3ServiceStub(startingSeiyuuMalId);

            const string returnedSeiyuuName           = "PostUpdateSeiyuuName";
            const string returnedSeiyuuAbout          = "PostUpdateSeiyuuAbout";
            const string returnedSeiyuuGivenName      = "John";
            const string returnedSeiyuuFamilyNameName = "Doe";
            const string returnedSeiyuuImageUrl       = "PostUpdateSeiyuuImageUrl";
            const int    returnedSeiyuuPopularity     = 1;
            var          returnedBirthdate            = new DateTime(1990, 1, 1);

            var returnedSeiyuu = new Person
            {
                Name             = returnedSeiyuuName,
                More             = returnedSeiyuuAbout,
                GivenName        = returnedSeiyuuGivenName,
                FamilyName       = returnedSeiyuuFamilyNameName,
                ImageURL         = returnedSeiyuuImageUrl,
                MemberFavorites  = returnedSeiyuuPopularity,
                Birthday         = returnedBirthdate,
                VoiceActingRoles = new List <VoiceActingRole>
                {
                    new VoiceActingRole
                    {
                        Role  = "Main",
                        Anime = new MALImageSubItem
                        {
                            MalId = animeMalId
                        },
                        Character = new MALImageSubItem
                        {
                            MalId = characterMalId
                        }
                    }
                }
            };

            var jikanServiceBuilder = new JikanServiceBuilder().WithPersonReturned(returnedSeiyuu);

            var anime = new SeiyuuBuilder()
                        .WithMalId(startingSeiyuuMalId)
                        .Build();

            await dbContext.AddAsync(anime);

            await dbContext.SaveChangesAsync();

            var handler = CreateHandler(dbContext, jikanServiceBuilder.Build(), s3Service, 5);

            // When
            await handler.HandleAsync();

            // Then
            jikanServiceBuilder.JikanClient.Verify(x => x.GetPerson(startingSeiyuuMalId + 1), Times.Once);
            dbContext.Seiyuus.Should().ContainSingle();
        }