test(adminui): migrate AdminUI.Tests to v3 greenfield schema + Batch-1 stubs
Migrate tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests (was 358 build errors) to the v3 Raw-only Tag schema and the Batch-1 AdminUI stubs. Production untouched. - Driver-page serialization tests: drop the retired pre-declared Tags editor (page *TagRow types + DriverOptions.Tags); multi-device pages keep their Devices editor (ToOptions(devices)). Enum-serialization round-trip coverage (CpuType/ModbusFamily/MelsecFamily/AbCipPlcFamily/AbLegacyPlcFamily/FocasCncSeries) preserved intact. - UnsTreeTestDb: reseed to v3 (Device->Tag raw slice, no EquipmentId/DriverInstanceId on Tag, no Namespace). - UnsTreeService tag tests: assert Batch-1 stubs (CreateTag/UpdateTag refusal, empty tag/tag-driver lists); DeleteTag stays live against a raw Tag. - Equipment #122 guard retained (validates input driver vs line cluster); drop the retired persisted-binding assertions + NamespaceId seeds. Area/Line #122 driver- orphan guard retired -> assert cross-cluster move now succeeds. - DeleteCluster: drop the deleted-Namespace child-check test. - OpcUaClientTagConfigModel/TagConfigValidator: address key FullName -> nodeId. - ScriptTagCatalog: project surviving Name/DataType/TagConfig; DriverInstanceId null. - VirtualTag {{equip}} equipment-tag-derived base is dark -> 3 tests skipped (Batch-3). Result: build green; 507 passed / 3 skipped / 0 failed.
This commit is contained in:
@@ -87,10 +87,15 @@ public sealed class UnsTreeServiceAreaLineTests
|
||||
area.ClusterId.ShouldBe("MAIN");
|
||||
}
|
||||
|
||||
/// <summary>The #122 guard blocks moving an area to a new cluster when driver-bound
|
||||
/// equipment would be orphaned from its driver's cluster.</summary>
|
||||
/// <summary>
|
||||
/// v3 Batch-1: the decision-#122 driver-orphan guard was RETIRED — equipment no longer binds a
|
||||
/// driver (<c>Equipment.DriverInstanceId</c> is gone), so a cluster move can never orphan
|
||||
/// driver-bound equipment. The former blocked/allowed guard tests are replaced by this one, which
|
||||
/// proves a cross-cluster area reassignment now succeeds unconditionally (equipment under the area
|
||||
/// rides along). The equipment↔driver cluster invariant is re-covered by the Batch-2 Raw-tree tests.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task UpdateArea_reassign_cluster_blocked_when_driver_bound_equipment_would_orphan()
|
||||
public async Task UpdateArea_reassign_cluster_now_allowed_guard_retired()
|
||||
{
|
||||
var (service, dbName) = Fresh();
|
||||
|
||||
@@ -106,16 +111,6 @@ public sealed class UnsTreeServiceAreaLineTests
|
||||
UnsLineId = "LINE-X",
|
||||
Name = "m",
|
||||
MachineCode = "machine_x",
|
||||
DriverInstanceId = "DRV-MAIN",
|
||||
});
|
||||
db.DriverInstances.Add(new DriverInstance
|
||||
{
|
||||
DriverInstanceId = "DRV-MAIN",
|
||||
ClusterId = "MAIN",
|
||||
NamespaceId = "NS-1",
|
||||
Name = "drv",
|
||||
DriverType = "Modbus",
|
||||
DriverConfig = "{}",
|
||||
});
|
||||
db.SaveChanges();
|
||||
rv = db.UnsAreas.Single(a => a.UnsAreaId == "AREA-X").RowVersion;
|
||||
@@ -123,97 +118,12 @@ public sealed class UnsTreeServiceAreaLineTests
|
||||
|
||||
var result = await service.UpdateAreaAsync("AREA-X", "a", null, "SITE-A", rv);
|
||||
|
||||
result.Ok.ShouldBeFalse();
|
||||
result.Error.ShouldNotBeNull();
|
||||
result.Error.ShouldContain("decision #122");
|
||||
result.Error.ShouldContain("EQ-BOUND");
|
||||
result.Error.ShouldContain("SITE-A");
|
||||
result.Error.ShouldContain("MAIN");
|
||||
|
||||
// The area must not have been moved.
|
||||
using var verify = UnsTreeTestDb.CreateNamed(dbName);
|
||||
verify.UnsAreas.Single(a => a.UnsAreaId == "AREA-X").ClusterId.ShouldBe("MAIN");
|
||||
}
|
||||
|
||||
/// <summary>The #122 guard allows the move when the area's driver-bound equipment's driver
|
||||
/// is already in the target cluster (driverCluster == newClusterId → no orphan).</summary>
|
||||
[Fact]
|
||||
public async Task UpdateArea_reassign_cluster_allowed_when_driver_is_in_target_cluster()
|
||||
{
|
||||
// Seed: AREA-Z in cluster MAIN, a line, equipment bound to DRV-SITE-A whose cluster is
|
||||
// SITE-A. Reassigning the area to SITE-A must be allowed because the driver is already
|
||||
// there — the #122 guard's `driverCluster != newClusterId` condition is false.
|
||||
var (service, dbName) = Fresh();
|
||||
|
||||
byte[] rv;
|
||||
using (var db = UnsTreeTestDb.CreateNamed(dbName))
|
||||
{
|
||||
db.UnsAreas.Add(new UnsArea { UnsAreaId = "AREA-Z", ClusterId = "MAIN", Name = "a" });
|
||||
db.UnsLines.Add(new UnsLine { UnsLineId = "LINE-Z", UnsAreaId = "AREA-Z", Name = "l" });
|
||||
db.DriverInstances.Add(new DriverInstance
|
||||
{
|
||||
DriverInstanceId = "DRV-SITE-A",
|
||||
ClusterId = "SITE-A",
|
||||
NamespaceId = "NS-1",
|
||||
Name = "drv",
|
||||
DriverType = "Modbus",
|
||||
DriverConfig = "{}",
|
||||
});
|
||||
db.Equipment.Add(new Equipment
|
||||
{
|
||||
EquipmentId = "EQ-BOUND-Z",
|
||||
EquipmentUuid = Guid.NewGuid(),
|
||||
UnsLineId = "LINE-Z",
|
||||
Name = "m",
|
||||
MachineCode = "machine_z",
|
||||
DriverInstanceId = "DRV-SITE-A",
|
||||
});
|
||||
db.SaveChanges();
|
||||
rv = db.UnsAreas.Single(a => a.UnsAreaId == "AREA-Z").RowVersion;
|
||||
}
|
||||
|
||||
var result = await service.UpdateAreaAsync("AREA-Z", "a", null, "SITE-A", rv);
|
||||
|
||||
result.Ok.ShouldBeTrue();
|
||||
result.Error.ShouldBeNull();
|
||||
|
||||
// Verify the area actually moved to SITE-A via a fresh context.
|
||||
// The area moved to SITE-A.
|
||||
using var verify = UnsTreeTestDb.CreateNamed(dbName);
|
||||
verify.UnsAreas.Single(a => a.UnsAreaId == "AREA-Z").ClusterId.ShouldBe("SITE-A");
|
||||
}
|
||||
|
||||
/// <summary>The #122 guard allows the move when the equipment under the area is driver-less
|
||||
/// (DriverInstanceId == null).</summary>
|
||||
[Fact]
|
||||
public async Task UpdateArea_reassign_cluster_allowed_when_equipment_driverless()
|
||||
{
|
||||
var (service, dbName) = Fresh();
|
||||
|
||||
byte[] rv;
|
||||
using (var db = UnsTreeTestDb.CreateNamed(dbName))
|
||||
{
|
||||
db.UnsAreas.Add(new UnsArea { UnsAreaId = "AREA-Y", ClusterId = "MAIN", Name = "a" });
|
||||
db.UnsLines.Add(new UnsLine { UnsLineId = "LINE-Y", UnsAreaId = "AREA-Y", Name = "l" });
|
||||
db.Equipment.Add(new Equipment
|
||||
{
|
||||
EquipmentId = "EQ-FREE",
|
||||
EquipmentUuid = Guid.NewGuid(),
|
||||
UnsLineId = "LINE-Y",
|
||||
Name = "m",
|
||||
MachineCode = "machine_y",
|
||||
DriverInstanceId = null,
|
||||
});
|
||||
db.SaveChanges();
|
||||
rv = db.UnsAreas.Single(a => a.UnsAreaId == "AREA-Y").RowVersion;
|
||||
}
|
||||
|
||||
var result = await service.UpdateAreaAsync("AREA-Y", "a", null, "SITE-A", rv);
|
||||
|
||||
result.Ok.ShouldBeTrue();
|
||||
result.Error.ShouldBeNull();
|
||||
|
||||
using var verify = UnsTreeTestDb.CreateNamed(dbName);
|
||||
verify.UnsAreas.Single(a => a.UnsAreaId == "AREA-Y").ClusterId.ShouldBe("SITE-A");
|
||||
verify.UnsAreas.Single(a => a.UnsAreaId == "AREA-X").ClusterId.ShouldBe("SITE-A");
|
||||
}
|
||||
|
||||
/// <summary>Updating an area that no longer exists returns the row-gone error.</summary>
|
||||
@@ -337,30 +247,22 @@ public sealed class UnsTreeServiceAreaLineTests
|
||||
result.Error.ShouldBe("Row no longer exists.");
|
||||
}
|
||||
|
||||
/// <summary>The #122 guard blocks reparenting a line to an area in a different cluster when
|
||||
/// the line's equipment is driver-bound (the driver lives in the original cluster).</summary>
|
||||
/// <summary>
|
||||
/// v3 Batch-1: the decision-#122 driver-orphan guard was RETIRED (equipment no longer binds a
|
||||
/// driver). The former blocked/allowed line-reparent guard tests are replaced by this one, which
|
||||
/// proves reparenting a line to an area in a different cluster now succeeds unconditionally.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task UpdateLine_reparent_to_other_cluster_blocked_when_driver_bound()
|
||||
public async Task UpdateLine_reparent_to_other_cluster_now_allowed_guard_retired()
|
||||
{
|
||||
var (service, dbName) = Fresh();
|
||||
|
||||
byte[] rv;
|
||||
using (var db = UnsTreeTestDb.CreateNamed(dbName))
|
||||
{
|
||||
// Source area A1 in cluster MAIN.
|
||||
db.UnsAreas.Add(new UnsArea { UnsAreaId = "A1-MAIN", ClusterId = "MAIN", Name = "area-main" });
|
||||
// Target area A2 in cluster SITE-A.
|
||||
db.UnsAreas.Add(new UnsArea { UnsAreaId = "A2-SITE-A", ClusterId = "SITE-A", Name = "area-site-a" });
|
||||
db.UnsLines.Add(new UnsLine { UnsLineId = "LINE-BOUND", UnsAreaId = "A1-MAIN", Name = "line" });
|
||||
db.DriverInstances.Add(new DriverInstance
|
||||
{
|
||||
DriverInstanceId = "DRV-MAIN-122",
|
||||
ClusterId = "MAIN",
|
||||
NamespaceId = "NS-1",
|
||||
Name = "drv",
|
||||
DriverType = "Modbus",
|
||||
DriverConfig = "{}",
|
||||
});
|
||||
db.Equipment.Add(new Equipment
|
||||
{
|
||||
EquipmentId = "EQ-LINE-BOUND",
|
||||
@@ -368,7 +270,6 @@ public sealed class UnsTreeServiceAreaLineTests
|
||||
UnsLineId = "LINE-BOUND",
|
||||
Name = "eq",
|
||||
MachineCode = "mc_line_bound",
|
||||
DriverInstanceId = "DRV-MAIN-122",
|
||||
});
|
||||
db.SaveChanges();
|
||||
rv = db.UnsLines.Single(l => l.UnsLineId == "LINE-BOUND").RowVersion;
|
||||
@@ -376,52 +277,12 @@ public sealed class UnsTreeServiceAreaLineTests
|
||||
|
||||
var result = await service.UpdateLineAsync("LINE-BOUND", "line", null, "A2-SITE-A", rv);
|
||||
|
||||
result.Ok.ShouldBeFalse();
|
||||
result.Error.ShouldNotBeNull();
|
||||
result.Error.ShouldContain("decision #122");
|
||||
result.Error.ShouldContain("EQ-LINE-BOUND");
|
||||
result.Error.ShouldContain("A2-SITE-A");
|
||||
result.Error.ShouldContain("MAIN");
|
||||
|
||||
// The line must not have moved.
|
||||
using var verify = UnsTreeTestDb.CreateNamed(dbName);
|
||||
verify.UnsLines.Single(l => l.UnsLineId == "LINE-BOUND").UnsAreaId.ShouldBe("A1-MAIN");
|
||||
}
|
||||
|
||||
/// <summary>The #122 guard allows reparenting a line to an area in a different cluster when
|
||||
/// the line's equipment is driver-less (DriverInstanceId == null).</summary>
|
||||
[Fact]
|
||||
public async Task UpdateLine_reparent_to_other_cluster_allowed_when_equipment_driverless()
|
||||
{
|
||||
var (service, dbName) = Fresh();
|
||||
|
||||
byte[] rv;
|
||||
using (var db = UnsTreeTestDb.CreateNamed(dbName))
|
||||
{
|
||||
db.UnsAreas.Add(new UnsArea { UnsAreaId = "A1-FREE", ClusterId = "MAIN", Name = "area-main" });
|
||||
db.UnsAreas.Add(new UnsArea { UnsAreaId = "A2-FREE", ClusterId = "SITE-A", Name = "area-site-a" });
|
||||
db.UnsLines.Add(new UnsLine { UnsLineId = "LINE-FREE", UnsAreaId = "A1-FREE", Name = "line" });
|
||||
db.Equipment.Add(new Equipment
|
||||
{
|
||||
EquipmentId = "EQ-LINE-FREE",
|
||||
EquipmentUuid = Guid.NewGuid(),
|
||||
UnsLineId = "LINE-FREE",
|
||||
Name = "eq",
|
||||
MachineCode = "mc_line_free",
|
||||
DriverInstanceId = null,
|
||||
});
|
||||
db.SaveChanges();
|
||||
rv = db.UnsLines.Single(l => l.UnsLineId == "LINE-FREE").RowVersion;
|
||||
}
|
||||
|
||||
var result = await service.UpdateLineAsync("LINE-FREE", "line", null, "A2-FREE", rv);
|
||||
|
||||
result.Ok.ShouldBeTrue();
|
||||
result.Error.ShouldBeNull();
|
||||
|
||||
// The line's UnsAreaId must have changed to A2-FREE.
|
||||
// The line moved to the target area.
|
||||
using var verify = UnsTreeTestDb.CreateNamed(dbName);
|
||||
verify.UnsLines.Single(l => l.UnsLineId == "LINE-FREE").UnsAreaId.ShouldBe("A2-FREE");
|
||||
verify.UnsLines.Single(l => l.UnsLineId == "LINE-BOUND").UnsAreaId.ShouldBe("A2-SITE-A");
|
||||
}
|
||||
|
||||
// ----- DeleteLine -----
|
||||
|
||||
Reference in New Issue
Block a user