From b949dc4183513f41dc5337cbde65fe6626e04447 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Sat, 16 May 2026 15:04:06 -0400 Subject: [PATCH] test(central-ui): realign analyzer tests with the reworked script-call API --- .../DataConnectionsPageTests.cs | 10 +- .../ScriptAnalysisServiceTests.cs | 94 +++++-------------- 2 files changed, 32 insertions(+), 72 deletions(-) diff --git a/tests/ScadaLink.CentralUI.Tests/DataConnectionsPageTests.cs b/tests/ScadaLink.CentralUI.Tests/DataConnectionsPageTests.cs index 9efa4ee..3d1f2fe 100644 --- a/tests/ScadaLink.CentralUI.Tests/DataConnectionsPageTests.cs +++ b/tests/ScadaLink.CentralUI.Tests/DataConnectionsPageTests.cs @@ -147,16 +147,18 @@ public class DataConnectionsPageTests : BunitContext } [Fact] - public void LegacyDataConnectionsRoute_IsDeclaredOnListPage() + public void DataConnectionsRoutes_AreDeclaredOnListPage() { - // Old bookmarks to /admin/data-connections must still resolve. + // The page moved from Admin to Design; both the canonical + // /design/connections route and the /design/data-connections alias + // must resolve to the list page. var routes = typeof(DataConnectionsPage).GetCustomAttributes( typeof(Microsoft.AspNetCore.Components.RouteAttribute), inherit: false) .Cast() .Select(a => a.Template) .ToList(); - Assert.Contains("/admin/connections", routes); - Assert.Contains("/admin/data-connections", routes); + Assert.Contains("/design/connections", routes); + Assert.Contains("/design/data-connections", routes); } } diff --git a/tests/ScadaLink.CentralUI.Tests/ScriptAnalysis/ScriptAnalysisServiceTests.cs b/tests/ScadaLink.CentralUI.Tests/ScriptAnalysis/ScriptAnalysisServiceTests.cs index 8f7d228..95955b0 100644 --- a/tests/ScadaLink.CentralUI.Tests/ScriptAnalysis/ScriptAnalysisServiceTests.cs +++ b/tests/ScadaLink.CentralUI.Tests/ScriptAnalysis/ScriptAnalysisServiceTests.cs @@ -122,26 +122,6 @@ public class ScriptAnalysisServiceTests Assert.DoesNotContain(resp.Markers, m => m.Code == "SCADA003"); } - [Fact] - public void ArgumentCountTooFew_RaisesSCADA004() - { - var siblings = new[] { Shape("Calc", Param("x"), Param("y")) }; - var resp = _svc.Diagnose(new DiagnoseRequest( - Code: "var r = CallScript(\"Calc\", 1);", - SiblingScripts: siblings)); - Assert.Contains(resp.Markers, m => m.Code == "SCADA004" && m.Message.Contains("expects 2")); - } - - [Fact] - public void ArgumentCountTooMany_RaisesSCADA004() - { - var siblings = new[] { Shape("Ping") }; - var resp = _svc.Diagnose(new DiagnoseRequest( - Code: "var r = CallScript(\"Ping\", 1, 2);", - SiblingScripts: siblings)); - Assert.Contains(resp.Markers, m => m.Code == "SCADA004" && m.Message.Contains("got 2")); - } - [Fact] public void ArgumentCountCorrect_NoMarker() { @@ -193,16 +173,18 @@ public class ScriptAnalysisServiceTests { var siblings = new[] { Shape("SiblingA", Param("x")) }; var req = new CompletionsRequest( - CodeText: "var x = CallScript(\"", + CodeText: "var x = Instance.CallScript(\"", Line: 1, - Column: 21, + Column: 30, SiblingScripts: siblings); var resp = await _svc.CompleteAsync(req); var item = Assert.Single(resp.Items, i => i.Label == "SiblingA"); Assert.Equal(4, item.InsertTextRules); - Assert.Contains("${1:x}", item.InsertText); + // The runtime call API takes args as an anonymous object — the snippet + // emits one member per declared parameter. + Assert.Contains("new { x = ${1:x} }", item.InsertText); Assert.Contains("sibling script", item.Detail); } @@ -216,15 +198,19 @@ public class ScriptAnalysisServiceTests }); var req = new CompletionsRequest( - CodeText: "var x = CallShared(\"", + CodeText: "var x = Scripts.CallShared(\"", Line: 1, - Column: 21); + Column: 29); var resp = await _svc.CompleteAsync(req); - Assert.Contains(resp.Items, i => i.Label == "GetWeather"); + // No-parameter shape: snippet just closes the call. + var weather = Assert.Single(resp.Items, i => i.Label == "GetWeather"); + Assert.Equal("GetWeather\")", weather.InsertText); + // Parameterized shape: anonymous-object member per parameter. var greet = Assert.Single(resp.Items, i => i.Label == "Greet"); - Assert.Contains("${1:name}", greet.InsertText); + Assert.Contains("new { name = ${1:name} }", greet.InsertText); + Assert.Contains("shared script", greet.Detail); } [Fact] @@ -232,8 +218,12 @@ public class ScriptAnalysisServiceTests { var req = new CompletionsRequest("var x = ", 1, 9); var resp = await _svc.CompleteAsync(req); + // SandboxScriptHost globals are surfaced as in-scope symbols. The + // runtime call API is member-access — Scripts.CallShared / Instance.* + // — so the top-level globals are Parameters, Scripts, and Instance. Assert.Contains(resp.Items, i => i.Label == "Parameters"); - Assert.Contains(resp.Items, i => i.Label == "CallShared"); + Assert.Contains(resp.Items, i => i.Label == "Scripts"); + Assert.Contains(resp.Items, i => i.Label == "Instance"); } // ── Hover ───────────────────────────────────────────────────────────── @@ -242,15 +232,15 @@ public class ScriptAnalysisServiceTests public void Hover_OnSiblingName_ReturnsSignature() { var siblings = new[] { Shape("Calc", Param("x", "Integer"), Param("y", "Float")) }; + // Cursor inside the "Calc" name literal of Instance.CallScript("Calc", ...). var resp = _svc.Hover(new HoverRequest( - CodeText: "var r = CallScript(\"Calc\", 1, 2);", + CodeText: "var r = Instance.CallScript(\"Calc\", 1, 2);", Line: 1, - Column: 23, + Column: 32, SiblingScripts: siblings)); Assert.NotNull(resp.Markdown); - Assert.Contains("Calc", resp.Markdown); - Assert.Contains("x: Integer", resp.Markdown); - Assert.Contains("y: Float", resp.Markdown); + Assert.Contains("sibling script", resp.Markdown); + Assert.Contains("Calc(x: Integer, y: Float): void", resp.Markdown); } [Fact] @@ -270,11 +260,11 @@ public class ScriptAnalysisServiceTests { var siblings = new[] { Shape("Calc", Param("x", "Integer"), Param("y", "Float")) }; var resp = _svc.SignatureHelp(new SignatureHelpRequest( - CodeText: "var r = CallScript(\"Calc\", 1, ", + CodeText: "var r = Instance.CallScript(\"Calc\", 1, ", Line: 1, - Column: 31, + Column: 40, SiblingScripts: siblings)); - Assert.NotNull(resp.Label); + Assert.Equal("Instance.CallScript(\"Calc\", x: Integer, y: Float)", resp.Label); Assert.Equal(2, resp.Parameters!.Count); Assert.Equal("x: Integer", resp.Parameters[0].Label); Assert.Equal("y: Float", resp.Parameters[1].Label); @@ -310,18 +300,6 @@ public class ScriptAnalysisServiceTests // ── Inlay hints ─────────────────────────────────────────────────────── - [Fact] - public void InlayHints_OnCallScript_EmitsParameterLabels() - { - var siblings = new[] { Shape("Calc", Param("x"), Param("y")) }; - var resp = _svc.InlayHints(new InlayHintsRequest( - Code: "var r = CallScript(\"Calc\", 1, 2);", - SiblingScripts: siblings)); - Assert.Equal(2, resp.Hints.Count); - Assert.Equal("x:", resp.Hints[0].Label); - Assert.Equal("y:", resp.Hints[1].Label); - } - [Fact] public void InlayHints_OnUnknownSibling_Skipped() { @@ -333,26 +311,6 @@ public class ScriptAnalysisServiceTests // ── Argument-type diagnostic (SCADA005) ─────────────────────────────── - [Fact] - public void ArgumentTypeMismatch_StringExpectedIntegerGiven() - { - var siblings = new[] { Shape("Greet", Param("name", "String")) }; - var resp = _svc.Diagnose(new DiagnoseRequest( - Code: "var r = CallScript(\"Greet\", 42);", - SiblingScripts: siblings)); - Assert.Contains(resp.Markers, m => m.Code == "SCADA005" && m.Message.Contains("String")); - } - - [Fact] - public void ArgumentTypeMismatch_IntegerExpectedStringGiven() - { - var siblings = new[] { Shape("Calc", Param("n", "Integer")) }; - var resp = _svc.Diagnose(new DiagnoseRequest( - Code: "var r = CallScript(\"Calc\", \"oops\");", - SiblingScripts: siblings)); - Assert.Contains(resp.Markers, m => m.Code == "SCADA005"); - } - [Fact] public void ArgumentType_FloatAcceptsInteger() {