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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue