using Microsoft.Data.Sqlite; using Scry.Core.Data; using Scry.Core.Models; using Xunit; namespace Scry.Tests; public class CardHashDatabaseTests : IDisposable { private readonly string _dbPath; private readonly CardHashDatabase _database; public CardHashDatabaseTests() { _dbPath = Path.Combine(Path.GetTempPath(), $"scry_test_{Guid.NewGuid()}.db"); _database = new CardHashDatabase(_dbPath); } [Fact] public async Task InsertHash_ThenRetrieve_ReturnsMatch() { var hash = new CardHash { CardId = "test-id", Name = "Test Card", SetCode = "TST", CollectorNumber = "1", Hash = new byte[] { 0x01, 0x02, 0x03 }, ImageUri = "https://example.com/image.jpg" }; await _database.InsertHashAsync(hash); var retrieved = await _database.GetHashByIdAsync("test-id"); Assert.NotNull(retrieved); Assert.Equal("Test Card", retrieved.Name); Assert.Equal("TST", retrieved.SetCode); Assert.Equal(hash.Hash, retrieved.Hash); } [Fact] public async Task InsertHashBatch_InsertsAllHashes() { var hashes = Enumerable.Range(0, 100).Select(i => new CardHash { CardId = $"card-{i}", Name = $"Card {i}", SetCode = "TST", Hash = new byte[] { (byte)i } }).ToList(); await _database.InsertHashBatchAsync(hashes); var count = await _database.GetHashCountAsync(); Assert.Equal(100, count); } [Fact] public async Task GetAllHashes_ReturnsAllHashes() { var hashes = Enumerable.Range(0, 10).Select(i => new CardHash { CardId = $"card-{i}", Name = $"Card {i}", SetCode = "TST", Hash = new byte[] { (byte)i } }).ToList(); await _database.InsertHashBatchAsync(hashes); var all = await _database.GetAllHashesAsync(); Assert.Equal(10, all.Count); } [Fact] public async Task Metadata_SetAndGet() { await _database.SetMetadataAsync("test_key", "test_value"); var value = await _database.GetMetadataAsync("test_key"); Assert.Equal("test_value", value); } [Fact] public async Task Clear_RemovesAllHashes() { var hashes = Enumerable.Range(0, 10).Select(i => new CardHash { CardId = $"card-{i}", Name = $"Card {i}", SetCode = "TST", Hash = new byte[] { (byte)i } }).ToList(); await _database.InsertHashBatchAsync(hashes); await _database.ClearAsync(); var count = await _database.GetHashCountAsync(); Assert.Equal(0, count); } [Fact] public async Task InsertHash_DuplicateId_Updates() { var hash1 = new CardHash { CardId = "duplicate-id", Name = "Original Name", SetCode = "TST", Hash = new byte[] { 0x01 } }; var hash2 = new CardHash { CardId = "duplicate-id", Name = "Updated Name", SetCode = "TST", Hash = new byte[] { 0x02 } }; await _database.InsertHashAsync(hash1); await _database.InsertHashAsync(hash2); var retrieved = await _database.GetHashByIdAsync("duplicate-id"); Assert.NotNull(retrieved); Assert.Equal("Updated Name", retrieved.Name); Assert.Equal(new byte[] { 0x02 }, retrieved.Hash); } public void Dispose() { _database.Dispose(); SqliteConnection.ClearAllPools(); try { if (File.Exists(_dbPath)) { File.Delete(_dbPath); } } catch (IOException) { } } }