Skip to content

Commit 79dc762

Browse files
authored
fix: apply transaction to public methods of CreditService (calcom#21356)
1 parent 95d6235 commit 79dc762

4 files changed

Lines changed: 440 additions & 191 deletions

File tree

packages/features/ee/billing/credit-service.test.ts

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,23 @@ import * as EmailManager from "@calcom/emails/email-manager";
66
import { CreditsRepository } from "@calcom/lib/server/repository/credits";
77
import { MembershipRepository } from "@calcom/lib/server/repository/membership";
88
import { TeamRepository } from "@calcom/lib/server/repository/team";
9+
import prisma from "@calcom/prisma";
910
import { CreditType } from "@calcom/prisma/enums";
1011

11-
import { CreditService } from "./credit-service";
12+
import { CreditService as OriginalCreditService } from "./credit-service";
1213
import { StripeBillingService } from "./stripe-billling-service";
1314
import { InternalTeamBilling } from "./teams/internal-team-billing";
1415

16+
const MOCK_TX = prisma;
17+
18+
vi.mock("@calcom/prisma", () => {
19+
return {
20+
default: {
21+
$transaction: vi.fn((fn) => fn(MOCK_TX)),
22+
},
23+
};
24+
});
25+
1526
vi.mock("stripe");
1627

1728
vi.mock("@calcom/lib/constants", async () => {
@@ -41,6 +52,39 @@ vi.mock("../workflows/lib/reminders/reminderScheduler", () => ({
4152
cancelScheduledMessagesAndScheduleEmails: vi.fn(),
4253
}));
4354

55+
// Create a testable version of CreditService that exposes protected methods
56+
class CreditService extends OriginalCreditService {
57+
public async _getTeamWithAvailableCredits(
58+
params: Parameters<OriginalCreditService["_getTeamWithAvailableCredits"]>[0]
59+
) {
60+
return super._getTeamWithAvailableCredits(params);
61+
}
62+
63+
public async _getUserOrTeamToCharge(
64+
params: Parameters<OriginalCreditService["_getUserOrTeamToCharge"]>[0]
65+
) {
66+
return super._getUserOrTeamToCharge(params);
67+
}
68+
69+
public async _createExpenseLog(props: Parameters<OriginalCreditService["_createExpenseLog"]>[0]) {
70+
return super._createExpenseLog(props);
71+
}
72+
73+
public async _handleLowCreditBalance(
74+
params: Parameters<OriginalCreditService["_handleLowCreditBalance"]>[0]
75+
) {
76+
return super._handleLowCreditBalance(params);
77+
}
78+
79+
public async _getAllCreditsForTeam(params: Parameters<OriginalCreditService["_getAllCreditsForTeam"]>[0]) {
80+
return super._getAllCreditsForTeam(params);
81+
}
82+
83+
public async _getAllCredits(params: Parameters<OriginalCreditService["_getAllCredits"]>[0]) {
84+
return super._getAllCredits(params);
85+
}
86+
}
87+
4488
describe("CreditService", () => {
4589
let creditService: CreditService;
4690
let stripeMock: any;
@@ -182,11 +226,11 @@ describe("CreditService", () => {
182226
user: null,
183227
});
184228

185-
vi.spyOn(CreditService.prototype, "getTeamWithAvailableCredits").mockResolvedValue(null);
229+
vi.spyOn(CreditService.prototype, "_getTeamWithAvailableCredits").mockResolvedValue(null);
186230

187231
vi.spyOn(EmailManager, "sendCreditBalanceLowWarningEmails").mockResolvedValue();
188232

189-
vi.spyOn(CreditService.prototype, "getAllCreditsForTeam").mockResolvedValue({
233+
vi.spyOn(CreditService.prototype, "_getAllCreditsForTeam").mockResolvedValue({
190234
totalMonthlyCredits: 500,
191235
totalRemainingMonthlyCredits: 20,
192236
additionalCredits: 60,
@@ -206,7 +250,8 @@ describe("CreditService", () => {
206250
creditType: CreditType.MONTHLY,
207251
credits: 5,
208252
smsSid: "sms-123",
209-
})
253+
}),
254+
MOCK_TX
210255
);
211256

212257
expect(EmailManager.sendCreditBalanceLowWarningEmails).toHaveBeenCalled();
@@ -243,7 +288,7 @@ describe("CreditService", () => {
243288

244289
vi.spyOn(EmailManager, "sendCreditBalanceLimitReachedEmails").mockResolvedValue();
245290

246-
vi.spyOn(CreditService.prototype, "getAllCreditsForTeam").mockResolvedValue({
291+
vi.spyOn(CreditService.prototype, "_getAllCreditsForTeam").mockResolvedValue({
247292
totalMonthlyCredits: 500,
248293
totalRemainingMonthlyCredits: -1,
249294
additionalCredits: 0,
@@ -263,7 +308,8 @@ describe("CreditService", () => {
263308
creditType: CreditType.ADDITIONAL,
264309
credits: 5,
265310
smsSid: "sms-123",
266-
})
311+
}),
312+
MOCK_TX
267313
);
268314

269315
expect(EmailManager.sendCreditBalanceLimitReachedEmails).toHaveBeenCalled();
@@ -272,7 +318,7 @@ describe("CreditService", () => {
272318

273319
describe("getUserOrTeamToCharge", () => {
274320
it("should return team with remaining credits when teamId is provided", async () => {
275-
vi.spyOn(CreditService.prototype, "getAllCreditsForTeam").mockResolvedValue({
321+
vi.spyOn(CreditService.prototype, "_getAllCreditsForTeam").mockResolvedValue({
276322
totalMonthlyCredits: 500,
277323
totalRemainingMonthlyCredits: 100,
278324
additionalCredits: 50,
@@ -291,7 +337,7 @@ describe("CreditService", () => {
291337
});
292338

293339
it("should use additional credits when monthly credits are out", async () => {
294-
vi.spyOn(CreditService.prototype, "getAllCreditsForTeam").mockResolvedValue({
340+
vi.spyOn(CreditService.prototype, "_getAllCreditsForTeam").mockResolvedValue({
295341
totalMonthlyCredits: 500,
296342
totalRemainingMonthlyCredits: 0,
297343
additionalCredits: 50,
@@ -319,7 +365,7 @@ describe("CreditService", () => {
319365
warningSentAt: null,
320366
});
321367

322-
vi.spyOn(CreditService.prototype, "getTeamWithAvailableCredits").mockResolvedValue({
368+
vi.spyOn(CreditService.prototype, "_getTeamWithAvailableCredits").mockResolvedValue({
323369
teamId: 1,
324370
availableCredits: 150,
325371
creditType: CreditType.MONTHLY,
@@ -429,7 +475,7 @@ describe("CreditService", () => {
429475
limitReachedAt: null,
430476
warningSentAt: null,
431477
});
432-
vi.spyOn(CreditService.prototype, "getTeamWithAvailableCredits").mockResolvedValue(null);
478+
vi.spyOn(CreditService.prototype, "_getTeamWithAvailableCredits").mockResolvedValue(null);
433479

434480
const hasAvailableCredits = await creditService.hasAvailableCredits({ userId: 1 });
435481
expect(hasAvailableCredits).toBe(true);
@@ -445,7 +491,7 @@ describe("CreditService", () => {
445491
warningSentAt: null,
446492
});
447493

448-
vi.spyOn(CreditService.prototype, "getTeamWithAvailableCredits").mockResolvedValue(null);
494+
vi.spyOn(CreditService.prototype, "_getTeamWithAvailableCredits").mockResolvedValue(null);
449495

450496
const result = await creditService.hasAvailableCredits({ userId: 1 });
451497
expect(result).toBe(false);
@@ -475,11 +521,11 @@ describe("CreditService", () => {
475521
team: null,
476522
});
477523

478-
vi.spyOn(CreditService.prototype, "getTeamWithAvailableCredits").mockResolvedValue(null);
524+
vi.spyOn(CreditService.prototype, "_getTeamWithAvailableCredits").mockResolvedValue(null);
479525

480526
vi.spyOn(EmailManager, "sendCreditBalanceLowWarningEmails").mockResolvedValue();
481527

482-
vi.spyOn(CreditService.prototype, "getAllCredits").mockResolvedValue({
528+
vi.spyOn(CreditService.prototype, "_getAllCredits").mockResolvedValue({
483529
totalMonthlyCredits: 0,
484530
totalRemainingMonthlyCredits: 0,
485531
additionalCredits: 10,
@@ -499,7 +545,8 @@ describe("CreditService", () => {
499545
creditType: CreditType.ADDITIONAL,
500546
credits: 5,
501547
smsSid: "sms-123",
502-
})
548+
}),
549+
MOCK_TX
503550
);
504551

505552
expect(EmailManager.sendCreditBalanceLowWarningEmails).toHaveBeenCalled();
@@ -537,9 +584,9 @@ describe("CreditService", () => {
537584

538585
vi.spyOn(EmailManager, "sendCreditBalanceLimitReachedEmails").mockResolvedValue();
539586

540-
vi.spyOn(CreditService.prototype, "getTeamWithAvailableCredits").mockResolvedValue(null);
587+
vi.spyOn(CreditService.prototype, "_getTeamWithAvailableCredits").mockResolvedValue(null);
541588

542-
vi.spyOn(CreditService.prototype, "getAllCredits").mockResolvedValue({
589+
vi.spyOn(CreditService.prototype, "_getAllCredits").mockResolvedValue({
543590
totalMonthlyCredits: 0,
544591
totalRemainingMonthlyCredits: 0,
545592
additionalCredits: 2,
@@ -559,7 +606,8 @@ describe("CreditService", () => {
559606
creditType: CreditType.ADDITIONAL,
560607
credits: 5,
561608
smsSid: "sms-123",
562-
})
609+
}),
610+
MOCK_TX
563611
);
564612

565613
expect(EmailManager.sendCreditBalanceLimitReachedEmails).toHaveBeenCalled();
@@ -568,9 +616,9 @@ describe("CreditService", () => {
568616

569617
describe("getUserOrTeamToCharge", () => {
570618
it("should return user with remaining credits when userId is provided", async () => {
571-
vi.spyOn(CreditService.prototype, "getTeamWithAvailableCredits").mockResolvedValue(null);
619+
vi.spyOn(CreditService.prototype, "_getTeamWithAvailableCredits").mockResolvedValue(null);
572620

573-
vi.spyOn(CreditService.prototype, "getAllCredits").mockResolvedValue({
621+
vi.spyOn(CreditService.prototype, "_getAllCredits").mockResolvedValue({
574622
totalMonthlyCredits: 0,
575623
totalRemainingMonthlyCredits: 0,
576624
additionalCredits: 10,

0 commit comments

Comments
 (0)