using Microsoft.VisualStudio.TestTools.UnitTesting; using YMhut.Box.Core.Tools; namespace YMhut.Box.Tests; [TestClass] public sealed class ToolCatalogTests { [TestMethod] public void DefaultCatalogContainsRequiredNativePages() { var catalog = new ToolCatalog(); Assert.IsNotNull(catalog.GetById("safe_browser")); Assert.IsNotNull(catalog.GetById("media_player")); Assert.IsNotNull(catalog.GetById("text_splitter")); Assert.IsNotNull(catalog.GetById("loan_emi_calculator")); Assert.IsNotNull(catalog.GetById("number_base_converter")); Assert.IsNotNull(catalog.GetById("ymhut_uutool_suite")); Assert.IsNotNull(catalog.GetById("html_js_playground")); Assert.IsNotNull(catalog.GetById("timezone_abbr_lookup")); Assert.IsNotNull(catalog.GetById("percentage_change_calculator")); Assert.IsNotNull(catalog.GetById("dev_environment_config")); Assert.IsNull(catalog.GetById("mmd_model_studio")); foreach (var id in new[] { "compression_codec", "totp_generator", "color_contrast_checker", "url_redirect_trace", "image_metadata_inspector", "markdown_preview" }) { Assert.IsNotNull(catalog.GetById(id), id); } Assert.IsGreaterThanOrEqualTo(160, catalog.Modules.Count); } [TestMethod] public void SearchFiltersByQueryAndCategory() { var catalog = new ToolCatalog(); var results = catalog.Search("browser", ToolCategory.Network).ToList(); Assert.HasCount(1, results); Assert.AreEqual("safe_browser", results[0].Id); } [TestMethod] public void ToolViewModelStartsWithInlinePreviewHidden() { var module = new ToolCatalog().GetById("json_formatter")!; var viewModel = (ToolModuleViewModel)module.CreateViewModel(); Assert.IsFalse(viewModel.InlinePreviewLoaded); } [TestMethod] public void EveryCatalogToolHasNativeWinUiPageSpec() { var catalog = new ToolCatalog(); var specs = ToolPageSpecCatalog.CreateFor(catalog); Assert.HasCount(catalog.Modules.Count, specs); foreach (var module in catalog.Modules) { Assert.IsTrue(specs.ContainsKey(module.Id), module.Id); var spec = specs[module.Id]; Assert.AreEqual(module.Id, spec.ToolId); Assert.IsTrue(Enum.IsDefined(spec.Layout), module.Id); Assert.IsNotEmpty(spec.ParameterControls, module.Id); Assert.IsTrue(Enum.IsDefined(spec.AssistPanelMode), module.Id); Assert.IsTrue(Enum.IsDefined(spec.InteractionMode), module.Id); Assert.IsTrue(Enum.IsDefined(spec.PageExperience), module.Id); Assert.IsTrue(Enum.IsDefined(spec.PageDensity), module.Id); Assert.IsTrue(Enum.IsDefined(spec.ResultPriority), module.Id); Assert.IsFalse(string.IsNullOrWhiteSpace(spec.DefaultFocusTarget), module.Id); if (spec.PageExperience != ToolPageExperienceKind.LivePreview) { Assert.IsFalse(string.IsNullOrWhiteSpace(spec.PrimaryActionLabel), module.Id); } if (spec.PrimaryInput != ToolPrimaryInputKind.None) { Assert.IsNotEmpty(spec.Parameters, module.Id); } Assert.IsFalse(string.IsNullOrWhiteSpace(spec.EmptyState), module.Id); Assert.IsFalse(string.IsNullOrWhiteSpace(spec.ErrorHint), module.Id); } } [TestMethod] public void RepresentativeToolSpecsUseGalleryNativeControls() { var catalog = new ToolCatalog(); Assert.AreEqual(ToolPrimaryInputKind.MultilineText, ToolPageSpecCatalog.For(catalog.GetById("json_formatter")!).PrimaryInput); Assert.AreEqual(ToolResultKind.JsonTree, ToolPageSpecCatalog.For(catalog.GetById("json_formatter")!).Result); Assert.AreEqual(ToolPrimaryInputKind.FixedOptions, ToolPageSpecCatalog.For(catalog.GetById("system_tool")!).PrimaryInput); Assert.AreEqual(ToolLayoutKind.SystemLauncher, ToolPageSpecCatalog.For(catalog.GetById("system_tool")!).Layout); Assert.AreEqual(ToolPrimaryInputKind.None, ToolPageSpecCatalog.For(catalog.GetById("baidu_hot")!).PrimaryInput); Assert.IsTrue(ToolPageSpecCatalog.For(catalog.GetById("archive_tool")!).RequiresFilePicker); Assert.IsTrue(ToolPageSpecCatalog.For(catalog.GetById("image_metadata_inspector")!).RequiresFilePicker); Assert.AreEqual(ToolLayoutKind.CodecWorkbench, ToolPageSpecCatalog.For(catalog.GetById("compression_codec")!).Layout); Assert.AreEqual(ToolLayoutKind.SecurityWorkbench, ToolPageSpecCatalog.For(catalog.GetById("totp_generator")!).Layout); Assert.AreEqual(ToolLayoutKind.TextWorkbench, ToolPageSpecCatalog.For(catalog.GetById("color_contrast_checker")!).Layout); Assert.AreEqual(ToolLayoutKind.QueryDashboard, ToolPageSpecCatalog.For(catalog.GetById("url_redirect_trace")!).Layout); Assert.AreEqual(ToolLayoutKind.FormatterWorkbench, ToolPageSpecCatalog.For(catalog.GetById("markdown_preview")!).Layout); Assert.AreEqual(ToolLayoutKind.RandomCinema, ToolPageSpecCatalog.For(catalog.GetById("random_cinema")!).Layout); Assert.AreEqual(ToolCategory.Image, catalog.GetById("random_cinema")!.Metadata.Category); } [TestMethod] public void ModelStudioToolIsRemovedFromCatalogAndSpecs() { var catalog = new ToolCatalog(); Assert.IsNull(catalog.GetById("mmd_model_studio")); Assert.IsFalse(ToolPageSpecCatalog.CreateFor(catalog).ContainsKey("mmd_model_studio")); } [TestMethod] public void ToolAssistAndInteractionModesMatchRepresentativeExperience() { var catalog = new ToolCatalog(); Assert.AreEqual(ToolAssistPanelMode.Custom, ToolPageSpecCatalog.For(catalog.GetById("color_picker")!).AssistPanelMode); Assert.AreEqual(ToolInteractionMode.LivePreview, ToolPageSpecCatalog.For(catalog.GetById("color_picker")!).InteractionMode); Assert.AreEqual(ToolPageExperienceKind.LivePreview, ToolPageSpecCatalog.For(catalog.GetById("color_picker")!).PageExperience); Assert.AreEqual(ToolAssistPanelMode.Hidden, ToolPageSpecCatalog.For(catalog.GetById("system_info")!).AssistPanelMode); Assert.AreEqual(ToolAssistPanelMode.Hidden, ToolPageSpecCatalog.For(catalog.GetById("baidu_hot")!).AssistPanelMode); Assert.AreEqual(ToolAssistPanelMode.RulesOnly, ToolPageSpecCatalog.For(catalog.GetById("json_formatter")!).AssistPanelMode); Assert.AreEqual(ToolAssistPanelMode.RulesOnly, ToolPageSpecCatalog.For(catalog.GetById("base64_codec")!).AssistPanelMode); Assert.AreEqual(ToolAssistPanelMode.SourceOnly, ToolPageSpecCatalog.For(catalog.GetById("weather")!).AssistPanelMode); Assert.AreEqual(ToolInteractionMode.ReferenceBrowser, ToolPageSpecCatalog.For(catalog.GetById("mime_lookup")!).InteractionMode); Assert.AreEqual(ToolPageExperienceKind.RemoteDashboard, ToolPageSpecCatalog.For(catalog.GetById("baidu_hot")!).PageExperience); Assert.AreEqual(ToolPageExperienceKind.FormCalculator, ToolPageSpecCatalog.For(catalog.GetById("bmi_calculator")!).PageExperience); Assert.AreEqual(ToolPageExperienceKind.FileWorkflow, ToolPageSpecCatalog.For(catalog.GetById("archive_tool")!).PageExperience); } [TestMethod] public void RuleDrivenToolsHaveRuleSpecsAndSourceOnlyCopyIsSanitized() { var catalog = new ToolCatalog(); var specs = ToolPageSpecCatalog.CreateFor(catalog); foreach (var spec in specs.Values.Where(spec => spec.AssistPanelMode == ToolAssistPanelMode.RulesOnly)) { Assert.IsTrue(spec.Rules.Count > 0 || spec.RequiresFilePicker || spec.ParameterControls.Contains(ToolParameterControlKind.NumberBox), spec.ToolId); } foreach (var spec in specs.Values.Where(spec => spec.AssistPanelMode == ToolAssistPanelMode.SourceOnly)) { var uiCopy = $"{spec.EmptyState} {spec.ErrorHint}"; Assert.IsFalse(uiCopy.Contains("http://", StringComparison.OrdinalIgnoreCase), spec.ToolId); Assert.IsFalse(uiCopy.Contains("https://", StringComparison.OrdinalIgnoreCase), spec.ToolId); Assert.IsFalse(uiCopy.Contains(".json", StringComparison.OrdinalIgnoreCase), spec.ToolId); } } [TestMethod] public void RuleAndParameterSpecsCarryBilingualText() { var catalog = new ToolCatalog(); var json = ToolPageSpecCatalog.For(catalog.GetById("json_formatter")!); var port = ToolPageSpecCatalog.For(catalog.GetById("port_lookup")!); Assert.AreEqual("模式", json.Rules[0].LocalizedLabel?.ForLanguage("zh-CN")); Assert.AreEqual("Mode", json.Rules[0].LocalizedLabel?.ForLanguage("en-US")); Assert.AreEqual("格式化", json.Rules[0].Options[0].LocalizedLabel?.ForLanguage("zh-CN")); Assert.AreEqual("Format", json.Rules[0].Options[0].LocalizedLabel?.ForLanguage("en-US")); Assert.AreEqual("来源", port.Rules[0].LocalizedLabel?.ForLanguage("zh-CN")); Assert.AreEqual("Source", port.Rules[0].LocalizedLabel?.ForLanguage("en-US")); Assert.AreEqual("预设", port.Parameters[0].LocalizedLabel?.ForLanguage("zh-CN")); Assert.AreEqual("Preset", port.Parameters[0].LocalizedLabel?.ForLanguage("en-US")); } [TestMethod] public void PageExperienceRulesKeepToolPagesCompact() { var catalog = new ToolCatalog(); var color = ToolPageSpecCatalog.For(catalog.GetById("color_picker")!); Assert.AreEqual(ToolPageExperienceKind.LivePreview, color.PageExperience); Assert.AreEqual(string.Empty, color.PrimaryActionLabel); var hot = ToolPageSpecCatalog.For(catalog.GetById("hotboard")!); Assert.AreEqual(ToolPageExperienceKind.RemoteDashboard, hot.PageExperience); Assert.IsFalse(hot.AutoRunOnOpen); Assert.AreEqual("查询", hot.PrimaryActionLabel); Assert.IsTrue(hot.ShowInputHeader); var bmi = ToolPageSpecCatalog.For(catalog.GetById("bmi_calculator")!); Assert.AreEqual(ToolPageExperienceKind.FormCalculator, bmi.PageExperience); Assert.AreEqual("计算", bmi.PrimaryActionLabel); Assert.AreNotEqual(ToolPrimaryInputKind.MultilineText, bmi.PrimaryInput); var json = ToolPageSpecCatalog.For(catalog.GetById("json_formatter")!); Assert.AreEqual(ToolPageExperienceKind.OneShotTransform, json.PageExperience); Assert.AreEqual("格式化", json.PrimaryActionLabel); } [TestMethod] public void CalculatorToolSpecsUseNativeFormInputsByArity() { var catalog = new ToolCatalog(); Assert.AreEqual(ToolPrimaryInputKind.NumberPair, ToolPageSpecCatalog.For(catalog.GetById("bmi_calculator")!).PrimaryInput); Assert.AreEqual(ToolPrimaryInputKind.NumberTriple, ToolPageSpecCatalog.For(catalog.GetById("loan_emi_calculator")!).PrimaryInput); Assert.AreEqual(ToolPrimaryInputKind.NumberQuad, ToolPageSpecCatalog.For(catalog.GetById("compound_interest_calculator")!).PrimaryInput); Assert.AreEqual(ToolPrimaryInputKind.DateRange, ToolPageSpecCatalog.For(catalog.GetById("shelf_life")!).PrimaryInput); Assert.IsTrue(ToolPageSpecCatalog.For(catalog.GetById("shelf_life")!).UsesNumberBox); } [TestMethod] public void SpecsCoverEveryStructuredResultKind() { var catalog = new ToolCatalog(); var resultKinds = catalog.Modules .Select(module => ToolPageSpecCatalog.For(module).Result) .Distinct() .ToHashSet(); foreach (ToolResultKind kind in Enum.GetValues()) { Assert.Contains(kind, resultKinds, kind.ToString()); } } [TestMethod] public async Task ToolExecutorReturnsStructuredDocuments() { var catalog = new ToolCatalog(); var samples = new Dictionary { ["json_formatter"] = "{\"name\":\"YMhut Box\"}", ["base64_codec"] = "YMhut Box", ["bmi_calculator"] = "70 1.75", ["text_diff"] = "WinUI\n---\nWinUI 3", ["color_picker"] = "#3399ff" }; foreach (var sample in samples) { var module = catalog.GetById(sample.Key)!; var result = await ToolExecutor.ExecuteAsync(module, sample.Value); Assert.IsTrue(result.Ok, sample.Key); Assert.IsNotNull(result.Document, sample.Key); Assert.AreEqual(module.Id, result.Document.ToolId); Assert.IsNotEmpty(result.Document.Blocks, sample.Key); Assert.AreEqual(result.Output, result.Document.RawText); } } [TestMethod] public void EveryResultKindBuildsStructuredDocumentBlocks() { var catalog = new ToolCatalog(); var samples = new Dictionary { ["ascii_art"] = "YMhut", ["xml_formatter"] = "YMhut", ["json_formatter"] = "{\"name\":\"YMhut\"}", ["base64_codec"] = "Encode:\nWU1odXQ=", ["regex_tool"] = "match | value\n1 | YMhut", ["hotboard"] = "1. YMhut 热点", ["cctv_news"] = "1. 新闻标题", ["qr_generator"] = "https://example.com/qr.png", ["smart_search"] = "Bing - https://www.bing.com/search?q=YMhut", ["archive_tool"] = "已创建归档:sample.zip", ["text_diff"] = "- old\n+ new", ["hash_manifest_verify"] = "OK hello", ["color_picker"] = "HEX: #336699\nRGB: 51, 102, 153", ["number_base"] = "DEC: 255\nHEX: 0xFF", ["system_tool"] = "OS: Windows\nProcessors: 8", ["random_cinema"] = "https://example.com/media.mp4", ["port_lookup"] = "数据源:YMhut Reference Data / IANA\n80 - HTTP: 网页服务" }; foreach (ToolResultKind kind in Enum.GetValues()) { var module = catalog.Modules.FirstOrDefault(module => ToolPageSpecCatalog.For(module).Result == kind); Assert.IsNotNull(module, kind.ToString()); var output = samples.TryGetValue(module.Id, out var sample) ? sample : "Key: Value\nItem: Result"; var document = ToolResultBuilder.FromOutput(module, output, "zh-CN"); Assert.AreEqual(module.Id, document.ToolId, kind.ToString()); Assert.AreEqual(kind, document.ResultKind, kind.ToString()); Assert.IsNotEmpty(document.Blocks, kind.ToString()); Assert.AreEqual("ok", document.Status, kind.ToString()); } } }