test(adminui): DB-backed tests for ScriptTagCatalog.GetEquipmentRelativeLeavesAsync
This commit is contained in:
@@ -287,4 +287,85 @@ public sealed class ScriptTagCatalogTests
|
||||
(await catalog.GetTagInfoAsync("motor.speed", default)).ShouldBeNull();
|
||||
(await catalog.GetTagInfoAsync("Motor.Speed", default)).ShouldNotBeNull();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// GetEquipmentRelativeLeavesAsync — DB-backed tests
|
||||
// -----------------------------------------------------------------------
|
||||
// Seeded paths and their leaf derivation:
|
||||
// TAG-EQ → "Motor.Speed" → leaf "Speed"
|
||||
// TAG-SP → "DelmiaReceiver_001.DownloadPath" → leaf "DownloadPath"
|
||||
// VTAG-1 → "Computed" → NO dot → excluded
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/// <summary>A null filter returns one leaf per dot-bearing path; the no-dot virtual-tag path is excluded.</summary>
|
||||
[Fact]
|
||||
public async Task GetEquipmentRelativeLeaves_no_filter_returns_dot_bearing_leaves_only()
|
||||
{
|
||||
var (catalog, opts) = Fresh();
|
||||
Seed(opts);
|
||||
|
||||
var leaves = await catalog.GetEquipmentRelativeLeavesAsync(null, default);
|
||||
|
||||
// Leaves derived from the two dot-bearing paths in Seed().
|
||||
leaves.ShouldContain("Speed"); // from "Motor.Speed"
|
||||
leaves.ShouldContain("DownloadPath"); // from "DelmiaReceiver_001.DownloadPath"
|
||||
|
||||
// Virtual tag "Computed" has no dot — must be excluded.
|
||||
leaves.ShouldNotContain("Computed");
|
||||
}
|
||||
|
||||
/// <summary>A prefix filter narrows to leaves that start with the given string (e.g. "Sp" → "Speed", not "DownloadPath").</summary>
|
||||
[Fact]
|
||||
public async Task GetEquipmentRelativeLeaves_prefix_filter_narrows_to_matching_leaves()
|
||||
{
|
||||
var (catalog, opts) = Fresh();
|
||||
Seed(opts);
|
||||
|
||||
var leaves = await catalog.GetEquipmentRelativeLeavesAsync("Sp", default);
|
||||
|
||||
leaves.ShouldContain("Speed");
|
||||
leaves.ShouldNotContain("DownloadPath");
|
||||
leaves.ShouldAllBe(l => l.StartsWith("Sp", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>The prefix filter is case-insensitive: "sp" (lowercase) still matches the leaf "Speed".</summary>
|
||||
[Fact]
|
||||
public async Task GetEquipmentRelativeLeaves_prefix_filter_is_case_insensitive()
|
||||
{
|
||||
var (catalog, opts) = Fresh();
|
||||
Seed(opts);
|
||||
|
||||
var leaves = await catalog.GetEquipmentRelativeLeavesAsync("sp", default);
|
||||
|
||||
leaves.ShouldContain("Speed");
|
||||
}
|
||||
|
||||
/// <summary>Two paths sharing the same leaf after different object prefixes produce one distinct entry.</summary>
|
||||
[Fact]
|
||||
public async Task GetEquipmentRelativeLeaves_duplicate_leaves_are_deduplicated()
|
||||
{
|
||||
var (catalog, opts) = Fresh();
|
||||
Seed(opts);
|
||||
|
||||
// Add a second equipment tag whose FullName produces the same leaf "Speed" as TAG-EQ.
|
||||
using (var db = new OtOpcUaConfigDbContext(opts))
|
||||
{
|
||||
db.Tags.Add(new Tag
|
||||
{
|
||||
TagId = "TAG-EQ2",
|
||||
DriverInstanceId = "DRV-1",
|
||||
EquipmentId = "EQ-1",
|
||||
Name = "Speed2",
|
||||
DataType = "Float",
|
||||
AccessLevel = TagAccessLevel.Read,
|
||||
TagConfig = "{\"FullName\":\"Conveyor.Speed\"}",
|
||||
});
|
||||
db.SaveChanges();
|
||||
}
|
||||
|
||||
var leaves = await catalog.GetEquipmentRelativeLeavesAsync(null, default);
|
||||
|
||||
// "Speed" must appear exactly once despite being produced by two different paths.
|
||||
leaves.Count(l => string.Equals(l, "Speed", StringComparison.Ordinal)).ShouldBe(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user