using System; using System.Linq; using Paca.Core.QuickActions; using Xunit; namespace Paca.Tests.App; public class QuickActionRegistryAndCatalogGateTests { [Fact] public void Gate_QuickActionCatalog_ContainsAtLeast200Actions() { var catalog = new QuickActionCatalog(); var actions = catalog.GetAllActions(); Assert.NotNull(actions); Assert.True(actions.Count >= 200, $"퀵 액션 총 개수는 적어도 200개 이상이어야 합니다. 현재: {actions.Count}개"); // Verify ID uniqueness var duplicateIds = actions.GroupBy(a => a.Id).Where(g => g.Count() > 1).Select(g => g.Key).ToList(); Assert.Empty(duplicateIds); } [Fact] public void Gate_QuickActionCatalog_AllCategoriesCovered() { var catalog = new QuickActionCatalog(); var actions = catalog.GetAllActions(); var categories = Enum.GetValues(); foreach (var cat in categories) { var inCat = actions.Where(a => a.Category == cat).ToList(); Assert.True(inCat.Count >= 10, $"카테고리 '{cat}'에 최소 10개 이상의 액션이 포함되어야 합니다. 현재: {inCat.Count}개"); } } [Fact] public void Gate_QuickActionCatalog_AllActionsHaveValidMetadata() { var catalog = new QuickActionCatalog(); var actions = catalog.GetAllActions(); foreach (var action in actions) { Assert.False(string.IsNullOrWhiteSpace(action.Id), "액션 ID는 비어 있을 수 없습니다."); Assert.False(string.IsNullOrWhiteSpace(action.Title), $"액션 ID '{action.Id}'의 Title이 비어 있습니다."); Assert.False(string.IsNullOrWhiteSpace(action.Keywords), $"액션 ID '{action.Id}'의 Keywords가 비어 있습니다."); Assert.NotNull(action.Handler); } } [Fact] public void Gate_QuickActionSearchEngine_FuzzyAndKeywordSearch() { var catalog = new QuickActionCatalog(); var searcher = new QuickActionSearchEngine(catalog); // Search by title or keyword var lockResults = searcher.Search("잠금"); Assert.Contains(lockResults, r => r.Action.Id == "sys.lock_workstation"); var b64Results = searcher.Search("base64"); Assert.Contains(b64Results, r => r.Action.Id == "dev.base64_encode"); var newTabResults = searcher.Search("새 탭"); Assert.Contains(newTabResults, r => r.Action.Id == "browser.new_tab"); } }