Fixing show creation

This commit is contained in:
Zoe Roux 2021-06-09 23:11:20 +02:00
parent d61f3538fe
commit 6cac991653
8 changed files with 105 additions and 49 deletions

View File

@ -119,7 +119,8 @@ namespace Kyoo.SqLite
/// <inheritdoc /> /// <inheritdoc />
protected override bool IsDuplicateException(Exception ex) protected override bool IsDuplicateException(Exception ex)
{ {
return ex.InnerException is SqliteException { SqliteExtendedErrorCode: 2067 /*SQLITE_CONSTRAINT_UNIQUE*/}; return ex.InnerException is SqliteException { SqliteExtendedErrorCode: 2067 /*SQLITE_CONSTRAINT_UNIQUE*/}
or SqliteException { SqliteExtendedErrorCode: 1555 /*SQLITE_CONSTRAINT_PRIMARYKEY*/};
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -24,9 +24,7 @@ namespace Kyoo.Tests
StudioRepository studio = new(_database); StudioRepository studio = new(_database);
PeopleRepository people = new(_database, provider, PeopleRepository people = new(_database, provider,
new Lazy<IShowRepository>(() => LibraryManager.ShowRepository)); new Lazy<IShowRepository>(() => LibraryManager.ShowRepository));
ShowRepository show = new(_database, studio, people, genre, provider, ShowRepository show = new(_database, studio, people, genre, provider);
new Lazy<ISeasonRepository>(() => LibraryManager.SeasonRepository),
new Lazy<IEpisodeRepository>(() => LibraryManager.EpisodeRepository));
SeasonRepository season = new(_database, provider, show, SeasonRepository season = new(_database, provider, show,
new Lazy<IEpisodeRepository>(() => LibraryManager.EpisodeRepository)); new Lazy<IEpisodeRepository>(() => LibraryManager.EpisodeRepository));
LibraryItemRepository libraryItem = new(_database, LibraryItemRepository libraryItem = new(_database,

View File

@ -74,5 +74,17 @@ namespace Kyoo.Tests
await _repository.Delete(TestSample.Get<T>()); await _repository.Delete(TestSample.Get<T>());
Assert.Equal(0, await _repository.GetCount()); Assert.Equal(0, await _repository.GetCount());
} }
[Fact]
public async Task CreateTest()
{
await Assert.ThrowsAsync<DuplicatedItemException>(() => _repository.Create(TestSample.Get<T>()));
await _repository.Delete(TestSample.Get<T>());
T expected = TestSample.Get<T>();
expected.ID = 0;
await _repository.Create(expected);
KAssert.DeepEqual(expected, await _repository.Get(expected.Slug));
}
} }
} }

View File

@ -1,3 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Kyoo.Models; using Kyoo.Models;
@ -5,12 +7,25 @@ using Xunit;
namespace Kyoo.Tests.SpecificTests namespace Kyoo.Tests.SpecificTests
{ {
public class GlobalTests public class GlobalTests : IDisposable, IAsyncDisposable
{ {
private readonly RepositoryActivator _repositories;
public GlobalTests()
{
_repositories = new RepositoryActivator();
}
[Fact]
[SuppressMessage("ReSharper", "EqualExpressionComparison")]
public void SampleTest()
{
Assert.False(ReferenceEquals(TestSample.Get<Show>(), TestSample.Get<Show>()));
}
[Fact] [Fact]
public async Task DeleteShowWithEpisodeAndSeason() public async Task DeleteShowWithEpisodeAndSeason()
{ {
RepositoryActivator repositories = new();
Show show = TestSample.Get<Show>(); Show show = TestSample.Get<Show>();
show.Seasons = new[] show.Seasons = new[]
{ {
@ -20,13 +35,24 @@ namespace Kyoo.Tests.SpecificTests
{ {
TestSample.Get<Episode>() TestSample.Get<Episode>()
}; };
await repositories.Context.AddAsync(show); await _repositories.Context.AddAsync(show);
Assert.Equal(1, await repositories.LibraryManager.ShowRepository.GetCount()); Assert.Equal(1, await _repositories.LibraryManager.ShowRepository.GetCount());
await repositories.LibraryManager.ShowRepository.Delete(show); await _repositories.LibraryManager.ShowRepository.Delete(show);
Assert.Equal(0, await repositories.LibraryManager.ShowRepository.GetCount()); Assert.Equal(0, await _repositories.LibraryManager.ShowRepository.GetCount());
Assert.Equal(0, await repositories.LibraryManager.SeasonRepository.GetCount()); Assert.Equal(0, await _repositories.LibraryManager.SeasonRepository.GetCount());
Assert.Equal(0, await repositories.LibraryManager.EpisodeRepository.GetCount()); Assert.Equal(0, await _repositories.LibraryManager.EpisodeRepository.GetCount());
}
public void Dispose()
{
_repositories.Dispose();
GC.SuppressFinalize(this);
}
public ValueTask DisposeAsync()
{
return _repositories.DisposeAsync();
} }
} }
} }

View File

@ -178,5 +178,43 @@ namespace Kyoo.Tests.SpecificTests
Assert.Null(edited.Genres); Assert.Null(edited.Genres);
Assert.Null(edited.Studio); Assert.Null(edited.Studio);
} }
[Fact]
public async Task CreateWithRelationsTest()
{
Show expected = TestSample.Get<Show>();
expected.ID = 0;
expected.Slug = "created-relation-test";
expected.ExternalIDs = new[]
{
new MetadataID<Show>
{
First = expected,
Second = new Provider("provider", "provider.png"),
DataID = "ID"
}
};
expected.Genres = new[]
{
new Genre
{
Name = "Genre",
Slug = "genre"
}
};
expected.People = new[]
{
new PeopleRole
{
People = TestSample.Get<People>(),
Show = expected,
ForPeople = false,
Role = "actor"
}
};
expected.Studio = new Studio("studio");
Show created = await _repository.Create(expected);
KAssert.DeepEqual(expected, created);
}
} }
} }

View File

@ -93,6 +93,7 @@ namespace Kyoo.Tests
public void Dispose() public void Dispose()
{ {
_connection.Close(); _connection.Close();
GC.SuppressFinalize(this);
} }
public async ValueTask DisposeAsync() public async ValueTask DisposeAsync()

View File

@ -6,11 +6,11 @@ namespace Kyoo.Tests
{ {
public static class TestSample public static class TestSample
{ {
private static readonly Dictionary<Type, object> Samples = new() private static readonly Dictionary<Type, Func<object>> Samples = new()
{ {
{ {
typeof(Show), typeof(Show),
new Show () => new Show
{ {
ID = 1, ID = 1,
Slug = "anohana", Slug = "anohana",
@ -37,7 +37,7 @@ namespace Kyoo.Tests
}, },
{ {
typeof(Season), typeof(Season),
new Season () => new Season
{ {
ID = 1, ID = 1,
ShowSlug = "anohana", ShowSlug = "anohana",
@ -52,7 +52,7 @@ namespace Kyoo.Tests
}, },
{ {
typeof(Episode), typeof(Episode),
new Episode () => new Episode
{ {
ID = 1, ID = 1,
ShowSlug = "anohana", ShowSlug = "anohana",
@ -70,7 +70,7 @@ namespace Kyoo.Tests
}, },
{ {
typeof(People), typeof(People),
new People () => new People
{ {
ID = 1, ID = 1,
Slug = "the-actor", Slug = "the-actor",
@ -82,7 +82,7 @@ namespace Kyoo.Tests
public static T Get<T>() public static T Get<T>()
{ {
return (T)Samples[typeof(T)]; return (T)Samples[typeof(T)]();
} }
} }
} }

View File

@ -33,14 +33,6 @@ namespace Kyoo.Controllers
/// A provider repository to handle externalID creation and deletion /// A provider repository to handle externalID creation and deletion
/// </summary> /// </summary>
private readonly IProviderRepository _providers; private readonly IProviderRepository _providers;
/// <summary>
/// A lazy loaded season repository to handle cascade deletion (seasons deletion whith it's show)
/// </summary>
private readonly Lazy<ISeasonRepository> _seasons;
/// <summary>
/// A lazy loaded episode repository to handle cascade deletion (episode deletion whith it's show)
/// </summary>
private readonly Lazy<IEpisodeRepository> _episodes;
/// <inheritdoc /> /// <inheritdoc />
protected override Expression<Func<Show, object>> DefaultSort => x => x.Title; protected override Expression<Func<Show, object>> DefaultSort => x => x.Title;
@ -53,15 +45,11 @@ namespace Kyoo.Controllers
/// <param name="people">A people repository</param> /// <param name="people">A people repository</param>
/// <param name="genres">A genres repository</param> /// <param name="genres">A genres repository</param>
/// <param name="providers">A provider repository</param> /// <param name="providers">A provider repository</param>
/// <param name="seasons">A lazy loaded season repository</param>
/// <param name="episodes">A lazy loaded episode repository</param>
public ShowRepository(DatabaseContext database, public ShowRepository(DatabaseContext database,
IStudioRepository studios, IStudioRepository studios,
IPeopleRepository people, IPeopleRepository people,
IGenreRepository genres, IGenreRepository genres,
IProviderRepository providers, IProviderRepository providers)
Lazy<ISeasonRepository> seasons,
Lazy<IEpisodeRepository> episodes)
: base(database) : base(database)
{ {
_database = database; _database = database;
@ -69,8 +57,6 @@ namespace Kyoo.Controllers
_people = people; _people = people;
_genres = genres; _genres = genres;
_providers = providers; _providers = providers;
_seasons = seasons;
_episodes = episodes;
} }
@ -103,12 +89,16 @@ namespace Kyoo.Controllers
await base.Validate(resource); await base.Validate(resource);
if (resource.Studio != null) if (resource.Studio != null)
resource.Studio = await _studios.CreateIfNotExists(resource.Studio); resource.Studio = await _studios.CreateIfNotExists(resource.Studio);
resource.Genres = await TaskUtils.DefaultIfNull(resource.Genres
?.SelectAsync(x => _genres.CreateIfNotExists(x))
.ToListAsync());
resource.GenreLinks = resource.Genres? resource.GenreLinks = resource.Genres?
.Select(x => Link.UCreate(resource, x)) .Select(x => Link.Create(resource, x))
.ToList(); .ToList();
await resource.GenreLinks.ForEachAsync(async id =>
{
id.Second = await _genres.CreateIfNotExists(id.Second);
id.SecondID = id.Second.ID;
_database.Entry(id.Second).State = EntityState.Detached;
});
await resource.ExternalIDs.ForEachAsync(async id => await resource.ExternalIDs.ForEachAsync(async id =>
{ {
id.Second = await _providers.CreateIfNotExists(id.Second); id.Second = await _providers.CreateIfNotExists(id.Second);
@ -139,8 +129,8 @@ namespace Kyoo.Controllers
if (changed.Genres != null || resetOld) if (changed.Genres != null || resetOld)
{ {
await Database.Entry(resource).Collection(x => x.GenreLinks).LoadAsync(); await Database.Entry(resource).Collection(x => x.Genres).LoadAsync();
resource.GenreLinks = changed.Genres?.Select(x => Link.UCreate(resource, x)).ToList(); resource.Genres = changed.Genres;
} }
if (changed.People != null || resetOld) if (changed.People != null || resetOld)
@ -191,18 +181,8 @@ namespace Kyoo.Controllers
/// <inheritdoc /> /// <inheritdoc />
public override async Task Delete(Show obj) public override async Task Delete(Show obj)
{ {
if (obj == null)
throw new ArgumentNullException(nameof(obj));
_database.Entry(obj).State = EntityState.Deleted; _database.Entry(obj).State = EntityState.Deleted;
await _database.SaveChangesAsync(); await _database.SaveChangesAsync();
// TODO handle that with events maybe. (for now, seasons & episodes might not be loaded)
if (obj.Seasons != null)
await _seasons.Value.DeleteRange(obj.Seasons);
if (obj.Episodes != null)
await _episodes.Value.DeleteRange(obj.Episodes);
} }
} }
} }