714 lines
18 KiB
TypeScript
714 lines
18 KiB
TypeScript
import prismock from "../../../../../tests/libs/__mocks__/prisma";
|
|
|
|
import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
|
|
|
|
import stripe from "@calcom/app-store/stripepayment/lib/server";
|
|
|
|
import {
|
|
getTeamWithPaymentMetadata,
|
|
purchaseTeamOrOrgSubscription,
|
|
updateQuantitySubscriptionFromStripe,
|
|
} from "./payments";
|
|
|
|
beforeEach(async () => {
|
|
vi.stubEnv("STRIPE_ORG_MONTHLY_PRICE_ID", "STRIPE_ORG_MONTHLY_PRICE_ID");
|
|
vi.stubEnv("STRIPE_TEAM_MONTHLY_PRICE_ID", "STRIPE_TEAM_MONTHLY_PRICE_ID");
|
|
vi.resetAllMocks();
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore
|
|
await prismock.reset();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
vi.unstubAllEnvs();
|
|
vi.resetAllMocks();
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore
|
|
await prismock.reset();
|
|
});
|
|
|
|
vi.mock("@calcom/app-store/stripepayment/lib/customer", () => {
|
|
return {
|
|
getStripeCustomerIdFromUserId: function () {
|
|
return "CUSTOMER_ID";
|
|
},
|
|
};
|
|
});
|
|
|
|
vi.mock("@calcom/lib/constant", () => {
|
|
return {
|
|
MINIMUM_NUMBER_OF_ORG_SEATS: 30,
|
|
};
|
|
});
|
|
|
|
vi.mock("@calcom/app-store/stripepayment/lib/server", () => {
|
|
return {
|
|
default: {
|
|
checkout: {
|
|
sessions: {
|
|
create: vi.fn(),
|
|
retrieve: vi.fn(),
|
|
},
|
|
},
|
|
prices: {
|
|
retrieve: vi.fn(),
|
|
create: vi.fn(),
|
|
},
|
|
subscriptions: {
|
|
retrieve: vi.fn(),
|
|
update: vi.fn(),
|
|
create: vi.fn(),
|
|
},
|
|
},
|
|
};
|
|
});
|
|
|
|
describe("purchaseTeamOrOrgSubscription", () => {
|
|
it("should use `seatsToChargeFor` to create price", async () => {
|
|
const FAKE_PAYMENT_ID = "FAKE_PAYMENT_ID";
|
|
const user = await prismock.user.create({
|
|
data: {
|
|
name: "test",
|
|
email: "test@email.com",
|
|
},
|
|
});
|
|
|
|
const checkoutSessionsCreate = mockStripeCheckoutSessionsCreate({
|
|
url: "SESSION_URL",
|
|
});
|
|
|
|
mockStripeCheckoutSessionRetrieve(
|
|
{
|
|
currency: "USD",
|
|
product: {
|
|
id: "PRODUCT_ID",
|
|
},
|
|
},
|
|
[FAKE_PAYMENT_ID]
|
|
);
|
|
|
|
mockStripeCheckoutPricesRetrieve({
|
|
id: "PRICE_ID",
|
|
product: {
|
|
id: "PRODUCT_ID",
|
|
},
|
|
});
|
|
|
|
mockStripePricesCreate({
|
|
id: "PRICE_ID",
|
|
});
|
|
|
|
const team = await prismock.team.create({
|
|
data: {
|
|
name: "test",
|
|
metadata: {
|
|
paymentId: FAKE_PAYMENT_ID,
|
|
},
|
|
},
|
|
});
|
|
|
|
const seatsToChargeFor = 1000;
|
|
expect(
|
|
await purchaseTeamOrOrgSubscription({
|
|
teamId: team.id,
|
|
seatsUsed: 10,
|
|
seatsToChargeFor,
|
|
userId: user.id,
|
|
isOrg: true,
|
|
pricePerSeat: 100,
|
|
})
|
|
).toEqual({ url: "SESSION_URL" });
|
|
|
|
expect(checkoutSessionsCreate).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
line_items: [
|
|
{
|
|
price: "PRICE_ID",
|
|
quantity: seatsToChargeFor,
|
|
},
|
|
],
|
|
})
|
|
);
|
|
});
|
|
it("Should create a monthly subscription if billing period is set to monthly", async () => {
|
|
const FAKE_PAYMENT_ID = "FAKE_PAYMENT_ID";
|
|
const user = await prismock.user.create({
|
|
data: {
|
|
name: "test",
|
|
email: "test@email.com",
|
|
},
|
|
});
|
|
|
|
const checkoutSessionsCreate = mockStripeCheckoutSessionsCreate({
|
|
url: "SESSION_URL",
|
|
});
|
|
|
|
mockStripeCheckoutSessionRetrieve(
|
|
{
|
|
currency: "USD",
|
|
product: {
|
|
id: "PRODUCT_ID",
|
|
},
|
|
},
|
|
[FAKE_PAYMENT_ID]
|
|
);
|
|
|
|
mockStripeCheckoutPricesRetrieve({
|
|
id: "PRICE_ID",
|
|
product: {
|
|
id: "PRODUCT_ID",
|
|
},
|
|
});
|
|
|
|
const checkoutPricesCreate = mockStripePricesCreate({
|
|
id: "PRICE_ID",
|
|
});
|
|
|
|
const team = await prismock.team.create({
|
|
data: {
|
|
name: "test",
|
|
metadata: {
|
|
paymentId: FAKE_PAYMENT_ID,
|
|
},
|
|
},
|
|
});
|
|
|
|
const seatsToChargeFor = 1000;
|
|
expect(
|
|
await purchaseTeamOrOrgSubscription({
|
|
teamId: team.id,
|
|
seatsUsed: 10,
|
|
seatsToChargeFor,
|
|
userId: user.id,
|
|
isOrg: true,
|
|
pricePerSeat: 100,
|
|
billingPeriod: "MONTHLY",
|
|
})
|
|
).toEqual({ url: "SESSION_URL" });
|
|
|
|
expect(checkoutPricesCreate).toHaveBeenCalledWith(
|
|
expect.objectContaining({ recurring: { interval: "month" } })
|
|
);
|
|
|
|
expect(checkoutSessionsCreate).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
line_items: [
|
|
{
|
|
price: "PRICE_ID",
|
|
quantity: seatsToChargeFor,
|
|
},
|
|
],
|
|
})
|
|
);
|
|
});
|
|
it("Should create a annual subscription if billing period is set to annual", async () => {
|
|
const FAKE_PAYMENT_ID = "FAKE_PAYMENT_ID";
|
|
const user = await prismock.user.create({
|
|
data: {
|
|
name: "test",
|
|
email: "test@email.com",
|
|
},
|
|
});
|
|
|
|
const checkoutSessionsCreate = mockStripeCheckoutSessionsCreate({
|
|
url: "SESSION_URL",
|
|
});
|
|
|
|
mockStripeCheckoutSessionRetrieve(
|
|
{
|
|
currency: "USD",
|
|
product: {
|
|
id: "PRODUCT_ID",
|
|
},
|
|
},
|
|
[FAKE_PAYMENT_ID]
|
|
);
|
|
|
|
mockStripeCheckoutPricesRetrieve({
|
|
id: "PRICE_ID",
|
|
product: {
|
|
id: "PRODUCT_ID",
|
|
},
|
|
});
|
|
|
|
const checkoutPricesCreate = mockStripePricesCreate({
|
|
id: "PRICE_ID",
|
|
});
|
|
|
|
const team = await prismock.team.create({
|
|
data: {
|
|
name: "test",
|
|
metadata: {
|
|
paymentId: FAKE_PAYMENT_ID,
|
|
},
|
|
},
|
|
});
|
|
|
|
const seatsToChargeFor = 1000;
|
|
expect(
|
|
await purchaseTeamOrOrgSubscription({
|
|
teamId: team.id,
|
|
seatsUsed: 10,
|
|
seatsToChargeFor,
|
|
userId: user.id,
|
|
isOrg: true,
|
|
pricePerSeat: 100,
|
|
billingPeriod: "ANNUALLY",
|
|
})
|
|
).toEqual({ url: "SESSION_URL" });
|
|
|
|
expect(checkoutPricesCreate).toHaveBeenCalledWith(
|
|
expect.objectContaining({ recurring: { interval: "year" } })
|
|
);
|
|
|
|
expect(checkoutSessionsCreate).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
line_items: [
|
|
{
|
|
price: "PRICE_ID",
|
|
quantity: seatsToChargeFor,
|
|
},
|
|
],
|
|
})
|
|
);
|
|
});
|
|
|
|
it("It should not create a custom price if price_per_seat is not set", async () => {
|
|
const FAKE_PAYMENT_ID = "FAKE_PAYMENT_ID";
|
|
const user = await prismock.user.create({
|
|
data: {
|
|
name: "test",
|
|
email: "test@email.com",
|
|
},
|
|
});
|
|
|
|
mockStripeCheckoutSessionsCreate({
|
|
url: "SESSION_URL",
|
|
});
|
|
|
|
mockStripeCheckoutSessionRetrieve(
|
|
{
|
|
currency: "USD",
|
|
product: {
|
|
id: "PRODUCT_ID",
|
|
},
|
|
},
|
|
[FAKE_PAYMENT_ID]
|
|
);
|
|
|
|
mockStripeCheckoutPricesRetrieve({
|
|
id: "PRICE_ID",
|
|
product: {
|
|
id: "PRODUCT_ID",
|
|
},
|
|
});
|
|
|
|
const checkoutPricesCreate = mockStripePricesCreate({
|
|
id: "PRICE_ID",
|
|
});
|
|
|
|
const team = await prismock.team.create({
|
|
data: {
|
|
name: "test",
|
|
metadata: {
|
|
paymentId: FAKE_PAYMENT_ID,
|
|
},
|
|
},
|
|
});
|
|
|
|
const seatsToChargeFor = 1000;
|
|
expect(
|
|
await purchaseTeamOrOrgSubscription({
|
|
teamId: team.id,
|
|
seatsUsed: 10,
|
|
seatsToChargeFor,
|
|
userId: user.id,
|
|
isOrg: true,
|
|
billingPeriod: "ANNUALLY",
|
|
})
|
|
).toEqual({ url: "SESSION_URL" });
|
|
|
|
expect(checkoutPricesCreate).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe("updateQuantitySubscriptionFromStripe", () => {
|
|
describe("For an organization", () => {
|
|
it("should not update subscription when team members are less than metadata.orgSeats", async () => {
|
|
const FAKE_PAYMENT_ID = "FAKE_PAYMENT_ID";
|
|
const FAKE_SUBITEM_ID = "FAKE_SUBITEM_ID";
|
|
const FAKE_SUB_ID = "FAKE_SUB_ID";
|
|
const FAKE_SUBSCRIPTION_QTY_IN_STRIPE = 1000;
|
|
const consoleInfoSpy = vi.spyOn(console, "info");
|
|
|
|
const organization = await createOrgWithMembersAndPaymentData({
|
|
paymentId: FAKE_PAYMENT_ID,
|
|
subscriptionId: FAKE_SUB_ID,
|
|
subscriptionItemId: FAKE_SUBITEM_ID,
|
|
membersInTeam: 2,
|
|
orgSeats: 5,
|
|
});
|
|
|
|
mockStripeCheckoutSessionRetrieve(
|
|
{
|
|
payment_status: "paid",
|
|
},
|
|
[FAKE_PAYMENT_ID]
|
|
);
|
|
|
|
mockStripeSubscriptionsRetrieve(
|
|
{
|
|
items: {
|
|
data: [
|
|
{
|
|
id: "FAKE_SUBITEM_ID",
|
|
quantity: FAKE_SUBSCRIPTION_QTY_IN_STRIPE,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
[FAKE_SUB_ID]
|
|
);
|
|
|
|
const mockedSubscriptionsUpdate = mockStripeSubscriptionsUpdate(null);
|
|
|
|
await updateQuantitySubscriptionFromStripe(organization.id);
|
|
// Ensure that we reached the flow we are expecting to
|
|
expect(consoleInfoSpy.mock.calls[0][0]).toContain("has less members");
|
|
|
|
// orgSeats is more than the current number of members - So, no update in stripe
|
|
expect(mockedSubscriptionsUpdate).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("should update subscription when team members are more than metadata.orgSeats", async () => {
|
|
const FAKE_PAYMENT_ID = "FAKE_PAYMENT_ID";
|
|
const FAKE_SUB_ID = "FAKE_SUB_ID";
|
|
const FAKE_SUBITEM_ID = "FAKE_SUBITEM_ID";
|
|
const FAKE_SUBSCRIPTION_QTY_IN_STRIPE = 1000;
|
|
const membersInTeam = 4;
|
|
const organization = await createOrgWithMembersAndPaymentData({
|
|
paymentId: FAKE_PAYMENT_ID,
|
|
subscriptionId: FAKE_SUB_ID,
|
|
subscriptionItemId: FAKE_SUBITEM_ID,
|
|
membersInTeam,
|
|
orgSeats: 3,
|
|
});
|
|
|
|
mockStripeCheckoutSessionRetrieve(
|
|
{
|
|
payment_status: "paid",
|
|
},
|
|
[FAKE_PAYMENT_ID]
|
|
);
|
|
|
|
mockStripeSubscriptionsRetrieve(
|
|
{
|
|
items: {
|
|
data: [
|
|
{
|
|
id: FAKE_SUBITEM_ID,
|
|
quantity: FAKE_SUBSCRIPTION_QTY_IN_STRIPE,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
[FAKE_SUB_ID]
|
|
);
|
|
|
|
const mockedSubscriptionsUpdate = mockStripeSubscriptionsUpdate(null);
|
|
|
|
await updateQuantitySubscriptionFromStripe(organization.id);
|
|
|
|
// orgSeats is more than the current number of members - So, no update in stripe
|
|
expect(mockedSubscriptionsUpdate).toHaveBeenCalledWith(FAKE_SUB_ID, {
|
|
items: [
|
|
{
|
|
quantity: membersInTeam,
|
|
id: FAKE_SUBITEM_ID,
|
|
},
|
|
],
|
|
});
|
|
});
|
|
|
|
it("should not update subscription when team members are less than MINIMUM_NUMBER_OF_ORG_SEATS(if metadata.orgSeats is null)", async () => {
|
|
const FAKE_PAYMENT_ID = "FAKE_PAYMENT_ID";
|
|
const FAKE_SUBITEM_ID = "FAKE_SUBITEM_ID";
|
|
const FAKE_SUB_ID = "FAKE_SUB_ID";
|
|
const FAKE_SUBSCRIPTION_QTY_IN_STRIPE = 1000;
|
|
const membersInTeam = 2;
|
|
const consoleInfoSpy = vi.spyOn(console, "info");
|
|
|
|
const organization = await createOrgWithMembersAndPaymentData({
|
|
paymentId: FAKE_PAYMENT_ID,
|
|
subscriptionId: FAKE_SUB_ID,
|
|
subscriptionItemId: FAKE_SUBITEM_ID,
|
|
membersInTeam,
|
|
orgSeats: null,
|
|
});
|
|
|
|
mockStripeSubscriptionsRetrieve(
|
|
{
|
|
items: {
|
|
data: [
|
|
{
|
|
id: "FAKE_SUBITEM_ID",
|
|
quantity: FAKE_SUBSCRIPTION_QTY_IN_STRIPE,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
[FAKE_SUB_ID]
|
|
);
|
|
|
|
mockStripeCheckoutSessionRetrieve(
|
|
{
|
|
payment_status: "paid",
|
|
},
|
|
[FAKE_PAYMENT_ID]
|
|
);
|
|
|
|
const mockedSubscriptionsUpdate = mockStripeSubscriptionsUpdate(null);
|
|
|
|
await updateQuantitySubscriptionFromStripe(organization.id);
|
|
// Ensure that we reached the flow we are expecting to
|
|
expect(consoleInfoSpy.mock.calls[0][0]).toContain("has less members");
|
|
// orgSeats is more than the current number of members - So, no update in stripe
|
|
expect(mockedSubscriptionsUpdate).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("should update subscription when team members are more than MINIMUM_NUMBER_OF_ORG_SEATS(if metadata.orgSeats is null)", async () => {
|
|
const FAKE_PAYMENT_ID = "FAKE_PAYMENT_ID";
|
|
const FAKE_SUB_ID = "FAKE_SUB_ID";
|
|
const FAKE_SUBITEM_ID = "FAKE_SUBITEM_ID";
|
|
const FAKE_SUBSCRIPTION_QTY_IN_STRIPE = 1000;
|
|
const membersInTeam = 35;
|
|
const organization = await createOrgWithMembersAndPaymentData({
|
|
paymentId: FAKE_PAYMENT_ID,
|
|
subscriptionId: FAKE_SUB_ID,
|
|
subscriptionItemId: FAKE_SUBITEM_ID,
|
|
membersInTeam,
|
|
orgSeats: null,
|
|
});
|
|
|
|
mockStripeCheckoutSessionRetrieve(
|
|
{
|
|
payment_status: "paid",
|
|
},
|
|
[FAKE_PAYMENT_ID]
|
|
);
|
|
|
|
mockStripeSubscriptionsRetrieve(
|
|
{
|
|
items: {
|
|
data: [
|
|
{
|
|
id: FAKE_SUBITEM_ID,
|
|
quantity: FAKE_SUBSCRIPTION_QTY_IN_STRIPE,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
[FAKE_SUB_ID]
|
|
);
|
|
|
|
const mockedSubscriptionsUpdate = mockStripeSubscriptionsUpdate(null);
|
|
|
|
await updateQuantitySubscriptionFromStripe(organization.id);
|
|
|
|
// orgSeats is more than the current number of members - So, no update in stripe
|
|
expect(mockedSubscriptionsUpdate).toHaveBeenCalledWith(FAKE_SUB_ID, {
|
|
items: [
|
|
{
|
|
quantity: membersInTeam,
|
|
id: FAKE_SUBITEM_ID,
|
|
},
|
|
],
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("getTeamWithPaymentMetadata", () => {
|
|
it("should error if paymentId is not set", async () => {
|
|
const team = await prismock.team.create({
|
|
data: {
|
|
isOrganization: true,
|
|
name: "TestTeam",
|
|
metadata: {
|
|
subscriptionId: "FAKE_SUB_ID",
|
|
subscriptionItemId: "FAKE_SUB_ITEM_ID",
|
|
},
|
|
},
|
|
});
|
|
expect(() => getTeamWithPaymentMetadata(team.id)).rejects.toThrow();
|
|
});
|
|
|
|
it("should error if subscriptionId is not set", async () => {
|
|
const team = await prismock.team.create({
|
|
data: {
|
|
isOrganization: true,
|
|
name: "TestTeam",
|
|
metadata: {
|
|
paymentId: "FAKE_PAY_ID",
|
|
subscriptionItemId: "FAKE_SUB_ITEM_ID",
|
|
},
|
|
},
|
|
});
|
|
expect(() => getTeamWithPaymentMetadata(team.id)).rejects.toThrow();
|
|
});
|
|
|
|
it("should error if subscriptionItemId is not set", async () => {
|
|
const team = await prismock.team.create({
|
|
data: {
|
|
isOrganization: true,
|
|
name: "TestTeam",
|
|
metadata: {
|
|
paymentId: "FAKE_PAY_ID",
|
|
subscriptionId: "FAKE_SUB_ID",
|
|
},
|
|
},
|
|
});
|
|
expect(() => getTeamWithPaymentMetadata(team.id)).rejects.toThrow();
|
|
});
|
|
|
|
it("should parse successfully if orgSeats is not set in metadata", async () => {
|
|
const team = await prismock.team.create({
|
|
data: {
|
|
isOrganization: true,
|
|
name: "TestTeam",
|
|
metadata: {
|
|
paymentId: "FAKE_PAY_ID",
|
|
subscriptionId: "FAKE_SUB_ID",
|
|
subscriptionItemId: "FAKE_SUB_ITEM_ID",
|
|
},
|
|
},
|
|
});
|
|
const teamWithPaymentData = await getTeamWithPaymentMetadata(team.id);
|
|
expect(teamWithPaymentData.metadata.orgSeats).toBeUndefined();
|
|
});
|
|
|
|
it("should parse successfully if orgSeats is set in metadata", async () => {
|
|
const team = await prismock.team.create({
|
|
data: {
|
|
isOrganization: true,
|
|
name: "TestTeam",
|
|
metadata: {
|
|
orgSeats: 5,
|
|
paymentId: "FAKE_PAY_ID",
|
|
subscriptionId: "FAKE_SUB_ID",
|
|
subscriptionItemId: "FAKE_SUB_ITEM_ID",
|
|
},
|
|
},
|
|
});
|
|
const teamWithPaymentData = await getTeamWithPaymentMetadata(team.id);
|
|
expect(teamWithPaymentData.metadata.orgSeats).toEqual(5);
|
|
});
|
|
});
|
|
|
|
async function createOrgWithMembersAndPaymentData({
|
|
paymentId,
|
|
subscriptionId,
|
|
subscriptionItemId,
|
|
orgSeats,
|
|
membersInTeam,
|
|
}: {
|
|
paymentId: string;
|
|
subscriptionId: string;
|
|
subscriptionItemId: string;
|
|
orgSeats?: number | null;
|
|
membersInTeam: number;
|
|
}) {
|
|
const organization = await prismock.team.create({
|
|
data: {
|
|
isOrganization: true,
|
|
name: "TestTeam",
|
|
metadata: {
|
|
// Make sure that payment is already done
|
|
paymentId,
|
|
orgSeats,
|
|
subscriptionId,
|
|
subscriptionItemId,
|
|
},
|
|
},
|
|
});
|
|
|
|
await Promise.all([
|
|
Array(membersInTeam)
|
|
.fill(0)
|
|
.map(async (_, index) => {
|
|
return await prismock.membership.create({
|
|
data: {
|
|
team: {
|
|
connect: {
|
|
id: organization.id,
|
|
},
|
|
},
|
|
user: {
|
|
create: {
|
|
name: "ABC",
|
|
email: `test-${index}@example.com`,
|
|
},
|
|
},
|
|
role: "MEMBER",
|
|
},
|
|
});
|
|
}),
|
|
]);
|
|
return organization;
|
|
}
|
|
|
|
function mockStripePricesCreate(data) {
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
return vi.mocked(stripe.prices.create).mockImplementation(() => new Promise((resolve) => resolve(data)));
|
|
}
|
|
|
|
function mockStripeCheckoutPricesRetrieve(data) {
|
|
return vi.mocked(stripe.prices.retrieve).mockImplementation(
|
|
async () =>
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
new Promise((resolve) => {
|
|
resolve(data);
|
|
})
|
|
);
|
|
}
|
|
|
|
function mockStripeCheckoutSessionRetrieve(data, expectedArgs) {
|
|
return vi.mocked(stripe.checkout.sessions.retrieve).mockImplementation(async (sessionId) =>
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
{
|
|
const conditionMatched = expectedArgs[0] === sessionId;
|
|
return new Promise((resolve) => resolve(conditionMatched ? data : null));
|
|
}
|
|
);
|
|
}
|
|
|
|
function mockStripeCheckoutSessionsCreate(data) {
|
|
return vi.mocked(stripe.checkout.sessions.create).mockImplementation(
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
async () => new Promise((resolve) => resolve(data))
|
|
);
|
|
}
|
|
|
|
function mockStripeSubscriptionsRetrieve(data, expectedArgs) {
|
|
return vi.mocked(stripe.subscriptions.retrieve).mockImplementation(
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
async (subscriptionId) => {
|
|
const conditionMatched = expectedArgs ? expectedArgs[0] === subscriptionId : true;
|
|
return new Promise((resolve) => resolve(conditionMatched ? data : undefined));
|
|
}
|
|
);
|
|
}
|
|
|
|
function mockStripeSubscriptionsUpdate(data) {
|
|
return vi.mocked(stripe.subscriptions.update).mockImplementation(
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
//@ts-ignore
|
|
async () => new Promise((resolve) => resolve(data))
|
|
);
|
|
}
|