From 5eee161ad184a8e6cab68a06166a9f29b217b3ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9C=A8=20Audrey=20=E2=9C=A8?= Date: Fri, 23 May 2025 12:21:45 -0400 Subject: [PATCH] add unit tests --- .../SendServiceCollectionExtension.cs | 3 + .../Services/SendAuthenticationQueryTests.cs | 135 ++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 test/Core.Test/Tools/Services/SendAuthenticationQueryTests.cs diff --git a/src/Core/Tools/SendFeatures/SendServiceCollectionExtension.cs b/src/Core/Tools/SendFeatures/SendServiceCollectionExtension.cs index 02327adaac..3dca1cb482 100644 --- a/src/Core/Tools/SendFeatures/SendServiceCollectionExtension.cs +++ b/src/Core/Tools/SendFeatures/SendServiceCollectionExtension.cs @@ -1,5 +1,7 @@ using Bit.Core.Tools.SendFeatures.Commands; using Bit.Core.Tools.SendFeatures.Commands.Interfaces; +using Bit.Core.Tools.SendFeatures.Queries; +using Bit.Core.Tools.SendFeatures.Queries.Interfaces; using Bit.Core.Tools.Services; using Microsoft.Extensions.DependencyInjection; @@ -14,5 +16,6 @@ public static class SendServiceCollectionExtension services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); } } diff --git a/test/Core.Test/Tools/Services/SendAuthenticationQueryTests.cs b/test/Core.Test/Tools/Services/SendAuthenticationQueryTests.cs new file mode 100644 index 0000000000..c34afc42bd --- /dev/null +++ b/test/Core.Test/Tools/Services/SendAuthenticationQueryTests.cs @@ -0,0 +1,135 @@ +using Bit.Core.Tools.Entities; +using Bit.Core.Tools.Models.Data; +using Bit.Core.Tools.Repositories; +using Bit.Core.Tools.SendFeatures.Queries; +using NSubstitute; +using Xunit; + +namespace Bit.Core.Test.Tools.Services; + +public class SendAuthenticationQueryTests +{ + private readonly ISendRepository _sendRepository; + private readonly SendAuthenticationQuery _sendAuthenticationQuery; + + public SendAuthenticationQueryTests() + { + _sendRepository = Substitute.For(); + _sendAuthenticationQuery = new SendAuthenticationQuery(_sendRepository); + } + + [Fact] + public void Constructor_WithNullRepository_ThrowsArgumentNullException() + { + // Act & Assert + var exception = Assert.Throws(() => new SendAuthenticationQuery(null)); + Assert.Equal("sendRepository", exception.ParamName); + } + + [Theory] + [MemberData(nameof(AuthenticationMethodTestCases))] + public async Task GetAuthenticationMethod_ReturnsExpectedAuthenticationMethod(Send? send, Type expectedType) + { + // Arrange + var sendId = Guid.NewGuid(); + _sendRepository.GetByIdAsync(sendId).Returns(send); + + // Act + var result = await _sendAuthenticationQuery.GetAuthenticationMethod(sendId); + + // Assert + Assert.IsType(expectedType, result); + } + + [Theory] + [MemberData(nameof(EmailParsingTestCases))] + public async Task GetAuthenticationMethod_WithEmails_ParsesEmailsCorrectly(string emailString, string[] expectedEmails) + { + // Arrange + var sendId = Guid.NewGuid(); + var send = CreateSend(accessCount: 0, maxAccessCount: 10, emails: emailString, password: null); + _sendRepository.GetByIdAsync(sendId).Returns(send); + + // Act + var result = await _sendAuthenticationQuery.GetAuthenticationMethod(sendId); + + // Assert + var emailOtp = Assert.IsType(result); + Assert.Equal(expectedEmails, emailOtp.Emails); + } + + [Fact] + public async Task GetAuthenticationMethod_WithBothEmailsAndPassword_ReturnsEmailOtp() + { + // Arrange + var sendId = Guid.NewGuid(); + var send = CreateSend(accessCount: 0, maxAccessCount: 10, emails: "test@example.com", password: "hashedpassword"); + _sendRepository.GetByIdAsync(sendId).Returns(send); + + // Act + var result = await _sendAuthenticationQuery.GetAuthenticationMethod(sendId); + + // Assert + Assert.IsType(result); + } + + [Fact] + public async Task GetAuthenticationMethod_CallsRepositoryWithCorrectSendId() + { + // Arrange + var sendId = Guid.NewGuid(); + var send = CreateSend(accessCount: 0, maxAccessCount: 10, emails: null, password: null); + _sendRepository.GetByIdAsync(sendId).Returns(send); + + // Act + await _sendAuthenticationQuery.GetAuthenticationMethod(sendId); + + // Assert + await _sendRepository.Received(1).GetByIdAsync(sendId); + } + + [Fact] + public async Task GetAuthenticationMethod_WhenRepositoryThrows_PropagatesException() + { + // Arrange + var sendId = Guid.NewGuid(); + var expectedException = new InvalidOperationException("Repository error"); + _sendRepository.GetByIdAsync(sendId).Returns(Task.FromException(expectedException)); + + // Act & Assert + var exception = await Assert.ThrowsAsync(() => + _sendAuthenticationQuery.GetAuthenticationMethod(sendId)); + Assert.Same(expectedException, exception); + } + + public static IEnumerable AuthenticationMethodTestCases() + { + yield return new object[] { null, typeof(NeverAuthenticate) }; + yield return new object[] { CreateSend(accessCount: 5, maxAccessCount: 5, emails: null, password: null), typeof(NeverAuthenticate) }; + yield return new object[] { CreateSend(accessCount: 6, maxAccessCount: 5, emails: null, password: null), typeof(NeverAuthenticate) }; + yield return new object[] { CreateSend(accessCount: 0, maxAccessCount: 10, emails: "test@example.com", password: null), typeof(EmailOtp) }; + yield return new object[] { CreateSend(accessCount: 0, maxAccessCount: 10, emails: null, password: "hashedpassword"), typeof(ResourcePassword) }; + yield return new object[] { CreateSend(accessCount: 0, maxAccessCount: 10, emails: null, password: null), typeof(NotAuthenticated) }; + } + + public static IEnumerable EmailParsingTestCases() + { + yield return new object[] { "test@example.com", new[] { "test@example.com" } }; + yield return new object[] { "test1@example.com,test2@example.com", new[] { "test1@example.com", "test2@example.com" } }; + yield return new object[] { " test@example.com , other@example.com ", new[] { "test@example.com", "other@example.com" } }; + yield return new object[] { "test@example.com,,other@example.com", new[] { "test@example.com", "other@example.com" } }; + yield return new object[] { " , test@example.com, ,other@example.com, ", new[] { "test@example.com", "other@example.com" } }; + } + + private static Send CreateSend(int accessCount, int? maxAccessCount, string? emails, string? password) + { + return new Send + { + Id = Guid.NewGuid(), + AccessCount = accessCount, + MaxAccessCount = maxAccessCount, + Emails = emails, + Password = password + }; + } +}