Skip to content

Commit c39e0d3

Browse files
committed
Initial commit
1 parent 39ac933 commit c39e0d3

File tree

2 files changed

+537
-0
lines changed

2 files changed

+537
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
using Bit.Billing.Constants;
2+
using Bit.Billing.Services;
3+
using Bit.Billing.Services.Implementations;
4+
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations.Interfaces;
5+
using Bit.Core.Services;
6+
using NSubstitute;
7+
using Stripe;
8+
using Xunit;
9+
10+
namespace Bit.Billing.Test.Services;
11+
12+
public class SubscriptionDeletedHandlerTests
13+
{
14+
private readonly IStripeEventService _stripeEventService;
15+
private readonly IUserService _userService;
16+
private readonly IStripeEventUtilityService _stripeEventUtilityService;
17+
private readonly IOrganizationDisableCommand _organizationDisableCommand;
18+
private readonly SubscriptionDeletedHandler _sut;
19+
20+
public SubscriptionDeletedHandlerTests()
21+
{
22+
_stripeEventService = Substitute.For<IStripeEventService>();
23+
_userService = Substitute.For<IUserService>();
24+
_stripeEventUtilityService = Substitute.For<IStripeEventUtilityService>();
25+
_organizationDisableCommand = Substitute.For<IOrganizationDisableCommand>();
26+
_sut = new SubscriptionDeletedHandler(
27+
_stripeEventService,
28+
_userService,
29+
_stripeEventUtilityService,
30+
_organizationDisableCommand);
31+
}
32+
33+
[Fact]
34+
public async Task HandleAsync_SubscriptionNotCanceled_DoesNothing()
35+
{
36+
// Arrange
37+
var stripeEvent = new Event();
38+
var subscription = new Subscription
39+
{
40+
Status = "active",
41+
CurrentPeriodEnd = DateTime.UtcNow.AddDays(30),
42+
Metadata = new Dictionary<string, string>()
43+
};
44+
45+
_stripeEventService.GetSubscription(stripeEvent, true).Returns(subscription);
46+
_stripeEventUtilityService.GetIdsFromMetadata(subscription.Metadata)
47+
.Returns(Tuple.Create<Guid?, Guid?, Guid?>(null, null, null));
48+
49+
// Act
50+
await _sut.HandleAsync(stripeEvent);
51+
52+
// Assert
53+
await _organizationDisableCommand.DidNotReceiveWithAnyArgs().DisableAsync(default, default);
54+
await _userService.DidNotReceiveWithAnyArgs().DisablePremiumAsync(default, default);
55+
}
56+
57+
[Fact]
58+
public async Task HandleAsync_OrganizationSubscriptionCanceled_DisablesOrganization()
59+
{
60+
// Arrange
61+
var stripeEvent = new Event();
62+
var organizationId = Guid.NewGuid();
63+
var subscription = new Subscription
64+
{
65+
Status = StripeSubscriptionStatus.Canceled,
66+
CurrentPeriodEnd = DateTime.UtcNow.AddDays(30),
67+
Metadata = new Dictionary<string, string>
68+
{
69+
{ "organizationId", organizationId.ToString() }
70+
}
71+
};
72+
73+
_stripeEventService.GetSubscription(stripeEvent, true).Returns(subscription);
74+
_stripeEventUtilityService.GetIdsFromMetadata(subscription.Metadata)
75+
.Returns(Tuple.Create<Guid?, Guid?, Guid?>(organizationId, null, null));
76+
77+
// Act
78+
await _sut.HandleAsync(stripeEvent);
79+
80+
// Assert
81+
await _organizationDisableCommand.Received(1)
82+
.DisableAsync(organizationId, subscription.CurrentPeriodEnd);
83+
}
84+
85+
[Fact]
86+
public async Task HandleAsync_UserSubscriptionCanceled_DisablesUserPremium()
87+
{
88+
// Arrange
89+
var stripeEvent = new Event();
90+
var userId = Guid.NewGuid();
91+
var subscription = new Subscription
92+
{
93+
Status = StripeSubscriptionStatus.Canceled,
94+
CurrentPeriodEnd = DateTime.UtcNow.AddDays(30),
95+
Metadata = new Dictionary<string, string>
96+
{
97+
{ "userId", userId.ToString() }
98+
}
99+
};
100+
101+
_stripeEventService.GetSubscription(stripeEvent, true).Returns(subscription);
102+
_stripeEventUtilityService.GetIdsFromMetadata(subscription.Metadata)
103+
.Returns(Tuple.Create<Guid?, Guid?, Guid?>(null, userId, null));
104+
105+
// Act
106+
await _sut.HandleAsync(stripeEvent);
107+
108+
// Assert
109+
await _userService.Received(1)
110+
.DisablePremiumAsync(userId, subscription.CurrentPeriodEnd);
111+
}
112+
113+
[Fact]
114+
public async Task HandleAsync_ProviderMigrationCancellation_DoesNotDisableOrganization()
115+
{
116+
// Arrange
117+
var stripeEvent = new Event();
118+
var organizationId = Guid.NewGuid();
119+
var subscription = new Subscription
120+
{
121+
Status = StripeSubscriptionStatus.Canceled,
122+
CurrentPeriodEnd = DateTime.UtcNow.AddDays(30),
123+
Metadata = new Dictionary<string, string>
124+
{
125+
{ "organizationId", organizationId.ToString() }
126+
},
127+
CancellationDetails = new SubscriptionCancellationDetails
128+
{
129+
Comment = "Cancelled as part of provider migration to Consolidated Billing"
130+
}
131+
};
132+
133+
_stripeEventService.GetSubscription(stripeEvent, true).Returns(subscription);
134+
_stripeEventUtilityService.GetIdsFromMetadata(subscription.Metadata)
135+
.Returns(Tuple.Create<Guid?, Guid?, Guid?>(organizationId, null, null));
136+
137+
// Act
138+
await _sut.HandleAsync(stripeEvent);
139+
140+
// Assert
141+
await _organizationDisableCommand.DidNotReceiveWithAnyArgs()
142+
.DisableAsync(default, default);
143+
}
144+
145+
[Fact]
146+
public async Task HandleAsync_AddedToProviderCancellation_DoesNotDisableOrganization()
147+
{
148+
// Arrange
149+
var stripeEvent = new Event();
150+
var organizationId = Guid.NewGuid();
151+
var subscription = new Subscription
152+
{
153+
Status = StripeSubscriptionStatus.Canceled,
154+
CurrentPeriodEnd = DateTime.UtcNow.AddDays(30),
155+
Metadata = new Dictionary<string, string>
156+
{
157+
{ "organizationId", organizationId.ToString() }
158+
},
159+
CancellationDetails = new SubscriptionCancellationDetails
160+
{
161+
Comment = "Organization was added to Provider"
162+
}
163+
};
164+
165+
_stripeEventService.GetSubscription(stripeEvent, true).Returns(subscription);
166+
_stripeEventUtilityService.GetIdsFromMetadata(subscription.Metadata)
167+
.Returns(Tuple.Create<Guid?, Guid?, Guid?>(organizationId, null, null));
168+
169+
// Act
170+
await _sut.HandleAsync(stripeEvent);
171+
172+
// Assert
173+
await _organizationDisableCommand.DidNotReceiveWithAnyArgs()
174+
.DisableAsync(default, default);
175+
}
176+
}

0 commit comments

Comments
 (0)