b211911f98
v2-ci / unit-tests (push) Failing after 13m22s
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
74 lines
3.1 KiB
C#
74 lines
3.1 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Shouldly;
|
|
using Xunit;
|
|
using ZB.MOM.WW.OtOpcUa.AdminUI.ScriptList;
|
|
using ZB.MOM.WW.OtOpcUa.Configuration;
|
|
using ZB.MOM.WW.OtOpcUa.Configuration.Entities;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.ScriptList;
|
|
|
|
/// <summary>R04 P8: the <c>/scripts</c> list is a projection without source; source loads per dialog.</summary>
|
|
[Trait("Category", "Unit")]
|
|
public sealed class ScriptListQueriesTests
|
|
{
|
|
private static OtOpcUaConfigDbContext NewDb(string name) =>
|
|
new(new DbContextOptionsBuilder<OtOpcUaConfigDbContext>().UseInMemoryDatabase(name).Options);
|
|
|
|
private static async Task<string> SeedAsync()
|
|
{
|
|
var name = Guid.NewGuid().ToString("N");
|
|
await using var db = NewDb(name);
|
|
db.Scripts.AddRange(
|
|
new Script { ScriptId = "s-b", Name = "Beta", SourceCode = "return 2;", SourceHash = "hb" },
|
|
new Script { ScriptId = "s-a", Name = "Alpha", SourceCode = "return 1;", SourceHash = "ha", Language = "CSharp" });
|
|
await db.SaveChangesAsync();
|
|
return name;
|
|
}
|
|
|
|
[Fact]
|
|
public async Task LoadRowsAsync_returns_name_ordered_rows_without_source()
|
|
{
|
|
var name = await SeedAsync();
|
|
await using var db = NewDb(name);
|
|
|
|
var rows = await ScriptListQueries.LoadRowsAsync(db, TestContext.Current.CancellationToken);
|
|
|
|
rows.Select(r => r.ScriptId).ShouldBe(["s-a", "s-b"]);
|
|
rows[0].ShouldBe(new ScriptListRow("s-a", "Alpha", "CSharp", "ha"));
|
|
// The row type has no source member at all — the list cannot load it by accident.
|
|
typeof(ScriptListRow).GetProperty("SourceCode").ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task LoadSourceAsync_returns_one_scripts_source_or_null_when_gone()
|
|
{
|
|
var name = await SeedAsync();
|
|
await using var db = NewDb(name);
|
|
|
|
(await ScriptListQueries.LoadSourceAsync(db, "s-b", TestContext.Current.CancellationToken)).ShouldBe("return 2;");
|
|
(await ScriptListQueries.LoadSourceAsync(db, "missing", TestContext.Current.CancellationToken)).ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void Scripts_page_uses_the_projection()
|
|
{
|
|
var src = AdminUiSource.Read("Components", "Pages", "Scripts.razor");
|
|
src.ShouldContain("ScriptListQueries.LoadRowsAsync(");
|
|
src.ShouldNotContain("List<Script>");
|
|
}
|
|
|
|
[Fact]
|
|
public void Source_fetch_failure_is_shown_in_the_dialog_not_thrown()
|
|
{
|
|
// Review r0 M7 source pin: the fetch sits inside a try whose catch sets _sourceError.
|
|
var src = AdminUiSource.Read("Components", "Pages", "Scripts.razor");
|
|
var fetch = src.IndexOf("ScriptListQueries.LoadSourceAsync(", StringComparison.Ordinal);
|
|
var tryAt = src.LastIndexOf("try", fetch, StringComparison.Ordinal);
|
|
var catchAt = src.IndexOf("catch (Exception ex)", fetch, StringComparison.Ordinal);
|
|
tryAt.ShouldBeGreaterThan(src.IndexOf("private async Task ShowSource", StringComparison.Ordinal));
|
|
catchAt.ShouldBeGreaterThan(fetch);
|
|
src.IndexOf("_sourceError = ", catchAt, StringComparison.Ordinal).ShouldBeGreaterThan(catchAt);
|
|
src.ShouldContain("@_sourceError");
|
|
}
|
|
}
|