using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Net.Http.Json; using System.Threading.Tasks; using Paca.Browser.ReadingList; using Paca.Browser.Tabs; using Paca.Mobile; using Paca.Mobile.Core; using Paca.Server; using Xunit; namespace Paca.Tests.Browser; public class ChromeReadingListSyncTests { [Fact] public void OmniboxActionEvaluator_Matches_ReadingList() { var matchKr = OmniboxActionEvaluator.GetMatchingActions("읽기 목록"); Assert.Contains(matchKr, a => a.ActionId == "action:reading-list"); var matchEn = OmniboxActionEvaluator.GetMatchingActions("reading list"); Assert.Contains(matchEn, a => a.ActionId == "action:reading-list"); var action = OmniboxActionEvaluator.AllActions.FirstOrDefault(a => a.ActionId == "action:reading-list"); Assert.NotNull(action); Assert.Contains("읽기 목록", action.DisplayTitle); } [Fact] public void ReadingListManager_Basic_Lifecycle() { var tempDir = Path.Combine(Path.GetTempPath(), "paca_reading_test_" + Guid.NewGuid().ToString("N")); try { var mgr = new ReadingListManager(tempDir); Assert.Empty(mgr.Items); var item1 = mgr.Add("Example Page", "https://example.com"); Assert.Single(mgr.Items); Assert.Single(mgr.UnreadItems); Assert.Empty(mgr.ReadItems); var marked = mgr.MarkAsRead(item1.Id, true); Assert.True(marked); Assert.Empty(mgr.UnreadItems); Assert.Single(mgr.ReadItems); var mgr2 = new ReadingListManager(tempDir); Assert.Single(mgr2.Items); Assert.True(mgr2.Items[0].IsRead); } finally { if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true); } } [Fact] public async Task ServerHost_ReadingList_Endpoints_Work() { var list = new List { new("id1", "Initial Item", "https://initial.org", DateTime.UtcNow, false) }; var server = await ServerHost.StartAsync(new ServerOptions { Port = 0, Token = "test_token_rl", ReadingListProvider = () => list, ReadingListAdder = (title, url) => list.Add(new ReadingListItemDto(Guid.NewGuid().ToString("N"), title, url, DateTime.UtcNow, false)) }); try { var baseUrl = $"http://127.0.0.1:{server.Port}"; using var client = new HttpClient { BaseAddress = new Uri(baseUrl) }; client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "test_token_rl"); var items = await client.GetFromJsonAsync>("/api/reading-list"); Assert.NotNull(items); Assert.Single(items); Assert.Equal("Initial Item", items[0].Title); var postResp = await client.PostAsJsonAsync("/api/reading-list", new AddReadingListItemRequestDto("New Article", "https://news.ycombinator.com")); Assert.True(postResp.IsSuccessStatusCode); var updated = await client.GetFromJsonAsync>("/api/reading-list"); Assert.NotNull(updated); Assert.Equal(2, updated.Count); Assert.Contains(updated, i => i.Url == "https://news.ycombinator.com"); } finally { await server.DisposeAsync(); } } [Fact] public async Task ApiClient_ReadingList_Sync_Methods_Work() { var list = new List(); var server = await ServerHost.StartAsync(new ServerOptions { Port = 0, Token = "test_token_api", ReadingListProvider = () => list, ReadingListAdder = (title, url) => list.Add(new ReadingListItemDto(Guid.NewGuid().ToString("N"), title, url, DateTime.UtcNow, false)) }); try { var apiClient = new ApiClient(); var configured = apiClient.Configure($"http://127.0.0.1:{server.Port}", "test_token_api"); Assert.True(configured); var empty = await apiClient.GetReadingListAsync(); Assert.NotNull(empty); Assert.Empty(empty); var ok = await apiClient.AddToReadingListAsync("Mobile Added", "https://mobile.example.com"); Assert.True(ok); var items = await apiClient.GetReadingListAsync(); Assert.NotNull(items); Assert.Single(items); Assert.Equal("Mobile Added", items[0].Title); Assert.Equal("https://mobile.example.com", items[0].Url); } finally { await server.DisposeAsync(); } } }