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:
Yun Chan 2026-09-14 00:39:44 +09:00
parent a88aafa1e5
commit 0e568f1f0a
975 changed files with 130593 additions and 16783 deletions

View file

@ -0,0 +1,141 @@
using System;
using System.IO;
using System.Linq;
using Paca.Core.QuickActions;
using Xunit;
namespace Paca.Tests.App;
public class QuickActionAdvancedUxAndLocalizationGateTests
{
private static readonly string SolutionRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", ".."));
private readonly string _xamlPath;
private readonly string _csPath;
public QuickActionAdvancedUxAndLocalizationGateTests()
{
_xamlPath = Path.Combine(SolutionRoot, "src", "Paca.App", "QuickActionLauncherWindow.xaml");
_csPath = Path.Combine(SolutionRoot, "src", "Paca.App", "QuickActionLauncherWindow.xaml.cs");
}
[Fact]
public void Gate_QuickAction_CrossLanguageSearch_SupportsKoreanEnglishJapanese()
{
var catalog = new QuickActionCatalog();
var searchEngine = new QuickActionSearchEngine(catalog);
// Korean search
var koResults = searchEngine.Search("새 탭");
Assert.NotEmpty(koResults);
Assert.Equal("browser.new_tab", koResults[0].Action.Id);
// English search
var enResults = searchEngine.Search("new tab");
Assert.NotEmpty(enResults);
Assert.Equal("browser.new_tab", enResults[0].Action.Id);
// Screenshot
var shotKo = searchEngine.Search("스크린샷");
var shotEn = searchEngine.Search("screenshot");
Assert.NotEmpty(shotKo);
Assert.NotEmpty(shotEn);
}
[Fact]
public void Gate_QuickAction_CategoryFilter_FiltersAccurately()
{
var catalog = new QuickActionCatalog();
var searchEngine = new QuickActionSearchEngine(catalog);
var browserOnly = searchEngine.Search(string.Empty, maxResults: 50, categoryFilter: QuickActionCategory.Browser);
Assert.NotEmpty(browserOnly);
Assert.All(browserOnly, r => Assert.Equal(QuickActionCategory.Browser, r.Action.Category));
var devOnly = searchEngine.Search(string.Empty, maxResults: 50, categoryFilter: QuickActionCategory.Developer);
Assert.NotEmpty(devOnly);
Assert.All(devOnly, r => Assert.Equal(QuickActionCategory.Developer, r.Action.Category));
}
[Fact]
public void Gate_QuickAction_AutocompleteSuggestion_ReturnsTopTitle()
{
var catalog = new QuickActionCatalog();
var searchEngine = new QuickActionSearchEngine(catalog);
string? suggestion = searchEngine.GetTopSuggestion("새");
Assert.NotNull(suggestion);
Assert.StartsWith("새", suggestion);
}
[Fact]
public void Gate_QuickAction_DisplayLocalization_ResultsContainLocalizedStringsForCulture()
{
var catalog = new QuickActionCatalog();
var searchEngine = new QuickActionSearchEngine(catalog);
// English culture
var enResults = searchEngine.Search("new tab", cultureCode: "en-US");
Assert.NotEmpty(enResults);
Assert.Equal("New Tab", enResults[0].Title);
Assert.Equal("Browser", enResults[0].CategoryName);
// Japanese culture
var jaResults = searchEngine.Search("new tab", cultureCode: "ja-JP");
Assert.NotEmpty(jaResults);
Assert.Contains("タブ", jaResults[0].Title);
Assert.Equal("ブラウザ", jaResults[0].CategoryName);
// Korean culture
var koResults = searchEngine.Search("new tab", cultureCode: "ko-KR");
Assert.NotEmpty(koResults);
Assert.Equal("새 탭 열기", koResults[0].Title);
Assert.Equal("브라우저", koResults[0].CategoryName);
}
[Fact]
public void Gate_QuickAction_Xaml_UsesStrictDesignTokensAndUnclippedShadow()
{
Assert.True(File.Exists(_xamlPath));
var xaml = File.ReadAllText(_xamlPath);
// Root font inheritance from SSOT
Assert.Contains("FontFamily=\"{DynamicResource UiFont}\"", xaml);
// Correct token check: CardBgHover must be used, NOT CardHoverBg
Assert.DoesNotContain("CardHoverBg", xaml);
Assert.Contains("CardBgHover", xaml);
// Selection token check
Assert.Contains("SelectionBrush", xaml);
// Category chips and autocomplete hint
Assert.Contains("CategoryChipBar", xaml);
Assert.Contains("AutocompleteHintText", xaml);
// Unclipped shadow margin
Assert.Contains("Margin=\"20\"", xaml);
}
[Fact]
public void Gate_QuickAction_CodeBehind_SupportsKeyboardNavigationAndShortcuts()
{
Assert.True(File.Exists(_csPath));
var cs = File.ReadAllText(_csPath);
// Quick numbers Ctrl+1 ~ Ctrl+9
Assert.Contains("ExecuteQuickNumberAction", cs);
// Golden ratio positioning
Assert.Contains("0.28", cs);
// Autocomplete Tab logic & Right arrow
Assert.Contains("Key.Tab", cs);
Assert.Contains("Key.Right", cs);
// SetForegroundWindow for input conflict defense
Assert.Contains("SetForegroundWindow", cs);
// Category prefix triggers
Assert.Contains("CheckCategoryPrefixTrigger", cs);
}
}