diff --git a/test/Core.Test/Services/CollectionServiceTests.cs b/test/Core.Test/Services/CollectionServiceTests.cs new file mode 100644 index 0000000000..ccf042823c --- /dev/null +++ b/test/Core.Test/Services/CollectionServiceTests.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Xunit; +using Bit.Core.Repositories; +using Bit.Core.Services; +using NSubstitute; +using Bit.Core.Exceptions; + +namespace Bit.Core.Test.Services +{ + public class CollectionServiceTest + { + readonly IEventService _eventService; + readonly IOrganizationRepository _organizationRepository; + readonly IOrganizationUserRepository _organizationUserRepository; + readonly ICollectionRepository _collectionRepository; + readonly IUserRepository _userRepository; + readonly IMailService _mailService; + + public CollectionServiceTest() + { + _eventService = Substitute.For(); + _organizationRepository = Substitute.For(); + _organizationUserRepository = Substitute.For(); + _collectionRepository = Substitute.For(); + _userRepository = Substitute.For(); + _mailService = Substitute.For(); + } + + [Fact] + public async Task SaveAsync_CollectionNotFound() + { + var collectionService = new CollectionService(_eventService, + _organizationRepository, + _organizationUserRepository, + _collectionRepository, + _userRepository, + _mailService); + + var id = Guid.NewGuid(); + + var collection = new Models.Table.Collection + { + Id = id, + }; + + var ex = await Assert.ThrowsAsync(() => collectionService.SaveAsync(collection)); + + Assert.Equal("The model state is invalid.", ex.Message); + Assert.Equal(1, ex.ModelState.ErrorCount); + Assert.Equal("Organization not found", ex.ModelState.Root.Errors[0].ErrorMessage); + } + + [Fact] + public async Task SaveAsync_DefaultCollectionId_createsCollectionInTheRepository() + { + // prepare the organization + var testOrganizationId = Guid.NewGuid(); + var testOrganization = new Models.Table.Organization() + { + Id = testOrganizationId, + }; + _organizationRepository.GetByIdAsync(testOrganizationId).Returns(testOrganization); + + var collectionService = new CollectionService(_eventService, + _organizationRepository, + _organizationUserRepository, + _collectionRepository, + _userRepository, + _mailService); + + // execute + var testCollection = new Models.Table.Collection + { + OrganizationId = testOrganizationId, + }; + await collectionService.SaveAsync(testCollection); + + // verify + await _collectionRepository.Received().CreateAsync(testCollection); + } + + [Fact] + public async Task SaveAsync_respectsMaxNumberOfCollectionsPerOrganization() + { + // prepare the organization + var testOrganizationId = Guid.NewGuid(); + var testOrganization = new Models.Table.Organization() + { + Id = testOrganizationId, + MaxCollections = 2, + }; + _organizationRepository.GetByIdAsync(testOrganizationId).Returns(testOrganization); + _collectionRepository.GetCountByOrganizationIdAsync(testOrganizationId).Returns(2); + + // execute + var collectionService = new CollectionService(_eventService, + _organizationRepository, + _organizationUserRepository, + _collectionRepository, + _userRepository, + _mailService); + + var testCollection = new Models.Table.Collection { OrganizationId = testOrganizationId }; + + // verify & expect exception to be thrown + var ex = await Assert.ThrowsAsync(() => collectionService.SaveAsync(testCollection)); + + Assert.Equal("The model state is invalid.", ex.Message); + Assert.Equal(1, ex.ModelState.ErrorCount); + Assert.Equal("You have reached the maximum number of collections (2) for this organization.", + ex.ModelState.Root.Errors[0].ErrorMessage); + } + + [Fact] + public async Task DeleteUserAsync_deletesValidUserWhoBelongsToCollection() + { + // prepare the organization + var testOrganizationId = Guid.NewGuid(); + var testOrganization = new Models.Table.Organization() + { + Id = testOrganizationId, + }; + var testUserId = Guid.NewGuid(); + var organizationUser = new Models.Table.OrganizationUser + { + Id = testUserId, + OrganizationId = testOrganizationId, + }; + _organizationUserRepository.GetByIdAsync(testUserId).Returns(organizationUser); + + // execute + var collectionService = new CollectionService(_eventService, + _organizationRepository, + _organizationUserRepository, + _collectionRepository, + _userRepository, + _mailService); + + var testCollection = new Models.Table.Collection { OrganizationId = testOrganizationId }; + await collectionService.DeleteUserAsync(testCollection, organizationUser.Id); + + // verify + await _collectionRepository.Received().DeleteUserAsync(testCollection.Id, organizationUser.Id); + } + + [Fact] + public async Task DeleteUserAsync_throwsIfUserIsInvalid() + { + // prepare the organization + var testOrganizationId = Guid.NewGuid(); + var testOrganization = new Models.Table.Organization() + { + Id = testOrganizationId, + }; + var testUserId = Guid.NewGuid(); + var nonOrganizationUser = new Models.Table.OrganizationUser + { + Id = testUserId, + OrganizationId = Guid.NewGuid(), + }; + _organizationUserRepository.GetByIdAsync(testUserId).Returns(nonOrganizationUser); + + // execute + var collectionService = new CollectionService(_eventService, + _organizationRepository, + _organizationUserRepository, + _collectionRepository, + _userRepository, + _mailService); + + var testCollection = new Models.Table.Collection { OrganizationId = testOrganizationId }; + + // verify + // invalid user + await Assert.ThrowsAsync(() => collectionService.DeleteUserAsync(testCollection, Guid.NewGuid())); + // user from other organization + await Assert.ThrowsAsync(() => collectionService.DeleteUserAsync(testCollection, testUserId)); + } + } +}