using System; using System.Collections.Generic; using System.Threading.Tasks; using FluentAssertions; using Microsoft.AspNetCore.Mvc; using Moq; using Xunit; using Haoliang.Api.Controllers; using Haoliang.Core.Services; using Haoliang.Models.Template; using Haoliang.Models.Device; namespace Haoliang.Tests.Controllers { public class TemplateControllerTests { private readonly Mock _templateService = new Mock(); private readonly Mock _tagMappingService = new Mock(); private readonly Mock _validationService = new Mock(); private readonly Mock _loggingService = new Mock(); private readonly TemplateController _controller; public TemplateControllerTests() { _controller = new TemplateController( _templateService.Object, _tagMappingService.Object, _validationService.Object, _loggingService.Object); } // 1. GetAllTemplates (2 tests) [Fact] public async Task GetAllTemplates_WhenSuccess_ReturnsOk() { _templateService.Setup(s => s.GetAllTemplatesAsync()).ReturnsAsync(new List()); var result = await _controller.GetAllTemplates(); result.Should().BeOfType(); } [Fact] public async Task GetAllTemplates_WhenException_Returns500() { _templateService.Setup(s => s.GetAllTemplatesAsync()).ThrowsAsync(new Exception("t")); var result = await _controller.GetAllTemplates(); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 2. GetTemplate (3 tests: found, not found, exception) [Fact] public async Task GetTemplate_WhenFound_ReturnsOk() { _templateService.Setup(s => s.GetTemplateByIdAsync(1)).ReturnsAsync(new CNCBrandTemplate()); var result = await _controller.GetTemplate(1); result.Should().BeOfType(); } [Fact] public async Task GetTemplate_WhenNotFound_Returns404() { _templateService.Setup(s => s.GetTemplateByIdAsync(1)).ReturnsAsync((CNCBrandTemplate?)null); var result = await _controller.GetTemplate(1); result.Should().BeOfType(); } [Fact] public async Task GetTemplate_WhenException_Returns500() { _templateService.Setup(s => s.GetTemplateByIdAsync(It.IsAny())).ThrowsAsync(new Exception("t")); var result = await _controller.GetTemplate(1); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 3. CreateTemplate (3 tests: success, validation fail, exception) [Fact] public async Task CreateTemplate_WhenValid_ReturnsOk() { _templateService.Setup(s => s.ValidateTemplateAsync(It.IsAny())).ReturnsAsync(true); _templateService.Setup(s => s.CreateTemplateAsync(It.IsAny())).ReturnsAsync(new CNCBrandTemplate()); var result = await _controller.CreateTemplate(new CNCBrandTemplate()); result.Should().BeOfType(); } [Fact] public async Task CreateTemplate_WhenValidationFails_ReturnsBadRequest() { _templateService.Setup(s => s.ValidateTemplateAsync(It.IsAny())).ReturnsAsync(false); var result = await _controller.CreateTemplate(new CNCBrandTemplate()); result.Should().BeOfType(); } [Fact] public async Task CreateTemplate_WhenException_Returns500() { _templateService.Setup(s => s.ValidateTemplateAsync(It.IsAny())).ThrowsAsync(new Exception("t")); var result = await _controller.CreateTemplate(new CNCBrandTemplate()); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 4. UpdateTemplate (4 tests: success, validation fail, not found, exception) [Fact] public async Task UpdateTemplate_WhenValid_ReturnsOk() { _templateService.Setup(s => s.ValidateTemplateAsync(It.IsAny())).ReturnsAsync(true); _templateService.Setup(s => s.UpdateTemplateAsync(1, It.IsAny())).ReturnsAsync(new CNCBrandTemplate()); var result = await _controller.UpdateTemplate(1, new CNCBrandTemplate()); result.Should().BeOfType(); } [Fact] public async Task UpdateTemplate_WhenValidationFails_ReturnsBadRequest() { _templateService.Setup(s => s.ValidateTemplateAsync(It.IsAny())).ReturnsAsync(false); var result = await _controller.UpdateTemplate(1, new CNCBrandTemplate()); result.Should().BeOfType(); } [Fact] public async Task UpdateTemplate_WhenNotFound_Returns404() { _templateService.Setup(s => s.ValidateTemplateAsync(It.IsAny())).ReturnsAsync(true); _templateService.Setup(s => s.UpdateTemplateAsync(1, It.IsAny())).ReturnsAsync((CNCBrandTemplate?)null); var result = await _controller.UpdateTemplate(1, new CNCBrandTemplate()); result.Should().BeOfType(); } [Fact] public async Task UpdateTemplate_WhenException_Returns500() { _templateService.Setup(s => s.ValidateTemplateAsync(It.IsAny())).ThrowsAsync(new Exception("t")); var result = await _controller.UpdateTemplate(1, new CNCBrandTemplate()); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 5. DeleteTemplate (3 tests: success, not found, exception) [Fact] public async Task DeleteTemplate_WhenSuccess_ReturnsOk() { _templateService.Setup(s => s.DeleteTemplateAsync(1)).ReturnsAsync(true); var result = await _controller.DeleteTemplate(1); result.Should().BeOfType(); } [Fact] public async Task DeleteTemplate_WhenNotFound_Returns404() { _templateService.Setup(s => s.DeleteTemplateAsync(1)).ReturnsAsync(false); var result = await _controller.DeleteTemplate(1); result.Should().BeOfType(); } [Fact] public async Task DeleteTemplate_WhenException_Returns500() { _templateService.Setup(s => s.DeleteTemplateAsync(It.IsAny())).ThrowsAsync(new Exception("t")); var result = await _controller.DeleteTemplate(1); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 6. EnableTemplate (3 tests) [Fact] public async Task EnableTemplate_WhenSuccess_ReturnsOk() { _templateService.Setup(s => s.EnableTemplateAsync(1)).ReturnsAsync(true); var result = await _controller.EnableTemplate(1); result.Should().BeOfType(); } [Fact] public async Task EnableTemplate_WhenNotFound_Returns404() { _templateService.Setup(s => s.EnableTemplateAsync(1)).ReturnsAsync(false); var result = await _controller.EnableTemplate(1); result.Should().BeOfType(); } [Fact] public async Task EnableTemplate_WhenException_Returns500() { _templateService.Setup(s => s.EnableTemplateAsync(It.IsAny())).ThrowsAsync(new Exception("t")); var result = await _controller.EnableTemplate(1); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 7. DisableTemplate (3 tests) [Fact] public async Task DisableTemplate_WhenSuccess_ReturnsOk() { _templateService.Setup(s => s.DisableTemplateAsync(1)).ReturnsAsync(true); var result = await _controller.DisableTemplate(1); result.Should().BeOfType(); } [Fact] public async Task DisableTemplate_WhenNotFound_Returns404() { _templateService.Setup(s => s.DisableTemplateAsync(1)).ReturnsAsync(false); var result = await _controller.DisableTemplate(1); result.Should().BeOfType(); } [Fact] public async Task DisableTemplate_WhenException_Returns500() { _templateService.Setup(s => s.DisableTemplateAsync(It.IsAny())).ThrowsAsync(new Exception("t")); var result = await _controller.DisableTemplate(1); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 8. CloneTemplate (2 tests) [Fact] public async Task CloneTemplate_WhenSuccess_ReturnsOk() { _templateService.Setup(s => s.CloneTemplateAsync(1, "new")).ReturnsAsync(new CNCBrandTemplate()); var result = await _controller.CloneTemplate(1, new CloneTemplateRequest { NewName = "new" }); result.Should().BeOfType(); } [Fact] public async Task CloneTemplate_WhenException_Returns500() { _templateService.Setup(s => s.CloneTemplateAsync(It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("t")); var result = await _controller.CloneTemplate(1, new CloneTemplateRequest { NewName = "new" }); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 9. TestTemplate (2 tests) [Fact] public async Task TestTemplate_WhenSuccess_ReturnsOk() { _templateService.Setup(s => s.TestTemplateAsync(1)).Returns(Task.CompletedTask); var result = await _controller.TestTemplate(1); result.Should().BeOfType(); } [Fact] public async Task TestTemplate_WhenException_Returns500() { _templateService.Setup(s => s.TestTemplateAsync(It.IsAny())).ThrowsAsync(new Exception("t")); var result = await _controller.TestTemplate(1); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 10. GetTemplatesByBrand (2 tests) [Fact] public async Task GetTemplatesByBrand_WhenSuccess_ReturnsOk() { _templateService.Setup(s => s.GetTemplatesByBrandAsync("Fanuc")).ReturnsAsync(new List()); var result = await _controller.GetTemplatesByBrand("Fanuc"); result.Should().BeOfType(); } [Fact] public async Task GetTemplatesByBrand_WhenException_Returns500() { _templateService.Setup(s => s.GetTemplatesByBrandAsync(It.IsAny())).ThrowsAsync(new Exception("t")); var result = await _controller.GetTemplatesByBrand("x"); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 11. GetActiveTemplates (2 tests) [Fact] public async Task GetActiveTemplates_WhenSuccess_ReturnsOk() { _templateService.Setup(s => s.GetActiveTemplatesAsync()).ReturnsAsync(new List()); var result = await _controller.GetActiveTemplates(); result.Should().BeOfType(); } [Fact] public async Task GetActiveTemplates_WhenException_Returns500() { _templateService.Setup(s => s.GetActiveTemplatesAsync()).ThrowsAsync(new Exception("t")); var result = await _controller.GetActiveTemplates(); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 12. ValidateTemplate (3 tests: valid, invalid, exception) [Fact] public async Task ValidateTemplate_WhenValid_ReturnsOk() { _templateService.Setup(s => s.ValidateTemplateAsync(It.IsAny())).ReturnsAsync(true); var result = await _controller.ValidateTemplate(new CNCBrandTemplate()); result.Should().BeOfType(); } [Fact] public async Task ValidateTemplate_WhenInvalid_ReturnsBadRequest() { _templateService.Setup(s => s.ValidateTemplateAsync(It.IsAny())).ReturnsAsync(false); _validationService.Setup(s => s.ValidateTemplateForDeviceAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new List()); var result = await _controller.ValidateTemplate(new CNCBrandTemplate()); result.Should().BeOfType(); } [Fact] public async Task ValidateTemplate_WhenException_Returns500() { _templateService.Setup(s => s.ValidateTemplateAsync(It.IsAny())).ThrowsAsync(new Exception("t")); var result = await _controller.ValidateTemplate(new CNCBrandTemplate()); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 13. MigrateTemplate (3 tests: can migrate, cannot, exception) [Fact] public async Task MigrateTemplate_WhenCanMigrate_ReturnsOk() { _validationService.Setup(s => s.GenerateMigrationReportAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new TemplateMigrationReport { CanMigrate = true }); var result = await _controller.MigrateTemplate(new TemplateMigrationRequest { Template = new CNCBrandTemplate(), TargetBrand = "Mitsubishi" }); result.Should().BeOfType(); } [Fact] public async Task MigrateTemplate_WhenCannotMigrate_ReturnsBadRequest() { _validationService.Setup(s => s.GenerateMigrationReportAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new TemplateMigrationReport { CanMigrate = false, Issues = new List { "issue" } }); var result = await _controller.MigrateTemplate(new TemplateMigrationRequest { Template = new CNCBrandTemplate(), TargetBrand = "Mitsubishi" }); result.Should().BeOfType(); } [Fact] public async Task MigrateTemplate_WhenException_Returns500() { _validationService.Setup(s => s.GenerateMigrationReportAsync(It.IsAny(), It.IsAny())) .ThrowsAsync(new Exception("t")); var result = await _controller.MigrateTemplate(new TemplateMigrationRequest { Template = new CNCBrandTemplate(), TargetBrand = "Mitsubishi" }); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 14. GetTagMappings (2 tests) [Fact] public async Task GetTagMappings_WhenSuccess_ReturnsOk() { _tagMappingService.Setup(s => s.GetMappingsByTemplateAsync(1)) .ReturnsAsync(new List()); var result = await _controller.GetTagMappings(1); result.Should().BeOfType(); } [Fact] public async Task GetTagMappings_WhenException_Returns500() { _tagMappingService.Setup(s => s.GetMappingsByTemplateAsync(It.IsAny())).ThrowsAsync(new Exception("t")); var result = await _controller.GetTagMappings(1); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 15. CreateTagMapping (2 tests) [Fact] public async Task CreateTagMapping_WhenSuccess_ReturnsOk() { _tagMappingService.Setup(s => s.CreateTagMappingAsync(It.IsAny())) .ReturnsAsync(new TagMapping()); var result = await _controller.CreateTagMapping(new TagMapping()); result.Should().BeOfType(); } [Fact] public async Task CreateTagMapping_WhenException_Returns500() { _tagMappingService.Setup(s => s.CreateTagMappingAsync(It.IsAny())).ThrowsAsync(new Exception("t")); var result = await _controller.CreateTagMapping(new TagMapping()); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } // 16. TestTagMapping (2 tests) [Fact] public async Task TestTagMapping_WhenSuccess_ReturnsOk() { _tagMappingService.Setup(s => s.MapDeviceTagsAsync(It.IsAny>(), It.IsAny())) .ReturnsAsync(new List()); var result = await _controller.TestTagMapping(new TestTagMappingRequest { DeviceTags = new List(), TemplateId = 1 }); result.Should().BeOfType(); } [Fact] public async Task TestTagMapping_WhenException_Returns500() { _tagMappingService.Setup(s => s.MapDeviceTagsAsync(It.IsAny>(), It.IsAny())) .ThrowsAsync(new Exception("t")); var result = await _controller.TestTagMapping(new TestTagMappingRequest { DeviceTags = new List(), TemplateId = 1 }); result.Should().BeOfType().Which.StatusCode.Should().Be(500); } } }