using System.Text.Json; namespace ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests; /// Verifies worker publication and termination in the deployed Linux runtime image. [Collection("Playwright")] public class SandboxWorkerDeploymentTests(PlaywrightFixture fixture) { /// Verifies that the worker runs scripts, bounds their output and recovers after a noncooperative script. /// A task that represents the asynchronous operation. [Fact] public async Task Medium_WorkerRunsBoundsOutputAndRecoversAfterNoncooperativeScript() { var page = await fixture.NewAuthenticatedPageAsync(); try { async Task Run(string code) => await page.EvaluateAsync(""" async code => { const response = await fetch('/api/script-analysis/run', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code, timeoutSeconds: 10 }) }); if (!response.ok) throw new Error(`Test Run HTTP ${response.status}`); return await response.json(); } """, code); var first = await Run("return 42;"); Assert.True(first.GetProperty("success").GetBoolean(), first.ToString()); Assert.Equal("42", first.GetProperty("returnValueJson").GetString()); var bounded = await Run("Console.Write(new string('x', 100000)); return new string('y', 100000);"); Assert.True(bounded.GetProperty("consoleOutput").GetString()!.Length <= 32768 + "\n… (truncated)".Length); Assert.Contains("truncated", bounded.GetProperty("consoleOutput").GetString()); Assert.True(bounded.GetRawText().Length < 100000); var timeout = await Run("while (true) { }"); Assert.False(timeout.GetProperty("success").GetBoolean()); Assert.Equal(4, timeout.GetProperty("errorKind").GetInt32()); var recovered = await Run("return 43;"); Assert.True(recovered.GetProperty("success").GetBoolean(), recovered.ToString()); Assert.Equal("43", recovered.GetProperty("returnValueJson").GetString()); } finally { await page.CloseAsync(); } } }