using System.Threading; using System.Threading.Tasks; using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.AdminUI.ScriptAnalysis; namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.ScriptAnalysis; public sealed class CtxCompletionGuardTests { private sealed class FakeCatalog : IScriptTagCatalog { public Task> GetPathsAsync(string? f, CancellationToken ct) => Task.FromResult>(new[] { "Line1.Speed" }); public Task GetTagInfoAsync(string path, CancellationToken ct) => Task.FromResult(new ScriptTagInfo(path, "Virtual tag", "Double", null)); public Task> GetEquipmentRelativeLeavesAsync(string? f, CancellationToken ct) => Task.FromResult>(System.Array.Empty()); } private static readonly ScriptAnalysisService Svc = new(new FakeCatalog()); [Fact] public async Task Completion_on_ctx_GetTag_literal_offers_catalog_paths() { // "return ctx.GetTag(" + '""' + ')' — col 20 lands on the closing quote of the empty string literal. var res = await Svc.CompleteAsync(new CompletionsRequest("return ctx.GetTag(\"\")", 1, 20)); res.Items.ShouldContain(i => i.InsertText == "Line1.Speed"); } [Fact] public async Task Completion_on_non_ctx_receiver_does_NOT_offer_catalog_paths() { // Same shape but receiver is "foo" — must NOT offer catalog paths. var res = await Svc.CompleteAsync(new CompletionsRequest("return foo.GetTag(\"\")", 1, 20)); res.Items.ShouldNotContain(i => i.InsertText == "Line1.Speed"); } [Fact] public async Task Hover_on_ctx_SetVirtualTag_literal_warns_write_is_dropped() { var md = (await Svc.Hover(new HoverRequest("return ctx.SetVirtualTag(\"V\", 1);", 1, 27))).Markdown; md.ShouldNotBeNull(); md!.ShouldContain("single-tag mode"); } [Fact] public async Task Hover_on_ctx_GetTag_literal_has_no_dropped_write_note() { var md = (await Svc.Hover(new HoverRequest("return ctx.GetTag(\"V\").Value;", 1, 20))).Markdown; md.ShouldNotBeNull(); md!.ShouldNotContain("single-tag mode"); } [Fact] public async Task Hover_on_non_ctx_receiver_literal_is_not_treated_as_a_tag_path() { var md = (await Svc.Hover(new HoverRequest("return bar.GetTag(\"V\");", 1, 20))).Markdown; (md is null || !md.Contains("Tag path")).ShouldBeTrue(); } }