Skip to content

Commit 9d86aff

Browse files
committed
DRY up tests
1 parent 3d801be commit 9d86aff

File tree

4 files changed

+219
-206
lines changed

4 files changed

+219
-206
lines changed

src/Infrastructure.EntityFramework/Repositories/CollectionRepository.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using Bit.Core.Enums;
44
using Bit.Core.Models.Data;
55
using Bit.Core.Repositories;
6-
using Bit.Core.Utilities;
76
using Bit.Infrastructure.EntityFramework.Models;
87
using Bit.Infrastructure.EntityFramework.Repositories.Queries;
98
using LinqToDB.EntityFrameworkCore;
@@ -809,15 +808,15 @@ public async Task CreateDefaultCollectionsAsync(Guid organizationId, IEnumerable
809808
var orgUserIdWithDefaultCollection = await GetOrgUserIdsWithDefaultCollectionAsync(dbContext, organizationId);
810809
var missingDefaultCollectionUserIds = organizationUserIds.Except(orgUserIdWithDefaultCollection);
811810

812-
var (collectionUsers, collections) = CollectionUtils.BuildDefaultUserCollections(organizationId, missingDefaultCollectionUserIds, defaultCollectionName);
811+
var (collections, collectionUsers) = CollectionUtils.BuildDefaultUserCollections(organizationId, missingDefaultCollectionUserIds, defaultCollectionName);
813812

814-
if (!collectionUsers.Any() || !collections.Any())
813+
if (!collections.Any() || !collectionUsers.Any())
815814
{
816815
return;
817816
}
818817

819-
await dbContext.BulkCopyAsync(collections);
820-
await dbContext.BulkCopyAsync(collectionUsers);
818+
await dbContext.BulkCopyAsync(Mapper.Map<IEnumerable<Collection>>(collections));
819+
await dbContext.BulkCopyAsync(Mapper.Map<IEnumerable<CollectionUser>>(collectionUsers));
821820

822821
await dbContext.SaveChangesAsync();
823822
}
Lines changed: 22 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,24 @@
1-
using Bit.Core.AdminConsole.Entities;
2-
using Bit.Core.Entities;
3-
using Bit.Core.Enums;
4-
using Bit.Core.Repositories;
1+
using Bit.Core.Repositories;
52
using Xunit;
63

74
namespace Bit.Infrastructure.IntegrationTest.AdminConsole.Repositories.CollectionRepository;
85

9-
public class CreateDefaultCollectionsBulkTests
6+
7+
public class CreateDefaultCollectionsBulkAsyncTests
108
{
119
[Theory, DatabaseData]
12-
public async Task CreateDefaultCollectionsBulkAsync_ShouldCreateDefaultCollection_WhenUsersDoNotHaveDefaultCollection(
10+
public async Task CreateDefaultCollectionsBulkAsync_CreatesDefaultCollections_Success(
1311
IOrganizationRepository organizationRepository,
1412
IUserRepository userRepository,
1513
IOrganizationUserRepository organizationUserRepository,
1614
ICollectionRepository collectionRepository)
1715
{
18-
// Arrange
19-
var organization = await organizationRepository.CreateTestOrganizationAsync();
20-
21-
var resultOrganizationUsers = await Task.WhenAll(
22-
CreateUserForOrgAsync(userRepository, organizationUserRepository, organization),
23-
CreateUserForOrgAsync(userRepository, organizationUserRepository, organization)
24-
);
25-
26-
var affectedOrgUserIds = resultOrganizationUsers.Select(organizationUser => organizationUser.Id).ToList();
27-
var defaultCollectionName = $"default-name-{organization.Id}";
28-
29-
// Act
30-
await collectionRepository.CreateDefaultCollectionsBulkAsync(organization.Id, affectedOrgUserIds, defaultCollectionName);
31-
32-
// Assert
33-
await AssertAllUsersHaveOneDefaultCollectionAsync(collectionRepository, resultOrganizationUsers, organization.Id);
34-
35-
await CleanupAsync(organizationRepository, userRepository, organization, resultOrganizationUsers);
16+
await CreateDefaultCollectionsSharedTests.CreatesDefaultCollections_Success(
17+
collectionRepository.CreateDefaultCollectionsBulkAsync,
18+
organizationRepository,
19+
userRepository,
20+
organizationUserRepository,
21+
collectionRepository);
3622
}
3723

3824
[Theory, DatabaseData]
@@ -42,34 +28,12 @@ public async Task CreateDefaultCollectionsBulkAsync_CreatesForNewUsersOnly_AndIg
4228
IOrganizationUserRepository organizationUserRepository,
4329
ICollectionRepository collectionRepository)
4430
{
45-
// Arrange
46-
var organization = await organizationRepository.CreateTestOrganizationAsync();
47-
48-
var arrangedOrganizationUsers = await Task.WhenAll(
49-
CreateUserForOrgAsync(userRepository, organizationUserRepository, organization),
50-
CreateUserForOrgAsync(userRepository, organizationUserRepository, organization)
51-
);
52-
53-
var arrangedOrgUserIds = arrangedOrganizationUsers.Select(organizationUser => organizationUser.Id);
54-
var defaultCollectionName = $"default-name-{organization.Id}";
55-
56-
await CreateUsersWithExistingDefaultCollectionsAsync(collectionRepository, organization.Id, arrangedOrgUserIds, defaultCollectionName, arrangedOrganizationUsers);
57-
58-
var newOrganizationUsers = new List<OrganizationUser>
59-
{
60-
await CreateUserForOrgAsync(userRepository, organizationUserRepository, organization)
61-
};
62-
63-
var affectedOrgUsers = newOrganizationUsers.Concat(arrangedOrganizationUsers).ToList();
64-
var affectedOrgUserIds = affectedOrgUsers.Select(organizationUser => organizationUser.Id).ToList();
65-
66-
// Act
67-
await collectionRepository.CreateDefaultCollectionsBulkAsync(organization.Id, affectedOrgUserIds, defaultCollectionName);
68-
69-
// Assert
70-
await AssertAllUsersHaveOneDefaultCollectionAsync(collectionRepository, affectedOrgUsers, organization.Id);
71-
72-
await CleanupAsync(organizationRepository, userRepository, organization, affectedOrgUsers);
31+
await CreateDefaultCollectionsSharedTests.CreatesForNewUsersOnly_AndIgnoresExistingUsers(
32+
collectionRepository.CreateDefaultCollectionsBulkAsync,
33+
organizationRepository,
34+
userRepository,
35+
organizationUserRepository,
36+
collectionRepository);
7337
}
7438

7539
[Theory, DatabaseData]
@@ -79,72 +43,11 @@ public async Task CreateDefaultCollectionsBulkAsync_IgnoresAllExistingUsers(
7943
IOrganizationUserRepository organizationUserRepository,
8044
ICollectionRepository collectionRepository)
8145
{
82-
// Arrange
83-
var organization = await organizationRepository.CreateTestOrganizationAsync();
84-
85-
var resultOrganizationUsers = await Task.WhenAll(
86-
CreateUserForOrgAsync(userRepository, organizationUserRepository, organization),
87-
CreateUserForOrgAsync(userRepository, organizationUserRepository, organization)
88-
);
89-
90-
var affectedOrgUserIds = resultOrganizationUsers.Select(organizationUser => organizationUser.Id).ToList();
91-
var defaultCollectionName = $"default-name-{organization.Id}";
92-
93-
await CreateUsersWithExistingDefaultCollectionsAsync(collectionRepository, organization.Id, affectedOrgUserIds, defaultCollectionName, resultOrganizationUsers);
94-
95-
// Act - Try to create again, should silently filter and not create duplicates
96-
await collectionRepository.CreateDefaultCollectionsBulkAsync(organization.Id, affectedOrgUserIds, defaultCollectionName);
97-
98-
// Assert - Original collections should remain unchanged, still only one per user
99-
await AssertAllUsersHaveOneDefaultCollectionAsync(collectionRepository, resultOrganizationUsers, organization.Id);
100-
101-
await CleanupAsync(organizationRepository, userRepository, organization, resultOrganizationUsers);
102-
}
103-
104-
private static async Task CreateUsersWithExistingDefaultCollectionsAsync(ICollectionRepository collectionRepository,
105-
Guid organizationId, IEnumerable<Guid> affectedOrgUserIds, string defaultCollectionName,
106-
OrganizationUser[] resultOrganizationUsers)
107-
{
108-
await collectionRepository.CreateDefaultCollectionsBulkAsync(organizationId, affectedOrgUserIds, defaultCollectionName);
109-
110-
await AssertAllUsersHaveOneDefaultCollectionAsync(collectionRepository, resultOrganizationUsers, organizationId);
111-
}
112-
113-
private static async Task AssertAllUsersHaveOneDefaultCollectionAsync(ICollectionRepository collectionRepository,
114-
IEnumerable<OrganizationUser> organizationUsers, Guid organizationId)
115-
{
116-
foreach (var organizationUser in organizationUsers)
117-
{
118-
var collectionDetails = await collectionRepository.GetManyByUserIdAsync(organizationUser!.UserId.Value);
119-
var defaultCollection = collectionDetails
120-
.SingleOrDefault(collectionDetail =>
121-
collectionDetail.OrganizationId == organizationId
122-
&& collectionDetail.Type == CollectionType.DefaultUserCollection);
123-
124-
Assert.NotNull(defaultCollection);
125-
}
126-
}
127-
128-
private static async Task<OrganizationUser> CreateUserForOrgAsync(IUserRepository userRepository,
129-
IOrganizationUserRepository organizationUserRepository, Organization organization)
130-
{
131-
var user = await userRepository.CreateTestUserAsync();
132-
var orgUser = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user);
133-
134-
return orgUser;
135-
}
136-
137-
private static async Task CleanupAsync(IOrganizationRepository organizationRepository,
138-
IUserRepository userRepository,
139-
Organization organization,
140-
IEnumerable<OrganizationUser> organizationUsers)
141-
{
142-
await organizationRepository.DeleteAsync(organization);
143-
144-
await userRepository.DeleteManyAsync(
145-
organizationUsers
146-
.Where(organizationUser => organizationUser.UserId != null)
147-
.Select(organizationUser => new User() { Id = organizationUser.UserId.Value })
148-
);
46+
await CreateDefaultCollectionsSharedTests.IgnoresAllExistingUsers(
47+
collectionRepository.CreateDefaultCollectionsBulkAsync,
48+
organizationRepository,
49+
userRepository,
50+
organizationUserRepository,
51+
collectionRepository);
14952
}
15053
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
using Bit.Core.AdminConsole.Entities;
2+
using Bit.Core.Entities;
3+
using Bit.Core.Enums;
4+
using Bit.Core.Repositories;
5+
using Xunit;
6+
7+
namespace Bit.Infrastructure.IntegrationTest.AdminConsole.Repositories.CollectionRepository;
8+
9+
/// <summary>
10+
/// Shared tests for CreateDefaultCollections methods - both bulk and non-bulk implementations,
11+
/// as they share the same behavior. Both test suites call the tests in this class.
12+
/// </summary>
13+
public static class CreateDefaultCollectionsSharedTests
14+
{
15+
public static async Task CreatesDefaultCollections_Success(
16+
Func<Guid, IEnumerable<Guid>, string, Task> createDefaultCollectionsFunc,
17+
IOrganizationRepository organizationRepository,
18+
IUserRepository userRepository,
19+
IOrganizationUserRepository organizationUserRepository,
20+
ICollectionRepository collectionRepository)
21+
{
22+
// Arrange
23+
var organization = await organizationRepository.CreateTestOrganizationAsync();
24+
25+
var resultOrganizationUsers = await Task.WhenAll(
26+
CreateUserForOrgAsync(userRepository, organizationUserRepository, organization),
27+
CreateUserForOrgAsync(userRepository, organizationUserRepository, organization)
28+
);
29+
30+
var affectedOrgUserIds = resultOrganizationUsers.Select(organizationUser => organizationUser.Id).ToList();
31+
var defaultCollectionName = $"default-name-{organization.Id}";
32+
33+
// Act
34+
await createDefaultCollectionsFunc(organization.Id, affectedOrgUserIds, defaultCollectionName);
35+
36+
// Assert
37+
await AssertAllUsersHaveOneDefaultCollectionAsync(collectionRepository, resultOrganizationUsers, organization.Id);
38+
39+
await CleanupAsync(organizationRepository, userRepository, organization, resultOrganizationUsers);
40+
}
41+
42+
public static async Task CreatesForNewUsersOnly_AndIgnoresExistingUsers(
43+
Func<Guid, IEnumerable<Guid>, string, Task> createDefaultCollectionsFunc,
44+
IOrganizationRepository organizationRepository,
45+
IUserRepository userRepository,
46+
IOrganizationUserRepository organizationUserRepository,
47+
ICollectionRepository collectionRepository)
48+
{
49+
// Arrange
50+
var organization = await organizationRepository.CreateTestOrganizationAsync();
51+
52+
var arrangedOrganizationUsers = await Task.WhenAll(
53+
CreateUserForOrgAsync(userRepository, organizationUserRepository, organization),
54+
CreateUserForOrgAsync(userRepository, organizationUserRepository, organization)
55+
);
56+
57+
var arrangedOrgUserIds = arrangedOrganizationUsers.Select(organizationUser => organizationUser.Id).ToList();
58+
var defaultCollectionName = $"default-name-{organization.Id}";
59+
60+
await CreateUsersWithExistingDefaultCollectionsAsync(createDefaultCollectionsFunc, collectionRepository, organization.Id, arrangedOrgUserIds, defaultCollectionName, arrangedOrganizationUsers);
61+
62+
var newOrganizationUsers = new List<OrganizationUser>
63+
{
64+
await CreateUserForOrgAsync(userRepository, organizationUserRepository, organization)
65+
};
66+
67+
var affectedOrgUsers = newOrganizationUsers.Concat(arrangedOrganizationUsers).ToList();
68+
var affectedOrgUserIds = affectedOrgUsers.Select(organizationUser => organizationUser.Id).ToList();
69+
70+
// Act
71+
await createDefaultCollectionsFunc(organization.Id, affectedOrgUserIds, defaultCollectionName);
72+
73+
// Assert
74+
await AssertAllUsersHaveOneDefaultCollectionAsync(collectionRepository, affectedOrgUsers, organization.Id);
75+
76+
await CleanupAsync(organizationRepository, userRepository, organization, affectedOrgUsers);
77+
}
78+
79+
public static async Task IgnoresAllExistingUsers(
80+
Func<Guid, IEnumerable<Guid>, string, Task> createDefaultCollectionsFunc,
81+
IOrganizationRepository organizationRepository,
82+
IUserRepository userRepository,
83+
IOrganizationUserRepository organizationUserRepository,
84+
ICollectionRepository collectionRepository)
85+
{
86+
// Arrange
87+
var organization = await organizationRepository.CreateTestOrganizationAsync();
88+
89+
var resultOrganizationUsers = await Task.WhenAll(
90+
CreateUserForOrgAsync(userRepository, organizationUserRepository, organization),
91+
CreateUserForOrgAsync(userRepository, organizationUserRepository, organization)
92+
);
93+
94+
var affectedOrgUserIds = resultOrganizationUsers.Select(organizationUser => organizationUser.Id).ToList();
95+
var defaultCollectionName = $"default-name-{organization.Id}";
96+
97+
await CreateUsersWithExistingDefaultCollectionsAsync(createDefaultCollectionsFunc, collectionRepository, organization.Id, affectedOrgUserIds, defaultCollectionName, resultOrganizationUsers);
98+
99+
// Act - Try to create again, should silently filter and not create duplicates
100+
await createDefaultCollectionsFunc(organization.Id, affectedOrgUserIds, defaultCollectionName);
101+
102+
// Assert - Original collections should remain unchanged, still only one per user
103+
await AssertAllUsersHaveOneDefaultCollectionAsync(collectionRepository, resultOrganizationUsers, organization.Id);
104+
105+
await CleanupAsync(organizationRepository, userRepository, organization, resultOrganizationUsers);
106+
}
107+
108+
private static async Task CreateUsersWithExistingDefaultCollectionsAsync(
109+
Func<Guid, IEnumerable<Guid>, string, Task> createDefaultCollectionsFunc,
110+
ICollectionRepository collectionRepository,
111+
Guid organizationId,
112+
IEnumerable<Guid> affectedOrgUserIds,
113+
string defaultCollectionName,
114+
OrganizationUser[] resultOrganizationUsers)
115+
{
116+
await createDefaultCollectionsFunc(organizationId, affectedOrgUserIds, defaultCollectionName);
117+
118+
await AssertAllUsersHaveOneDefaultCollectionAsync(collectionRepository, resultOrganizationUsers, organizationId);
119+
}
120+
121+
private static async Task AssertAllUsersHaveOneDefaultCollectionAsync(ICollectionRepository collectionRepository,
122+
IEnumerable<OrganizationUser> organizationUsers, Guid organizationId)
123+
{
124+
foreach (var organizationUser in organizationUsers)
125+
{
126+
var collectionDetails = await collectionRepository.GetManyByUserIdAsync(organizationUser!.UserId.Value);
127+
var defaultCollection = collectionDetails
128+
.SingleOrDefault(collectionDetail =>
129+
collectionDetail.OrganizationId == organizationId
130+
&& collectionDetail.Type == CollectionType.DefaultUserCollection);
131+
132+
Assert.NotNull(defaultCollection);
133+
}
134+
}
135+
136+
private static async Task<OrganizationUser> CreateUserForOrgAsync(IUserRepository userRepository,
137+
IOrganizationUserRepository organizationUserRepository, Organization organization)
138+
{
139+
var user = await userRepository.CreateTestUserAsync();
140+
var orgUser = await organizationUserRepository.CreateTestOrganizationUserAsync(organization, user);
141+
142+
return orgUser;
143+
}
144+
145+
private static async Task CleanupAsync(IOrganizationRepository organizationRepository,
146+
IUserRepository userRepository,
147+
Organization organization,
148+
IEnumerable<OrganizationUser> organizationUsers)
149+
{
150+
await organizationRepository.DeleteAsync(organization);
151+
152+
await userRepository.DeleteManyAsync(
153+
organizationUsers
154+
.Where(organizationUser => organizationUser.UserId != null)
155+
.Select(organizationUser => new User() { Id = organizationUser.UserId.Value })
156+
);
157+
}
158+
}

0 commit comments

Comments
 (0)