using System; using System.IO; using System.Linq; using System.Windows.Controls; using Paca.App; using Paca.Browser; using Paca.Browser.ReadingList; using Paca.Browser.Tabs; using Paca.Tests.Infrastructure; using Xunit; namespace Paca.Tests.Browser; public class ChromeParityMilestone8Tests { [Fact] public void ReadingListManager_Add_새_항목을_읽지않음_목록에_추가한다() { var tempDir = Path.Combine(Path.GetTempPath(), $"vd_readlist_{Guid.NewGuid():N}"); try { var mgr = new ReadingListManager(tempDir); var item = mgr.Add("C# 12 신기능 가이드", "https://learn.microsoft.com/csharp"); Assert.NotNull(item); Assert.Equal("C# 12 신기능 가이드", item.Title); Assert.Equal("https://learn.microsoft.com/csharp", item.Url); Assert.False(item.IsRead); Assert.Single(mgr.Items); Assert.Single(mgr.UnreadItems); Assert.Empty(mgr.ReadItems); } finally { try { if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true); } catch { } } } [Fact] public void ReadingListManager_Add_동일_URL_재추가시_기존_항목_갱신() { var tempDir = Path.Combine(Path.GetTempPath(), $"vd_readlist_dup_{Guid.NewGuid():N}"); try { var mgr = new ReadingListManager(tempDir); mgr.Add("구글 메인", "https://google.com"); var item2 = mgr.Add("구글 검색 포털", "https://google.com"); Assert.Single(mgr.Items); Assert.Equal("구글 검색 포털", item2.Title); } finally { try { if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true); } catch { } } } [Fact] public void ReadingListManager_MarkAsRead_읽음_상태를_변경한다() { var tempDir = Path.Combine(Path.GetTempPath(), $"vd_readlist_read_{Guid.NewGuid():N}"); try { var mgr = new ReadingListManager(tempDir); var item = mgr.Add("Tech News", "https://news.ycombinator.com"); var success = mgr.MarkAsRead(item.Id, true); Assert.True(success); Assert.True(item.IsRead); Assert.Empty(mgr.UnreadItems); Assert.Single(mgr.ReadItems); } finally { try { if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true); } catch { } } } [Fact] public void ReadingListManager_Remove_항목을_삭제한다() { var tempDir = Path.Combine(Path.GetTempPath(), $"vd_readlist_del_{Guid.NewGuid():N}"); try { var mgr = new ReadingListManager(tempDir); var item = mgr.Add("To Delete", "https://example.com"); var removed = mgr.Remove(item.Id); Assert.True(removed); Assert.Empty(mgr.Items); } finally { try { if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true); } catch { } } } [Fact] public void ReadingListManager_ClearRead_읽은_항목만_일괄_삭제한다() { var tempDir = Path.Combine(Path.GetTempPath(), $"vd_readlist_clear_{Guid.NewGuid():N}"); try { var mgr = new ReadingListManager(tempDir); var i1 = mgr.Add("Item 1", "https://site1.com"); var i2 = mgr.Add("Item 2", "https://site2.com"); mgr.MarkAsRead(i1.Id, true); var count = mgr.ClearRead(); Assert.Equal(1, count); Assert.Single(mgr.Items); Assert.Equal("Item 2", mgr.Items[0].Title); } finally { try { if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true); } catch { } } } [Fact] public void ReadingListManager_Persistence_디스크에_저장되고_새_인스턴스에서_복원된다() { var tempDir = Path.Combine(Path.GetTempPath(), $"vd_readlist_persist_{Guid.NewGuid():N}"); try { var mgr1 = new ReadingListManager(tempDir); mgr1.Add("Persistent Item", "https://persistent.com"); var mgr2 = new ReadingListManager(tempDir); Assert.Single(mgr2.Items); Assert.Equal("Persistent Item", mgr2.Items[0].Title); Assert.Equal("https://persistent.com", mgr2.Items[0].Url); } finally { try { if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true); } catch { } } } [Theory] [InlineData("chrome://reading-list", ChromeInternalAction.ReadingList)] [InlineData("paca://reading-list", ChromeInternalAction.ReadingList)] public void ChromeInternalUrlRouter_읽기_목록_라우팅(string url, ChromeInternalAction expectedAction) { var action = ChromeInternalUrlRouter.Route(url); Assert.Equal(expectedAction, action); } [Fact] public void BuildTabContextMenu_읽기_목록에_탭_추가_옵션이_포함된다() { using var sta = StaDispatcher.Start(); WpfTestApp.Ensure(sta.Dispatcher); sta.Invoke(() => { var dataDir = Path.Combine(Path.GetTempPath(), $"vd_tab_readlist_{Guid.NewGuid():N}"); Environment.SetEnvironmentVariable("VD_DATA_DIR", dataDir); try { var win = new MainWindow(); win.TabsManager.Tabs.Clear(); var t1 = win.TabsManager.NewTab("https://site1.com"); t1.Title = "사이트 1"; var menu = win.BuildTabContextMenu(t1); var items = menu.Items.OfType().Select(m => m.Header?.ToString()).ToList(); Assert.Contains("읽기 목록에 탭 추가", items); } finally { try { if (Directory.Exists(dataDir)) Directory.Delete(dataDir, true); } catch { } } }); } }