using Bit.Core.AdminConsole.EventIntegrations.OrganizationIntegrations.Interfaces; using Bit.Core.Repositories; using Bit.Core.Settings; using Bit.Core.Utilities; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using NSubstitute; using StackExchange.Redis; using Xunit; using ZiggyCreatures.Caching.Fusion; namespace Bit.Core.Test.AdminConsole.EventIntegrations; public class EventIntegrationServiceCollectionExtensionsTests { private readonly IServiceCollection _services; private readonly GlobalSettings _globalSettings; public EventIntegrationServiceCollectionExtensionsTests() { _services = new ServiceCollection(); _globalSettings = CreateGlobalSettings([]); // Add required infrastructure services _services.TryAddSingleton(_globalSettings); _services.TryAddSingleton(_globalSettings); _services.AddLogging(); // Mock Redis connection for cache _services.AddSingleton(Substitute.For()); // Mock required repository dependencies for commands _services.TryAddScoped(_ => Substitute.For()); _services.TryAddScoped(_ => Substitute.For()); } [Fact] public void AddEventIntegrationsCommandsQueries_RegistersAllServices() { _services.AddEventIntegrationsCommandsQueries(_globalSettings); using var provider = _services.BuildServiceProvider(); var cache = provider.GetRequiredKeyedService(EventIntegrationsCacheConstants.CacheName); Assert.NotNull(cache); using var scope = provider.CreateScope(); var sp = scope.ServiceProvider; Assert.NotNull(sp.GetService()); Assert.NotNull(sp.GetService()); Assert.NotNull(sp.GetService()); Assert.NotNull(sp.GetService()); } [Fact] public void AddEventIntegrationsCommandsQueries_CommandsQueries_AreRegisteredAsScoped() { _services.AddEventIntegrationsCommandsQueries(_globalSettings); var createIntegrationDescriptor = _services.First(s => s.ServiceType == typeof(ICreateOrganizationIntegrationCommand)); Assert.Equal(ServiceLifetime.Scoped, createIntegrationDescriptor.Lifetime); } [Fact] public void AddEventIntegrationsCommandsQueries_CommandsQueries_DifferentInstancesPerScope() { _services.AddEventIntegrationsCommandsQueries(_globalSettings); var provider = _services.BuildServiceProvider(); ICreateOrganizationIntegrationCommand? instance1, instance2, instance3; using (var scope1 = provider.CreateScope()) { instance1 = scope1.ServiceProvider.GetService(); } using (var scope2 = provider.CreateScope()) { instance2 = scope2.ServiceProvider.GetService(); } using (var scope3 = provider.CreateScope()) { instance3 = scope3.ServiceProvider.GetService(); } Assert.NotNull(instance1); Assert.NotNull(instance2); Assert.NotNull(instance3); Assert.NotSame(instance1, instance2); Assert.NotSame(instance2, instance3); Assert.NotSame(instance1, instance3); } [Fact] public void AddEventIntegrationsCommandsQueries_CommandsQueries__SameInstanceWithinScope() { _services.AddEventIntegrationsCommandsQueries(_globalSettings); var provider = _services.BuildServiceProvider(); using var scope = provider.CreateScope(); var instance1 = scope.ServiceProvider.GetService(); var instance2 = scope.ServiceProvider.GetService(); Assert.NotNull(instance1); Assert.NotNull(instance2); Assert.Same(instance1, instance2); } [Fact] public void AddEventIntegrationsCommandsQueries_MultipleCalls_IsIdempotent() { _services.AddEventIntegrationsCommandsQueries(_globalSettings); _services.AddEventIntegrationsCommandsQueries(_globalSettings); _services.AddEventIntegrationsCommandsQueries(_globalSettings); var createConfigCmdDescriptors = _services.Where(s => s.ServiceType == typeof(ICreateOrganizationIntegrationCommand)).ToList(); Assert.Single(createConfigCmdDescriptors); var updateIntegrationCmdDescriptors = _services.Where(s => s.ServiceType == typeof(IUpdateOrganizationIntegrationCommand)).ToList(); Assert.Single(updateIntegrationCmdDescriptors); } [Fact] public void AddOrganizationIntegrationCommandsQueries_RegistersAllIntegrationServices() { _services.AddOrganizationIntegrationCommandsQueries(); Assert.Contains(_services, s => s.ServiceType == typeof(ICreateOrganizationIntegrationCommand)); Assert.Contains(_services, s => s.ServiceType == typeof(IUpdateOrganizationIntegrationCommand)); Assert.Contains(_services, s => s.ServiceType == typeof(IDeleteOrganizationIntegrationCommand)); Assert.Contains(_services, s => s.ServiceType == typeof(IGetOrganizationIntegrationsQuery)); } [Fact] public void AddOrganizationIntegrationCommandsQueries_MultipleCalls_IsIdempotent() { _services.AddOrganizationIntegrationCommandsQueries(); _services.AddOrganizationIntegrationCommandsQueries(); _services.AddOrganizationIntegrationCommandsQueries(); var createCmdDescriptors = _services.Where(s => s.ServiceType == typeof(ICreateOrganizationIntegrationCommand)).ToList(); Assert.Single(createCmdDescriptors); } private static GlobalSettings CreateGlobalSettings(Dictionary data) { var config = new ConfigurationBuilder() .AddInMemoryCollection(data) .Build(); var settings = new GlobalSettings(); config.GetSection("GlobalSettings").Bind(settings); return settings; } }