From 222db2f4fc532547a8e73308dc2efa145c782021 Mon Sep 17 00:00:00 2001 From: Kevin Snyder Date: Thu, 1 Jan 2026 08:50:16 -0500 Subject: [PATCH] Updated UI Unit Tests to reflect v1.1.0 --- .../IntegrationTests/ApplicationTests.cs | 81 ++++- .../Execution_UI.Tests/Pages/CastPageTests.cs | 278 +++++++++++++++--- .../Pages/ErrorPageTests.cs | 189 ++++++++++-- .../Pages/IndexPageTests.cs | 275 ++++++++++++++--- .../Pages/PrivacyPageTests.cs | 137 ++++++++- 5 files changed, 833 insertions(+), 127 deletions(-) diff --git a/Execution_UI/Execution_UI.Tests/IntegrationTests/ApplicationTests.cs b/Execution_UI/Execution_UI.Tests/IntegrationTests/ApplicationTests.cs index ad765fbb..160796e3 100644 --- a/Execution_UI/Execution_UI.Tests/IntegrationTests/ApplicationTests.cs +++ b/Execution_UI/Execution_UI.Tests/IntegrationTests/ApplicationTests.cs @@ -5,6 +5,10 @@ namespace Execution_UI.Tests.IntegrationTests { + /// + /// Integration tests for the Execution_UI application. + /// These tests verify end-to-end HTTP requests and responses. + /// public class ApplicationTests : IClassFixture> { private readonly WebApplicationFactory _factory; @@ -15,7 +19,7 @@ public ApplicationTests(WebApplicationFactory factory) } [Fact] - public async Task Get_IndexPage_ReturnsSuccessStatusCode() + public async Task Get_IndexPage_ReturnsOkStatusCode() { // Arrange var client = _factory.CreateClient(); @@ -24,30 +28,77 @@ public async Task Get_IndexPage_ReturnsSuccessStatusCode() var response = await client.GetAsync("/"); // Assert - Assert.True(response.IsSuccessStatusCode || response.StatusCode == HttpStatusCode.OK); + Assert.True(response.IsSuccessStatusCode, $"Expected success status code, got {response.StatusCode}"); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); } [Fact] - public async Task Get_PrivacyPage_ReturnsSuccessStatusCode() + public async Task Get_IndexPage_ReturnsHtmlContent() + { + // Arrange + var client = _factory.CreateClient(); + + // Act + var response = await client.GetAsync("/"); + var content = await response.Content.ReadAsStringAsync(); + + // Assert + Assert.True(response.IsSuccessStatusCode); + Assert.NotEmpty(content); + Assert.True(content.Contains(" + /// Unit tests for CastModel page model. + /// Tests initialization, properties, and data structure integrity. + /// public class CastPageTests { + private Mock> CreateMockLogger() + { + return new Mock>(); + } + + #region Constructor Tests + [Fact] - public void CastModel_Constructor_InitializesWithValidLogger() + public void Constructor_WithValidLogger_InitializesSuccessfully() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); // Act var model = new CastModel(mockLogger.Object); @@ -22,36 +34,61 @@ public void CastModel_Constructor_InitializesWithValidLogger() } [Fact] - public void CastModel_InheritsFromPageModel() + public void Constructor_InitializesOriginatorUUIDsList() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); // Act var model = new CastModel(mockLogger.Object); // Assert - Assert.IsAssignableFrom(model); + Assert.NotNull(model.originatorUUIDs); + Assert.IsType>(model.originatorUUIDs); + Assert.Empty(model.originatorUUIDs); } [Fact] - public void CastModel_OriginatorUUIDs_IsInitializedAsEmptyList() + public void Constructor_InitializesDisplayNamesList() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); + + // Act var model = new CastModel(mockLogger.Object); - // Act & Assert - Assert.NotNull(model.originatorUUIDs); - Assert.IsType>(model.originatorUUIDs); - Assert.Empty(model.originatorUUIDs); + // Assert + Assert.NotNull(model.displayNames); + Assert.IsType>(model.displayNames); + Assert.Empty(model.displayNames); } + #endregion + + #region Inheritance Tests + [Fact] - public void CastModel_SelectedValue_CanBeSet() + public void CastModel_InheritsFromPageModel() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); + + // Act + var model = new CastModel(mockLogger.Object); + + // Assert + Assert.IsAssignableFrom(model); + } + + #endregion + + #region Property Tests + + [Fact] + public void SelectedValue_CanBeSet() + { + // Arrange + var mockLogger = CreateMockLogger(); var model = new CastModel(mockLogger.Object); var testValue = "test-value"; @@ -63,36 +100,106 @@ public void CastModel_SelectedValue_CanBeSet() } [Fact] - public void CastModel_SelectedValue_CanBeNull() + public void SelectedValue_CanBeSetToNull() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); var model = new CastModel(mockLogger.Object); // Act - model.SelectedValue = null!; + model.SelectedValue = null; // Assert Assert.Null(model.SelectedValue); } [Fact] - public void CastModel_RootDir_IsNotEmpty() + public void SelectedValue_CanBeSetMultipleTimes() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); var model = new CastModel(mockLogger.Object); + var value1 = "value1"; + var value2 = "value2"; - // Act & Assert + // Act + model.SelectedValue = value1; + Assert.Equal(value1, model.SelectedValue); + model.SelectedValue = value2; + + // Assert + Assert.Equal(value2, model.SelectedValue); + } + + [Fact] + public void Options_CanBeSet() + { + // Arrange + var mockLogger = CreateMockLogger(); + var model = new CastModel(mockLogger.Object); + var items = new List { "option1", "option2", "option3" }; + var selectList = new SelectList(items); + + // Act + model.Options = selectList; + + // Assert + Assert.NotNull(model.Options); + Assert.Equal(3, model.Options.Count()); + } + + [Fact] + public void Options_CanBeNull() + { + // Arrange + var mockLogger = CreateMockLogger(); + var model = new CastModel(mockLogger.Object); + + // Act + model.Options = null; + + // Assert + Assert.Null(model.Options); + } + + #endregion + + #region Root Directory Tests + + [Fact] + public void RootDir_IsNotEmpty() + { + // Arrange + var mockLogger = CreateMockLogger(); + + // Act + var model = new CastModel(mockLogger.Object); + + // Assert Assert.NotNull(model.rootDir); Assert.NotEmpty(model.rootDir); } [Fact] - public void CastModel_OriginatorUUIDs_CanAddItems() + public void RootDir_ContainsValidPath() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); + var model = new CastModel(mockLogger.Object); + + // Act & Assert + Assert.True(model.rootDir.Contains("..") || model.rootDir.Contains(Path.DirectorySeparatorChar.ToString())); + } + + #endregion + + #region List Operations Tests + + [Fact] + public void OriginatorUUIDs_CanAddItem() + { + // Arrange + var mockLogger = CreateMockLogger(); var model = new CastModel(mockLogger.Object); var testUuid = "test-uuid-123"; @@ -105,33 +212,134 @@ public void CastModel_OriginatorUUIDs_CanAddItems() } [Fact] - public void CastModel_Options_CanBeSet() + public void OriginatorUUIDs_CanAddMultipleItems() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); var model = new CastModel(mockLogger.Object); - var items = new List { "option1", "option2" }; - var selectList = new Microsoft.AspNetCore.Mvc.Rendering.SelectList(items); + var uuid1 = "uuid-1"; + var uuid2 = "uuid-2"; + var uuid3 = "uuid-3"; // Act - model.Options = selectList; + model.originatorUUIDs.Add(uuid1); + model.originatorUUIDs.Add(uuid2); + model.originatorUUIDs.Add(uuid3); // Assert - Assert.NotNull(model.Options); + Assert.Equal(3, model.originatorUUIDs.Count); + Assert.Contains(uuid1, model.originatorUUIDs); + Assert.Contains(uuid2, model.originatorUUIDs); + Assert.Contains(uuid3, model.originatorUUIDs); } [Fact] - public void CastModel_StaticConfigurationValues_AreNotNull() + public void DisplayNames_CanAddItem() + { + // Arrange + var mockLogger = CreateMockLogger(); + var model = new CastModel(mockLogger.Object); + var displayName = "Test Client"; + + // Act + model.displayNames.Add(displayName); + + // Assert + Assert.Single(model.displayNames); + Assert.Contains(displayName, model.displayNames); + } + + [Fact] + public void StartRun_InitializesAsEmptyList() + { + // Arrange + var mockLogger = CreateMockLogger(); + + // Act + var model = new CastModel(mockLogger.Object); + + // Assert + Assert.NotNull(model.startRun); + Assert.IsType>(model.startRun); + Assert.Empty(model.startRun); + } + + [Fact] + public void StopRun_InitializesAsEmptyList() + { + // Arrange + var mockLogger = CreateMockLogger(); + + // Act + var model = new CastModel(mockLogger.Object); + + // Assert + Assert.NotNull(model.stopRun); + Assert.IsType>(model.stopRun); + Assert.Empty(model.stopRun); + } + + [Fact] + public void PauseRun_InitializesAsEmptyList() + { + // Arrange + var mockLogger = CreateMockLogger(); + + // Act + var model = new CastModel(mockLogger.Object); + + // Assert + Assert.NotNull(model.pauseRun); + Assert.IsType>(model.pauseRun); + Assert.Empty(model.pauseRun); + } + + [Fact] + public void ResumeRun_InitializesAsEmptyList() + { + // Arrange + var mockLogger = CreateMockLogger(); + + // Act + var model = new CastModel(mockLogger.Object); + + // Assert + Assert.NotNull(model.resumeRun); + Assert.IsType>(model.resumeRun); + Assert.Empty(model.resumeRun); + } + + [Fact] + public void AbortRun_InitializesAsEmptyList() + { + // Arrange + var mockLogger = CreateMockLogger(); + + // Act + var model = new CastModel(mockLogger.Object); + + // Assert + Assert.NotNull(model.abortRun); + Assert.IsType>(model.abortRun); + Assert.Empty(model.abortRun); + } + + #endregion + + #region BindProperty Tests + + [Fact] + public void SelectedValue_HasBindPropertyAttribute() { // Arrange & Act - // Note: These may be null if appsettings.json is not properly configured - // This test documents that these properties exist - var model = new CastModel(new Mock>().Object); + var propertyInfo = typeof(CastModel).GetProperty("SelectedValue"); - // Assert - Just verify the properties exist and can be accessed - Assert.NotNull(model); - // The static fields are set from configuration, so they might be null - // depending on appsettings.json configuration + // Assert + Assert.NotNull(propertyInfo); + var attributes = propertyInfo.GetCustomAttributes(typeof(Microsoft.AspNetCore.Mvc.BindPropertyAttribute), false); + Assert.NotEmpty(attributes); } + + #endregion } } diff --git a/Execution_UI/Execution_UI.Tests/Pages/ErrorPageTests.cs b/Execution_UI/Execution_UI.Tests/Pages/ErrorPageTests.cs index ebc6b449..ef2fccbb 100644 --- a/Execution_UI/Execution_UI.Tests/Pages/ErrorPageTests.cs +++ b/Execution_UI/Execution_UI.Tests/Pages/ErrorPageTests.cs @@ -9,17 +9,59 @@ namespace Execution_UI.Tests.Pages { + /// + /// Unit tests for ErrorModel page model. + /// Tests error page initialization, request ID handling, and attributes. + /// public class ErrorPageTests { + private Mock> CreateMockLogger() + { + return new Mock>(); + } + + #region Constructor Tests + + [Fact] + public void Constructor_WithValidLogger_InitializesSuccessfully() + { + // Arrange + var mockLogger = CreateMockLogger(); + + // Act + var model = new ErrorModel(mockLogger.Object); + + // Assert + Assert.NotNull(model); + } + [Fact] - public void ErrorModel_OnGet_WithValidPageContext_SetsRequestId() + public void Constructor_InitializesRequestIdAsNull() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); + + // Act var model = new ErrorModel(mockLogger.Object); + // Assert + Assert.Null(model.RequestId); + } + + #endregion + + #region OnGet Tests + + [Fact] + public void OnGet_WithValidPageContext_SetsRequestId() + { + // Arrange + var mockLogger = CreateMockLogger(); + var model = new ErrorModel(mockLogger.Object); + var traceId = "test-trace-id-123"; + var mockHttpContext = new Mock(); - mockHttpContext.Setup(c => c.TraceIdentifier).Returns("test-trace-id"); + mockHttpContext.Setup(c => c.TraceIdentifier).Returns(traceId); var pageContext = new PageContext { @@ -32,83 +74,180 @@ public void ErrorModel_OnGet_WithValidPageContext_SetsRequestId() // Assert Assert.NotNull(model.RequestId); + Assert.Equal(traceId, model.RequestId); + } + + [Fact] + public void OnGet_WithActivityId_SetsRequestIdFromActivity() + { + // Arrange + var mockLogger = CreateMockLogger(); + var model = new ErrorModel(mockLogger.Object); + + var mockHttpContext = new Mock(); + mockHttpContext.Setup(c => c.TraceIdentifier).Returns("trace-id"); + + var pageContext = new PageContext + { + HttpContext = mockHttpContext.Object + }; + model.PageContext = pageContext; + + // Act + model.OnGet(); + + // Assert + // Should set RequestId from either Activity or TraceIdentifier + Assert.NotNull(model.RequestId); + Assert.NotEmpty(model.RequestId); + } + + [Fact] + public void OnGet_ExecutesSuccessfully() + { + // Arrange + var mockLogger = CreateMockLogger(); + var model = new ErrorModel(mockLogger.Object); + + var mockHttpContext = new Mock(); + mockHttpContext.Setup(c => c.TraceIdentifier).Returns("test-id"); + + model.PageContext = new PageContext { HttpContext = mockHttpContext.Object }; + + // Act & Assert + var exception = Record.Exception(() => model.OnGet()); + Assert.Null(exception); } + #endregion + + #region ShowRequestId Property Tests + [Fact] - public void ErrorModel_ShowRequestId_ReturnsTrueWhenRequestIdIsSet() + public void ShowRequestId_ReturnsTrueWhenRequestIdIsSet() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); var model = new ErrorModel(mockLogger.Object) { RequestId = "test-id" }; - // Act & Assert - Assert.True(model.ShowRequestId); + // Act + var result = model.ShowRequestId; + + // Assert + Assert.True(result); } [Fact] - public void ErrorModel_ShowRequestId_ReturnsFalseWhenRequestIdIsNull() + public void ShowRequestId_ReturnsFalseWhenRequestIdIsNull() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); var model = new ErrorModel(mockLogger.Object) { RequestId = null }; - // Act & Assert - Assert.False(model.ShowRequestId); + // Act + var result = model.ShowRequestId; + + // Assert + Assert.False(result); } [Fact] - public void ErrorModel_ShowRequestId_ReturnsFalseWhenRequestIdIsEmpty() + public void ShowRequestId_ReturnsFalseWhenRequestIdIsEmpty() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); var model = new ErrorModel(mockLogger.Object) { RequestId = string.Empty }; - // Act & Assert - Assert.False(model.ShowRequestId); + // Act + var result = model.ShowRequestId; + + // Assert + Assert.False(result); } [Fact] - public void ErrorModel_Constructor_InitializesWithValidLogger() + public void ShowRequestId_ReturnsFalseWhenRequestIdIsWhitespace() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); + var model = new ErrorModel(mockLogger.Object) + { + RequestId = " " + }; // Act - var model = new ErrorModel(mockLogger.Object); + var result = model.ShowRequestId; // Assert - Assert.NotNull(model); + // string.IsNullOrEmpty returns false for whitespace, so ShowRequestId should be true + Assert.True(result); } + #endregion + + #region Attribute Tests + [Fact] - public void ErrorModel_IsAttributeResponseCache() + public void ErrorModel_HasResponseCacheAttribute() { // Arrange & Act - var model = new ErrorModel(new Mock>().Object); + var attributes = typeof(ErrorModel).GetCustomAttributes(typeof(ResponseCacheAttribute), false); // Assert - var attributes = typeof(ErrorModel).GetCustomAttributes(typeof(ResponseCacheAttribute), false); Assert.NotEmpty(attributes); + var responseCache = attributes[0] as ResponseCacheAttribute; + Assert.NotNull(responseCache); + Assert.Equal(0, responseCache.Duration); + Assert.Equal(ResponseCacheLocation.None, responseCache.Location); + Assert.True(responseCache.NoStore); } [Fact] - public void ErrorModel_IsAttributeIgnoreAntiforgeryToken() + public void ErrorModel_HasIgnoreAntiforgeryTokenAttribute() { // Arrange & Act - var model = new ErrorModel(new Mock>().Object); + var attributes = typeof(ErrorModel).GetCustomAttributes(typeof(IgnoreAntiforgeryTokenAttribute), false); // Assert - var attributes = typeof(ErrorModel).GetCustomAttributes(typeof(IgnoreAntiforgeryTokenAttribute), false); Assert.NotEmpty(attributes); } + + #endregion + + #region Integration Tests + + [Fact] + public void ErrorModel_WorkflowWithValidContext() + { + // Arrange + var mockLogger = CreateMockLogger(); + var model = new ErrorModel(mockLogger.Object); + + var mockHttpContext = new Mock(); + mockHttpContext.Setup(c => c.TraceIdentifier).Returns("workflow-test-id"); + + var pageContext = new PageContext { HttpContext = mockHttpContext.Object }; + model.PageContext = pageContext; + + // Act + model.OnGet(); + var shouldShow = model.ShowRequestId; + + // Assert + Assert.NotNull(model.RequestId); + Assert.True(shouldShow); + Assert.Equal("workflow-test-id", model.RequestId); + } + + #endregion } } diff --git a/Execution_UI/Execution_UI.Tests/Pages/IndexPageTests.cs b/Execution_UI/Execution_UI.Tests/Pages/IndexPageTests.cs index 12c1770b..8a1f6147 100644 --- a/Execution_UI/Execution_UI.Tests/Pages/IndexPageTests.cs +++ b/Execution_UI/Execution_UI.Tests/Pages/IndexPageTests.cs @@ -5,82 +5,149 @@ using Microsoft.Extensions.Logging; using Execution_UI.Pages; using System.Net.Mime; -using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; namespace Execution_UI.Tests.Pages { + /// + /// Unit tests for IndexModel page model. + /// Tests page initialization and file download functionality. + /// public class IndexPageTests { + private Mock> CreateMockLogger() + { + return new Mock>(); + } + + private Mock CreateMockEnvironment(string? contentRootPath = null) + { + var mockEnvironment = new Mock(); + if (contentRootPath != null) + { + mockEnvironment.Setup(e => e.ContentRootPath).Returns(contentRootPath); + } + return mockEnvironment; + } + + #region Constructor Tests + [Fact] - public void IndexModel_OnGet_DoesNotThrowException() + public void Constructor_WithValidDependencies_InitializesSuccessfully() { // Arrange - var mockLogger = new Mock>(); - var mockEnvironment = new Mock(); + var mockLogger = CreateMockLogger(); + var mockEnvironment = CreateMockEnvironment(); + + // Act + var model = new IndexModel(mockLogger.Object, mockEnvironment.Object); + + // Assert + Assert.NotNull(model); + } + + [Fact] + public void Constructor_WithNullLogger_AcceptsNull() + { + // Arrange + var mockEnvironment = CreateMockEnvironment(); + + // Act & Assert - Constructor signature allows null + var model = new IndexModel(null!, mockEnvironment.Object); + Assert.NotNull(model); + } + + [Fact] + public void Constructor_WithNullEnvironment_AcceptsNull() + { + // Arrange + var mockLogger = CreateMockLogger(); + + // Act & Assert - Constructor signature allows null + var model = new IndexModel(mockLogger.Object, null!); + Assert.NotNull(model); + } + + #endregion + + #region OnGet Tests + + [Fact] + public void OnGet_DoesNotThrowException() + { + // Arrange + var mockLogger = CreateMockLogger(); + var mockEnvironment = CreateMockEnvironment(); var model = new IndexModel(mockLogger.Object, mockEnvironment.Object); // Act & Assert - Should not throw - var result = Record.Exception(() => model.OnGet()); - Assert.Null(result); + var exception = Record.Exception(() => model.OnGet()); + Assert.Null(exception); } [Fact] - public void IndexModel_OnGet_LogsInformation() + public void OnGet_ExecutesSuccessfully() { // Arrange - var mockLogger = new Mock>(); - var mockEnvironment = new Mock(); + var mockLogger = CreateMockLogger(); + var mockEnvironment = CreateMockEnvironment(); var model = new IndexModel(mockLogger.Object, mockEnvironment.Object); // Act model.OnGet(); - // Assert - Verify logger was called - mockLogger.VerifyLogging(l => l == LogLevel.Information, Times.Never()); + // Assert - Model should be in valid state after OnGet + Assert.NotNull(model); } + #endregion + + #region OnGetDownloadClientDLL Tests + [Fact] - public void IndexModel_OnGetDownloadClientDLL_FileNotFound_ReturnsNotFound() + public void OnGetDownloadClientDLL_FileNotFound_ReturnsNotFound() { // Arrange - var mockLogger = new Mock>(); - var mockEnvironment = new Mock(); - mockEnvironment.Setup(e => e.ContentRootPath).Returns(Path.GetTempPath()); - - var model = new IndexModel(mockLogger.Object, mockEnvironment.Object); + var mockLogger = CreateMockLogger(); + var tempDir = Path.Combine(Path.GetTempPath(), $"test_dll_notfound_{Guid.NewGuid()}"); + var clientDir = Path.Combine(tempDir, "clients"); + Directory.CreateDirectory(clientDir); - // Create a temporary directory for testing - var tempClientPath = Path.Combine(Path.GetTempPath(), "clients"); - Directory.CreateDirectory(tempClientPath); - mockEnvironment.Setup(e => e.ContentRootPath).Returns(Path.GetTempPath()); + try + { + var mockEnvironment = CreateMockEnvironment(tempDir); + var model = new IndexModel(mockLogger.Object, mockEnvironment.Object); - // Act - var result = model.OnGetDownloadClientDLL(); + // Act + var result = model.OnGetDownloadClientDLL(); - // Assert - Assert.IsType(result); + // Assert + Assert.IsType(result); + } + finally + { + if (Directory.Exists(tempDir)) + Directory.Delete(tempDir, true); + } } [Fact] - public void IndexModel_OnGetDownloadClientDLL_FileExists_ReturnsPhysicalFile() + public void OnGetDownloadClientDLL_FileExists_ReturnsPhysicalFile() { // Arrange - var mockLogger = new Mock>(); - var mockEnvironment = new Mock(); - - var tempDir = Path.Combine(Path.GetTempPath(), $"test_clients_{Guid.NewGuid()}"); + var mockLogger = CreateMockLogger(); + var tempDir = Path.Combine(Path.GetTempPath(), $"test_dll_exists_{Guid.NewGuid()}"); var clientDir = Path.Combine(tempDir, "clients"); Directory.CreateDirectory(clientDir); var testFilePath = Path.Combine(clientDir, "CAST_Client_Service.dll"); - File.WriteAllText(testFilePath, "test content"); - - mockEnvironment.Setup(e => e.ContentRootPath).Returns(tempDir); - var model = new IndexModel(mockLogger.Object, mockEnvironment.Object); + File.WriteAllText(testFilePath, "test dll content"); try { + var mockEnvironment = CreateMockEnvironment(tempDir); + var model = new IndexModel(mockLogger.Object, mockEnvironment.Object); + // Act var result = model.OnGetDownloadClientDLL(); @@ -93,24 +160,154 @@ public void IndexModel_OnGetDownloadClientDLL_FileExists_ReturnsPhysicalFile() } finally { - // Cleanup if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true); } } [Fact] - public void IndexModel_Constructor_InitializesWithValidDependencies() + public void OnGetDownloadClientDLL_FileExists_ReturnsCorrectContentType() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); + var tempDir = Path.Combine(Path.GetTempPath(), $"test_dll_contenttype_{Guid.NewGuid()}"); + var clientDir = Path.Combine(tempDir, "clients"); + Directory.CreateDirectory(clientDir); + + var testFilePath = Path.Combine(clientDir, "CAST_Client_Service.dll"); + File.WriteAllText(testFilePath, "test content"); + + try + { + var mockEnvironment = CreateMockEnvironment(tempDir); + var model = new IndexModel(mockLogger.Object, mockEnvironment.Object); + + // Act + var result = model.OnGetDownloadClientDLL() as PhysicalFileResult; + + // Assert + Assert.NotNull(result); + Assert.Equal("application/octet-stream", result.ContentType); + } + finally + { + if (Directory.Exists(tempDir)) + Directory.Delete(tempDir, true); + } + } + + [Fact] + public void OnGetDownloadClientDLL_FileExists_ReturnsCorrectFileName() + { + // Arrange + var mockLogger = CreateMockLogger(); + var tempDir = Path.Combine(Path.GetTempPath(), $"test_dll_filename_{Guid.NewGuid()}"); + var clientDir = Path.Combine(tempDir, "clients"); + Directory.CreateDirectory(clientDir); + + var testFilePath = Path.Combine(clientDir, "CAST_Client_Service.dll"); + File.WriteAllText(testFilePath, "test"); + + try + { + var mockEnvironment = CreateMockEnvironment(tempDir); + var model = new IndexModel(mockLogger.Object, mockEnvironment.Object); + + // Act + var result = model.OnGetDownloadClientDLL() as PhysicalFileResult; + + // Assert + Assert.NotNull(result); + Assert.Equal("CAST_Client_Service.dll", result.FileDownloadName); + } + finally + { + if (Directory.Exists(tempDir)) + Directory.Delete(tempDir, true); + } + } + + [Fact] + public void OnGetDownloadClientDLL_NoClientsDirectory_ReturnsNotFound() + { + // Arrange + var mockLogger = CreateMockLogger(); + var tempDir = Path.Combine(Path.GetTempPath(), $"test_dll_nodir_{Guid.NewGuid()}"); + // Don't create the clients directory + + try + { + var mockEnvironment = CreateMockEnvironment(tempDir); + var model = new IndexModel(mockLogger.Object, mockEnvironment.Object); + + // Act + var result = model.OnGetDownloadClientDLL(); + + // Assert + Assert.IsType(result); + } + finally + { + if (Directory.Exists(tempDir)) + Directory.Delete(tempDir, true); + } + } + + [Fact] + public void OnGetDownloadClientDLL_EnvironmentContentRootPathIsUsed() + { + // Arrange + var mockLogger = CreateMockLogger(); + var expectedContentRoot = "/expected/content/root"; var mockEnvironment = new Mock(); + mockEnvironment.Setup(e => e.ContentRootPath).Returns(expectedContentRoot); - // Act var model = new IndexModel(mockLogger.Object, mockEnvironment.Object); + // Act + var result = model.OnGetDownloadClientDLL(); + // Assert - Assert.NotNull(model); + mockEnvironment.Verify(e => e.ContentRootPath, Times.AtLeastOnce); + Assert.IsType(result); + } + + #endregion + + #region Integration Tests + + [Fact] + public void IndexModel_WorkflowOnGetThenOnGetDownloadClientDLL() + { + // Arrange + var mockLogger = CreateMockLogger(); + var tempDir = Path.Combine(Path.GetTempPath(), $"test_workflow_{Guid.NewGuid()}"); + var clientDir = Path.Combine(tempDir, "clients"); + Directory.CreateDirectory(clientDir); + + var testFilePath = Path.Combine(clientDir, "CAST_Client_Service.dll"); + File.WriteAllText(testFilePath, "content"); + + try + { + var mockEnvironment = CreateMockEnvironment(tempDir); + var model = new IndexModel(mockLogger.Object, mockEnvironment.Object); + + // Act + model.OnGet(); + var downloadResult = model.OnGetDownloadClientDLL(); + + // Assert + Assert.NotNull(model); + Assert.IsType(downloadResult); + } + finally + { + if (Directory.Exists(tempDir)) + Directory.Delete(tempDir, true); + } } + + #endregion } } diff --git a/Execution_UI/Execution_UI.Tests/Pages/PrivacyPageTests.cs b/Execution_UI/Execution_UI.Tests/Pages/PrivacyPageTests.cs index 951957a1..cd66ca93 100644 --- a/Execution_UI/Execution_UI.Tests/Pages/PrivacyPageTests.cs +++ b/Execution_UI/Execution_UI.Tests/Pages/PrivacyPageTests.cs @@ -6,52 +6,120 @@ namespace Execution_UI.Tests.Pages { + /// + /// Unit tests for PrivacyModel page model. + /// Tests basic page initialization and method execution. + /// public class PrivacyPageTests { + private Mock> CreateMockLogger() + { + return new Mock>(); + } + + #region Constructor Tests + [Fact] - public void PrivacyModel_OnGet_DoesNotThrowException() + public void Constructor_WithValidLogger_InitializesSuccessfully() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); + + // Act var model = new PrivacyModel(mockLogger.Object); - // Act & Assert - Should not throw - var result = Record.Exception(() => model.OnGet()); - Assert.Null(result); + // Assert + Assert.NotNull(model); } [Fact] - public void PrivacyModel_OnGet_ExecutesSuccessfully() + public void Constructor_WithNullLogger_AcceptsNull() + { + // Arrange - Nullable parameters are allowed in C# + // Act & Assert - Constructor signature allows null + var model = new PrivacyModel(null!); + Assert.NotNull(model); + } + + [Fact] + public void Constructor_StoresLoggerReference() { // Arrange - var mockLogger = new Mock>(); - var model = new PrivacyModel(mockLogger.Object); + var mockLogger = CreateMockLogger(); // Act - model.OnGet(); + var model = new PrivacyModel(mockLogger.Object); - // Assert - Verify no exception and model is valid + // Assert Assert.NotNull(model); + // Logger is stored but typically private, so we just verify construction succeeded + } + + #endregion + + #region Inheritance Tests + + [Fact] + public void PrivacyModel_InheritsFromPageModel() + { + // Arrange + var mockLogger = CreateMockLogger(); + + // Act + var model = new PrivacyModel(mockLogger.Object); + + // Assert + Assert.IsAssignableFrom(model); } [Fact] - public void PrivacyModel_Constructor_InitializesWithValidLogger() + public void PrivacyModel_IsPageModel() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); // Act var model = new PrivacyModel(mockLogger.Object); // Assert + Assert.True(model is PageModel); + } + + #endregion + + #region OnGet Tests + + [Fact] + public void OnGet_DoesNotThrowException() + { + // Arrange + var mockLogger = CreateMockLogger(); + var model = new PrivacyModel(mockLogger.Object); + + // Act & Assert - Should not throw + var result = Record.Exception(() => model.OnGet()); + Assert.Null(result); + } + + [Fact] + public void OnGet_ExecutesSuccessfully() + { + // Arrange + var mockLogger = CreateMockLogger(); + var model = new PrivacyModel(mockLogger.Object); + + // Act + model.OnGet(); + + // Assert - Verify no exception and model is in valid state Assert.NotNull(model); } [Fact] - public void PrivacyModel_CanCallOnGetMultipleTimes() + public void OnGet_CanBeCalledMultipleTimes() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); var model = new PrivacyModel(mockLogger.Object); // Act & Assert @@ -63,16 +131,53 @@ public void PrivacyModel_CanCallOnGetMultipleTimes() } [Fact] - public void PrivacyModel_InheritsFromPageModel() + public void OnGet_DoesNotModifyModelState() { // Arrange - var mockLogger = new Mock>(); + var mockLogger = CreateMockLogger(); + var model = new PrivacyModel(mockLogger.Object); + + // Act + model.OnGet(); + var modelStateBeforeSecondCall = model.ModelState.Count; + model.OnGet(); + var modelStateAfterSecondCall = model.ModelState.Count; + + // Assert + Assert.Equal(modelStateBeforeSecondCall, modelStateAfterSecondCall); + } + + [Fact] + public void OnGet_HasVoidReturnType() + { + // Arrange + var mockLogger = CreateMockLogger(); + var model = new PrivacyModel(mockLogger.Object); + + // Act & Assert + model.OnGet(); // Should not throw or return a value + Assert.NotNull(model); + } + + #endregion + + #region Integration Tests + + [Fact] + public void PrivacyModel_CompleteWorkflow() + { + // Arrange + var mockLogger = CreateMockLogger(); // Act var model = new PrivacyModel(mockLogger.Object); + model.OnGet(); // Assert + Assert.NotNull(model); Assert.IsAssignableFrom(model); } + + #endregion } }