using System.Collections.ObjectModel; using System.IO; using System.Reflection; using System.Text; using System.Windows; using System.Windows.Controls; using Paca.App; using Paca.App.ViewModels; using Paca.Browser; using Paca.Tests.Infrastructure; using Xunit; namespace Paca.Tests.Browser; /// /// 북마크 시스템 & 북마크 바 UX 파이프라인. /// /// /// 즐겨찾기(북마크) 바 레이아웃, 단축키(Ctrl+Shift+B), 설정창 연동 및 컨텍스트 메뉴 검증. /// public class BookmarkBarIntegrationTests { [Fact] public void AppConfig_BookmarkBarVisible_기본값은_false이며_직렬화_가능하다() { var config = new AppConfig(); Assert.False(config.BookmarkBarVisible); config.BookmarkBarVisible = true; var json = System.Text.Json.JsonSerializer.Serialize(config); var restored = System.Text.Json.JsonSerializer.Deserialize(json); Assert.NotNull(restored); Assert.True(restored.BookmarkBarVisible); } [Fact] public void MainWindowXaml_BookmarkBar가_ToolbarRow_아래_배치되고_컨텍스트메뉴_요소가_존재한다() { var xaml = SourceTree.MainWindowXaml; Assert.Contains("x:Name=\"BookmarkBar\"", xaml); Assert.Contains("Grid.Row=\"1\"", xaml); Assert.Contains("BookmarkBarList", xaml); Assert.Contains("BookmarkBar_Click", xaml); // 컨텍스트 메뉴 또는 마우스 휠 클릭 핸들러 Assert.Contains("BookmarkBarContextMenu", xaml); } [Fact] public void MainWindow_ApplyBookmarkBarVisible_메서드가_존재한다() { var method = typeof(MainWindow).GetMethod("ApplyBookmarkBarVisible", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); Assert.NotNull(method); } [Fact] public void MainWindowCs_CtrlShiftB_단축키와_설정동기화_로직이_존재한다() { var cs = SourceTree.MainWindowCs; Assert.Contains("Key.B", cs); Assert.Contains("ToggleBookmarkBar", cs); Assert.Contains("ApplyBookmarkBarVisible", cs); } [Fact] public void SettingsWindowXaml_북마크바_설정_체크박스가_존재한다() { var xaml = SourceTree.SettingsWindowXaml; Assert.Contains("BookmarkBarVisibleBox", xaml); } } /// /// 일반적인 브라우저 UX를 따르는 즐겨찾기(현재 페이지 등록, 팝업 모달 편집, 주소창 별표, Ctrl+D 단축키) 검증. /// public class BookmarkUxTests { private static string AppRoot => SourceTree.AppPath(""); [Fact] public void MainWindowXaml_주소창_내부에_BookmarkStarBtn이_존재한다() { var xaml = File.ReadAllText(Path.Combine(AppRoot, "MainWindow.xaml")); Assert.Contains("x:Name=\"BookmarkStarBtn\"", xaml); Assert.Contains("BookmarkStarBtn_Click", xaml); Assert.Contains("Visibility=\"Collapsed\"", xaml); } [Theory] [InlineData("", true)] [InlineData(" ", true)] [InlineData(null, true)] [InlineData("about:blank", true)] [InlineData("about:newtab", true)] [InlineData("about:srcdoc", true)] [InlineData("https://example.com", false)] [InlineData("http://localhost:5000", false)] public void 빈탭_URL_판별_시_즐겨찾기_별표_버튼_숨김_여부를_올바르게_판정한다(string? url, bool shouldHide) { bool isBlank = string.IsNullOrWhiteSpace(url) || url.StartsWith("about:", StringComparison.OrdinalIgnoreCase); Assert.Equal(shouldHide, isBlank); } [Fact] public void MainWindowXaml_즐겨찾기_추가_수정_팝업_BookmarkEditPopup이_정의되어_있다() { var xaml = File.ReadAllText(Path.Combine(AppRoot, "MainWindow.xaml")); Assert.Contains("x:Name=\"BookmarkEditPopup\"", xaml); Assert.Contains("BookmarkEditHeaderTitle", xaml); Assert.Contains("BookmarkEditNameBox", xaml); Assert.Contains("BookmarkEditUrlBox", xaml); Assert.Contains("BookmarkEditFolderCombo", xaml); Assert.Contains("BookmarkEditDoneBtn", xaml); Assert.Contains("BookmarkEditDeleteBtn", xaml); Assert.Contains("BookmarkEditCancelBtn", xaml); } [Fact] public void MainWindowCs_Ctrl_D_단축키_핸들러가_존재한다() { var cs = File.ReadAllText(Path.Combine(AppRoot, "MainWindow.xaml.cs")); Assert.Contains("ModifierKeys.Control && e.Key == Key.D", cs); } [Fact] public void MainWindowCs_별표_상태_갱신_및_편집_다이얼로그_메서드가_존재한다() { var cs = File.ReadAllText(Path.Combine(AppRoot, "MainWindow.xaml.cs")) + File.ReadAllText(Path.Combine(AppRoot, "MainWindow.Usecases.cs")); Assert.Contains("UpdateBookmarkStarState", cs); Assert.Contains("ShowBookmarkEditDialog", cs); } [Fact] public void MainWindowCs_AnyPopupOpen_및_CloseAllPopups에_BookmarkEditPopup이_포함된다() { var cs = File.ReadAllText(Path.Combine(AppRoot, "MainWindow.xaml.cs")) + File.ReadAllText(Path.Combine(AppRoot, "MainWindow.Usecases.cs")); Assert.Contains("BookmarkEditPopup.IsOpen", cs); Assert.Contains("BookmarkEditPopup", cs); } [Fact] public void 북마크_폴더_목록_추출_및_갱신_로직_검증() { var bookmarks = new ObservableCollection { new("네이버", "https://naver.com", "포털"), new("구글", "https://google.com", "포털"), new("유튜브", "https://youtube.com", "동영상"), new("깃허브", "https://github.com", null), }; // 폴더 목록 추출 var folders = bookmarks .Select(b => b.Folder) .Where(f => !string.IsNullOrWhiteSpace(f)) .Distinct() .OrderBy(f => f) .ToList(); Assert.Equal(2, folders.Count); Assert.Contains("포털", folders); Assert.Contains("동영상", folders); } [Fact] public void 북마크_폴더_즐겨찾기바_선택시_null_정규화_로직_검증() { string? NormalizeFolder(string? input) { var folderText = input?.Trim(); return string.IsNullOrWhiteSpace(folderText) || folderText == "즐겨찾기 바" ? null : folderText; } Assert.Null(NormalizeFolder("즐겨찾기 바")); Assert.Null(NormalizeFolder(" ")); Assert.Null(NormalizeFolder(null)); Assert.Equal("개발 폴더", NormalizeFolder("개발 폴더")); Assert.Equal("기타 즐겨찾기", NormalizeFolder("기타 즐겨찾기")); } }