You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
611 lines
23 KiB
611 lines
23 KiB
using Bit.Core.AdminConsole.Entities; |
|
using Bit.Core.AdminConsole.Repositories; |
|
using Bit.Core.Billing.Enums; |
|
using Bit.Core.Entities; |
|
using Bit.Core.Enums; |
|
using Bit.Core.Models.Data; |
|
using Bit.Core.Repositories; |
|
using Xunit; |
|
|
|
namespace Bit.Infrastructure.IntegrationTest.AdminConsole.Repositories.CollectionRepository; |
|
|
|
public class CollectionRepositoryTests |
|
{ |
|
/// <summary> |
|
/// Test to ensure that access relationships are retrieved when requested |
|
/// </summary> |
|
[DatabaseTheory, DatabaseData] |
|
public async Task GetByIdWithPermissionsAsync_WithRelationships_Success(IUserRepository userRepository, |
|
IOrganizationRepository organizationRepository, |
|
ICollectionRepository collectionRepository, |
|
IOrganizationUserRepository organizationUserRepository, IGroupRepository groupRepository) |
|
{ |
|
var user = await userRepository.CreateAsync(new User |
|
{ |
|
Name = "Test User", |
|
Email = $"test+{Guid.NewGuid()}@email.com", |
|
ApiKey = "TEST", |
|
SecurityStamp = "stamp", |
|
}); |
|
|
|
var organization = await organizationRepository.CreateAsync(new Organization |
|
{ |
|
Name = "Test Org", |
|
PlanType = PlanType.EnterpriseAnnually, |
|
Plan = "Test Plan", |
|
BillingEmail = "billing@email.com" |
|
}); |
|
|
|
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser |
|
{ |
|
OrganizationId = organization.Id, |
|
UserId = user.Id, |
|
Status = OrganizationUserStatusType.Confirmed, |
|
}); |
|
|
|
var group = await groupRepository.CreateAsync(new Group |
|
{ |
|
Name = "Test Group", |
|
OrganizationId = organization.Id, |
|
}); |
|
|
|
var collection = new Collection { Name = "Test Collection", OrganizationId = organization.Id, }; |
|
|
|
await collectionRepository.CreateAsync(collection, groups: new[] |
|
{ |
|
new CollectionAccessSelection |
|
{ |
|
Id = group.Id, HidePasswords = false, ReadOnly = true, Manage = false |
|
} |
|
}, users: new[] |
|
{ |
|
new CollectionAccessSelection() |
|
{ |
|
Id = orgUser.Id, HidePasswords = false, ReadOnly = false, Manage = true |
|
} |
|
}); |
|
|
|
var collectionWithPermissions = await collectionRepository.GetByIdWithPermissionsAsync(collection.Id, user.Id, true); |
|
|
|
Assert.NotNull(collectionWithPermissions); |
|
Assert.Equal(1, collectionWithPermissions.Users?.Count()); |
|
Assert.Equal(1, collectionWithPermissions.Groups?.Count()); |
|
Assert.True(collectionWithPermissions.Assigned); |
|
Assert.True(collectionWithPermissions.Manage); |
|
Assert.False(collectionWithPermissions.ReadOnly); |
|
Assert.False(collectionWithPermissions.HidePasswords); |
|
} |
|
|
|
/// <summary> |
|
/// Test to ensure that a user's explicitly assigned permissions replaces any group permissions |
|
/// that user may belong to |
|
/// </summary> |
|
[DatabaseTheory, DatabaseData] |
|
public async Task GetByIdWithPermissionsAsync_UserOverrideGroup_Success(IUserRepository userRepository, |
|
IOrganizationRepository organizationRepository, |
|
ICollectionRepository collectionRepository, |
|
IOrganizationUserRepository organizationUserRepository, IGroupRepository groupRepository) |
|
{ |
|
var user = await userRepository.CreateAsync(new User |
|
{ |
|
Name = "Test User", |
|
Email = $"test+{Guid.NewGuid()}@email.com", |
|
ApiKey = "TEST", |
|
SecurityStamp = "stamp", |
|
}); |
|
|
|
var organization = await organizationRepository.CreateAsync(new Organization |
|
{ |
|
Name = "Test Org", |
|
PlanType = PlanType.EnterpriseAnnually, |
|
Plan = "Test Plan", |
|
BillingEmail = "billing@email.com" |
|
}); |
|
|
|
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser |
|
{ |
|
OrganizationId = organization.Id, |
|
UserId = user.Id, |
|
Status = OrganizationUserStatusType.Confirmed, |
|
}); |
|
|
|
var group = await groupRepository.CreateAsync(new Group |
|
{ |
|
Name = "Test Group", |
|
OrganizationId = organization.Id, |
|
}); |
|
|
|
// Assign the test user to the test group |
|
await groupRepository.UpdateUsersAsync(group.Id, new[] { orgUser.Id }); |
|
|
|
var collection = new Collection { Name = "Test Collection", OrganizationId = organization.Id, }; |
|
|
|
await collectionRepository.CreateAsync(collection, groups: new[] |
|
{ |
|
new CollectionAccessSelection |
|
{ |
|
Id = group.Id, HidePasswords = false, ReadOnly = false, Manage = true // Group is Manage |
|
} |
|
}, users: new[] |
|
{ |
|
new CollectionAccessSelection() |
|
{ |
|
Id = orgUser.Id, HidePasswords = false, ReadOnly = true, Manage = false // User is given ReadOnly (should override group) |
|
} |
|
}); |
|
|
|
var collectionWithPermissions = await collectionRepository.GetByIdWithPermissionsAsync(collection.Id, user.Id, true); |
|
|
|
Assert.NotNull(collectionWithPermissions); |
|
Assert.Equal(1, collectionWithPermissions.Users?.Count()); |
|
Assert.Equal(1, collectionWithPermissions.Groups?.Count()); |
|
Assert.True(collectionWithPermissions.Assigned); |
|
Assert.False(collectionWithPermissions.Manage); |
|
Assert.True(collectionWithPermissions.ReadOnly); |
|
Assert.False(collectionWithPermissions.HidePasswords); |
|
} |
|
|
|
/// <summary> |
|
/// Test to ensure that the returned permissions are the most permissive combination of group permissions when |
|
/// multiple groups are assigned to the same collection with different permissions |
|
/// </summary> |
|
[DatabaseTheory, DatabaseData] |
|
public async Task GetByIdWithPermissionsAsync_CombineGroupPermissions_Success(IUserRepository userRepository, |
|
IOrganizationRepository organizationRepository, |
|
ICollectionRepository collectionRepository, |
|
IOrganizationUserRepository organizationUserRepository, IGroupRepository groupRepository) |
|
{ |
|
var user = await userRepository.CreateAsync(new User |
|
{ |
|
Name = "Test User", |
|
Email = $"test+{Guid.NewGuid()}@email.com", |
|
ApiKey = "TEST", |
|
SecurityStamp = "stamp", |
|
}); |
|
|
|
var organization = await organizationRepository.CreateAsync(new Organization |
|
{ |
|
Name = "Test Org", |
|
PlanType = PlanType.EnterpriseAnnually, |
|
Plan = "Test Plan", |
|
BillingEmail = "billing@email.com" |
|
}); |
|
|
|
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser |
|
{ |
|
OrganizationId = organization.Id, |
|
UserId = user.Id, |
|
Status = OrganizationUserStatusType.Confirmed, |
|
}); |
|
|
|
var group = await groupRepository.CreateAsync(new Group |
|
{ |
|
Name = "Test Group", |
|
OrganizationId = organization.Id, |
|
}); |
|
|
|
var group2 = await groupRepository.CreateAsync(new Group |
|
{ |
|
Name = "Test Group 2", |
|
OrganizationId = organization.Id, |
|
}); |
|
|
|
// Assign the test user to the test groups |
|
await groupRepository.UpdateUsersAsync(group.Id, new[] { orgUser.Id }); |
|
await groupRepository.UpdateUsersAsync(group2.Id, new[] { orgUser.Id }); |
|
|
|
var collection = new Collection { Name = "Test Collection", OrganizationId = organization.Id, }; |
|
|
|
await collectionRepository.CreateAsync(collection, groups: new[] |
|
{ |
|
new CollectionAccessSelection |
|
{ |
|
Id = group.Id, HidePasswords = false, ReadOnly = true, Manage = false // Group 1 is ReadOnly |
|
}, |
|
new CollectionAccessSelection |
|
{ |
|
Id = group2.Id, HidePasswords = false, ReadOnly = false, Manage = true // Group 2 is Manage |
|
} |
|
}, users: new List<CollectionAccessSelection>()); // No explicit user permissions for this test |
|
|
|
var collectionWithPermissions = await collectionRepository.GetByIdWithPermissionsAsync(collection.Id, user.Id, true); |
|
|
|
Assert.NotNull(collectionWithPermissions); |
|
Assert.Equal(2, collectionWithPermissions.Groups?.Count()); |
|
Assert.True(collectionWithPermissions.Assigned); |
|
|
|
// Since Group2 is Manage the user should have Manage |
|
Assert.True(collectionWithPermissions.Manage); |
|
|
|
// Similarly, ReadOnly and HidePassword should be false |
|
Assert.False(collectionWithPermissions.ReadOnly); |
|
Assert.False(collectionWithPermissions.HidePasswords); |
|
} |
|
|
|
/// <summary> |
|
/// Test to ensure the basic usage works as expected |
|
/// </summary> |
|
[DatabaseTheory, DatabaseData] |
|
public async Task GetManyByOrganizationIdWithPermissionsAsync_Success(IUserRepository userRepository, |
|
IOrganizationRepository organizationRepository, |
|
ICollectionRepository collectionRepository, |
|
IOrganizationUserRepository organizationUserRepository, IGroupRepository groupRepository) |
|
{ |
|
var user = await userRepository.CreateAsync(new User |
|
{ |
|
Name = "Test User", |
|
Email = $"test+{Guid.NewGuid()}@email.com", |
|
ApiKey = "TEST", |
|
SecurityStamp = "stamp", |
|
}); |
|
|
|
var organization = await organizationRepository.CreateAsync(new Organization |
|
{ |
|
Name = "Test Org", |
|
PlanType = PlanType.EnterpriseAnnually, |
|
Plan = "Test Plan", |
|
BillingEmail = "billing@email.com" |
|
}); |
|
|
|
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser |
|
{ |
|
OrganizationId = organization.Id, |
|
UserId = user.Id, |
|
Status = OrganizationUserStatusType.Confirmed, |
|
}); |
|
|
|
var group = await groupRepository.CreateAsync(new Group |
|
{ |
|
Name = "Test Group", |
|
OrganizationId = organization.Id, |
|
}); |
|
|
|
var collection1 = new Collection { Name = "Collection 1", OrganizationId = organization.Id, }; |
|
|
|
await collectionRepository.CreateAsync(collection1, groups: new[] |
|
{ |
|
new CollectionAccessSelection |
|
{ |
|
Id = group.Id, HidePasswords = false, ReadOnly = true, Manage = false |
|
} |
|
}, users: new[] |
|
{ |
|
new CollectionAccessSelection() |
|
{ |
|
Id = orgUser.Id, HidePasswords = false, ReadOnly = false, Manage = true |
|
} |
|
}); |
|
|
|
var collection2 = new Collection { Name = "Collection 2", OrganizationId = organization.Id, }; |
|
|
|
await collectionRepository.CreateAsync(collection2, null, users: new[] |
|
{ |
|
new CollectionAccessSelection() |
|
{ |
|
Id = orgUser.Id, HidePasswords = false, ReadOnly = true, Manage = false |
|
} |
|
}); |
|
|
|
var collection3 = new Collection { Name = "Collection 3", OrganizationId = organization.Id, }; |
|
|
|
await collectionRepository.CreateAsync(collection3, groups: new[] |
|
{ |
|
new CollectionAccessSelection() |
|
{ |
|
Id = group.Id, HidePasswords = false, ReadOnly = false, Manage = true |
|
} |
|
}, null); |
|
|
|
// Create a default user collection (should be excluded from admin console results) |
|
var defaultCollection = new Collection |
|
{ |
|
Name = "My Items Collection", |
|
OrganizationId = organization.Id, |
|
Type = CollectionType.DefaultUserCollection |
|
}; |
|
|
|
await collectionRepository.CreateAsync(defaultCollection, null, users: new[] |
|
{ |
|
new CollectionAccessSelection() |
|
{ |
|
Id = orgUser.Id, HidePasswords = false, ReadOnly = false, Manage = true |
|
} |
|
}); |
|
|
|
var collections = await collectionRepository.GetManyByOrganizationIdWithPermissionsAsync(organization.Id, user.Id, true); |
|
|
|
Assert.NotNull(collections); |
|
|
|
// Should return only 3 collections (excluding the default user collection) |
|
Assert.Equal(3, collections.Count); |
|
|
|
collections = collections.OrderBy(c => c.Name).ToList(); |
|
|
|
Assert.Collection(collections, c1 => |
|
{ |
|
Assert.NotNull(c1); |
|
Assert.Equal(1, c1.Users?.Count()); |
|
Assert.Equal(1, c1.Groups?.Count()); |
|
Assert.True(c1.Assigned); |
|
Assert.True(c1.Manage); |
|
Assert.False(c1.ReadOnly); |
|
Assert.False(c1.HidePasswords); |
|
Assert.False(c1.Unmanaged); |
|
}, c2 => |
|
{ |
|
Assert.NotNull(c2); |
|
Assert.Equal(1, c2.Users?.Count()); |
|
Assert.Equal(0, c2.Groups?.Count()); |
|
Assert.True(c2.Assigned); |
|
Assert.False(c2.Manage); |
|
Assert.True(c2.ReadOnly); |
|
Assert.False(c2.HidePasswords); |
|
Assert.True(c2.Unmanaged); |
|
}, c3 => |
|
{ |
|
Assert.NotNull(c3); |
|
Assert.Equal(0, c3.Users?.Count()); |
|
Assert.Equal(1, c3.Groups?.Count()); |
|
Assert.False(c3.Assigned); |
|
Assert.False(c3.Manage); |
|
Assert.False(c3.ReadOnly); |
|
Assert.False(c3.HidePasswords); |
|
Assert.False(c3.Unmanaged); |
|
}); |
|
} |
|
|
|
/// <summary> |
|
/// Test to ensure collections assigned to multiple groups do not duplicate in the results |
|
/// </summary> |
|
[DatabaseTheory, DatabaseData] |
|
public async Task GetManyByOrganizationIdWithPermissionsAsync_GroupBy_Success(IUserRepository userRepository, |
|
IOrganizationRepository organizationRepository, |
|
ICollectionRepository collectionRepository, |
|
IOrganizationUserRepository organizationUserRepository, IGroupRepository groupRepository) |
|
{ |
|
var user = await userRepository.CreateAsync(new User |
|
{ |
|
Name = "Test User", |
|
Email = $"test+{Guid.NewGuid()}@email.com", |
|
ApiKey = "TEST", |
|
SecurityStamp = "stamp", |
|
}); |
|
|
|
var organization = await organizationRepository.CreateAsync(new Organization |
|
{ |
|
Name = "Test Org", |
|
PlanType = PlanType.EnterpriseAnnually, |
|
Plan = "Test Plan", |
|
BillingEmail = "billing@email.com" |
|
}); |
|
|
|
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser |
|
{ |
|
OrganizationId = organization.Id, |
|
UserId = user.Id, |
|
Status = OrganizationUserStatusType.Confirmed, |
|
}); |
|
|
|
var group = await groupRepository.CreateAsync(new Group |
|
{ |
|
Name = "Test Group", |
|
OrganizationId = organization.Id, |
|
}); |
|
|
|
var group2 = await groupRepository.CreateAsync(new Group |
|
{ |
|
Name = "Test Group 2", |
|
OrganizationId = organization.Id, |
|
}); |
|
|
|
// Assign the test user to the test groups |
|
await groupRepository.UpdateUsersAsync(group.Id, new[] { orgUser.Id }); |
|
await groupRepository.UpdateUsersAsync(group2.Id, new[] { orgUser.Id }); |
|
|
|
var collection1 = new Collection { Name = "Collection 1", OrganizationId = organization.Id, }; |
|
|
|
await collectionRepository.CreateAsync(collection1, groups: new[] |
|
{ |
|
new CollectionAccessSelection |
|
{ |
|
Id = group.Id, HidePasswords = false, ReadOnly = true, Manage = false |
|
}, |
|
}, users: new[] |
|
{ |
|
new CollectionAccessSelection() |
|
{ |
|
Id = orgUser.Id, HidePasswords = false, ReadOnly = false, Manage = true |
|
} |
|
}); |
|
|
|
var collection2 = new Collection { Name = "Collection 2", OrganizationId = organization.Id, }; |
|
|
|
await collectionRepository.CreateAsync(collection2, null, users: new[] |
|
{ |
|
new CollectionAccessSelection() |
|
{ |
|
Id = orgUser.Id, HidePasswords = false, ReadOnly = true, Manage = false |
|
} |
|
}); |
|
|
|
var collection3 = new Collection { Name = "Collection 3", OrganizationId = organization.Id, }; |
|
|
|
await collectionRepository.CreateAsync(collection3, groups: new[] |
|
{ |
|
new CollectionAccessSelection() |
|
{ |
|
Id = group.Id, HidePasswords = false, ReadOnly = false, Manage = true |
|
}, |
|
new CollectionAccessSelection() |
|
{ |
|
Id = group2.Id, HidePasswords = false, ReadOnly = true, Manage = false |
|
} |
|
}, null); |
|
|
|
var collections = await collectionRepository.GetManyByOrganizationIdWithPermissionsAsync(organization.Id, user.Id, true); |
|
|
|
Assert.NotNull(collections); |
|
|
|
Assert.Equal(3, collections.Count); |
|
|
|
collections = collections.OrderBy(c => c.Name).ToList(); |
|
|
|
Assert.Collection(collections, c1 => |
|
{ |
|
Assert.NotNull(c1); |
|
Assert.Equal(1, c1.Users?.Count()); |
|
Assert.Equal(1, c1.Groups?.Count()); |
|
Assert.True(c1.Assigned); |
|
Assert.True(c1.Manage); |
|
Assert.False(c1.ReadOnly); |
|
Assert.False(c1.HidePasswords); |
|
Assert.False(c1.Unmanaged); |
|
}, c2 => |
|
{ |
|
Assert.NotNull(c2); |
|
Assert.Equal(1, c2.Users?.Count()); |
|
Assert.Equal(0, c2.Groups?.Count()); |
|
Assert.True(c2.Assigned); |
|
Assert.False(c2.Manage); |
|
Assert.True(c2.ReadOnly); |
|
Assert.False(c2.HidePasswords); |
|
Assert.True(c2.Unmanaged); |
|
}, c3 => |
|
{ |
|
Assert.NotNull(c3); |
|
Assert.Equal(0, c3.Users?.Count()); |
|
Assert.Equal(2, c3.Groups?.Count()); |
|
Assert.True(c3.Assigned); // User is a member of both Groups |
|
Assert.True(c3.Manage); // Group 2 is Manage |
|
Assert.False(c3.ReadOnly); |
|
Assert.False(c3.HidePasswords); |
|
Assert.False(c3.Unmanaged); |
|
}); |
|
} |
|
|
|
/// <summary> |
|
/// Test to ensure collections are properly retrieved by organization |
|
/// </summary> |
|
[DatabaseTheory, DatabaseData] |
|
public async Task GetManyByOrganizationIdAsync_Success( |
|
IUserRepository userRepository, |
|
IOrganizationRepository organizationRepository, |
|
ICollectionRepository collectionRepository, |
|
IOrganizationUserRepository organizationUserRepository) |
|
{ |
|
var user = await userRepository.CreateAsync(new User |
|
{ |
|
Name = "Test User", |
|
Email = $"test+{Guid.NewGuid()}@email.com", |
|
ApiKey = "TEST", |
|
SecurityStamp = "stamp", |
|
}); |
|
|
|
var organization = await organizationRepository.CreateAsync(new Organization |
|
{ |
|
Name = "Test Org", |
|
PlanType = PlanType.EnterpriseAnnually, |
|
Plan = "Test Plan", |
|
BillingEmail = "billing@email.com" |
|
}); |
|
|
|
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser |
|
{ |
|
OrganizationId = organization.Id, |
|
UserId = user.Id, |
|
Status = OrganizationUserStatusType.Confirmed, |
|
}); |
|
|
|
var collection1 = new Collection { Name = "Collection 1", OrganizationId = organization.Id, }; |
|
await collectionRepository.CreateAsync(collection1, null, null); |
|
|
|
var collection2 = new Collection { Name = "Collection 2", OrganizationId = organization.Id, }; |
|
await collectionRepository.CreateAsync(collection2, null, null); |
|
|
|
var collection3 = new Collection { Name = "Collection 3", OrganizationId = organization.Id, }; |
|
await collectionRepository.CreateAsync(collection3, null, null); |
|
|
|
// Create a default user collection |
|
var defaultCollection = new Collection |
|
{ |
|
Name = "My Items", |
|
OrganizationId = organization.Id, |
|
Type = CollectionType.DefaultUserCollection |
|
}; |
|
await collectionRepository.CreateAsync(defaultCollection, null, null); |
|
|
|
var collections = await collectionRepository.GetManyByOrganizationIdAsync(organization.Id); |
|
|
|
Assert.NotNull(collections); |
|
Assert.Equal(4, collections.Count); |
|
Assert.All(collections, c => Assert.Equal(organization.Id, c.OrganizationId)); |
|
|
|
Assert.Contains(collections, c => c.Name == "Collection 1"); |
|
Assert.Contains(collections, c => c.Name == "Collection 2"); |
|
Assert.Contains(collections, c => c.Name == "Collection 3"); |
|
Assert.Contains(collections, c => c.Name == "My Items"); |
|
} |
|
|
|
/// <summary> |
|
/// Test to ensure organization properly retrieves shared collections |
|
/// </summary> |
|
[DatabaseTheory, DatabaseData] |
|
public async Task GetManySharedCollectionsByOrganizationIdAsync_Success( |
|
IUserRepository userRepository, |
|
IOrganizationRepository organizationRepository, |
|
ICollectionRepository collectionRepository, |
|
IOrganizationUserRepository organizationUserRepository) |
|
{ |
|
var user = await userRepository.CreateAsync(new User |
|
{ |
|
Name = "Test User", |
|
Email = $"test+{Guid.NewGuid()}@email.com", |
|
ApiKey = "TEST", |
|
SecurityStamp = "stamp", |
|
}); |
|
|
|
var organization = await organizationRepository.CreateAsync(new Organization |
|
{ |
|
Name = "Test Org", |
|
PlanType = PlanType.EnterpriseAnnually, |
|
Plan = "Test Plan", |
|
BillingEmail = "billing@email.com" |
|
}); |
|
|
|
var orgUser = await organizationUserRepository.CreateAsync(new OrganizationUser |
|
{ |
|
OrganizationId = organization.Id, |
|
UserId = user.Id, |
|
Status = OrganizationUserStatusType.Confirmed, |
|
}); |
|
|
|
var collection1 = new Collection { Name = "Collection 1", OrganizationId = organization.Id, }; |
|
await collectionRepository.CreateAsync(collection1, null, null); |
|
|
|
var collection2 = new Collection { Name = "Collection 2", OrganizationId = organization.Id, }; |
|
await collectionRepository.CreateAsync(collection2, null, null); |
|
|
|
var collection3 = new Collection { Name = "Collection 3", OrganizationId = organization.Id, }; |
|
await collectionRepository.CreateAsync(collection3, null, null); |
|
|
|
// Create a default user collection (should not be returned by this method) |
|
var defaultCollection = new Collection |
|
{ |
|
Name = "My Items", |
|
OrganizationId = organization.Id, |
|
Type = CollectionType.DefaultUserCollection |
|
}; |
|
await collectionRepository.CreateAsync(defaultCollection, null, null); |
|
|
|
var collections = await collectionRepository.GetManySharedCollectionsByOrganizationIdAsync(organization.Id); |
|
|
|
Assert.NotNull(collections); |
|
Assert.Equal(3, collections.Count); // Should only return the 3 shared collections, excluding the default user collection |
|
Assert.All(collections, c => Assert.Equal(organization.Id, c.OrganizationId)); |
|
|
|
Assert.Contains(collections, c => c.Name == "Collection 1"); |
|
Assert.Contains(collections, c => c.Name == "Collection 2"); |
|
Assert.Contains(collections, c => c.Name == "Collection 3"); |
|
Assert.DoesNotContain(collections, c => c.Name == "My Items"); |
|
} |
|
}
|
|
|