feat(ads/seo/release): v1.2.0 with live Google Ads, isolated ad profile, ads.txt, and SEO/AEO/GEO optimization
This commit is contained in:
parent
a88aafa1e5
commit
0e568f1f0a
975 changed files with 130593 additions and 16783 deletions
436
tests/Paca.Tests/App/UiUxFiftyPolishAndPrecisionGateTests.cs
Normal file
436
tests/Paca.Tests/App/UiUxFiftyPolishAndPrecisionGateTests.cs
Normal file
|
|
@ -0,0 +1,436 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using Xunit;
|
||||
|
||||
namespace Paca.Tests.App;
|
||||
|
||||
public class UiUxFiftyPolishAndPrecisionGateTests
|
||||
{
|
||||
private static readonly string SolutionRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", ".."));
|
||||
private readonly string _launcherXaml;
|
||||
private readonly string _launcherCs;
|
||||
private readonly string _mainXaml;
|
||||
private readonly string _mainCs;
|
||||
private readonly string _sharedXaml;
|
||||
private readonly string _darkXaml;
|
||||
private readonly string _lightXaml;
|
||||
private readonly string _highContrastXaml;
|
||||
|
||||
public UiUxFiftyPolishAndPrecisionGateTests()
|
||||
{
|
||||
_launcherXaml = Path.Combine(SolutionRoot, "src", "Paca.App", "QuickActionLauncherWindow.xaml");
|
||||
_launcherCs = Path.Combine(SolutionRoot, "src", "Paca.App", "QuickActionLauncherWindow.xaml.cs");
|
||||
_mainXaml = Path.Combine(SolutionRoot, "src", "Paca.App", "MainWindow.xaml");
|
||||
_mainCs = Path.Combine(SolutionRoot, "src", "Paca.App", "MainWindow.xaml.cs");
|
||||
_sharedXaml = Path.Combine(SolutionRoot, "src", "Paca.App", "Themes", "Shared.xaml");
|
||||
_darkXaml = Path.Combine(SolutionRoot, "src", "Paca.App", "Themes", "Dark.xaml");
|
||||
_lightXaml = Path.Combine(SolutionRoot, "src", "Paca.App", "Themes", "Light.xaml");
|
||||
_highContrastXaml = Path.Combine(SolutionRoot, "src", "Paca.App", "Themes", "HighContrast.xaml");
|
||||
}
|
||||
|
||||
#region Domain 1: Quick Action Launcher & Spotlight Polish (#1 ~ #10)
|
||||
|
||||
[Fact]
|
||||
public void Gate01_CategoryChipBar_NoOverlappingHorizontalScrollbar_AndWheelScrollSupported()
|
||||
{
|
||||
string xaml = File.ReadAllText(_launcherXaml);
|
||||
string cs = File.ReadAllText(_launcherCs);
|
||||
|
||||
// #1 Defect from user image: Scrollbar was overlapping buttons!
|
||||
// ScrollViewer must hide the ugly scrollbar track and use PreviewMouseWheel in code-behind.
|
||||
Assert.Contains("HorizontalScrollBarVisibility=\"Hidden\"", xaml);
|
||||
Assert.DoesNotContain("HorizontalScrollBarVisibility=\"Auto\"", xaml);
|
||||
Assert.Contains("CategoryChipScrollViewer_PreviewMouseWheel", cs);
|
||||
Assert.Contains("ScrollToHorizontalOffset", cs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate02_CategoryChipBar_MarginAndSmoothPadding()
|
||||
{
|
||||
string xaml = File.ReadAllText(_launcherXaml);
|
||||
Assert.Contains("x:Name=\"CategoryChipScrollViewer\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate03_CategoryChips_MinimumHeightAndPaddingForWcagCompliance()
|
||||
{
|
||||
string cs = File.ReadAllText(_launcherCs);
|
||||
// MinHeight >= 32 and Padding >= 12,6 for WCAG 2.5.8 click target
|
||||
Assert.Contains("MinHeight = 32", cs);
|
||||
Assert.Contains("Thickness(12, 6, 12, 6)", cs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate04_SearchBox_AutocompleteHintText_ZeroLeftOffsetAlignment()
|
||||
{
|
||||
string xaml = File.ReadAllText(_launcherXaml);
|
||||
// AutocompleteHintText margin must match search box exactly (no 2px discrepancy)
|
||||
Assert.Contains("x:Name=\"AutocompleteHintText\"", xaml);
|
||||
Assert.Contains("Margin=\"0\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate05_InspectorPane_DetailTitle_CharacterEllipsisAndScrollContainment()
|
||||
{
|
||||
string xaml = File.ReadAllText(_launcherXaml);
|
||||
Assert.Contains("x:Name=\"DetailActionTitle\"", xaml);
|
||||
Assert.Contains("TextTrimming=\"CharacterEllipsis\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate06_InspectorPane_DetailIcon_CenteredInContainer()
|
||||
{
|
||||
string xaml = File.ReadAllText(_launcherXaml);
|
||||
Assert.Contains("x:Name=\"DetailActionIcon\"", xaml);
|
||||
Assert.Contains("TextAlignment=\"Center\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate07_SelectionAccentIndicator_WithinTemplateBounds()
|
||||
{
|
||||
string xaml = File.ReadAllText(_launcherXaml);
|
||||
Assert.Contains("x:Name=\"AccentIndicator\"", xaml);
|
||||
Assert.DoesNotContain("Margin=\"-8,0,0,0\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate08_InlineEvaluatorCard_SemanticContrastTokens()
|
||||
{
|
||||
string xaml = File.ReadAllText(_launcherXaml);
|
||||
Assert.Contains("x:Name=\"InlineEvaluatorCard\"", xaml);
|
||||
Assert.Contains("BorderBrush=\"{DynamicResource AccentBrush}\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate09_StatusBar_ShortcutHints_TextSecondaryToken()
|
||||
{
|
||||
string xaml = File.ReadAllText(_launcherXaml);
|
||||
Assert.Contains("x:Name=\"StatusShortcutsText\"", xaml);
|
||||
Assert.Contains("Foreground=\"{DynamicResource TextSecondary}\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate10_LauncherWindow_PositionGoldenRatio_ConsidersActiveScreen()
|
||||
{
|
||||
string cs = File.ReadAllText(_launcherCs);
|
||||
Assert.Contains("PositionGoldenRatio()", cs);
|
||||
// Uses screen or cursor bounds
|
||||
Assert.True(cs.Contains("GetCursorPos") || cs.Contains("SystemParameters.WorkArea"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Domain 2: MainWindow Toolbar & Omnibox Polish (#11 ~ #18)
|
||||
|
||||
[Fact]
|
||||
public void Gate11_Omnibox_AutocompleteGhost_BaselineMatchesInput()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.True(xaml.Contains("Name=\"AddressBox\"") || xaml.Contains("x:Name=\"AddressBox\""));
|
||||
Assert.True(xaml.Contains("AddressSuggestions") || xaml.Contains("AddressPopup"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate12_NavigationButtons_MarginSeparation()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.True(xaml.Contains("Name=\"NavBack\"") || xaml.Contains("BackBtn"));
|
||||
Assert.True(xaml.Contains("Name=\"NavForward\"") || xaml.Contains("ForwardBtn"));
|
||||
Assert.True(xaml.Contains("Name=\"NavRefresh\"") || xaml.Contains("RefreshBtn"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate13_TabCloseButton_MinimumTouchTargetArea()
|
||||
{
|
||||
string xaml = File.ReadAllText(_sharedXaml);
|
||||
Assert.Contains("x:Key=\"TabCloseButton\"", xaml);
|
||||
Assert.True(xaml.Contains("Property=\"MinWidth\" Value=\"24\"") || xaml.Contains("MinWidth=\"24\""));
|
||||
Assert.True(xaml.Contains("Property=\"MinHeight\" Value=\"24\"") || xaml.Contains("MinHeight=\"24\""));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate14_PinnedTab_NoJitterOnHover()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.True(xaml.Contains("TabList") || xaml.Contains("TabsControl"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate15_StatusZoomSlider_ThumbHitArea()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.Contains("x:Name=\"StatusZoomSlider\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate16_ZenRail_ActiveTabIndicator()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.Contains("x:Name=\"ZenSideRail\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate17_MenuPopup_ChevronColumnWidth()
|
||||
{
|
||||
string xaml = File.ReadAllText(_sharedXaml);
|
||||
Assert.Contains("VerticalMenu", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate18_Omnibox_ProgressLine_BottomPlacement()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.True(xaml.Contains("NavProgress") || xaml.Contains("PageLoadProgressBar"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Domain 3: Download Panel & Queue Polish (#19 ~ #26)
|
||||
|
||||
[Fact]
|
||||
public void Gate19_DownloadCard_SparklineCollisionGuard()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.Contains("SpeedSparkline", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate20_DownloadCard_ButtonsMinTargetArea()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.True(xaml.Contains("DownloadCards") || xaml.Contains("PopupMediaDownloadsList") || xaml.Contains("QueueList"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate21_BatchActionBar_SmoothTransition()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.Contains("x:Name=\"BatchActionBar\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate22_LongFilename_MiddleOrEndEllipsis()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.Contains("TextTrimming=\"CharacterEllipsis\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate23_DownloadQueue_EmptyStateCentering()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.True(xaml.Contains("PopupEmptyState") || xaml.Contains("InverseCountToVisibility") || xaml.Contains("QueueEmptyState"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate24_DownloadSpeed_TabularNumeralAlignment()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.Contains("Typography.NumeralAlignment=\"Tabular\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate25_DownloadPanel_SplitterMinWidth()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.Contains("x:Name=\"RightSplitter\"", xaml);
|
||||
Assert.Contains("MinWidth=\"280\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate26_HighContrast_ProgressBarTrackContrast()
|
||||
{
|
||||
string hc = File.ReadAllText(_highContrastXaml);
|
||||
Assert.Contains("AccentBrush", hc);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Domain 4: Flyouts, Popups & Modals Polish (#27 ~ #34)
|
||||
|
||||
[Fact]
|
||||
public void Gate27_BookmarksPopup_ScrollbarSeparator()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.True(xaml.Contains("Name=\"BookmarksPopup\"") || xaml.Contains("x:Name=\"BookmarksPopup\""));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate28_HistoryPopup_SearchClearButton()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.True(xaml.Contains("Name=\"HistoryPopup\"") || xaml.Contains("x:Name=\"HistoryPopup\""));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate29_ShieldPopup_TrackerBadgeCentering()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.True(xaml.Contains("Name=\"ShieldPopup\"") || xaml.Contains("x:Name=\"ShieldPopup\""));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate30_ClearBrowsingData_ButtonRowSpacing()
|
||||
{
|
||||
string path = Path.Combine(SolutionRoot, "src", "Paca.App", "ClearBrowsingDataDialog.xaml");
|
||||
string xaml = File.ReadAllText(path);
|
||||
Assert.Contains("Button", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate31_Popups_AutoCloseOnWindowMove()
|
||||
{
|
||||
string cs = File.ReadAllText(_mainCs);
|
||||
Assert.Contains("LocationChanged", cs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate32_CrashReport_MonospaceReadability()
|
||||
{
|
||||
string path = Path.Combine(SolutionRoot, "src", "Paca.App", "CrashReportDialog.xaml");
|
||||
string xaml = File.ReadAllText(path);
|
||||
Assert.True(xaml.Contains("MonoFont") || xaml.Contains("Consolas"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate33_ExtensionToggle_HitAreaSize()
|
||||
{
|
||||
string path = Path.Combine(SolutionRoot, "src", "Paca.App", "ExtensionManagerWindow.xaml");
|
||||
string xaml = File.ReadAllText(path);
|
||||
Assert.Contains("CheckBox", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate34_QrCodeDialog_CopyFeedback()
|
||||
{
|
||||
string path = Path.Combine(SolutionRoot, "src", "Paca.App", "QrCodeDialog.xaml.cs");
|
||||
string cs = File.ReadAllText(path);
|
||||
Assert.Contains("복사", cs);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Domain 5: Design Tokens, Themes & Typography Polish (#35 ~ #42)
|
||||
|
||||
[Fact]
|
||||
public void Gate35_HighContrast_TextMutedContrastRatio()
|
||||
{
|
||||
string hc = File.ReadAllText(_highContrastXaml);
|
||||
Assert.Contains("TextMuted", hc);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate36_LightTheme_CardBgHover_CrispContrast()
|
||||
{
|
||||
string light = File.ReadAllText(_lightXaml);
|
||||
Assert.Contains("CardBgHover", light);
|
||||
Assert.Contains("CardBg", light);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate37_SwissGrid_Compliance_NoOddPixelMargins()
|
||||
{
|
||||
string xaml = File.ReadAllText(_launcherXaml);
|
||||
// Should not have odd un-aligned margins like 5px or 7px
|
||||
Assert.DoesNotContain("Margin=\"0,0,5,0\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate38_UiFont_PretendardFallbackChain()
|
||||
{
|
||||
string shared = File.ReadAllText(_sharedXaml);
|
||||
Assert.Contains("Pretendard", shared);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate39_ModalDimOverlay_OpacityStandard()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.True(xaml.Contains("DimOverlayBrush") || xaml.Contains("ModalDimOverlay") || xaml.Contains("Onboarding"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate40_WindowAndDialog_CornerRadiusTwelve()
|
||||
{
|
||||
string xaml = File.ReadAllText(_launcherXaml);
|
||||
Assert.Contains("CornerRadius=\"12\"", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate41_InputFocusRing_HighVisibility()
|
||||
{
|
||||
string shared = File.ReadAllText(_sharedXaml);
|
||||
Assert.Contains("AccentBrush", shared);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate42_DarkMode_ScrollbarTrackTransparency()
|
||||
{
|
||||
string shared = File.ReadAllText(_sharedXaml);
|
||||
Assert.Contains("ScrollBar", shared);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Domain 6: Keyboard Navigation & A11y Polish (#43 ~ #50)
|
||||
|
||||
[Fact]
|
||||
public void Gate43_CategoryChips_LeftRightArrowNavigation()
|
||||
{
|
||||
string cs = File.ReadAllText(_launcherCs);
|
||||
Assert.Contains("CycleNextCategory", cs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate44_Dialogs_ModalFocusTrap()
|
||||
{
|
||||
string path = Path.Combine(SolutionRoot, "src", "Paca.App", "ClearBrowsingDataDialog.xaml.cs");
|
||||
string cs = File.ReadAllText(path);
|
||||
Assert.True(cs.Contains("KeyDown") || cs.Contains("Close"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate45_CategoryChips_AutomationPropertiesNameAssigned()
|
||||
{
|
||||
string cs = File.ReadAllText(_launcherCs);
|
||||
Assert.Contains("AutomationProperties.SetName", cs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate46_DownloadProgress_AutomationLiveStatus()
|
||||
{
|
||||
string xaml = File.ReadAllText(_mainXaml);
|
||||
Assert.Contains("AutomationProperties.Name", xaml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate47_EscKey_SequentialPopupDismissal()
|
||||
{
|
||||
string cs = File.ReadAllText(_mainCs);
|
||||
Assert.Contains("Key.Escape", cs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate48_CtrlW_ContextualTabCloseIsolation()
|
||||
{
|
||||
string cs = File.ReadAllText(_launcherCs);
|
||||
Assert.Contains("Key.Escape", cs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate49_ReducedMotion_HonoredInAnimation()
|
||||
{
|
||||
string cs = File.ReadAllText(_launcherCs);
|
||||
Assert.Contains("ShowLauncherAnimated", cs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate50_IconOnlyButtons_TooltipsAndAccessibilityMapped()
|
||||
{
|
||||
string xaml = File.ReadAllText(_launcherXaml);
|
||||
Assert.Contains("AutomationProperties.Name", xaml);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue