using Xunit; using Moq; using FluentAssertions; using Haoliang.Core.Services; using Haoliang.Models.Template; using Haoliang.Data.Repositories; namespace Haoliang.Tests; public class TemplateServiceTests { private readonly Mock _mockTemplateRepository; private readonly TemplateService _templateService; public TemplateServiceTests() { _mockTemplateRepository = new Mock(); _templateService = new TemplateService(_mockTemplateRepository.Object); } [Fact] public async Task GetAllTemplatesAsync_ReturnsTemplatesFromRepository() { var templates = new List { new CNCBrandTemplate { Id = 1, BrandName = "Fanuc", Description = "Fanuc CNC" }, new CNCBrandTemplate { Id = 2, BrandName = "Mitsubishi", Description = "Mitsubishi CNC" } }; _mockTemplateRepository.Setup(r => r.GetAllAsync()).ReturnsAsync(templates); var result = await _templateService.GetAllTemplatesAsync(); result.Should().HaveCount(2); result.Should().BeEquivalentTo(templates); } [Fact] public async Task GetTemplateByIdAsync_ReturnsTemplate_WhenExists() { var template = new CNCBrandTemplate { Id = 1, BrandName = "Fanuc", Description = "Fanuc CNC" }; _mockTemplateRepository.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(template); var result = await _templateService.GetTemplateByIdAsync(1); result.Should().NotBeNull(); result!.BrandName.Should().Be("Fanuc"); } [Fact] public async Task GetTemplateByIdAsync_ReturnsNull_WhenNotExists() { _mockTemplateRepository.Setup(r => r.GetByIdAsync(999)).ReturnsAsync((CNCBrandTemplate?)null); var result = await _templateService.GetTemplateByIdAsync(999); result.Should().BeNull(); } [Fact] public async Task CreateTemplateAsync_SetsCreatedAtUpdatedAtAndIsEnabled() { var template = new CNCBrandTemplate { BrandName = "NewBrand", Description = "New CNC" }; _mockTemplateRepository.Setup(r => r.AddAsync(It.IsAny())).Returns(Task.CompletedTask); _mockTemplateRepository.Setup(r => r.SaveAsync()).ReturnsAsync(1); var beforeCreate = DateTime.Now; var result = await _templateService.CreateTemplateAsync(template); var afterCreate = DateTime.Now; result.CreatedAt.Should().BeOnOrAfter(beforeCreate); result.CreatedAt.Should().BeOnOrBefore(afterCreate); result.UpdatedAt.Should().BeOnOrAfter(beforeCreate); result.UpdatedAt.Should().BeOnOrBefore(afterCreate); result.IsEnabled.Should().BeTrue(); } [Fact] public async Task UpdateTemplateAsync_UpdatesTemplate_WhenExists() { var existing = new CNCBrandTemplate { Id = 1, BrandName = "Original", Description = "Original Desc" }; _mockTemplateRepository.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(existing); _mockTemplateRepository.Setup(r => r.Update(It.IsAny())).Verifiable(); _mockTemplateRepository.Setup(r => r.SaveAsync()).ReturnsAsync(1); var updated = await _templateService.UpdateTemplateAsync(1, new CNCBrandTemplate { BrandName = "Updated", Description = "Updated Desc" }); updated.Should().NotBeNull(); updated!.BrandName.Should().Be("Updated"); updated.Description.Should().Be("Updated Desc"); } [Fact] public async Task UpdateTemplateAsync_ReturnsNull_WhenNotExists() { _mockTemplateRepository.Setup(r => r.GetByIdAsync(999)).ReturnsAsync((CNCBrandTemplate?)null); var result = await _templateService.UpdateTemplateAsync(999, new CNCBrandTemplate()); result.Should().BeNull(); } [Fact] public async Task DeleteTemplateAsync_ReturnsTrue_WhenTemplateExists() { var template = new CNCBrandTemplate { Id = 1 }; _mockTemplateRepository.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(template); _mockTemplateRepository.Setup(r => r.Remove(template)).Verifiable(); _mockTemplateRepository.Setup(r => r.SaveAsync()).ReturnsAsync(1); var result = await _templateService.DeleteTemplateAsync(1); result.Should().BeTrue(); } [Fact] public async Task DeleteTemplateAsync_ReturnsFalse_WhenTemplateNotExists() { _mockTemplateRepository.Setup(r => r.GetByIdAsync(999)).ReturnsAsync((CNCBrandTemplate?)null); var result = await _templateService.DeleteTemplateAsync(999); result.Should().BeFalse(); } [Fact] public async Task EnableTemplateAsync_CallsUpdateTemplateEnabled() { _mockTemplateRepository.Setup(r => r.UpdateTemplateEnabledAsync(1, true)).Returns(Task.CompletedTask); var result = await _templateService.EnableTemplateAsync(1); result.Should().BeTrue(); _mockTemplateRepository.Verify(r => r.UpdateTemplateEnabledAsync(1, true), Times.Once); } [Fact] public async Task DisableTemplateAsync_CallsUpdateTemplateEnabled() { _mockTemplateRepository.Setup(r => r.UpdateTemplateEnabledAsync(1, false)).Returns(Task.CompletedTask); var result = await _templateService.DisableTemplateAsync(1); result.Should().BeTrue(); _mockTemplateRepository.Verify(r => r.UpdateTemplateEnabledAsync(1, false), Times.Once); } [Fact] public async Task CloneTemplateAsync_CreatesCopyWithNewName() { var original = new CNCBrandTemplate { Id = 1, BrandName = "Original", Description = "Original Description", FieldMappings = new List { new TemplateFieldMapping { SourceFieldPath = "tag1", StandardFieldId = "Status" } } }; _mockTemplateRepository.Setup(r => r.GetByIdAsync(1)).ReturnsAsync(original); _mockTemplateRepository.Setup(r => r.AddAsync(It.IsAny())).Returns(Task.CompletedTask); _mockTemplateRepository.Setup(r => r.SaveAsync()).ReturnsAsync(1); var result = await _templateService.CloneTemplateAsync(1, "ClonedTemplate"); result.Should().NotBeNull(); result!.BrandName.Should().Be("ClonedTemplate"); result.Description.Should().Be("Original Description (Cloned)"); result.FieldMappings.Should().HaveCount(1); result.IsEnabled.Should().BeFalse(); } [Fact] public async Task CloneTemplateAsync_ReturnsNull_WhenOriginalNotExists() { _mockTemplateRepository.Setup(r => r.GetByIdAsync(999)).ReturnsAsync((CNCBrandTemplate?)null); var result = await _templateService.CloneTemplateAsync(999, "NewName"); result.Should().BeNull(); } [Fact] public async Task GetTemplatesByBrandAsync_ReturnsMatchingTemplates() { var templates = new List { new CNCBrandTemplate { Id = 1, BrandName = "Fanuc" } }; _mockTemplateRepository.Setup(r => r.FindAsync(t => t.BrandName == "Fanuc")).ReturnsAsync(templates); var result = await _templateService.GetTemplatesByBrandAsync("Fanuc"); result.Should().HaveCount(1); } [Fact] public async Task GetActiveTemplatesAsync_ReturnsEnabledTemplates() { var activeTemplates = new List { new CNCBrandTemplate { Id = 1, BrandName = "Fanuc", IsEnabled = true } }; _mockTemplateRepository.Setup(r => r.GetEnabledTemplatesAsync()).ReturnsAsync(activeTemplates); var result = await _templateService.GetActiveTemplatesAsync(); result.Should().HaveCount(1); } [Fact] public async Task ValidateTemplateAsync_ReturnsTrue() { var template = new CNCBrandTemplate { BrandName = "Test", Description = "Test" }; var result = await _templateService.ValidateTemplateAsync(template); result.Should().BeTrue(); } [Fact] public async Task TestTemplateAsync_Completes() { await _templateService.TestTemplateAsync(1); } }