+13








a4a3eb5ea9
* WIP: Billing service * WIP * Update __handler.ts * Update index.ts * WIP * WIP Signed-off-by: zomars <zomars@me.com> * WIP Signed-off-by: zomars <zomars@me.com> * Update delete.handler.ts * Update delete.handler.ts * Update internal-team-billing.ts * WIP * Type fixes Signed-off-by: zomars <zomars@me.com> * WIP Signed-off-by: zomars <zomars@me.com> * Discard changes to apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts * Discard changes to packages/app-store/skype/config.json * style: update text area (#15934) * chore: update text-editor input * chore: update text-editor input * final update * Update Editor.tsx --------- Co-authored-by: unknown <adhabal2002@gmail.com> Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> * fix: #15697 Assignment warning modal poping up ,even when hosts are added . (#15699) * removed reduntand check on assignedusers * update for managed eventtype * formatted * comments * Updated comments * extracted checkForEmptyAssignment and added tests * updated comments * updated to show dialog also when not yet saved * update translations * updated comments * updated translation * updated types * chore: update naming and comments * Delete apps/web/lib/checkForEmptyAssignment.ts deleted since file was renamed * Delete apps/web/test/lib/checkForEmptyAssignment.test.ts deleted as the file is renamed to be more descriptive * update to do teamcheck before * chore: revert name to CheckForEmptyAssignment * updated check conditions * updated useEffect dependencies --------- Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> * fix: getting an error when a team member tries to leave (#15925) a team Co-authored-by: Somay Chauhan <somaychauhan98@gmail.com> Co-authored-by: Amit Sharma <74371312+Amit91848@users.noreply.github.com> * feat: add transitions to more components (#15916) * add transitions to more components * chore: Remove duplicate class * fix: Change minimum number of teams required for org self-serve (#15955) * fix: Change minimum number of teams required for org self-serve Signed-off-by: Souptik Datta <souptikdatta2001@gmail.com> * refactor: Use a new constant for displaying org helper text dialogue Signed-off-by: Souptik Datta <souptikdatta2001@gmail.com> * Update packages/lib/constants.ts * Update turbo.json --------- Signed-off-by: Souptik Datta <souptikdatta2001@gmail.com> Co-authored-by: Keith Williams <keithwillcode@gmail.com> * feat: pwa ready and add shortcut for quick access (#15957) * chore: Update site.webmanifest with additional display properties * chore: Update site.webmanifest with additional display properties * Update apps/web/public/site.webmanifest --------- Co-authored-by: Keith Williams <keithwillcode@gmail.com> * i18n: update translations for "by proceeding, ..." (#15921) * feat: Add title attribute to iframe in embed.ts (#15944) * feat: Add title attribute to iframe in embed.ts * Update packages/embeds/embed-core/src/embed.ts --------- Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> * fix: Assignment reminder modal appears when deleting a team event type (#15544) * fix: Assignment reminder modal appears when deleting a team event type * update * Update EventTypeSingleLayout.tsx * Update event-types-single-view.tsx * update * Early return https://handbook.cal.com/engineering/best-practices/prefer-early-returns --------- Co-authored-by: Keith Williams <keithwillcode@gmail.com> Co-authored-by: Hariom <hariombalhara@gmail.com> * fix: Add CORP and COEP headers to embedded pages (#15275) * Add CORP headers * Improve test * Add unit tests as well --------- Co-authored-by: Keith Williams <keithwillcode@gmail.com> * feat: No-show bookings - do not count towards a member's round robin assignment (#15323) * feat: No-show bookings - do not count towards a member's round robin assignment * filter no show organizer * remove logs * fix: filter bookings where host attendee is no show * fix: use not condition for noShow * chore: test * add default false for noShowHost * Revert "chore: test" This reverts commit c914a8fc4a14ca9c7d8c4a08ff8b0f463789171c. * chore: integration test * fix: noShowHost not working for null * Update packages/lib/server/getLuckyUser.ts * chore: update test description --------- Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Co-authored-by: gh0st91848 <gh0st91848@gmail.com> Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> * refactor: v1 orgs unlimited teams (#15908) * refactor: v1 orgs unlimited teams * fix: response message ownerId --------- Co-authored-by: Keith Williams <keithwillcode@gmail.com> * fix: refresh connect atoms on token change (#15933) * added dropdown * change comment * fix: added types --------- Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: Keith Williams <keithwillcode@gmail.com> * fix: Next.js bundle analysis (#15903) * fix: Next.js bundle analysis * Added the main checkout back * fix: type in webhook payload (#15912) Co-authored-by: CarinaWolli <wollencarina@gmail.com> * fix: auto accept (#15975) * fix: auto accept * Update packages/lib/server/repository/organization.ts Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> --------- Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> * fix: Broken GitHub workflows (#15979) * test: Delete credential endpoint (#15322) * Init * Add mock trpc context * Intro mockDatabaseClient * Introduce mockDatabaseClient class * Add delete video app test * Add calendar test * Remove unused func from bookingScenario * Remove console.log * Add app repository * Add createMany method to event type repository * Remove instance of MockDatabaseClient from video test * Add destination calendar repository * Remove instances of MockDatabaseClient * abstract logic to own handler * Remove dev dependency * Clean up * Type fix * Pull yarn.lock from main --------- Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> * fix: #15967 Show better error when wrong variable is used in custom event name (#15974) * update to show exact err msg with custom event name * updated tests for validateCustomEventName --------- Co-authored-by: Keith Williams <keithwillcode@gmail.com> Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> * WIP Signed-off-by: zomars <zomars@me.com> * Update yarn.lock * Update publish.handler.ts * Update internal-team-billing.test.ts * rename create to init * remove sync services * wip tests for delete team * wip tets * wip tests * tests/internal-test * remove return that is inaccessable * remove team calls to use repository * remove redudant file * update team repo * add stripe mocks and test * fix constants * tests to main stripe handler * remove logs * fix constants * Update packages/features/ee/billing/api/webhook/_customer.subscription.deleted.team-plan.ts Co-authored-by: Omar López <zomars@me.com> * move workflow logic to a service * use static method > creating new class * fix: remove http code deep in repo + tests * Feedback * Update index.ts * Type fix * Lazy load fixes --------- Signed-off-by: zomars <zomars@me.com> Signed-off-by: Souptik Datta <souptikdatta2001@gmail.com> Co-authored-by: Rohan Advani <122167726+RNAdvani@users.noreply.github.com> Co-authored-by: unknown <adhabal2002@gmail.com> Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Co-authored-by: Vijay <vijayraghav22@gmail.com> Co-authored-by: Somay Chauhan <somaychauhan98@gmail.com> Co-authored-by: Amit Sharma <74371312+Amit91848@users.noreply.github.com> Co-authored-by: Hichem Fantar <hichemfantar2049@gmail.com> Co-authored-by: Souptik Datta <souptikdatta2001@gmail.com> Co-authored-by: Keith Williams <keithwillcode@gmail.com> Co-authored-by: Johannes Maendle <141119154+jomaendle2@users.noreply.github.com> Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Co-authored-by: gh0st91848 <gh0st91848@gmail.com> Co-authored-by: Lauris Skraucis <lauris.skraucis@gmail.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com> Co-authored-by: sean-brydon <sean@cal.com> Co-authored-by: sean <sean@brydon.io>
177 lines
6.0 KiB
TypeScript
177 lines
6.0 KiB
TypeScript
import prismaMock from "../../../../../tests/libs/__mocks__/prismaMock";
|
|
|
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
|
|
import { purchaseTeamOrOrgSubscription } from "@calcom/features/ee/teams/lib/payments";
|
|
import { WEBAPP_URL } from "@calcom/lib/constants";
|
|
|
|
import * as billingModule from "..";
|
|
import { InternalTeamBilling } from "./internal-team-billing";
|
|
import { TeamBillingPublishResponseStatus } from "./team-billing";
|
|
|
|
vi.mock("@calcom/lib/constants", async () => {
|
|
const actual = await vi.importActual("@calcom/lib/constants");
|
|
return {
|
|
...actual,
|
|
WEBAPP_URL: "http://localhost:3000",
|
|
};
|
|
});
|
|
|
|
vi.mock("..", () => ({
|
|
default: {
|
|
handleSubscriptionCancel: vi.fn(),
|
|
handleSubscriptionUpdate: vi.fn(),
|
|
checkoutSessionIsPaid: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
vi.mock("@calcom/features/ee/teams/lib/payments", () => ({
|
|
purchaseTeamOrOrgSubscription: vi.fn(),
|
|
}));
|
|
const mockTeam = {
|
|
id: 1,
|
|
metadata: {
|
|
subscriptionId: "sub_123",
|
|
subscriptionItemId: "si_456",
|
|
paymentId: "cs_789",
|
|
},
|
|
isOrganization: true,
|
|
parentId: null,
|
|
};
|
|
|
|
describe("InternalTeamBilling", () => {
|
|
beforeEach(() => {
|
|
vi.resetAllMocks();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
describe("cancel", () => {
|
|
const internalTeamBilling = new InternalTeamBilling(mockTeam);
|
|
it("should cancel the subscription and downgrade the team", async () => {
|
|
await internalTeamBilling.cancel();
|
|
|
|
expect(billingModule.default.handleSubscriptionCancel).toHaveBeenCalledWith("sub_123");
|
|
expect(prismaMock.team.update).toHaveBeenCalledWith({
|
|
where: { id: 1 },
|
|
data: {
|
|
metadata: {},
|
|
},
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("publish", () => {
|
|
const internalTeamBilling = new InternalTeamBilling(mockTeam);
|
|
it("should create a checkout session and update the team", async () => {
|
|
vi.spyOn(billingModule.default, "checkoutSessionIsPaid").mockResolvedValue(false);
|
|
vi.mocked(purchaseTeamOrOrgSubscription).mockResolvedValue({
|
|
url: "http://checkout.url",
|
|
});
|
|
prismaMock.membership.count.mockResolvedValue(5);
|
|
prismaMock.membership.findFirstOrThrow.mockResolvedValue({ userId: 123 });
|
|
|
|
const result = await internalTeamBilling.publish();
|
|
expect(result).toEqual({
|
|
redirectUrl: "http://checkout.url",
|
|
status: TeamBillingPublishResponseStatus.REQUIRES_PAYMENT,
|
|
});
|
|
|
|
expect(prismaMock.membership.count).toHaveBeenCalledWith({ where: { teamId: 1 } });
|
|
expect(prismaMock.membership.findFirstOrThrow).toHaveBeenCalledWith({
|
|
where: { teamId: 1, role: "OWNER" },
|
|
select: { userId: true },
|
|
});
|
|
});
|
|
it("should return upgrade url if upgrade is required", async () => {
|
|
const internalTeamBilling = new InternalTeamBilling(mockTeam);
|
|
const mockUrl = `${WEBAPP_URL}/api/teams/${mockTeam.id}/upgrade?session_id=cs_789`;
|
|
vi.spyOn(internalTeamBilling, "checkIfTeamPaymentRequired").mockResolvedValue({
|
|
url: mockUrl,
|
|
paymentId: "cs_789",
|
|
paymentRequired: false,
|
|
});
|
|
|
|
const result = await internalTeamBilling.publish();
|
|
|
|
expect(result).toEqual({
|
|
redirectUrl: mockUrl,
|
|
status: TeamBillingPublishResponseStatus.REQUIRES_UPGRADE,
|
|
});
|
|
expect(internalTeamBilling.checkIfTeamPaymentRequired).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe("updateQuantity", () => {
|
|
it("should update the subscription quantity", async () => {
|
|
const mockTeamNotOrg = {
|
|
...mockTeam,
|
|
isOrganization: false,
|
|
};
|
|
const internalTeamBilling = new InternalTeamBilling(mockTeamNotOrg);
|
|
prismaMock.membership.count.mockResolvedValue(10);
|
|
vi.spyOn(internalTeamBilling, "checkIfTeamPaymentRequired").mockResolvedValue({
|
|
url: "http://checkout.url",
|
|
paymentId: "cs_789",
|
|
paymentRequired: false,
|
|
});
|
|
|
|
await internalTeamBilling.updateQuantity();
|
|
|
|
expect(billingModule.default.handleSubscriptionUpdate).toHaveBeenCalledWith({
|
|
subscriptionId: "sub_123",
|
|
subscriptionItemId: "si_456",
|
|
membershipCount: 10,
|
|
});
|
|
});
|
|
|
|
it("should not update if membership count is less than minimum for organizations", async () => {
|
|
const internalTeamBilling = new InternalTeamBilling(mockTeam);
|
|
prismaMock.membership.count.mockResolvedValue(2);
|
|
vi.spyOn(internalTeamBilling, "checkIfTeamPaymentRequired").mockResolvedValue({
|
|
url: "http://checkout.url",
|
|
paymentId: "cs_789",
|
|
paymentRequired: false,
|
|
});
|
|
|
|
await internalTeamBilling.updateQuantity();
|
|
|
|
expect(billingModule.default.handleSubscriptionUpdate).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe("checkIfTeamPaymentRequired", () => {
|
|
const internalTeamBilling = new InternalTeamBilling(mockTeam);
|
|
it("should return payment required if no paymentId", async () => {
|
|
internalTeamBilling.team.metadata.paymentId = undefined;
|
|
|
|
const result = await internalTeamBilling.checkIfTeamPaymentRequired();
|
|
|
|
expect(result).toEqual({ url: null, paymentId: null, paymentRequired: true });
|
|
});
|
|
|
|
it("should return payment required if checkout session is not paid", async () => {
|
|
vi.spyOn(billingModule.default, "checkoutSessionIsPaid").mockResolvedValue(false);
|
|
const internalTeamBilling = new InternalTeamBilling(mockTeam);
|
|
|
|
const result = await internalTeamBilling.checkIfTeamPaymentRequired();
|
|
|
|
expect(result).toEqual({ url: null, paymentId: "cs_789", paymentRequired: true });
|
|
});
|
|
|
|
it("should return upgrade URL if checkout session is paid", async () => {
|
|
vi.spyOn(billingModule.default, "checkoutSessionIsPaid").mockResolvedValue(true);
|
|
const internalTeamBilling = new InternalTeamBilling(mockTeam);
|
|
const result = await internalTeamBilling.checkIfTeamPaymentRequired();
|
|
|
|
expect(result).toEqual({
|
|
url: `${WEBAPP_URL}/api/teams/1/upgrade?session_id=cs_789`,
|
|
paymentId: "cs_789",
|
|
paymentRequired: false,
|
|
});
|
|
});
|
|
});
|
|
});
|