Skip to content

Commit b3ac38b

Browse files
author
Bruno Bergher
committed
Tests
1 parent 5cfee3c commit b3ac38b

File tree

2 files changed

+209
-2
lines changed

2 files changed

+209
-2
lines changed

webview-ui/src/components/chat/__tests__/ChatView.spec.tsx

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
89123
vi.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+
})

webview-ui/src/components/welcome/__tests__/RooTips.spec.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ vi.mock("react-i18next", () => ({
77
useTranslation: () => ({
88
t: (key: string) => key, // Simple mock that returns the key
99
}),
10+
Trans: ({
11+
children,
12+
components,
13+
}: {
14+
children?: React.ReactNode
15+
components?: Record<string, React.ReactElement>
16+
}) => {
17+
// Simple mock that renders children or the first component if no children
18+
return children || (components && Object.values(components)[0]) || null
19+
},
1020
}))
1121

1222
vi.mock("@vscode/webview-ui-toolkit/react", () => ({
@@ -29,8 +39,8 @@ describe("RooTips Component", () => {
2939
})
3040

3141
test("renders only the top two tips", () => {
32-
// Ensure only two tips are present (check by link role)
33-
expect(screen.getAllByRole("link")).toHaveLength(2)
42+
// Ensure only two tips are present plus the docs link in the Trans component (3 total links)
43+
expect(screen.getAllByRole("link")).toHaveLength(3)
3444
})
3545
})
3646
})

0 commit comments

Comments
 (0)