using Microsoft.Extensions.Options; using TeleWave.Domain.Media; using TeleWave.Infrastructure.Media; using Xunit; namespace TeleWave.Integration.Tests; /// /// Файловая часть ручного разбора: перечисление, перенос и подчистка спутников. Работает с реальной /// ФС во временном каталоге — код удаляет файлы, и проверять его на моках бессмысленно. /// 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); } }