11import { render , screen , fireEvent , waitFor , act } from "@testing-library/react"
22import { describe , it , expect , vi , beforeEach , afterEach } from "vitest"
33import DismissibleUpsell from "../DismissibleUpsell"
4+ import { TelemetryEventName } from "@roo-code/types"
45
56// Mock the vscode API
67const mockPostMessage = vi . fn ( )
@@ -10,6 +11,14 @@ vi.mock("@src/utils/vscode", () => ({
1011 } ,
1112} ) )
1213
14+ // Mock telemetryClient
15+ const mockCapture = vi . fn ( )
16+ vi . mock ( "@src/utils/TelemetryClient" , ( ) => ( {
17+ telemetryClient : {
18+ capture : ( eventName : string , properties ?: Record < string , any > ) => mockCapture ( eventName , properties ) ,
19+ } ,
20+ } ) )
21+
1322// Mock the translation hook
1423vi . mock ( "@src/i18n/TranslationContext" , ( ) => ( {
1524 useAppTranslation : ( ) => ( {
@@ -26,6 +35,7 @@ vi.mock("@src/i18n/TranslationContext", () => ({
2635describe ( "DismissibleUpsell" , ( ) => {
2736 beforeEach ( ( ) => {
2837 mockPostMessage . mockClear ( )
38+ mockCapture . mockClear ( )
2939 vi . clearAllTimers ( )
3040 } )
3141
@@ -72,7 +82,7 @@ describe("DismissibleUpsell", () => {
7282 } )
7383 } )
7484
75- it ( "hides the upsell when dismiss button is clicked" , async ( ) => {
85+ it ( "hides the upsell when dismiss button is clicked and tracks telemetry " , async ( ) => {
7686 const onDismiss = vi . fn ( )
7787 const { container } = render (
7888 < DismissibleUpsell upsellId = "test-upsell" onDismiss = { onDismiss } >
@@ -92,6 +102,11 @@ describe("DismissibleUpsell", () => {
92102 const dismissButton = screen . getByRole ( "button" , { name : / d i s m i s s / i } )
93103 fireEvent . click ( dismissButton )
94104
105+ // Check that telemetry was tracked
106+ expect ( mockCapture ) . toHaveBeenCalledWith ( TelemetryEventName . UPSELL_DISMISSED , {
107+ upsellId : "test-upsell" ,
108+ } )
109+
95110 // Check that the dismiss message was sent BEFORE hiding
96111 expect ( mockPostMessage ) . toHaveBeenCalledWith ( {
97112 type : "dismissUpsell" ,
@@ -351,7 +366,7 @@ describe("DismissibleUpsell", () => {
351366 } )
352367 } )
353368
354- it ( "calls onClick when the container is clicked" , async ( ) => {
369+ it ( "calls onClick when the container is clicked and tracks telemetry " , async ( ) => {
355370 const onClick = vi . fn ( )
356371 render (
357372 < DismissibleUpsell upsellId = "test-upsell" onClick = { onClick } >
@@ -372,6 +387,11 @@ describe("DismissibleUpsell", () => {
372387 fireEvent . click ( container )
373388
374389 expect ( onClick ) . toHaveBeenCalledTimes ( 1 )
390+
391+ // Check that telemetry was tracked
392+ expect ( mockCapture ) . toHaveBeenCalledWith ( TelemetryEventName . UPSELL_CLICKED , {
393+ upsellId : "test-upsell" ,
394+ } )
375395 } )
376396
377397 it ( "does not call onClick when dismiss button is clicked" , async ( ) => {
@@ -470,7 +490,7 @@ describe("DismissibleUpsell", () => {
470490 } )
471491 } )
472492
473- it ( "dismisses when clicked if dismissOnClick is true" , async ( ) => {
493+ it ( "dismisses when clicked if dismissOnClick is true and tracks both telemetry events " , async ( ) => {
474494 const onClick = vi . fn ( )
475495 const onDismiss = vi . fn ( )
476496 const { container } = render (
@@ -493,6 +513,14 @@ describe("DismissibleUpsell", () => {
493513 expect ( onClick ) . toHaveBeenCalledTimes ( 1 )
494514 expect ( onDismiss ) . toHaveBeenCalledTimes ( 1 )
495515
516+ // Check that both telemetry events were tracked
517+ expect ( mockCapture ) . toHaveBeenCalledWith ( TelemetryEventName . UPSELL_CLICKED , {
518+ upsellId : "test-upsell" ,
519+ } )
520+ expect ( mockCapture ) . toHaveBeenCalledWith ( TelemetryEventName . UPSELL_DISMISSED , {
521+ upsellId : "test-upsell" ,
522+ } )
523+
496524 expect ( mockPostMessage ) . toHaveBeenCalledWith ( {
497525 type : "dismissUpsell" ,
498526 upsellId : "test-upsell" ,
@@ -503,6 +531,46 @@ describe("DismissibleUpsell", () => {
503531 } )
504532 } )
505533
534+ it ( "dismisses on container click when dismissOnClick is true and no onClick is provided; tracks only dismissal" , async ( ) => {
535+ const onDismiss = vi . fn ( )
536+ const { container } = render (
537+ < DismissibleUpsell upsellId = "test-upsell" onDismiss = { onDismiss } dismissOnClick = { true } >
538+ < div > Test content</ div >
539+ </ DismissibleUpsell > ,
540+ )
541+
542+ // Make component visible
543+ makeUpsellVisible ( )
544+
545+ // Wait for component to be visible
546+ await waitFor ( ( ) => {
547+ expect ( screen . getByText ( "Test content" ) ) . toBeInTheDocument ( )
548+ } )
549+
550+ // Click on the container (not the dismiss button)
551+ const containerDiv = screen . getByText ( "Test content" ) . parentElement as HTMLElement
552+ fireEvent . click ( containerDiv )
553+
554+ // onDismiss should be called
555+ expect ( onDismiss ) . toHaveBeenCalledTimes ( 1 )
556+
557+ // Telemetry: only dismissal should be tracked
558+ expect ( mockCapture ) . toHaveBeenCalledWith ( TelemetryEventName . UPSELL_DISMISSED , {
559+ upsellId : "test-upsell" ,
560+ } )
561+ expect ( mockCapture ) . not . toHaveBeenCalledWith ( TelemetryEventName . UPSELL_CLICKED , expect . anything ( ) )
562+
563+ // Dismiss message should be sent
564+ expect ( mockPostMessage ) . toHaveBeenCalledWith ( {
565+ type : "dismissUpsell" ,
566+ upsellId : "test-upsell" ,
567+ } )
568+
569+ // Component should be hidden
570+ await waitFor ( ( ) => {
571+ expect ( container . firstChild ) . toBeNull ( )
572+ } )
573+ } )
506574 it ( "does not dismiss when clicked if dismissOnClick is false" , async ( ) => {
507575 const onClick = vi . fn ( )
508576 const onDismiss = vi . fn ( )
0 commit comments