Files
calendar/packages/features/feature-opt-in/components/FeatureOptInBanner.tsx
T
Eunjae LeeandGitHub 087fa03513 test: add e2e test for Feature Opt-In banner (#27100)
## What does this PR do?

Adds an end-to-end test for the Feature Opt-In banner flow. This test verifies the complete user journey from seeing the banner to enabling a feature.

Currently `OPT_IN_FEATURES` in `packages/features/feature-opt-in/config.ts` is empty, so this e2e test skips. Once we uncomment the `bookings-v3` item from the config, this e2e test will run and pass. This is a preparation for when we enable the feature.

**Changes:**
- Creates a new e2e test file (`feature-opt-in-banner.e2e.ts`) that tests the complete opt-in flow
- Adds `data-testid` attributes to banner and dialog components for reliable test selectors

## Mandatory Tasks (DO NOT REMOVE)

- [x] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). N/A - test only.
- [x] I confirm automated tests are in place that prove my fix is effective or that my feature works.

## How should this be tested?

1. Add the `ready-for-e2e` label to run e2e tests in CI
2. The test should pass when run with `PLAYWRIGHT_HEADLESS=1 yarn e2e feature-opt-in-banner.e2e.ts`

**Test requirements:**
- The `bookings-v3` feature flag must exist in the Features table (the test uses `prisma.feature.upsert` to ensure this)
- The test will skip if `bookings-v3` is not in `OPT_IN_FEATURES`

## Checklist

- [x] I have read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
- [x] My code follows the style guidelines of this project
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have checked if my changes generate no new warnings

## Updates since last revision

- Replaced text-based locators (`getByText`, `getByRole`) with `data-testid` selectors for more reliable element targeting
- Added `data-testid` attributes to `FeatureOptInBanner`, `FeatureOptInConfirmDialog`, and `FeatureOptInSuccessDialog` components

## Human Review Checklist

- [ ] Verify the `data-testid` attributes don't conflict with existing test IDs in the codebase
- [ ] Confirm the test correctly skips when `bookings-v3` is not in `OPT_IN_FEATURES`
- [ ] Check that the added `data-testid` attributes follow the project's naming conventions

---
Link to Devin run: https://app.devin.ai/sessions/97158ab1b7414e3988ba803b30d95b3e
Requested by: @eunjae-lee
2026-01-22 12:09:13 +01:00

68 lines
2.0 KiB
TypeScript

"use client";
import type { OptInFeatureConfig } from "@calcom/features/feature-opt-in/config";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { Button } from "@calcom/ui/components/button";
import Image from "next/image";
import type { ReactElement } from "react";
interface FeatureOptInBannerProps {
featureConfig: OptInFeatureConfig;
onDismiss: () => void;
onOpenDialog: () => void;
}
export function FeatureOptInBanner({
featureConfig,
onDismiss,
onOpenDialog,
}: FeatureOptInBannerProps): ReactElement {
const { t } = useLocale();
return (
<div
data-testid="feature-opt-in-banner"
className="bg-default border-subtle fixed bottom-5 right-5 z-50 max-w-xs rounded-lg border shadow-lg group">
<div className="p-4">
<h3 data-testid="feature-opt-in-banner-title" className="text-emphasis text-lg font-semibold">
{t(featureConfig.i18n.title)}
</h3>
<p className="text-subtle mt-1 text-base">{t(featureConfig.i18n.description)}</p>
<Button
type="button"
onClick={onDismiss}
variant="icon"
StartIcon="x"
color="minimal"
className="absolute top-1.5 right-1.5 opacity-0 pointer-events-none transition-opacity group-hover:opacity-100 group-hover:pointer-events-auto"
aria-label={t("close")}></Button>
<Button
data-testid="feature-opt-in-banner-try-it"
className="mt-3"
size="sm"
color="secondary"
onClick={onOpenDialog}>
{t("try_it")}
</Button>
</div>
<div className="p-1">
<div
className="relative w-full"
style={{ aspectRatio: featureConfig.bannerImage.width / featureConfig.bannerImage.height }}>
<Image
src={featureConfig.bannerImage.src}
alt={t(featureConfig.i18n.title)}
fill
className="object-contain"
/>
</div>
</div>
</div>
);
}
export default FeatureOptInBanner;