using VideoDownloader.App.Browser.Features; namespace VideoDownloader.Tests.Browser; /// 페이지 다운로드 추상화(다운로드 매니저 UI 의 로직 코어) — fake op 로 검증. public interface IFakeOpHost { } public class PageDownloadTrackerTests { private sealed class FakeOp : IDownloadOperation { public string Uri { get; set; } = "https://x.test/file.zip"; public string FileName { get; set; } = "file.zip"; public long BytesReceived { get; set; } public long TotalBytesToReceive { get; set; } = 1000; public string State { get; set; } = "InProgress"; public bool Paused, Resumed, Cancelled; public event Action? Changed; public void Raise() => Changed?.Invoke(); public void Pause() { Paused = true; State = "Paused"; Raise(); } public void Resume() { Resumed = true; State = "InProgress"; Raise(); } public void Cancel() { Cancelled = true; State = "Cancelled"; Raise(); } } [Fact] public void Add는_항목을_등록하고_최근순_정렬한다() { var t = new PageDownloadTracker(); var a = new FakeOp { FileName = "a.zip" }; var b = new FakeOp { FileName = "b.zip" }; t.Add(a, a.FileName); t.Add(b, b.FileName); Assert.Equal(2, t.Items.Count); Assert.Equal("b.zip", t.Items[0].FileName); // 최신 우선 } [Fact] public void 진행률과_속도를_계산한다() { var t = new PageDownloadTracker(); var op = new FakeOp { TotalBytesToReceive = 1000 }; var item = t.Add(op, "f.zip"); item.UpdateSpeed(500, TimeSpan.FromSeconds(2)); // 500B/2s = 250 B/s Assert.Equal(50.0, item.Percent, 2); Assert.Equal(250, item.BytesPerSecond); Assert.Equal("250.0 B/s", item.SpeedText); } [Fact] public void 속도_단위는_KB_MB로_표시된다() { var t = new PageDownloadTracker(); var item = t.Add(new FakeOp { TotalBytesToReceive = 10_000_000 }, "f"); item.UpdateSpeed(0, TimeSpan.FromSeconds(1)); // 초기 Assert.Equal("—", item.SpeedText); item = t.Add(new FakeOp { TotalBytesToReceive = 10_000_000 }, "g"); item.UpdateSpeed(2048 * 100, TimeSpan.FromSeconds(1)); // 200 KB/s Assert.Equal("200.0 KB/s", item.SpeedText); item = t.Add(new FakeOp { TotalBytesToReceive = 10_000_000 }, "h"); item.UpdateSpeed(3 * 1024 * 1024L, TimeSpan.FromSeconds(1)); // 3 MB/s Assert.Equal("3.0 MB/s", item.SpeedText); } [Fact] public void Pause_Resume_Cancel_위임() { var t = new PageDownloadTracker(); var op = new FakeOp(); var item = t.Add(op, "f"); t.Pause(item); t.Resume(item); t.Cancel(item); Assert.True(op.Paused && op.Resumed && op.Cancelled); } [Fact] public void 완료_항목은_ClearCompleted로_일괄_제거() { var t = new PageDownloadTracker(); var done = new FakeOp { State = "Completed" }; var running = new FakeOp { State = "InProgress" }; t.Add(done, "d"); t.Add(running, "r"); t.ClearCompleted(); Assert.Single(t.Items); Assert.Equal("r", t.Items[0].FileName); } [Fact] public void 취소된_항목도_ClearCompleted로_제거된다() { var t = new PageDownloadTracker(); var c = new FakeOp { State = "Interrupted" }; t.Add(c, "c"); t.ClearCompleted(); Assert.Empty(t.Items); } }