using System.IO; using System.Text.RegularExpressions; using Paca.App; using Paca.Tests.Infrastructure; using Xunit; namespace Paca.Tests.App; public class ScrollBarAndSectionBorderGateTests { [Fact] public void Gate475_LightAndDarkThemes_ScrollBarThumbBrush_ContrastAndAlpha_Audit() { // DoD: 라이트 테마에서 스크롤바가 시커멓게 렌더링되지 않도록 // 1. Light.xaml 에 미니멀 반투명 스크롤바 브러시가 정의되어야 함 var lightXaml = SourceTree.ThemeLightXaml; Assert.True(SourceTree.HasKey(lightXaml, "ScrollBarThumbBrush"), "Light.xaml must define ScrollBarThumbBrush"); Assert.True(SourceTree.HasKey(lightXaml, "ScrollBarTrackBrush"), "Light.xaml must define ScrollBarTrackBrush"); // 2. Shared.xaml 에서 정적 다크 색상(#4A5568)으로 덮어쓰지 않고 각 테마 사전을 존중해야 함 var sharedXaml = File.ReadAllText(SourceTree.AppPath("Themes/Shared.xaml")); Assert.DoesNotContain("", sharedXaml); } [Fact] public void Gate476_MainWindow_SectionBorders_MinimalFlatSurfaces_Audit() { // DoD: 불필요한 1px 와이어프레임 보더라인을 소거하고 서피스 배경색으로 유기적 분리 var mainWindowXaml = File.ReadAllText(SourceTree.AppPath("MainWindow.xaml")); // 1. 우측 도킹 패널(Grid.Column="2")의 불필요한 BorderThickness 1px 제거 (BorderThickness="0") var panelMatch = Regex.Match(mainWindowXaml, @"]*Grid\.Column=""2""[^>]*BorderThickness=""([^""]+)"""); Assert.True(panelMatch.Success, "Grid.Column 2 Border should have BorderThickness attribute"); Assert.Equal("0", panelMatch.Groups[1].Value); // 2. RightSplitter 내 하드코딩된 1px Rectangle 보더선 제거 (이중 보더 방지) Assert.DoesNotContain("", mainWindowXaml); // 3. SideTabsContainer(세그먼트 탭 컨테이너)의 테두리 1px 제거 (BorderThickness="0") var sideTabsMatch = Regex.Match(mainWindowXaml, @"]*x:Name=""SideTabsContainer""[^>]*BorderThickness=""([^""]+)"""); Assert.True(sideTabsMatch.Success, "SideTabsContainer should have BorderThickness"); Assert.Equal("0", sideTabsMatch.Groups[1].Value); // 4. ToolbarRow 내 캡션 버튼 직전의 1px 분리선 제거 Assert.DoesNotContain("", mainWindowXaml); // 5. RightTabSideHost(우측 세로 탭 호스트) 불필요 1px 보더 제거 (BorderThickness="0") var rightTabMatch = Regex.Match(mainWindowXaml, @"]*x:Name=""RightTabSideHost""[^>]*BorderThickness=""([^""]+)"""); if (rightTabMatch.Success) { Assert.Equal("0", rightTabMatch.Groups[1].Value); } } [Fact] public void Gate477_TabViewService_PreferredColorScheme_SynchronizedWithAppTheme_Audit() { // DoD: WebView2 초기화 시 CoreWebView2Profile.PreferredColorScheme 을 테마에 동기화 var tabViewServiceCs = File.ReadAllText(SourceTree.AppPath("Services/TabViewService.cs")); Assert.Contains("PreferredColorScheme", tabViewServiceCs); Assert.Contains("CoreWebView2PreferredColorScheme", tabViewServiceCs); } [Fact] public void Gate478_TabViewService_ScrollbarThemeScript_InjectedForLightAndDark_Audit() { // DoD: WebView2 웹 콘텐츠 스크롤바가 OS 다크모드에 의해 17px 검정으로 튀지 않도록 // 커스텀 미니멀 스크롤바 스타일 스크립트(AddScriptToExecuteOnDocumentCreatedAsync)가 등록되어야 함 var tabViewServiceCs = File.ReadAllText(SourceTree.AppPath("Services/TabViewService.cs")); Assert.Contains("::-webkit-scrollbar", tabViewServiceCs); Assert.Contains("scrollbar-color", tabViewServiceCs); } [Fact] public void Gate479_MainWindow_LiveThemeSwitch_UpdatesAllTabsPreferredColorScheme_Audit() { // DoD: 라이브 테마 전환 시 열려있는 모든 탭의 PreferredColorScheme 및 스크롤바를 갱신 var usecasesCs = File.ReadAllText(SourceTree.AppPath("MainWindow.Usecases.cs")); Assert.Contains("PreferredColorScheme", usecasesCs); } [Fact] public void Gate480_MainWindow_DesktopBrowser_NoWhiteBorderArtifacts_Audit() { // DoD: 데스크탑 브라우저 UI에서 툴바 하단 및 우측 스플리터 영역에 흰색 보더/라인 아티팩트가 노출되지 않아야 함 var mainWindowXaml = File.ReadAllText(SourceTree.AppPath("MainWindow.xaml")); // 1. ToolbarRow 하단의 2px 그라디언트 보더(AccentFadeBrush)로 인한 흰색 라인 방지: BorderThickness="0" var toolbarMatch = Regex.Match(mainWindowXaml, @"]*x:Name=""ToolbarRow""[^>]*BorderThickness=""([^""]+)"""); Assert.True(toolbarMatch.Success, "ToolbarRow should have BorderThickness attribute"); Assert.Equal("0", toolbarMatch.Groups[1].Value); // 2. RightSplitter 가 Transparent 로 남아 윈도우 배경(#FFFFFF)이 투과되는 7px 흰색 줄 방지: Background="{DynamicResource PanelBg}" var splitterMatch = Regex.Match(mainWindowXaml, @"]*x:Name=""RightSplitter""[^>]*Background=""([^""]+)"""); Assert.True(splitterMatch.Success, "RightSplitter should specify Background"); Assert.Contains("PanelBg", splitterMatch.Groups[1].Value); // 3. RightSplitter Template 내부 handle 도 PanelBg 배경을 유지해야 함 var handleMatch = Regex.Match(mainWindowXaml, @"]*x:Name=""handle""[^>]*Background=""([^""]+)"""); Assert.True(handleMatch.Success, "RightSplitter handle should specify Background"); Assert.Contains("PanelBg", handleMatch.Groups[1].Value); // 4. MainGrid 에 PanelBg 배경이 지정되어 그리드 간극 투과를 원천 차단 var mainGridMatch = Regex.Match(mainWindowXaml, @"]*x:Name=""MainGrid""[^>]*Background=""([^""]+)"""); Assert.True(mainGridMatch.Success, "MainGrid should specify Background=\"{DynamicResource PanelBg}\""); Assert.Contains("PanelBg", mainGridMatch.Groups[1].Value); } }