using System.Collections.Generic; using System.Linq; using Paca.Browser.Tabs; using Xunit; namespace Paca.Tests.Browser; public class ChromeParityTabOperationsTests { private static TabManager CreateManager() { return new TabManager(() => new TabItem()); } [Fact] public void NewTabAfter_기준_탭의_바로_오른쪽에_새_탭을_삽입하고_활성화한다() { var mgr = CreateManager(); var tabA = mgr.NewTab("https://a.com"); var tabB = mgr.NewTab("https://b.com"); var tabC = mgr.NewTab("https://c.com"); // [A, B, C] 상태에서 B 바로 뒤에 새 탭 삽입 var newTab = mgr.NewTabAfter(tabB, "https://b2.com", activate: true); Assert.Equal(4, mgr.Tabs.Count); Assert.Equal(tabA, mgr.Tabs[0]); Assert.Equal(tabB, mgr.Tabs[1]); Assert.Equal(newTab, mgr.Tabs[2]); Assert.Equal(tabC, mgr.Tabs[3]); Assert.Equal("https://b2.com", newTab.Url); Assert.Same(newTab, mgr.ActiveTab); } [Fact] public void NewTabAfter_마지막_탭_뒤에_추가하면_맨_뒤에_배치된다() { var mgr = CreateManager(); var tabA = mgr.NewTab("https://a.com"); var tabB = mgr.NewTab("https://b.com"); var newTab = mgr.NewTabAfter(tabB, "https://new.com"); Assert.Equal(3, mgr.Tabs.Count); Assert.Equal(newTab, mgr.Tabs[2]); } [Fact] public void DuplicateTab_현재_탭의_URL과_제목을_복제하여_바로_우측에_생성한다() { var mgr = CreateManager(); var tab1 = mgr.NewTab("https://github.com"); tab1.Title = "GitHub - Paca"; var tab2 = mgr.NewTab("https://google.com"); var dup = mgr.DuplicateTab(tab1); Assert.NotNull(dup); Assert.Equal(3, mgr.Tabs.Count); Assert.Equal(tab1, mgr.Tabs[0]); Assert.Equal(dup, mgr.Tabs[1]); Assert.Equal(tab2, mgr.Tabs[2]); Assert.Equal("https://github.com", dup.Url); Assert.Equal("GitHub - Paca", dup.Title); Assert.Same(dup, mgr.ActiveTab); } [Fact] public void CloseOtherTabs_대상_탭을_제외한_모든_탭을_닫으며_잠긴_탭은_보존한다() { var mgr = CreateManager(); var tabA = mgr.NewTab("https://a.com"); var tabB = mgr.NewTab("https://b.com"); var tabC = mgr.NewTab("https://c.com"); var tabD = mgr.NewTab("https://d.com"); // C는 잠금 상태 tabC.IsLocked = true; // B를 제외한 다른 탭 닫기 int closedCount = mgr.CloseOtherTabs(tabB); // A와 D만 닫혀야 함 (C는 잠금이라 생존) Assert.Equal(2, closedCount); Assert.Equal(2, mgr.Tabs.Count); Assert.Contains(tabB, mgr.Tabs); Assert.Contains(tabC, mgr.Tabs); Assert.DoesNotContain(tabA, mgr.Tabs); Assert.DoesNotContain(tabD, mgr.Tabs); Assert.Same(tabB, mgr.ActiveTab); // 닫힌 탭들은 닫힌 스택에 보존되어 복원 가능해야 함 Assert.Equal(2, mgr.ClosedStack.Count); } [Fact] public void CloseTabsToTheRight_오른쪽_탭들만_닫으며_잠긴_탭은_보존한다() { var mgr = CreateManager(); var tab1 = mgr.NewTab("https://1.com"); var tab2 = mgr.NewTab("https://2.com"); var tab3 = mgr.NewTab("https://3.com"); var tab4 = mgr.NewTab("https://4.com"); var tab5 = mgr.NewTab("https://5.com"); // tab4는 잠금 상태 tab4.IsLocked = true; // tab2 기준 오른쪽 탭 닫기 int closedCount = mgr.CloseTabsToTheRight(tab2); // tab3, tab5가 닫혀야 함 (tab4는 잠금이라 보존) Assert.Equal(2, closedCount); Assert.Equal(3, mgr.Tabs.Count); Assert.Equal(tab1, mgr.Tabs[0]); Assert.Equal(tab2, mgr.Tabs[1]); Assert.Equal(tab4, mgr.Tabs[2]); Assert.Same(tab2, mgr.ActiveTab); } [Fact] public void ReopenClosedTab_CloseOtherTabs로_닫힌_탭들을_역순으로_완전_복원한다() { var mgr = CreateManager(); var tabA = mgr.NewTab("https://a.com"); var tabB = mgr.NewTab("https://b.com"); var tabC = mgr.NewTab("https://c.com"); mgr.CloseOtherTabs(tabA); Assert.Single(mgr.Tabs); // Ctrl+Shift+T 2회 실행으로 복원 var restored1 = mgr.ReopenClosedTab(); var restored2 = mgr.ReopenClosedTab(); Assert.NotNull(restored1); Assert.NotNull(restored2); Assert.Equal(3, mgr.Tabs.Count); } [Fact] public void MainWindow_TabContextMenu는_크롬_표준_옵션들이_모두_포함된다() { using var sta = Paca.Tests.Infrastructure.StaDispatcher.Start(); Paca.Tests.Infrastructure.WpfTestApp.Ensure(sta.Dispatcher); sta.Invoke(() => { var dataDir = System.IO.Path.Combine(System.IO.Path.GetTempPath(), $"vd_chrometab_{System.Guid.NewGuid():N}"); System.Environment.SetEnvironmentVariable("VD_DATA_DIR", dataDir); try { var win = new Paca.App.MainWindow(); var tab = new TabItem { Title = "테스트 탭", Url = "https://example.com" }; var menu = win.BuildTabContextMenu(tab); Assert.NotNull(menu); var headers = menu.Items.OfType().Select(m => m.Header?.ToString()).ToList(); Assert.Contains("오른쪽에 새 탭", headers); Assert.Contains("탭 복제", headers); Assert.Contains("다른 탭 닫기", headers); Assert.Contains("오른쪽 탭 닫기", headers); Assert.Contains("탭 닫기", headers); } finally { try { if (System.IO.Directory.Exists(dataDir)) System.IO.Directory.Delete(dataDir, true); } catch { } } }); } }