Files
calendar/apps/web/components/apps/InstallAppButtonChild.tsx
T
3ebac0194e fix: block Google Meet installation without Google Calendar dependency (#25513)
* fix: block Google Meet installation without Google Calendar dependency

  - Prevent users from installing Google Meet when Google Calendar is not connected
  - Update AppDependencyComponent to show error state for unmet dependencies
  - Fix InstallAppButtonChild to respect disabled prop from dependencies check
  - Ensure consistent dependency validation across App Store and app detail pages

  Fixes #25497

* test: add unit tests for dependency validation
- Add tests for AppDependencyComponent (8 tests)
- Add tests for InstallAppButtonChild (5 tests)
- Cover dependency blocking behavior
- Test visual state changes (bg-error/bg-subtle)

* test: resolve type-check error in InstallAppButtonChild tests

- Add complete MockCredential type definition
- Create factory function to generate typed mock credentials
- Eliminate code duplication across test cases

* fix: remove redundant disabled prop assignment

Disabled state is already passed through via props.disableInstall
which gets converted to props.disabled in InstallAppButtonWithoutPlanCheck.
This change addresses the review comment to avoid unnecessary duplication

---------

Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
2025-12-09 17:56:20 +00:00

48 lines
1.4 KiB
TypeScript

import { useLocale } from "@calcom/lib/hooks/useLocale";
import type { RouterOutputs } from "@calcom/trpc/react";
import type { AppFrontendPayload } from "@calcom/types/App";
import type { ButtonProps } from "@calcom/ui/components/button";
import { Button } from "@calcom/ui/components/button";
export const InstallAppButtonChild = ({
multiInstall,
credentials,
paid,
...props
}: {
multiInstall?: boolean;
credentials?: RouterOutputs["viewer"]["apps"]["appCredentialsByType"]["credentials"];
paid?: AppFrontendPayload["paid"];
} & ButtonProps) => {
const { t } = useLocale();
const shouldDisableInstallation = !multiInstall ? !!(credentials && credentials.length) : false;
const isDisabled = shouldDisableInstallation || props.disabled;
// Paid apps don't support team installs at the moment
// Also, cal.ai(the only paid app at the moment) doesn't support team install either
if (paid) {
return (
<Button
data-testid="install-app-button"
{...props}
disabled={isDisabled}
color="primary"
size="base">
{paid.trial ? t("start_paid_trial") : t("subscribe")}
</Button>
);
}
return (
<Button
data-testid="install-app-button"
{...props}
disabled={isDisabled}
color="primary"
size="base">
{multiInstall ? t("install_another") : t("install_app")}
</Button>
);
};