using System.Collections.ObjectModel;
using System.IO;
using Paca.App.Browser.Features;
using Paca.App.Core;
using Paca.App.ViewModels;
using Paca.Browser;
using Paca.Browser.Tabs;
using Paca.Core.Config;
using Paca.Core.Detection;
namespace Paca.Tests.Infrastructure;
///
/// 19차 핵심 시나리오 파이프라인 프레임워크:
/// 다운로드 엔진, 탭 세션, 재생목록, 미디어 감지 파이프라인의 종단간 생명주기를
/// Fluent DSL로 간결하고 강력하게 테스트할 수 있는 프레임워크.
///
public sealed class AppScenarioPipeline : IDisposable
{
public string TempDir { get; }
public AppConfig Config { get; }
public DownloadManager DownloadManager { get; }
public MediaPlaylist Playlist { get; }
public TabManager TabManager { get; }
public List DetectedItems { get; } = new();
private AppScenarioPipeline()
{
TempDir = Path.Combine(Path.GetTempPath(), "VD_Test_" + Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(TempDir);
Environment.SetEnvironmentVariable("VD_DATA_DIR", TempDir);
Config = new AppConfig
{
OutputFolder = Path.Combine(TempDir, "downloads"),
RestoreSession = true,
PlaylistLoopMode = "all"
};
Directory.CreateDirectory(Config.OutputFolder);
DownloadManager = new DownloadManager(
Config,
_ => Task.FromResult(new List()),
_ => { });
DownloadManager.ItemDetected += item => DetectedItems.Add(item);
Playlist = new MediaPlaylist();
TabManager = new TabManager(() => new TabItem(), _ => { });
}
public static AppScenarioPipeline Create() => new();
public AppScenarioPipeline SimulateMediaDetection(string url, MediaKind kind, string? pageUrl = null)
{
DownloadManager.OnDetected(new DetectionContext(url, pageUrl ?? "https://test.local", kind));
return this;
}
public AppScenarioPipeline AddPlaylistTrack(string url, string title, string kind)
{
Playlist.Add(new MediaTrack(url, title, kind, DateTime.UtcNow));
return this;
}
public AppScenarioPipeline SimulateNextTrack()
{
Playlist.Next();
return this;
}
public AppScenarioPipeline SimulateTrackPlayed(MediaTrack track)
{
Playlist.MarkPlayed(track);
return this;
}
public AppScenarioPipeline OpenTab(string url)
{
TabManager.NewTab(url);
return this;
}
public SessionSnapshot SaveSession() => TabManager.CaptureSession();
public AppScenarioPipeline RestoreSession(SessionSnapshot snapshot)
{
TabManager.RestoreSession(snapshot);
return this;
}
public void AssertQueueCount(int count)
{
Xunit.Assert.Equal(count, DownloadManager.Items.Count);
}
public void AssertDetectedCount(int count)
{
Xunit.Assert.Equal(count, DetectedItems.Count);
}
public AppScenarioPipeline SetScheduleGate(Func gate)
{
DownloadManager.DownloadGate = gate;
return this;
}
public AppScenarioPipeline SelectItems(Func predicate)
{
foreach (var item in DownloadManager.Items)
{
item.IsSelected = predicate(item);
}
return this;
}
public AppScenarioPipeline BatchPause()
{
foreach (var item in DownloadManager.Items.Where(i => i.IsSelected).ToList())
{
DownloadManager.Pause(item);
}
return this;
}
public AppScenarioPipeline BatchResume()
{
foreach (var item in DownloadManager.Items.Where(i => i.IsSelected).ToList())
{
DownloadManager.Resume(item);
}
return this;
}
public AppScenarioPipeline BatchCancel()
{
foreach (var item in DownloadManager.Items.Where(i => i.IsSelected).ToList())
{
DownloadManager.Cancel(item);
}
return this;
}
public AppScenarioPipeline BatchDelete()
{
foreach (var item in DownloadManager.Items.Where(i => i.IsSelected).ToList())
{
DownloadManager.Items.Remove(item);
}
return this;
}
public void AssertPlaylistCount(int count)
{
Xunit.Assert.Equal(count, Playlist.Tracks.Count);
}
public void AssertCurrentTrack(Func predicate)
{
Xunit.Assert.True(predicate(Playlist.Current), "현재 재생목록 트랙이 조건에 부합하지 않습니다.");
}
public void Dispose()
{
try
{
if (Directory.Exists(TempDir))
Directory.Delete(TempDir, recursive: true);
}
catch { }
}
}