@@ -85,6 +85,40 @@ vi.mock("@src/components/modals/Announcement", () => ({
8585 } ,
8686} ) )
8787
88+ // Mock RooCloudCTA component
89+ vi . mock ( "@src/components/welcome/RooCloudCTA" , ( ) => ( {
90+ default : function MockRooCloudCTA ( ) {
91+ return (
92+ < div data-testid = "roo-cloud-cta" >
93+ < div > rooCloudCTA.title</ div >
94+ < div > rooCloudCTA.description</ div >
95+ < div > rooCloudCTA.joinWaitlist</ div >
96+ </ div >
97+ )
98+ } ,
99+ } ) )
100+
101+ // Mock RooTips component
102+ vi . mock ( "@src/components/welcome/RooTips" , ( ) => ( {
103+ default : function MockRooTips ( ) {
104+ return < div data-testid = "roo-tips" > Tips content</ div >
105+ } ,
106+ } ) )
107+
108+ // Mock RooHero component
109+ vi . mock ( "@src/components/welcome/RooHero" , ( ) => ( {
110+ default : function MockRooHero ( ) {
111+ return < div data-testid = "roo-hero" > Hero content</ div >
112+ } ,
113+ } ) )
114+
115+ // Mock TelemetryBanner component
116+ vi . mock ( "../common/TelemetryBanner" , ( ) => ( {
117+ default : function MockTelemetryBanner ( ) {
118+ return null // Don't render anything to avoid interference
119+ } ,
120+ } ) )
121+
88122// Mock i18n
89123vi . mock ( "react-i18next" , ( ) => ( {
90124 useTranslation : ( ) => ( {
@@ -191,6 +225,8 @@ const mockPostMessage = (state: Partial<ExtensionState>) => {
191225 shouldShowAnnouncement : false ,
192226 allowedCommands : [ ] ,
193227 alwaysAllowExecute : false ,
228+ cloudIsAuthenticated : false ,
229+ telemetrySetting : "enabled" ,
194230 ...state ,
195231 } ,
196232 } ,
@@ -1310,3 +1346,164 @@ describe("ChatView - Version Indicator Tests", () => {
13101346 expect ( versionButton ) . not . toBeInTheDocument ( )
13111347 } )
13121348} )
1349+
1350+ describe ( "ChatView - RooCloudCTA Display Tests" , ( ) => {
1351+ beforeEach ( ( ) => vi . clearAllMocks ( ) )
1352+
1353+ it ( "does not show RooCloudCTA when user is authenticated to Cloud" , ( ) => {
1354+ const { queryByTestId, getByTestId } = renderChatView ( )
1355+
1356+ // Hydrate state with user authenticated to cloud and some task history
1357+ mockPostMessage ( {
1358+ cloudIsAuthenticated : true ,
1359+ taskHistory : [
1360+ { id : "1" , ts : Date . now ( ) - 4000 } ,
1361+ { id : "2" , ts : Date . now ( ) - 3000 } ,
1362+ { id : "3" , ts : Date . now ( ) - 2000 } ,
1363+ { id : "4" , ts : Date . now ( ) - 1000 } ,
1364+ { id : "5" , ts : Date . now ( ) } ,
1365+ ] ,
1366+ clineMessages : [ ] , // No active task
1367+ } )
1368+
1369+ // Should not show RooCloudCTA but should show RooTips
1370+ expect ( queryByTestId ( "roo-cloud-cta" ) ) . not . toBeInTheDocument ( )
1371+ expect ( getByTestId ( "roo-tips" ) ) . toBeInTheDocument ( )
1372+ } )
1373+
1374+ it ( "does not show RooCloudCTA when user has only run 3 tasks in their history" , ( ) => {
1375+ const { queryByTestId, getByTestId } = renderChatView ( )
1376+
1377+ // Hydrate state with user not authenticated and only 3 tasks in history
1378+ mockPostMessage ( {
1379+ cloudIsAuthenticated : false ,
1380+ taskHistory : [
1381+ { id : "1" , ts : Date . now ( ) - 2000 } ,
1382+ { id : "2" , ts : Date . now ( ) - 1000 } ,
1383+ { id : "3" , ts : Date . now ( ) } ,
1384+ ] ,
1385+ clineMessages : [ ] , // No active task
1386+ } )
1387+
1388+ // Should not show RooCloudCTA but should show RooTips
1389+ expect ( queryByTestId ( "roo-cloud-cta" ) ) . not . toBeInTheDocument ( )
1390+ expect ( getByTestId ( "roo-tips" ) ) . toBeInTheDocument ( )
1391+ } )
1392+
1393+ it ( "shows RooCloudCTA when user is not authenticated and has run 4 or more tasks" , async ( ) => {
1394+ const { getByTestId, queryByTestId } = renderChatView ( )
1395+
1396+ // Hydrate state with user not authenticated and 4+ tasks in history
1397+ mockPostMessage ( {
1398+ cloudIsAuthenticated : false ,
1399+ taskHistory : [
1400+ { id : "1" , ts : Date . now ( ) - 3000 } ,
1401+ { id : "2" , ts : Date . now ( ) - 2000 } ,
1402+ { id : "3" , ts : Date . now ( ) - 1000 } ,
1403+ { id : "4" , ts : Date . now ( ) } ,
1404+ ] ,
1405+ clineMessages : [ ] , // No active task
1406+ } )
1407+
1408+ // Should show RooCloudCTA and not RooTips
1409+ await waitFor ( ( ) => {
1410+ expect ( getByTestId ( "roo-cloud-cta" ) ) . toBeInTheDocument ( )
1411+ } )
1412+ expect ( queryByTestId ( "roo-tips" ) ) . not . toBeInTheDocument ( )
1413+ } )
1414+
1415+ it ( "shows RooCloudCTA when user is not authenticated and has run 5 tasks" , async ( ) => {
1416+ const { getByTestId, queryByTestId } = renderChatView ( )
1417+
1418+ // Hydrate state with user not authenticated and 5 tasks in history
1419+ mockPostMessage ( {
1420+ cloudIsAuthenticated : false ,
1421+ taskHistory : [
1422+ { id : "1" , ts : Date . now ( ) - 4000 } ,
1423+ { id : "2" , ts : Date . now ( ) - 3000 } ,
1424+ { id : "3" , ts : Date . now ( ) - 2000 } ,
1425+ { id : "4" , ts : Date . now ( ) - 1000 } ,
1426+ { id : "5" , ts : Date . now ( ) } ,
1427+ ] ,
1428+ clineMessages : [ ] , // No active task
1429+ } )
1430+
1431+ // Should show RooCloudCTA and not RooTips
1432+ await waitFor ( ( ) => {
1433+ expect ( getByTestId ( "roo-cloud-cta" ) ) . toBeInTheDocument ( )
1434+ } )
1435+ expect ( queryByTestId ( "roo-tips" ) ) . not . toBeInTheDocument ( )
1436+ } )
1437+
1438+ it ( "does not show RooCloudCTA when there is an active task (regardless of auth status)" , async ( ) => {
1439+ const { queryByTestId } = renderChatView ( )
1440+
1441+ // Hydrate state with user not authenticated, 4+ tasks, but with an active task
1442+ mockPostMessage ( {
1443+ cloudIsAuthenticated : false ,
1444+ taskHistory : [
1445+ { id : "1" , ts : Date . now ( ) - 3000 } ,
1446+ { id : "2" , ts : Date . now ( ) - 2000 } ,
1447+ { id : "3" , ts : Date . now ( ) - 1000 } ,
1448+ { id : "4" , ts : Date . now ( ) } ,
1449+ ] ,
1450+ clineMessages : [
1451+ {
1452+ type : "say" ,
1453+ say : "task" ,
1454+ ts : Date . now ( ) ,
1455+ text : "Active task in progress" ,
1456+ } ,
1457+ ] ,
1458+ } )
1459+
1460+ // Wait for the state to be updated and the task view to be shown
1461+ await waitFor ( ( ) => {
1462+ // Should not show RooCloudCTA when there's an active task
1463+ expect ( queryByTestId ( "roo-cloud-cta" ) ) . not . toBeInTheDocument ( )
1464+ // Should not show RooTips either since the entire welcome screen is hidden during active tasks
1465+ expect ( queryByTestId ( "roo-tips" ) ) . not . toBeInTheDocument ( )
1466+ // Should not show RooHero either since the entire welcome screen is hidden during active tasks
1467+ expect ( queryByTestId ( "roo-hero" ) ) . not . toBeInTheDocument ( )
1468+ } )
1469+ } )
1470+
1471+ it ( "shows RooTips when user is authenticated (instead of RooCloudCTA)" , ( ) => {
1472+ const { queryByTestId, getByTestId } = renderChatView ( )
1473+
1474+ // Hydrate state with user authenticated to cloud
1475+ mockPostMessage ( {
1476+ cloudIsAuthenticated : true ,
1477+ taskHistory : [
1478+ { id : "1" , ts : Date . now ( ) - 3000 } ,
1479+ { id : "2" , ts : Date . now ( ) - 2000 } ,
1480+ { id : "3" , ts : Date . now ( ) - 1000 } ,
1481+ { id : "4" , ts : Date . now ( ) } ,
1482+ ] ,
1483+ clineMessages : [ ] , // No active task
1484+ } )
1485+
1486+ // Should not show RooCloudCTA but should show RooTips
1487+ expect ( queryByTestId ( "roo-cloud-cta" ) ) . not . toBeInTheDocument ( )
1488+ expect ( getByTestId ( "roo-tips" ) ) . toBeInTheDocument ( )
1489+ } )
1490+
1491+ it ( "shows RooTips when user has fewer than 4 tasks (instead of RooCloudCTA)" , ( ) => {
1492+ const { queryByTestId, getByTestId } = renderChatView ( )
1493+
1494+ // Hydrate state with user not authenticated but fewer than 4 tasks
1495+ mockPostMessage ( {
1496+ cloudIsAuthenticated : false ,
1497+ taskHistory : [
1498+ { id : "1" , ts : Date . now ( ) - 2000 } ,
1499+ { id : "2" , ts : Date . now ( ) - 1000 } ,
1500+ { id : "3" , ts : Date . now ( ) } ,
1501+ ] ,
1502+ clineMessages : [ ] , // No active task
1503+ } )
1504+
1505+ // Should not show RooCloudCTA but should show RooTips
1506+ expect ( queryByTestId ( "roo-cloud-cta" ) ) . not . toBeInTheDocument ( )
1507+ expect ( getByTestId ( "roo-tips" ) ) . toBeInTheDocument ( )
1508+ } )
1509+ } )
0 commit comments