using System; using System.IO; using System.Linq; using System.Windows.Controls; using System.Windows.Input; using Paca.App; using Paca.Browser; using Paca.Browser.Tabs; using Paca.Tests.Infrastructure; using Xunit; namespace Paca.Tests.Browser; public class ChromeParityMilestone5Tests { private readonly SearchEngineResolver _resolver = new("Google"); [Theory] [InlineData("? localhost:3000", "localhost:3000")] [InlineData("? https://google.com", "https://google.com")] [InlineData("? example.org", "example.org")] [InlineData("? 192.168.1.1", "192.168.1.1")] public void SearchEngineResolver_물음표_접두사는_URL_여부와_무관하게_강제_검색으로_처리한다(string input, string expectedQuery) { var intent = _resolver.Resolve(input); Assert.NotNull(intent); Assert.False(intent.IsUrl); Assert.Equal("Google", intent.EngineName); Assert.Contains(Uri.EscapeDataString(expectedQuery).Replace("%20", "+"), intent.Target); } [Theory] [InlineData("google flutter", "Google", "google.com/search")] [InlineData("naver 날씨", "Naver", "search.naver.com")] [InlineData("bing openai", "Bing", "bing.com/search")] [InlineData("ddg privacy", "DuckDuckGo", "duckduckgo.com")] [InlineData("youtube music", "YouTube", "youtube.com/results")] [InlineData("gh dotnet", "GitHub", "github.com/search")] [InlineData("github wpf", "GitHub", "github.com/search")] [InlineData("w quantum", "Wikipedia", "wikipedia.org")] [InlineData("wikipedia cosmos", "Wikipedia", "wikipedia.org")] public void SearchEngineResolver_확장_키워드_및_별칭으로_검색엔진을_전환한다(string input, string expectedEngine, string expectedHost) { var intent = _resolver.Resolve(input); Assert.NotNull(intent); Assert.False(intent.IsUrl); Assert.Equal(expectedEngine, intent.EngineName); Assert.Contains(expectedHost, intent.Target); } [Fact] public void SearchEngineResolver_view_source_스킴은_URL로_인식한다() { var intent = _resolver.Resolve("view-source:https://example.com/test"); Assert.NotNull(intent); Assert.True(intent.IsUrl); Assert.Equal("view-source:https://example.com/test", intent.Target); } [Fact] public void TabManager_특정_닫은_탭을_선택하여_복원하거나_일괄_복원할_수_있다() { var mgr = new TabManager(() => new TabItem()); mgr.Tabs.Clear(); var t1 = mgr.NewTab("https://site1.com"); t1.Title = "사이트 1"; var t2 = mgr.NewTab("https://site2.com"); t2.Title = "사이트 2"; var t3 = mgr.NewTab("https://site3.com"); t3.Title = "사이트 3"; // t1, t2 닫기 mgr.CloseTab(t1); mgr.CloseTab(t2); var closed = mgr.ClosedTabs; Assert.Equal(2, closed.Count); Assert.Contains(closed, t => t.Title == "사이트 1"); Assert.Contains(closed, t => t.Title == "사이트 2"); // t1만 선택 복원 var restored = mgr.RestoreClosedTab(t1); Assert.NotNull(restored); Assert.Equal("사이트 1", restored.Title); Assert.Single(mgr.ClosedTabs); Assert.Equal("사이트 2", mgr.ClosedTabs[0].Title); // 남은 모든 탭 일괄 복원 int restoredAllCount = mgr.RestoreAllClosedTabs(); Assert.Equal(1, restoredAllCount); Assert.Empty(mgr.ClosedTabs); } [Fact] public void BuildTabStripContextMenu_닫은탭이_있을때_최근에_닫은_탭_하위_항목을_표시한다() { using var sta = StaDispatcher.Start(); WpfTestApp.Ensure(sta.Dispatcher); sta.Invoke(() => { var dataDir = Path.Combine(Path.GetTempPath(), $"vd_tabstrip_recent_{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 t2 = win.TabsManager.NewTab("https://site2.com"); t2.Title = "유지 사이트 2"; win.TabsManager.CloseTab(t1); var menu = win.BuildTabStripContextMenu(); var items = menu.Items.OfType().ToList(); var reopenItem = items.FirstOrDefault(m => m.Header?.ToString() == "닫은 탭 다시 열기"); Assert.NotNull(reopenItem); Assert.True(reopenItem.IsEnabled); // 최근 닫은 탭 서브메뉴 확인 var recentSubmenu = items.FirstOrDefault(m => m.Header?.ToString()?.Contains("최근에 닫은 탭") == true); Assert.NotNull(recentSubmenu); Assert.True(recentSubmenu.Items.Count > 0); } finally { try { if (Directory.Exists(dataDir)) Directory.Delete(dataDir, true); } catch { } } }); } }