Refactor manual inbox handling: update ImportManualInboxCommand to accept ManualImportItem objects, enhancing file import functionality with explicit season and episode numbers. Implement CleanupManualLeftoversAsync in IMediaStorage to remove unnecessary files after import. Update frontend components to support new import structure and improve user experience in manual media management.
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using TeleWave.Domain.Media;
|
||||
using TeleWave.Infrastructure.Media;
|
||||
using Xunit;
|
||||
|
||||
namespace TeleWave.Integration.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Файловая часть ручного разбора: перечисление, перенос и подчистка спутников. Работает с реальной
|
||||
/// ФС во временном каталоге — код удаляет файлы, и проверять его на моках бессмысленно.
|
||||
/// </summary>
|
||||
public sealed class ManualInboxStorageTests : IDisposable
|
||||
{
|
||||
private readonly string _root = Path.Combine(
|
||||
Path.GetTempPath(),
|
||||
"telewave-tests-" + Guid.NewGuid().ToString("N")[..8]
|
||||
);
|
||||
|
||||
private readonly FileSystemMediaStorage _storage;
|
||||
private readonly MediaPathResolver _paths;
|
||||
|
||||
public ManualInboxStorageTests()
|
||||
{
|
||||
_paths = new MediaPathResolver(Options.Create(new StorageOptions { RootPath = _root }));
|
||||
_paths.EnsureDirectories();
|
||||
_storage = new FileSystemMediaStorage(_paths);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListManualInbox_WalksSubdirectories_AndReturnsRelativePaths()
|
||||
{
|
||||
Write("Сериал/s01e01.mkv");
|
||||
Write("Сериал/s01e02.mkv");
|
||||
Write("одиночный.mp4");
|
||||
|
||||
var files = _storage.ListManualInbox(int.MaxValue);
|
||||
|
||||
Assert.Equal(3, files.Count);
|
||||
// Разделитель нормализован: путь уезжает в URL и возвращается строкой запроса.
|
||||
Assert.Contains(files, f => f.RelativePath == "Сериал/s01e01.mkv");
|
||||
Assert.Contains(files, f => f.RelativePath == "одиночный.mp4");
|
||||
Assert.All(files, f => Assert.True(f.SizeBytes > 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PromoteToOriginal_MovesFileOutOfManual()
|
||||
{
|
||||
Write("Сериал/s01e01.mkv");
|
||||
var assetId = Guid.NewGuid();
|
||||
|
||||
await _storage.PromoteToOriginalAsync(
|
||||
MediaSource.ManualInbox,
|
||||
"Сериал/s01e01.mkv",
|
||||
assetId,
|
||||
".mkv",
|
||||
default
|
||||
);
|
||||
|
||||
Assert.False(File.Exists(Path.Combine(_paths.ManualDir, "Сериал", "s01e01.mkv")));
|
||||
Assert.True(File.Exists(_paths.OriginalPath(assetId, ".mkv")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Cleanup_RemovesSiblings_ButKeepsOtherVideos()
|
||||
{
|
||||
Write("Сериал/s01e01.mkv");
|
||||
Write("Сериал/s01e01.srt");
|
||||
Write("Сериал/s01e01.ru.srt");
|
||||
Write("Сериал/s01e01.nfo");
|
||||
Write("Сериал/s01e01.Extended.mkv");
|
||||
Write("Сериал/s01e02.mkv");
|
||||
Write("Сериал/s01e02.srt");
|
||||
|
||||
// Так делает импорт: сначала файл уходит в originals/, потом подчищаются спутники.
|
||||
await _storage.PromoteToOriginalAsync(
|
||||
MediaSource.ManualInbox,
|
||||
"Сериал/s01e01.mkv",
|
||||
Guid.NewGuid(),
|
||||
".mkv",
|
||||
default
|
||||
);
|
||||
await _storage.CleanupManualLeftoversAsync("Сериал/s01e01.mkv", default);
|
||||
|
||||
var left = Directory
|
||||
.EnumerateFiles(Path.Combine(_paths.ManualDir, "Сериал"))
|
||||
.Select(Path.GetFileName)
|
||||
.ToList();
|
||||
|
||||
// Субтитры и nfo забранной серии ушли…
|
||||
Assert.DoesNotContain("s01e01.srt", left);
|
||||
Assert.DoesNotContain("s01e01.ru.srt", left);
|
||||
Assert.DoesNotContain("s01e01.nfo", left);
|
||||
// …а другой материал и спутники соседних серий остались.
|
||||
Assert.Contains("s01e01.Extended.mkv", left);
|
||||
Assert.Contains("s01e02.mkv", left);
|
||||
Assert.Contains("s01e02.srt", left);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Cleanup_RemovesEmptiedFolder_ButNotManualRoot()
|
||||
{
|
||||
Write("Сериал/один.mkv");
|
||||
Write("Сериал/один.srt");
|
||||
Write("в-корне.mkv");
|
||||
|
||||
await _storage.PromoteToOriginalAsync(
|
||||
MediaSource.ManualInbox,
|
||||
"Сериал/один.mkv",
|
||||
Guid.NewGuid(),
|
||||
".mkv",
|
||||
default
|
||||
);
|
||||
await _storage.CleanupManualLeftoversAsync("Сериал/один.mkv", default);
|
||||
|
||||
Assert.False(Directory.Exists(Path.Combine(_paths.ManualDir, "Сериал")));
|
||||
|
||||
// Файл в корне забираем — сам корень manual/ остаться обязан.
|
||||
await _storage.PromoteToOriginalAsync(
|
||||
MediaSource.ManualInbox,
|
||||
"в-корне.mkv",
|
||||
Guid.NewGuid(),
|
||||
".mkv",
|
||||
default
|
||||
);
|
||||
await _storage.CleanupManualLeftoversAsync("в-корне.mkv", default);
|
||||
|
||||
Assert.True(Directory.Exists(_paths.ManualDir));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Cleanup_KeepsFolderThatStillHasFiles()
|
||||
{
|
||||
Write("Сериал/s01e01.mkv");
|
||||
Write("Сериал/s01e02.mkv");
|
||||
|
||||
await _storage.PromoteToOriginalAsync(
|
||||
MediaSource.ManualInbox,
|
||||
"Сериал/s01e01.mkv",
|
||||
Guid.NewGuid(),
|
||||
".mkv",
|
||||
default
|
||||
);
|
||||
await _storage.CleanupManualLeftoversAsync("Сериал/s01e01.mkv", default);
|
||||
|
||||
Assert.True(File.Exists(Path.Combine(_paths.ManualDir, "Сериал", "s01e02.mkv")));
|
||||
}
|
||||
|
||||
private void Write(string relativePath)
|
||||
{
|
||||
var full = Path.Combine(_paths.ManualDir, relativePath.Replace('/', Path.DirectorySeparatorChar));
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(full)!);
|
||||
File.WriteAllText(full, "x");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Directory.Exists(_root))
|
||||
Directory.Delete(_root, recursive: true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user