using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using API.Constants;
using API.Data.Repositories;
using API.DTOs.KavitaPlus.Metadata;
using API.DTOs.Recommendation;
using API.DTOs.Scrobbling;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Entities.MetadataMatching;
using API.Entities.Person;
using API.Helpers.Builders;
using API.Services.Plus;
using API.Services.Tasks.Metadata;
using API.SignalR;
using Hangfire;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NSubstitute;
using Xunit;
namespace API.Tests.Services;
///
/// Given these rely on Kavita+, this will not have any [Fact]/[Theory] on them and must be manually checked
///
public class ExternalMetadataServiceTests : AbstractDbTest
{
private readonly ExternalMetadataService _externalMetadataService;
private readonly Dictionary _genreLookup = new Dictionary();
private readonly Dictionary _tagLookup = new Dictionary();
private readonly Dictionary _personLookup = new Dictionary();
public ExternalMetadataServiceTests()
{
// Set up Hangfire to use in-memory storage for testing
GlobalConfiguration.Configuration.UseInMemoryStorage();
_externalMetadataService = new ExternalMetadataService(UnitOfWork, Substitute.For>(),
Mapper, Substitute.For(), Substitute.For(), Substitute.For(),
Substitute.For());
}
#region Gloabl
[Fact]
public async Task Off_Modification()
{
await ResetDb();
const string seriesName = "Test - Summary";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = false;
metadataSettings.EnableSummary = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Summary = "Test"
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(string.Empty, postSeries.Metadata.Summary);
}
#endregion
#region Summary
[Fact]
public async Task Summary_NoExisting_Off_Modification()
{
await ResetDb();
const string seriesName = "Test - Summary";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableSummary = false;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Summary = "Test"
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(string.Empty, postSeries.Metadata.Summary);
}
[Fact]
public async Task Summary_NoExisting_Modification()
{
await ResetDb();
const string seriesName = "Test - Summary";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableSummary = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Summary = "Test"
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.False(string.IsNullOrEmpty(postSeries.Metadata.Summary));
Assert.Equal(series.Metadata.Summary, postSeries.Metadata.Summary);
}
[Fact]
public async Task Summary_Existing_NoModification()
{
await ResetDb();
const string seriesName = "Test - Summary";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithSummary("This summary is not locked")
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableSummary = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Summary = "This should not write"
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.False(string.IsNullOrEmpty(postSeries.Metadata.Summary));
Assert.Equal("This summary is not locked", postSeries.Metadata.Summary);
}
[Fact]
public async Task Summary_Existing_Locked_NoModification()
{
await ResetDb();
const string seriesName = "Test - Summary";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithSummary("This summary is not locked", true)
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableSummary = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Summary = "This should not write"
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.False(string.IsNullOrEmpty(postSeries.Metadata.Summary));
Assert.Equal("This summary is not locked", postSeries.Metadata.Summary);
}
[Fact]
public async Task Summary_Existing_Locked_Override_Modification()
{
await ResetDb();
const string seriesName = "Test - Summary";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithSummary("This summary is not locked", true)
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableSummary = true;
metadataSettings.Overrides = [MetadataSettingField.Summary];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Summary = "This should write"
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.False(string.IsNullOrEmpty(postSeries.Metadata.Summary));
Assert.Equal("This should write", postSeries.Metadata.Summary);
}
#endregion
#region Release Year
[Fact]
public async Task ReleaseYear_NoExisting_Off_NoModification()
{
await ResetDb();
const string seriesName = "Test - Release Year";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableStartDate = false;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
StartDate = DateTime.UtcNow
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(0, postSeries.Metadata.ReleaseYear);
}
[Fact]
public async Task ReleaseYear_NoExisting_Modification()
{
await ResetDb();
const string seriesName = "Test - Release Year";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableStartDate = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
StartDate = DateTime.UtcNow
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(DateTime.UtcNow.Year, postSeries.Metadata.ReleaseYear);
}
[Fact]
public async Task ReleaseYear_Existing_NoModification()
{
await ResetDb();
const string seriesName = "Test - Release Year";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithReleaseYear(1990)
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableStartDate = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
StartDate = DateTime.UtcNow
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(1990, postSeries.Metadata.ReleaseYear);
}
[Fact]
public async Task ReleaseYear_Existing_Locked_NoModification()
{
await ResetDb();
const string seriesName = "Test - Release Year";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithReleaseYear(1990, true)
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableStartDate = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
StartDate = DateTime.UtcNow
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(1990, postSeries.Metadata.ReleaseYear);
}
[Fact]
public async Task ReleaseYear_Existing_Locked_Override_Modification()
{
await ResetDb();
const string seriesName = "Test - Release Year";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithReleaseYear(1990, true)
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableStartDate = true;
metadataSettings.Overrides = [MetadataSettingField.StartDate];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
StartDate = DateTime.UtcNow
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(DateTime.UtcNow.Year, postSeries.Metadata.ReleaseYear);
}
#endregion
#region LocalizedName
[Fact]
public async Task LocalizedName_NoExisting_Off_Modification()
{
await ResetDb();
const string seriesName = "Test - Localized Name";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithLocalizedNameAllowEmpty(string.Empty)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableLocalizedName = false;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Synonyms = [seriesName, "設定しないでください", "Kimchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(string.Empty, postSeries.LocalizedName);
}
[Fact]
public async Task LocalizedName_NoExisting_Modification()
{
await ResetDb();
const string seriesName = "Test - Localized Name";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithLocalizedNameAllowEmpty(string.Empty)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableLocalizedName = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Synonyms = [seriesName, "設定しないでください", "Kimchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal("Kimchi", postSeries.LocalizedName);
}
[Fact]
public async Task LocalizedName_Existing_NoModification()
{
await ResetDb();
const string seriesName = "Test - Localized Name";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithLocalizedName("Localized Name here")
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableLocalizedName = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Synonyms = [seriesName, "設定しないでください", "Kimchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal("Localized Name here", postSeries.LocalizedName);
}
[Fact]
public async Task LocalizedName_Existing_Locked_NoModification()
{
await ResetDb();
const string seriesName = "Test - Localized Name";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithLocalizedName("Localized Name here", true)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableLocalizedName = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Synonyms = [seriesName, "設定しないでください", "Kimchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal("Localized Name here", postSeries.LocalizedName);
}
[Fact]
public async Task LocalizedName_Existing_Locked_Override_Modification()
{
await ResetDb();
const string seriesName = "Test - Localized Name";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithLocalizedName("Localized Name here", true)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableLocalizedName = true;
metadataSettings.Overrides = [MetadataSettingField.LocalizedName];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Synonyms = [seriesName, "設定しないでください", "Kimchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal("Kimchi", postSeries.LocalizedName);
}
[Fact]
public async Task LocalizedName_OnlyNonEnglishSynonyms_Modification()
{
await ResetDb();
const string seriesName = "Test - Localized Name";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithLocalizedNameAllowEmpty(string.Empty)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableLocalizedName = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Synonyms = [seriesName, "設定しないでください"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.True(string.IsNullOrEmpty(postSeries.LocalizedName));
}
#endregion
#region Publication Status
[Fact]
public async Task PublicationStatus_NoExisting_Off_NoModification()
{
await ResetDb();
const string seriesName = "Test - Publication Status";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("2").Build())
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePublicationStatus = false;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Volumes = 2
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(PublicationStatus.OnGoing, postSeries.Metadata.PublicationStatus);
}
[Fact]
public async Task PublicationStatus_NoExisting_Modification()
{
await ResetDb();
const string seriesName = "Test - Publication Status";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("2").Build())
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePublicationStatus = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Volumes = 2
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(PublicationStatus.Completed, postSeries.Metadata.PublicationStatus);
}
[Fact]
public async Task PublicationStatus_Existing_Modification()
{
await ResetDb();
const string seriesName = "Test - Publication Status";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithPublicationStatus(PublicationStatus.Hiatus)
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("2").Build())
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePublicationStatus = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Volumes = 2
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(PublicationStatus.Completed, postSeries.Metadata.PublicationStatus);
}
[Fact]
public async Task PublicationStatus_Existing_Locked_NoModification()
{
await ResetDb();
const string seriesName = "Test - Publication Status";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithPublicationStatus(PublicationStatus.Hiatus, true)
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("2").Build())
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePublicationStatus = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Volumes = 2
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(PublicationStatus.Hiatus, postSeries.Metadata.PublicationStatus);
}
[Fact]
public async Task PublicationStatus_Existing_Locked_Override_Modification()
{
await ResetDb();
const string seriesName = "Test - Publication Status";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithPublicationStatus(PublicationStatus.Hiatus, true)
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("2").Build())
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePublicationStatus = true;
metadataSettings.Overrides = [MetadataSettingField.PublicationStatus];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Volumes = 2
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(PublicationStatus.Completed, postSeries.Metadata.PublicationStatus);
}
[Fact]
public async Task PublicationStatus_Existing_CorrectState_Modification()
{
await ResetDb();
const string seriesName = "Test - Publication Status";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithPublicationStatus(PublicationStatus.Hiatus)
.Build())
.WithVolume(new VolumeBuilder("1")
.WithChapter(new ChapterBuilder("1").Build())
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePublicationStatus = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Volumes = 2
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(PublicationStatus.Ended, postSeries.Metadata.PublicationStatus);
}
#endregion
#region Age Rating
[Fact]
public async Task AgeRating_NoExisting_Modification()
{
await ResetDb();
const string seriesName = "Test - Age Rating";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.AgeRatingMappings = new Dictionary()
{
{"Ecchi", AgeRating.Teen}, // Genre
{"H", AgeRating.R18Plus}, // Tag
};
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Ecchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(AgeRating.Teen, postSeries.Metadata.AgeRating);
}
[Fact]
public async Task AgeRating_ExistingHigher_NoModification()
{
await ResetDb();
const string seriesName = "Test - Age Rating";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithAgeRating(AgeRating.Mature)
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.AgeRatingMappings = new Dictionary()
{
{"Ecchi", AgeRating.Teen}, // Genre
{"H", AgeRating.R18Plus}, // Tag
};
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Ecchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(AgeRating.Mature, postSeries.Metadata.AgeRating);
}
[Fact]
public async Task AgeRating_ExistingLower_Modification()
{
await ResetDb();
const string seriesName = "Test - Age Rating";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithAgeRating(AgeRating.Everyone)
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.AgeRatingMappings = new Dictionary()
{
{"Ecchi", AgeRating.Teen}, // Genre
{"H", AgeRating.R18Plus}, // Tag
};
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Ecchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(AgeRating.Teen, postSeries.Metadata.AgeRating);
}
[Fact]
public async Task AgeRating_Existing_Locked_NoModification()
{
await ResetDb();
const string seriesName = "Test - Age Rating";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithAgeRating(AgeRating.Everyone, true)
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.AgeRatingMappings = new Dictionary()
{
{"Ecchi", AgeRating.Teen}, // Genre
{"H", AgeRating.R18Plus}, // Tag
};
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Ecchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(AgeRating.Everyone, postSeries.Metadata.AgeRating);
}
[Fact]
public async Task AgeRating_Existing_Locked_Override_Modification()
{
await ResetDb();
const string seriesName = "Test - Age Rating";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithAgeRating(AgeRating.Everyone, true)
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.Overrides = [MetadataSettingField.AgeRating];
metadataSettings.AgeRatingMappings = new Dictionary()
{
{"Ecchi", AgeRating.Teen}, // Genre
{"H", AgeRating.R18Plus}, // Tag
};
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Ecchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(AgeRating.Teen, postSeries.Metadata.AgeRating);
}
#endregion
#region Genres
[Fact]
public async Task Genres_NoExisting_Off_NoModification()
{
await ResetDb();
const string seriesName = "Test - Genres";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableGenres = false;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Ecchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal([], postSeries.Metadata.Genres);
}
[Fact]
public async Task Genres_NoExisting_Modification()
{
await ResetDb();
const string seriesName = "Test - Genres";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableGenres = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Ecchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(["Ecchi"], postSeries.Metadata.Genres.Select(g => g.Title));
}
[Fact]
public async Task Genres_Existing_Modification()
{
await ResetDb();
const string seriesName = "Test - Genres";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithGenre(_genreLookup["Action"])
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableGenres = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Ecchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(["Ecchi"], postSeries.Metadata.Genres.Select(g => g.Title));
}
[Fact]
public async Task Genres_Existing_Locked_NoModification()
{
await ResetDb();
const string seriesName = "Test - Genres";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithGenre(_genreLookup["Action"], true)
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableGenres = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Ecchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(["Action"], postSeries.Metadata.Genres.Select(g => g.Title));
}
[Fact]
public async Task Genres_Existing_Locked_Override_Modification()
{
await ResetDb();
const string seriesName = "Test - Genres";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithGenre(_genreLookup["Action"], true)
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableGenres = true;
metadataSettings.Overrides = [MetadataSettingField.Genres];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Ecchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(["Ecchi"], postSeries.Metadata.Genres.Select(g => g.Title));
}
#endregion
#region Tags
[Fact]
public async Task Tags_NoExisting_Off_NoModification()
{
await ResetDb();
const string seriesName = "Test - Tags";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableTags = false;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Tags = [new MetadataTagDto() {Name = "Boxing"}]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal([], postSeries.Metadata.Tags);
}
[Fact]
public async Task Tags_NoExisting_Modification()
{
await ResetDb();
const string seriesName = "Test - Tags";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableTags = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Tags = [new MetadataTagDto() {Name = "Boxing"}]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(["Boxing"], postSeries.Metadata.Tags.Select(t => t.Title));
}
[Fact]
public async Task Tags_Existing_Locked_NoModification()
{
await ResetDb();
const string seriesName = "Test - Tags";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithTag(_tagLookup["H"], true)
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableTags = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Tags = [new MetadataTagDto() {Name = "Boxing"}]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(["H"], postSeries.Metadata.Tags.Select(t => t.Title));
}
[Fact]
public async Task Tags_Existing_Locked_Override_Modification()
{
await ResetDb();
const string seriesName = "Test - Tags";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithTag(_tagLookup["H"], true)
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableTags = true;
metadataSettings.Overrides = [MetadataSettingField.Tags];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Tags = [new MetadataTagDto() {Name = "Boxing"}]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(["Boxing"], postSeries.Metadata.Tags.Select(t => t.Title));
}
#endregion
#region People - Writers/Artists
[Fact]
public async Task People_Writer_NoExisting_Off_NoModification()
{
await ResetDb();
const string seriesName = "Test - People - Writer/Artists";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = false;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Staff = [CreateStaff("John", "Doe", "Story")]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal([], postSeries.Metadata.People.Where(p => p.Role == PersonRole.Writer));
}
[Fact]
public async Task People_Writer_NoExisting_Modification()
{
await ResetDb();
const string seriesName = "Test - People - Writer/Artists";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Staff = [CreateStaff("John", "Doe", "Story")]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(["John Doe"], postSeries.Metadata.People.Where(p => p.Role == PersonRole.Writer).Select(p => p.Person.Name));
}
[Fact]
public async Task People_Writer_Locked_NoModification()
{
await ResetDb();
const string seriesName = "Test - People - Writer/Artists";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithPerson(_personLookup["Johnny Twowheeler"], PersonRole.Writer)
.Build())
.Build();
series.Metadata.WriterLocked = true;
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Staff = [CreateStaff("John", "Doe", "Story")]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[]{"Johnny Twowheeler"}.OrderBy(s => s),
postSeries.Metadata.People.Where(p => p.Role == PersonRole.Writer)
.Select(p => p.Person.Name)
.OrderBy(s => s));
}
[Fact]
public async Task People_Writer_Locked_Override_Modification()
{
await ResetDb();
const string seriesName = "Test - People - Writer/Artists";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithPerson(_personLookup["Johnny Twowheeler"], PersonRole.Writer)
.Build())
.Build();
series.Metadata.WriterLocked = true;
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = true;
metadataSettings.Overrides = [MetadataSettingField.People];
metadataSettings.PersonRoles = [PersonRole.Writer];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Staff = [CreateStaff("John", "Doe", "Story")]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[]{"John Doe", "Johnny Twowheeler"}.OrderBy(s => s),
postSeries.Metadata.People.Where(p => p.Role == PersonRole.Writer)
.Select(p => p.Person.Name)
.OrderBy(s => s));
Assert.True( postSeries.Metadata.People.Where(p => p.Role == PersonRole.Writer)
.FirstOrDefault(p => p.Person.Name == "John Doe")!.KavitaPlusConnection);
}
[Fact]
public async Task People_Writer_Locked_Override_ReverseNamingMatch_Modification()
{
await ResetDb();
const string seriesName = "Test - People - Writer/Artists";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithPerson(_personLookup["Johnny Twowheeler"], PersonRole.Writer)
.Build())
.Build();
series.Metadata.WriterLocked = true;
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = false;
metadataSettings.Overrides = [MetadataSettingField.People];
metadataSettings.PersonRoles = [PersonRole.Writer];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Staff = [CreateStaff("Twowheeler", "Johnny", "Story")]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[]{"Johnny Twowheeler"}.OrderBy(s => s),
postSeries.Metadata.People.Where(p => p.Role == PersonRole.Writer)
.Select(p => p.Person.Name)
.OrderBy(s => s));
}
[Fact]
public async Task People_Writer_Locked_Override_PersonRoleNotSet_NoModification()
{
await ResetDb();
const string seriesName = "Test - People - Writer/Artists";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithPerson(_personLookup["Johnny Twowheeler"], PersonRole.Writer)
.Build())
.Build();
series.Metadata.WriterLocked = true;
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = true;
metadataSettings.Overrides = [MetadataSettingField.People];
metadataSettings.PersonRoles = [];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Staff = [CreateStaff("John", "Doe", "Story")]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[]{"Johnny Twowheeler"}.OrderBy(s => s),
postSeries.Metadata.People.Where(p => p.Role == PersonRole.Writer)
.Select(p => p.Person.Name)
.OrderBy(s => s));
}
[Fact]
public async Task People_Writer_OverrideReMatchDeletesOld_Modification()
{
await ResetDb();
const string seriesName = "Test - People - Writer/Artists";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = true;
metadataSettings.Overrides = [MetadataSettingField.People];
metadataSettings.PersonRoles = [PersonRole.Writer];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Staff = [CreateStaff("John", "Doe", "Story")]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[]{"John Doe"}.OrderBy(s => s),
postSeries.Metadata.People.Where(p => p.Role == PersonRole.Writer)
.Select(p => p.Person.Name)
.OrderBy(s => s));
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Staff = [CreateStaff("John", "Doe 2", "Story")]
}, 1);
postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[]{"John Doe 2"}.OrderBy(s => s),
postSeries.Metadata.People.Where(p => p.Role == PersonRole.Writer)
.Select(p => p.Person.Name)
.OrderBy(s => s));
}
#endregion
#region People Alias
[Fact]
public async Task PeopleAliasing_AddAsAlias()
{
await ResetDb();
const string seriesName = "Test - People - Add as Alias";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
Context.Person.Add(new PersonBuilder("John Doe").Build());
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = true;
metadataSettings.Overrides = [MetadataSettingField.People];
metadataSettings.PersonRoles = [PersonRole.Writer];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Staff = [CreateStaff("Doe", "John", "Story")]
}, 1);
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
var allWriters = postSeries.Metadata.People.Where(p => p.Role == PersonRole.Writer).ToList();
Assert.Single(allWriters);
var johnDoe = allWriters[0].Person;
Assert.Contains("Doe John", johnDoe.Aliases.Select(pa => pa.Alias));
}
[Fact]
public async Task PeopleAliasing_AddOnAlias()
{
await ResetDb();
const string seriesName = "Test - People - Add as Alias";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
Context.Person.Add(new PersonBuilder("John Doe").WithAlias("Doe John").Build());
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = true;
metadataSettings.Overrides = [MetadataSettingField.People];
metadataSettings.PersonRoles = [PersonRole.Writer];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Staff = [CreateStaff("Doe", "John", "Story")]
}, 1);
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
var allWriters = postSeries.Metadata.People.Where(p => p.Role == PersonRole.Writer).ToList();
Assert.Single(allWriters);
var johnDoe = allWriters[0].Person;
Assert.Contains("Doe John", johnDoe.Aliases.Select(pa => pa.Alias));
}
[Fact]
public async Task PeopleAliasing_DontAddAsAlias_SameButNotSwitched()
{
await ResetDb();
const string seriesName = "Test - People - Add as Alias";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = true;
metadataSettings.Overrides = [MetadataSettingField.People];
metadataSettings.PersonRoles = [PersonRole.Writer];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Staff = [CreateStaff("John", "Doe Doe", "Story"), CreateStaff("Doe", "John Doe", "Story")]
}, 1);
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
var allWriters = postSeries.Metadata.People.Where(p => p.Role == PersonRole.Writer).ToList();
Assert.Equal(2, allWriters.Count);
}
#endregion
#region People - Characters
[Fact]
public async Task People_Character_NoExisting_Off_NoModification()
{
await ResetDb();
const string seriesName = "Test - People - Character";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = false;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Characters = [CreateCharacter("John", "Doe", CharacterRole.Main)]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal([], postSeries.Metadata.People.Where(p => p.Role == PersonRole.Character));
}
[Fact]
public async Task People_Character_NoExisting_Modification()
{
await ResetDb();
const string seriesName = "Test - People - Character";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Characters = [CreateCharacter("John", "Doe", CharacterRole.Main)]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(["John Doe"], postSeries.Metadata.People.Where(p => p.Role == PersonRole.Character).Select(p => p.Person.Name));
}
[Fact]
public async Task People_Character_Locked_NoModification()
{
await ResetDb();
const string seriesName = "Test - People - Character";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithPerson(_personLookup["Johnny Twowheeler"], PersonRole.Character)
.Build())
.Build();
series.Metadata.CharacterLocked = true;
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Characters = [CreateCharacter("John", "Doe", CharacterRole.Main)]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[]{"Johnny Twowheeler"}.OrderBy(s => s),
postSeries.Metadata.People.Where(p => p.Role == PersonRole.Character)
.Select(p => p.Person.Name)
.OrderBy(s => s));
}
[Fact]
public async Task People_Character_Locked_Override_Modification()
{
await ResetDb();
const string seriesName = "Test - People - Character";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithPerson(_personLookup["Johnny Twowheeler"], PersonRole.Character)
.Build())
.Build();
series.Metadata.WriterLocked = true;
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = true;
metadataSettings.Overrides = [MetadataSettingField.People];
metadataSettings.PersonRoles = [PersonRole.Character];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Characters = [CreateCharacter("John", "Doe", CharacterRole.Main)]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[]{"John Doe", "Johnny Twowheeler"}.OrderBy(s => s),
postSeries.Metadata.People.Where(p => p.Role == PersonRole.Character)
.Select(p => p.Person.Name)
.OrderBy(s => s));
Assert.True( postSeries.Metadata.People.Where(p => p.Role == PersonRole.Character)
.FirstOrDefault(p => p.Person.Name == "John Doe")!.KavitaPlusConnection);
}
[Fact]
public async Task People_Character_Locked_Override_ReverseNamingNoMatch_Modification()
{
await ResetDb();
const string seriesName = "Test - People - Character";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithPerson(_personLookup["Johnny Twowheeler"], PersonRole.Character)
.Build())
.Build();
series.Metadata.WriterLocked = true;
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = false;
metadataSettings.Overrides = [MetadataSettingField.People];
metadataSettings.PersonRoles = [PersonRole.Character];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Characters = [CreateCharacter("Twowheeler", "Johnny", CharacterRole.Main)]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[]{"Johnny Twowheeler", "Twowheeler Johnny"}.OrderBy(s => s),
postSeries.Metadata.People.Where(p => p.Role == PersonRole.Character)
.Select(p => p.Person.Name)
.OrderBy(s => s));
}
[Fact]
public async Task People_Character_Locked_Override_PersonRoleNotSet_NoModification()
{
await ResetDb();
const string seriesName = "Test - People - Character";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithPerson(_personLookup["Johnny Twowheeler"], PersonRole.Character)
.Build())
.Build();
series.Metadata.WriterLocked = true;
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = true;
metadataSettings.Overrides = [MetadataSettingField.People];
metadataSettings.PersonRoles = [];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Characters = [CreateCharacter("John", "Doe", CharacterRole.Main)]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[]{"Johnny Twowheeler"}.OrderBy(s => s),
postSeries.Metadata.People.Where(p => p.Role == PersonRole.Character)
.Select(p => p.Person.Name)
.OrderBy(s => s));
}
[Fact]
public async Task People_Character_OverrideReMatchDeletesOld_Modification()
{
await ResetDb();
const string seriesName = "Test - People - Character";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnablePeople = true;
metadataSettings.FirstLastPeopleNaming = true;
metadataSettings.Overrides = [MetadataSettingField.People];
metadataSettings.PersonRoles = [PersonRole.Character];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Characters = [CreateCharacter("John", "Doe", CharacterRole.Main)]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[]{"John Doe"}.OrderBy(s => s),
postSeries.Metadata.People.Where(p => p.Role == PersonRole.Character)
.Select(p => p.Person.Name)
.OrderBy(s => s));
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Characters = [CreateCharacter("John", "Doe 2", CharacterRole.Main)]
}, 1);
postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[]{"John Doe 2"}.OrderBy(s => s),
postSeries.Metadata.People.Where(p => p.Role == PersonRole.Character)
.Select(p => p.Person.Name)
.OrderBy(s => s));
}
#endregion
#region Series Cover
// Not sure how to test this
#endregion
#region Relationships
// Not enabled
// Non-Sequel
[Fact]
public async Task Relationships_NonSequel()
{
await ResetDb();
const string seriesName = "Test - Relationships Side Story";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
var series2 = new SeriesBuilder("Test - Relationships Side Story - Target")
.WithLibraryId(1)
.WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.WithExternalMetadata(new ExternalSeriesMetadata()
{
AniListId = 10
})
.Build();
Context.Series.Attach(series2);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableRelationships = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Relations = [new SeriesRelationship()
{
Relation = RelationKind.SideStory,
SeriesName = new ALMediaTitle()
{
PreferredTitle = series2.Name,
EnglishTitle = null,
NativeTitle = series2.Name,
RomajiTitle = series2.Name,
},
AniListId = 10,
PlusMediaFormat = PlusMediaFormat.Manga
}]
}, 1);
// Repull Series and validate what is overwritten
var sourceSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata | SeriesIncludes.Related);
Assert.NotNull(sourceSeries);
Assert.Single(sourceSeries.Relations);
Assert.Equal(series2.Name, sourceSeries.Relations.First().TargetSeries.Name);
}
[Fact]
public async Task Relationships_NonSequel_LocalizedName()
{
await ResetDb();
const string seriesName = "Test - Relationships Side Story";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
var series2 = new SeriesBuilder("Test - Relationships Side Story - Target")
.WithLibraryId(1)
.WithLocalizedName("School bus")
.WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series2);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableRelationships = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Relations = [new SeriesRelationship()
{
Relation = RelationKind.SideStory,
SeriesName = new ALMediaTitle()
{
PreferredTitle = "School bus",
EnglishTitle = null,
NativeTitle = series2.Name,
RomajiTitle = series2.Name,
},
AniListId = 10,
PlusMediaFormat = PlusMediaFormat.Manga
}]
}, 1);
// Repull Series and validate what is overwritten
var sourceSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata | SeriesIncludes.Related);
Assert.NotNull(sourceSeries);
Assert.Single(sourceSeries.Relations);
Assert.Equal(series2.Name, sourceSeries.Relations.First().TargetSeries.Name);
}
// Non-Sequel with no match due to Format difference
[Fact]
public async Task Relationships_NonSequel_FormatDifference()
{
await ResetDb();
const string seriesName = "Test - Relationships Side Story";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
var series2 = new SeriesBuilder("Test - Relationships Side Story - Target")
.WithLibraryId(1)
.WithLocalizedName("School bus")
.WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series2);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableRelationships = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Relations = [new SeriesRelationship()
{
Relation = RelationKind.SideStory,
SeriesName = new ALMediaTitle()
{
PreferredTitle = "School bus",
EnglishTitle = null,
NativeTitle = series2.Name,
RomajiTitle = series2.Name,
},
AniListId = 10,
PlusMediaFormat = PlusMediaFormat.Book
}]
}, 1);
// Repull Series and validate what is overwritten
var sourceSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata | SeriesIncludes.Related);
Assert.NotNull(sourceSeries);
Assert.Empty(sourceSeries.Relations);
}
// Non-Sequel existing relationship with new link, both exist
[Fact]
public async Task Relationships_NonSequel_ExistingLink_DifferentType_BothExist()
{
await ResetDb();
var existingRelationshipSeries = new SeriesBuilder("Existing")
.WithLibraryId(1)
.Build();
Context.Series.Attach(existingRelationshipSeries);
await Context.SaveChangesAsync();
const string seriesName = "Test - Relationships Side Story";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithFormat(MangaFormat.Archive)
.WithRelationship(existingRelationshipSeries.Id, RelationKind.Annual)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
var series2 = new SeriesBuilder("Test - Relationships Side Story - Target")
.WithLibraryId(1)
.WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.WithExternalMetadata(new ExternalSeriesMetadata()
{
AniListId = 10
})
.Build();
Context.Series.Attach(series2);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableRelationships = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Relations = [new SeriesRelationship()
{
Relation = RelationKind.SideStory,
SeriesName = new ALMediaTitle()
{
PreferredTitle = series2.Name,
EnglishTitle = null,
NativeTitle = series2.Name,
RomajiTitle = series2.Name,
},
PlusMediaFormat = PlusMediaFormat.Manga
}]
}, 2);
// Repull Series and validate what is overwritten
var sourceSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(2, SeriesIncludes.Metadata | SeriesIncludes.Related);
Assert.NotNull(sourceSeries);
Assert.Equal(seriesName, sourceSeries.Name);
Assert.Contains(sourceSeries.Relations, r => r.RelationKind == RelationKind.Annual && r.TargetSeriesId == existingRelationshipSeries.Id);
Assert.Contains(sourceSeries.Relations, r => r.RelationKind == RelationKind.SideStory && r.TargetSeriesId == series2.Id);
}
// Sequel/Prequel
[Fact]
public async Task Relationships_Sequel_CreatesPrequel()
{
await ResetDb();
const string seriesName = "Test - Relationships Source";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
var series2 = new SeriesBuilder("Test - Relationships Target")
.WithLibraryId(1)
.WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series2);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableRelationships = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Relations = [new SeriesRelationship()
{
Relation = RelationKind.Sequel,
SeriesName = new ALMediaTitle()
{
PreferredTitle = series2.Name,
EnglishTitle = null,
NativeTitle = series2.Name,
RomajiTitle = series2.Name,
},
PlusMediaFormat = PlusMediaFormat.Manga
}]
}, 1);
// Repull Series and validate what is overwritten
var sourceSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata | SeriesIncludes.Related);
Assert.NotNull(sourceSeries);
Assert.Single(sourceSeries.Relations);
Assert.Equal(series2.Name, sourceSeries.Relations.First().TargetSeries.Name);
var sequel = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(2, SeriesIncludes.Metadata | SeriesIncludes.Related);
Assert.NotNull(sequel);
Assert.Equal(seriesName, sequel.Relations.First().TargetSeries.Name);
}
[Fact]
public async Task Relationships_Prequel_CreatesSequel()
{
await ResetDb();
// ID 1: Blue Lock - Episode Nagi
var series = new SeriesBuilder("Blue Lock - Episode Nagi")
.WithLibraryId(1)
.WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
// ID 2: Blue Lock
var series2 = new SeriesBuilder("Blue Lock")
.WithLibraryId(1)
.WithFormat(MangaFormat.Archive)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series2);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableRelationships = true;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
// Apply to Blue Lock - Episode Nagi (ID 1), setting Blue Lock (ID 2) as its prequel
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = "Blue Lock - Episode Nagi", // The series we're updating metadata for
Relations = [new SeriesRelationship()
{
Relation = RelationKind.Prequel, // Blue Lock is the prequel to Nagi
SeriesName = new ALMediaTitle()
{
PreferredTitle = "Blue Lock",
EnglishTitle = "Blue Lock",
NativeTitle = "ブルーロック",
RomajiTitle = "Blue Lock",
},
PlusMediaFormat = PlusMediaFormat.Manga,
AniListId = 106130,
MalId = 114745,
Provider = ScrobbleProvider.AniList
}]
}, 1); // Apply to series ID 1 (Nagi)
// Verify Blue Lock - Episode Nagi has Blue Lock as prequel
var nagiSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata | SeriesIncludes.Related);
Assert.NotNull(nagiSeries);
Assert.Single(nagiSeries.Relations);
Assert.Equal("Blue Lock", nagiSeries.Relations.First().TargetSeries.Name);
Assert.Equal(RelationKind.Prequel, nagiSeries.Relations.First().RelationKind);
// Verify Blue Lock has Blue Lock - Episode Nagi as sequel
var blueLockSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(2, SeriesIncludes.Metadata | SeriesIncludes.Related);
Assert.NotNull(blueLockSeries);
Assert.Single(blueLockSeries.Relations);
Assert.Equal("Blue Lock - Episode Nagi", blueLockSeries.Relations.First().TargetSeries.Name);
Assert.Equal(RelationKind.Sequel, blueLockSeries.Relations.First().RelationKind);
}
#endregion
#region Blacklist
[Fact]
public async Task Blacklist_Genres()
{
await ResetDb();
const string seriesName = "Test - Blacklist Genres";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableTags = true;
metadataSettings.EnableGenres = true;
metadataSettings.Blacklist = ["Sports", "Action"];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Boxing", "Sports", "Action"],
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[] {"Boxing"}.OrderBy(s => s), postSeries.Metadata.Genres.Select(t => t.Title).OrderBy(s => s));
}
[Fact]
public async Task Blacklist_Tags()
{
await ResetDb();
const string seriesName = "Test - Blacklist Tags";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableTags = true;
metadataSettings.EnableGenres = true;
metadataSettings.Blacklist = ["Sports", "Action"];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Tags = [new MetadataTagDto() {Name = "Boxing"}, new MetadataTagDto() {Name = "Sports"}, new MetadataTagDto() {Name = "Action"}]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[] {"Boxing"}.OrderBy(s => s), postSeries.Metadata.Tags.Select(t => t.Title).OrderBy(s => s));
}
// Blacklist Tag
// Field Map then Blacklist Genre
// Field Map then Blacklist Tag
#endregion
#region Whitelist
[Fact]
public async Task Whitelist_Tags()
{
await ResetDb();
const string seriesName = "Test - Whitelist Tags";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableTags = true;
metadataSettings.Whitelist = ["Sports", "Action"];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Tags = [new MetadataTagDto() {Name = "Boxing"}, new MetadataTagDto() {Name = "Sports"}, new MetadataTagDto() {Name = "Action"}]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[] {"Sports", "Action"}.OrderBy(s => s), postSeries.Metadata.Tags.Select(t => t.Title).OrderBy(s => s));
}
[Fact]
public async Task Whitelist_WithFieldMap_Tags()
{
await ResetDb();
const string seriesName = "Test - Whitelist Tags";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableTags = true;
metadataSettings.FieldMappings = [new MetadataFieldMapping()
{
SourceType = MetadataFieldType.Tag,
SourceValue = "Boxing",
DestinationType = MetadataFieldType.Tag,
DestinationValue = "Sports",
ExcludeFromSource = false
}];
metadataSettings.Whitelist = ["Sports", "Action"];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Tags = [new MetadataTagDto() {Name = "Boxing"}, new MetadataTagDto() {Name = "Action"}]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(new[] {"Sports", "Action"}.OrderBy(s => s), postSeries.Metadata.Tags.Select(t => t.Title).OrderBy(s => s));
}
#endregion
#region Field Mapping
[Fact]
public async Task FieldMap_GenreToGenre_KeepSource_Modification()
{
await ResetDb();
const string seriesName = "Test - Genres Field Mapping";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableGenres = true;
metadataSettings.Overrides = [MetadataSettingField.Genres];
metadataSettings.FieldMappings = [new MetadataFieldMapping()
{
SourceType = MetadataFieldType.Genre,
SourceValue = "Ecchi",
DestinationType = MetadataFieldType.Genre,
DestinationValue = "Fanservice",
ExcludeFromSource = false
}];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Ecchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(
new[] { "Ecchi", "Fanservice" }.OrderBy(s => s),
postSeries.Metadata.Genres.Select(g => g.Title).OrderBy(s => s)
);
}
[Fact]
public async Task FieldMap_GenreToGenre_RemoveSource_Modification()
{
await ResetDb();
const string seriesName = "Test - Genres Field Mapping";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableGenres = true;
metadataSettings.Overrides = [MetadataSettingField.Genres];
metadataSettings.FieldMappings = [new MetadataFieldMapping()
{
SourceType = MetadataFieldType.Genre,
SourceValue = "Ecchi",
DestinationType = MetadataFieldType.Genre,
DestinationValue = "Fanservice",
ExcludeFromSource = true
}];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Ecchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(["Fanservice"], postSeries.Metadata.Genres.Select(g => g.Title));
}
[Fact]
public async Task FieldMap_TagToTag_KeepSource_Modification()
{
await ResetDb();
const string seriesName = "Test - Tag Field Mapping";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableTags = true;
metadataSettings.FieldMappings = [new MetadataFieldMapping()
{
SourceType = MetadataFieldType.Tag,
SourceValue = "Ecchi",
DestinationType = MetadataFieldType.Tag,
DestinationValue = "Fanservice",
ExcludeFromSource = false
}];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Tags = [new MetadataTagDto() {Name = "Ecchi"}]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(
new[] { "Ecchi", "Fanservice" }.OrderBy(s => s),
postSeries.Metadata.Tags.Select(g => g.Title).OrderBy(s => s)
);
}
[Fact]
public async Task Tags_Existing_FieldMap_RemoveSource_Modification()
{
await ResetDb();
const string seriesName = "Test - Tag Field Mapping";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableTags = true;
metadataSettings.Overrides = [MetadataSettingField.Genres];
metadataSettings.FieldMappings = [new MetadataFieldMapping()
{
SourceType = MetadataFieldType.Tag,
SourceValue = "Ecchi",
DestinationType = MetadataFieldType.Tag,
DestinationValue = "Fanservice",
ExcludeFromSource = true
}];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Tags = [new MetadataTagDto() {Name = "Ecchi"}]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(["Fanservice"], postSeries.Metadata.Tags.Select(g => g.Title));
}
[Fact]
public async Task FieldMap_GenreToTag_KeepSource_Modification()
{
await ResetDb();
const string seriesName = "Test - Genres Field Mapping";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableGenres = true;
metadataSettings.EnableTags = true;
metadataSettings.Overrides = [MetadataSettingField.Genres, MetadataSettingField.Tags];
metadataSettings.FieldMappings = [new MetadataFieldMapping()
{
SourceType = MetadataFieldType.Genre,
SourceValue = "Ecchi",
DestinationType = MetadataFieldType.Tag,
DestinationValue = "Fanservice",
ExcludeFromSource = false
}];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
Genres = ["Ecchi"]
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(
new[] {"Ecchi"}.OrderBy(s => s),
postSeries.Metadata.Genres.Select(g => g.Title).OrderBy(s => s)
);
Assert.Equal(
new[] {"Fanservice"}.OrderBy(s => s),
postSeries.Metadata.Tags.Select(g => g.Title).OrderBy(s => s)
);
}
[Fact]
public async Task FieldMap_GenreToGenre_RemoveSource_NoExternalGenre_NoModification()
{
await ResetDb();
const string seriesName = "Test - Genres Field Mapping";
var series = new SeriesBuilder(seriesName)
.WithLibraryId(1)
.WithMetadata(new SeriesMetadataBuilder()
.WithGenre(_genreLookup["Action"])
.Build())
.Build();
Context.Series.Attach(series);
await Context.SaveChangesAsync();
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = true;
metadataSettings.EnableGenres = true;
metadataSettings.EnableTags = true;
metadataSettings.Overrides = [MetadataSettingField.Genres, MetadataSettingField.Tags];
metadataSettings.FieldMappings = [new MetadataFieldMapping()
{
SourceType = MetadataFieldType.Genre,
SourceValue = "Action",
DestinationType = MetadataFieldType.Genre,
DestinationValue = "Adventure",
ExcludeFromSource = true
}];
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
await _externalMetadataService.WriteExternalMetadataToSeries(new ExternalSeriesDetailDto()
{
Name = seriesName,
}, 1);
// Repull Series and validate what is overwritten
var postSeries = await UnitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Metadata);
Assert.NotNull(postSeries);
Assert.Equal(
new[] {"Action"}.OrderBy(s => s),
postSeries.Metadata.Genres.Select(g => g.Title).OrderBy(s => s)
);
}
#endregion
protected override async Task ResetDb()
{
Context.Series.RemoveRange(Context.Series);
Context.AppUser.RemoveRange(Context.AppUser);
Context.Genre.RemoveRange(Context.Genre);
Context.Tag.RemoveRange(Context.Tag);
Context.Person.RemoveRange(Context.Person);
var metadataSettings = await UnitOfWork.SettingsRepository.GetMetadataSettings();
metadataSettings.Enabled = false;
metadataSettings.EnableSummary = false;
metadataSettings.EnableCoverImage = false;
metadataSettings.EnableLocalizedName = false;
metadataSettings.EnableGenres = false;
metadataSettings.EnablePeople = false;
metadataSettings.EnableRelationships = false;
metadataSettings.EnableTags = false;
metadataSettings.EnablePublicationStatus = false;
metadataSettings.EnableStartDate = false;
Context.MetadataSettings.Update(metadataSettings);
await Context.SaveChangesAsync();
Context.AppUser.Add(new AppUserBuilder("Joe", "Joe")
.WithRole(PolicyConstants.AdminRole)
.WithLibrary(await Context.Library.FirstAsync(l => l.Id == 1))
.Build());
// Create a bunch of Genres for this test and store their string in _genreLookup
_genreLookup.Clear();
var g1 = new GenreBuilder("Action").Build();
var g2 = new GenreBuilder("Ecchi").Build();
Context.Genre.Add(g1);
Context.Genre.Add(g2);
_genreLookup.Add("Action", g1);
_genreLookup.Add("Ecchi", g2);
_tagLookup.Clear();
var t1 = new TagBuilder("H").Build();
var t2 = new TagBuilder("Boxing").Build();
Context.Tag.Add(t1);
Context.Tag.Add(t2);
_tagLookup.Add("H", t1);
_tagLookup.Add("Boxing", t2);
_personLookup.Clear();
var p1 = new PersonBuilder("Johnny Twowheeler").Build();
var p2 = new PersonBuilder("Boxing").Build();
Context.Person.Add(p1);
Context.Person.Add(p2);
_personLookup.Add("Johnny Twowheeler", p1);
_personLookup.Add("Batman Robin", p2);
await Context.SaveChangesAsync();
}
private static SeriesStaffDto CreateStaff(string first, string last, string role)
{
return new SeriesStaffDto() {Name = $"{first} {last}", Role = role, Url = "", FirstName = first, LastName = last};
}
private static SeriesCharacter CreateCharacter(string first, string last, CharacterRole role)
{
return new SeriesCharacter() {Name = $"{first} {last}", Description = "", Url = "", ImageUrl = "", Role = role};
}
}