using Microsoft.EntityFrameworkCore; using ZB.MOM.WW.ScadaBridge.Commons.Entities.Schemas; using ZB.MOM.WW.ScadaBridge.ConfigurationDatabase; using ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Repositories; using Xunit; namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests; /// /// Round-trip tests for (M9 template-level JSON-Schema /// library, Task T32a). Uses the in-memory SQLite harness () /// — the schema is materialized via EnsureCreated() from the same model the /// migration was generated from, so the tests run unconditionally (no live MSSQL needed) /// while still exercising the real unique-Name index. Mirrors the /// SecurityRepositoryTests in-memory harness shape. /// public class SharedSchemaRepositoryTests : IDisposable { private readonly ScadaBridgeDbContext _context; private readonly SharedSchemaRepository _repository; public SharedSchemaRepositoryTests() { _context = SqliteTestHelper.CreateInMemoryContext(); _repository = new SharedSchemaRepository(_context); } public void Dispose() { _context.Database.CloseConnection(); _context.Dispose(); } [Fact] public async Task Add_ThenGetByName_RoundTrips() { var schema = new SharedSchema { Name = "TankReading", Scope = "Plant", SchemaJson = "{\"type\":\"object\",\"properties\":{\"level\":{\"type\":\"number\"}}}", }; var id = await _repository.AddAsync(schema); Assert.True(id > 0, "AddAsync should return the store-generated identity."); var byName = await _repository.GetByNameAsync("TankReading"); Assert.NotNull(byName); Assert.Equal(id, byName!.Id); Assert.Equal("TankReading", byName.Name); Assert.Equal("Plant", byName.Scope); Assert.Equal( "{\"type\":\"object\",\"properties\":{\"level\":{\"type\":\"number\"}}}", byName.SchemaJson); var byId = await _repository.GetByIdAsync(id); Assert.NotNull(byId); Assert.Equal("TankReading", byId!.Name); } [Fact] public async Task GetByName_Unknown_ReturnsNull() { var missing = await _repository.GetByNameAsync("DoesNotExist"); Assert.Null(missing); } [Fact] public async Task Add_DuplicateName_Throws() { await _repository.AddAsync(new SharedSchema { Name = "Dup", SchemaJson = "{}" }); // The UNIQUE index on Name must reject the second insert. await Assert.ThrowsAnyAsync(() => _repository.AddAsync(new SharedSchema { Name = "Dup", SchemaJson = "{}" })); } [Fact] public async Task NullableScope_RoundTrips() { var id = await _repository.AddAsync(new SharedSchema { Name = "NoScope", SchemaJson = "{}" }); var loaded = await _repository.GetByIdAsync(id); Assert.NotNull(loaded); Assert.Null(loaded!.Scope); } [Fact] public async Task List_ReturnsAll_OrderedByName() { await _repository.AddAsync(new SharedSchema { Name = "Bravo", SchemaJson = "{}" }); await _repository.AddAsync(new SharedSchema { Name = "Alpha", SchemaJson = "{}" }); var all = await _repository.ListAsync(); Assert.Equal(2, all.Count); Assert.Equal("Alpha", all[0].Name); Assert.Equal("Bravo", all[1].Name); } [Fact] public async Task Update_PersistsChanges() { var id = await _repository.AddAsync(new SharedSchema { Name = "Edit", SchemaJson = "{}" }); var loaded = await _repository.GetByIdAsync(id); Assert.NotNull(loaded); loaded!.SchemaJson = "{\"type\":\"string\"}"; loaded.Scope = "Updated"; await _repository.UpdateAsync(loaded); var reloaded = await _repository.GetByIdAsync(id); Assert.NotNull(reloaded); Assert.Equal("{\"type\":\"string\"}", reloaded!.SchemaJson); Assert.Equal("Updated", reloaded.Scope); } [Fact] public async Task Delete_RemovesRow() { var id = await _repository.AddAsync(new SharedSchema { Name = "ToDelete", SchemaJson = "{}" }); await _repository.DeleteAsync(id); Assert.Null(await _repository.GetByIdAsync(id)); } }