Files
lmxopcua/tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests/ScriptAnalysis/CtxCompletionGuardTests.cs
T
Joseph Doherty b211911f98
v2-ci / unit-tests (push) Failing after 13m22s
test: migrate AdminUI/ControlPlane/Runtime/Host tests to xunit.v3 (#756)
Akka.TestKit.Xunit2 -> Akka.TestKit.Xunit 1.5.62 (xunit.v3 TestKit; needs xunit.v3 3.2.2, set via
VersionOverride on the four projects). Removes the xunit 2.9.3 pin. IAsyncLifetime returns ValueTask,
SqlServerFactAttribute gains the source-info ctor, and xUnit1051 call sites pass
TestContext.Current.CancellationToken. Test counts unchanged.

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
2026-11-10 08:57:33 -05:00

57 lines
2.7 KiB
C#

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<IReadOnlyList<string>> GetPathsAsync(string? f, CancellationToken ct)
=> Task.FromResult<IReadOnlyList<string>>(new[] { "Line1.Speed" });
public Task<ScriptTagInfo?> GetTagInfoAsync(string path, CancellationToken ct)
=> Task.FromResult<ScriptTagInfo?>(new ScriptTagInfo(path, "Virtual tag", "Double", null));
public Task<IReadOnlyList<string>> GetEquipmentReferenceNamesAsync(string equipmentId, string? f, CancellationToken ct)
=> Task.FromResult<IReadOnlyList<string>>(System.Array.Empty<string>());
}
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), TestContext.Current.CancellationToken);
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), TestContext.Current.CancellationToken);
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), TestContext.Current.CancellationToken)).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), TestContext.Current.CancellationToken)).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), TestContext.Current.CancellationToken)).Markdown;
(md is null || !md.Contains("Tag path")).ShouldBeTrue();
}
}