// Kyoo - A portable and vast media library solution. // Copyright (c) Kyoo. // // See AUTHORS.md and LICENSE file in the project root for full license information. // // Kyoo is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. // // Kyoo is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Kyoo. If not, see . using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using FluentAssertions; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Kyoo.Postgresql; using Kyoo.Utils; using Microsoft.EntityFrameworkCore; using Xunit; using Xunit.Abstractions; namespace Kyoo.Tests.Database { namespace PostgreSQL { [Collection(nameof(Postgresql))] public class ShowTests : AShowTests { public ShowTests(PostgresFixture postgres, ITestOutputHelper output) : base(new RepositoryActivator(output, postgres)) { } } } public abstract class AShowTests : RepositoryTests { private readonly IShowRepository _repository; protected AShowTests(RepositoryActivator repositories) : base(repositories) { _repository = Repositories.LibraryManager.ShowRepository; } [Fact] public async Task EditTest() { Show value = await _repository.Get(TestSample.Get().Slug); value.Path = "/super"; value.Title = "New Title"; Show edited = await _repository.Edit(value, false); KAssert.DeepEqual(value, edited); await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows.FirstAsync(); KAssert.DeepEqual(show, value); } [Fact] public async Task EditGenreTest() { Show value = await _repository.Get(TestSample.Get().Slug); value.Genres = new[] { new Genre("test") }; Show edited = await _repository.Edit(value, false); Assert.Equal(value.Slug, edited.Slug); Assert.Equal(value.Genres.Select(x => new { x.Slug, x.Name }), edited.Genres.Select(x => new { x.Slug, x.Name })); await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows .Include(x => x.Genres) .FirstAsync(); Assert.Equal(value.Slug, show.Slug); Assert.Equal(value.Genres.Select(x => new { x.Slug, x.Name }), show.Genres.Select(x => new { x.Slug, x.Name })); } [Fact] public async Task AddGenreTest() { Show value = await _repository.Get(TestSample.Get().Slug); await Repositories.LibraryManager.Load(value, x => x.Genres); value.Genres.Add(new Genre("test")); Show edited = await _repository.Edit(value, false); Assert.Equal(value.Slug, edited.Slug); Assert.Equal(value.Genres.Select(x => new { x.Slug, x.Name }), edited.Genres.Select(x => new { x.Slug, x.Name })); await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows .Include(x => x.Genres) .FirstAsync(); Assert.Equal(value.Slug, show.Slug); Assert.Equal(value.Genres.Select(x => new { x.Slug, x.Name }), show.Genres.Select(x => new { x.Slug, x.Name })); } [Fact] public async Task EditStudioTest() { Show value = await _repository.Get(TestSample.Get().Slug); value.Studio = new Studio("studio"); Show edited = await _repository.Edit(value, false); Assert.Equal(value.Slug, edited.Slug); Assert.Equal("studio", edited.Studio.Slug); await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows .Include(x => x.Studio) .FirstAsync(); Assert.Equal(value.Slug, show.Slug); Assert.Equal("studio", show.Studio.Slug); } [Fact] public async Task EditAliasesTest() { Show value = await _repository.Get(TestSample.Get().Slug); value.Aliases = new[] { "NiceNewAlias", "SecondAlias" }; Show edited = await _repository.Edit(value, false); Assert.Equal(value.Slug, edited.Slug); Assert.Equal(value.Aliases, edited.Aliases); await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows.FirstAsync(); Assert.Equal(value.Slug, show.Slug); Assert.Equal(value.Aliases, show.Aliases); } [Fact] public async Task EditPeopleTest() { Show value = await _repository.Get(TestSample.Get().Slug); value.People = new[] { new PeopleRole { Show = value, People = TestSample.Get(), ForPeople = false, Type = "Actor", Role = "NiceCharacter" } }; Show edited = await _repository.Edit(value, false); Assert.Equal(value.Slug, edited.Slug); Assert.Equal(edited.People.First().ShowID, value.ID); Assert.Equal( value.People.Select(x => new { x.Role, x.Slug, x.People.Name }), edited.People.Select(x => new { x.Role, x.Slug, x.People.Name })); await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows .Include(x => x.People) .ThenInclude(x => x.People) .FirstAsync(); Assert.Equal(value.Slug, show.Slug); Assert.Equal( value.People.Select(x => new { x.Role, x.Slug, x.People.Name }), show.People.Select(x => new { x.Role, x.Slug, x.People.Name })); } [Fact] public async Task EditExternalIDsTest() { Show value = await _repository.Get(TestSample.Get().Slug); value.ExternalIDs = new[] { new MetadataID { Provider = new Provider("test", "test.png"), DataID = "1234" } }; Show edited = await _repository.Edit(value, false); Assert.Equal(value.Slug, edited.Slug); Assert.Equal( value.ExternalIDs.Select(x => new { x.DataID, x.Provider.Slug }), edited.ExternalIDs.Select(x => new { x.DataID, x.Provider.Slug })); await using DatabaseContext database = Repositories.Context.New(); Show show = await database.Shows .Include(x => x.ExternalIDs) .ThenInclude(x => x.Provider) .FirstAsync(); Assert.Equal(value.Slug, show.Slug); Assert.Equal( value.ExternalIDs.Select(x => new { x.DataID, x.Provider.Slug }), show.ExternalIDs.Select(x => new { x.DataID, x.Provider.Slug })); } [Fact] public async Task EditResetOldTest() { Show value = await _repository.Get(TestSample.Get().Slug); Show newValue = new() { ID = value.ID, Title = "Reset" }; await Assert.ThrowsAsync(() => _repository.Edit(newValue, true)); newValue.Slug = "reset"; Show edited = await _repository.Edit(newValue, true); Assert.Equal(value.ID, edited.ID); Assert.Null(edited.Overview); Assert.Equal("reset", edited.Slug); Assert.Equal("Reset", edited.Title); Assert.Null(edited.Aliases); Assert.Null(edited.ExternalIDs); Assert.Null(edited.People); Assert.Null(edited.Genres); Assert.Null(edited.Studio); } [Fact] public async Task CreateWithRelationsTest() { Show expected = TestSample.Get(); expected.ID = 0; expected.Slug = "created-relation-test"; expected.ExternalIDs = new[] { new MetadataID { Provider = new Provider("provider", "provider.png"), DataID = "ID" } }; expected.Genres = new[] { new Genre { Name = "Genre", Slug = "genre" } }; expected.People = new[] { new PeopleRole { People = TestSample.Get(), Show = expected, ForPeople = false, Role = "actor" } }; expected.Studio = new Studio("studio"); Show created = await _repository.Create(expected); KAssert.DeepEqual(expected, created); await using DatabaseContext context = Repositories.Context.New(); Show retrieved = await context.Shows .Include(x => x.ExternalIDs) .ThenInclude(x => x.Provider) .Include(x => x.Genres) .Include(x => x.People) .ThenInclude(x => x.People) .Include(x => x.Studio) .FirstAsync(x => x.ID == created.ID); retrieved.People.ForEach(x => { x.Show = null; x.People.Roles = null; }); retrieved.Studio.Shows = null; retrieved.Genres.ForEach(x => x.Shows = null); expected.Genres.ForEach(x => x.Shows = null); expected.People.ForEach(x => { x.Show = null; x.People.Roles = null; }); retrieved.Should().BeEquivalentTo(expected); } [Fact] public async Task CreateWithExternalID() { Show expected = TestSample.Get(); expected.ID = 0; expected.Slug = "created-relation-test"; expected.ExternalIDs = new[] { new MetadataID { Provider = TestSample.Get(), DataID = "ID" } }; Show created = await _repository.Create(expected); KAssert.DeepEqual(expected, created); await using DatabaseContext context = Repositories.Context.New(); Show retrieved = await context.Shows .Include(x => x.ExternalIDs) .ThenInclude(x => x.Provider) .FirstAsync(x => x.ID == created.ID); KAssert.DeepEqual(expected, retrieved); Assert.Equal(1, retrieved.ExternalIDs.Count); Assert.Equal("ID", retrieved.ExternalIDs.First().DataID); } [Fact] public async Task SlugDuplicationTest() { Show test = TestSample.Get(); test.ID = 0; test.Slug = "300"; Show created = await _repository.Create(test); Assert.Equal("300!", created.Slug); } [Fact] public async Task GetSlugTest() { Show reference = TestSample.Get(); Assert.Equal(reference.Slug, await _repository.GetSlug(reference.ID)); } [Theory] [InlineData("test")] [InlineData("super")] [InlineData("title")] [InlineData("TiTlE")] [InlineData("SuPeR")] public async Task SearchTest(string query) { Show value = new() { Slug = "super-test", Title = "This is a test title?" }; await _repository.Create(value); ICollection ret = await _repository.Search(query); KAssert.DeepEqual(value, ret.First()); } [Fact] public async Task DeleteShowWithEpisodeAndSeason() { Show show = TestSample.Get(); await Repositories.LibraryManager.Load(show, x => x.Seasons); await Repositories.LibraryManager.Load(show, x => x.Episodes); Assert.Equal(1, await _repository.GetCount()); Assert.Equal(1, show.Seasons.Count); Assert.Equal(1, show.Episodes.Count); await _repository.Delete(show); Assert.Equal(0, await Repositories.LibraryManager.ShowRepository.GetCount()); Assert.Equal(0, await Repositories.LibraryManager.SeasonRepository.GetCount()); Assert.Equal(0, await Repositories.LibraryManager.EpisodeRepository.GetCount()); } [Fact] public async Task AddShowLinkTest() { await Repositories.LibraryManager.Create(TestSample.GetNew()); await _repository.AddShowLink(1, 2, null); await using DatabaseContext context = Repositories.Context.New(); Show show = context.Shows .Include(x => x.Libraries) .First(x => x.ID == 1); Assert.Contains(2, show.Libraries.Select(x => x.ID)); } } }