using System.Security.Cryptography; using System.Text; using Microsoft.EntityFrameworkCore; using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.AdminUI.Uns; namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Uns; /// /// Verifies — the create-new-script path the inline /// virtual-tag panel calls when no script is bound yet. A new Script row is inserted with a /// system-generated SC-… id (mirroring the Script-edit page convention), a blank source, a /// hash matching that blank source, and the CSharp language; the new id is returned via /// so the panel can bind the virtual tag to it. Two calls /// produce two distinct rows with distinct ids. /// [Trait("Category", "Unit")] public sealed class UnsTreeServiceCreateScriptTests { private static (UnsTreeService Service, string DbName) Fresh() { var dbName = $"uns-createscript-{Guid.NewGuid():N}"; return (new UnsTreeService(UnsTreeTestDb.Factory(dbName)), dbName); } private static string HashOf(string source) => Convert.ToHexStringLower(SHA256.HashData(Encoding.UTF8.GetBytes(source))); /// /// A create inserts exactly one Script row carrying a non-empty generated id, the expected blank /// source + matching hash, the CSharp language, and a name; the generated id is echoed back. /// [Fact] public async Task CreateScript_inserts_one_row_with_generated_id_and_blank_source() { var (service, dbName) = Fresh(); var result = await service.CreateScriptAsync("my new script"); result.Ok.ShouldBeTrue(); result.Error.ShouldBeNull(); result.CreatedId.ShouldNotBeNullOrWhiteSpace(); result.CreatedId!.ShouldStartWith("SC-"); using var db = UnsTreeTestDb.CreateNamed(dbName); db.Scripts.Count().ShouldBe(1); var script = db.Scripts.Single(); script.ScriptId.ShouldBe(result.CreatedId); script.Name.ShouldBe("my new script"); script.SourceCode.ShouldBe(""); script.SourceHash.ShouldBe(HashOf("")); script.Language.ShouldBe("CSharp"); } /// A whitespace/empty name falls back to a sensible non-empty default. [Fact] public async Task CreateScript_blank_name_uses_a_default_name() { var (service, dbName) = Fresh(); var result = await service.CreateScriptAsync(" "); result.Ok.ShouldBeTrue(); using var db = UnsTreeTestDb.CreateNamed(dbName); db.Scripts.Single().Name.ShouldNotBeNullOrWhiteSpace(); } /// Two creates insert two rows with distinct, non-empty ids. [Fact] public async Task CreateScript_twice_produces_distinct_ids() { var (service, dbName) = Fresh(); var first = await service.CreateScriptAsync("first"); var second = await service.CreateScriptAsync("second"); first.Ok.ShouldBeTrue(); second.Ok.ShouldBeTrue(); first.CreatedId.ShouldNotBe(second.CreatedId); using var db = UnsTreeTestDb.CreateNamed(dbName); db.Scripts.Count().ShouldBe(2); db.Scripts.Select(s => s.ScriptId).Distinct().Count().ShouldBe(2); } }