-
Notifications
You must be signed in to change notification settings - Fork 401
Expand file tree
/
Copy pathsidebar-section-header.test.tsx
More file actions
132 lines (119 loc) · 4.23 KB
/
Copy pathsidebar-section-header.test.tsx
File metadata and controls
132 lines (119 loc) · 4.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { type ReactElement } from "react"
import { fireEvent, render } from "@testing-library/react"
import { NextIntlClientProvider } from "next-intl"
import { describe, expect, it, vi, beforeEach } from "vitest"
import { SidebarSectionHeader } from "./sidebar-section-header"
import enMessages from "@/i18n/messages/en.json"
// The hover-reveal action buttons carry only an aria-label (icon, no text), so
// getByLabelText addresses them unambiguously. CSS hides them until hover, but
// fireEvent dispatches directly on the node regardless of pointer-events, so the
// wiring is testable without a real pointer.
const onToggle = vi.fn()
const onNewChat = vi.fn()
const onOpenFolder = vi.fn()
const onCloneRepository = vi.fn()
function renderWithIntl(ui: ReactElement) {
return render(
<NextIntlClientProvider locale="en" messages={enMessages}>
{ui}
</NextIntlClientProvider>
)
}
beforeEach(() => {
onToggle.mockClear()
onNewChat.mockClear()
onOpenFolder.mockClear()
onCloneRepository.mockClear()
})
describe("SidebarSectionHeader folders-section actions", () => {
it("renders Open Folder and Clone Repository buttons on the folders section", () => {
const { getByLabelText } = renderWithIntl(
<SidebarSectionHeader
section="folders"
expanded
onToggle={onToggle}
onOpenFolder={onOpenFolder}
onCloneRepository={onCloneRepository}
/>
)
expect(getByLabelText("Open Folder")).not.toBeNull()
expect(getByLabelText("Clone Repository")).not.toBeNull()
})
it("invokes the matching handler without toggling the section", () => {
const { getByLabelText } = renderWithIntl(
<SidebarSectionHeader
section="folders"
expanded
onToggle={onToggle}
onOpenFolder={onOpenFolder}
onCloneRepository={onCloneRepository}
/>
)
fireEvent.click(getByLabelText("Open Folder"))
expect(onOpenFolder).toHaveBeenCalledTimes(1)
fireEvent.click(getByLabelText("Clone Repository"))
expect(onCloneRepository).toHaveBeenCalledTimes(1)
// The actions are siblings of the toggle button (never nested), so clicking
// them never collapses/expands the section.
expect(onToggle).not.toHaveBeenCalled()
})
it("renders only the actions whose callbacks are provided", () => {
const { getByLabelText, queryByLabelText } = renderWithIntl(
<SidebarSectionHeader
section="folders"
expanded
onToggle={onToggle}
onOpenFolder={onOpenFolder}
/>
)
expect(getByLabelText("Open Folder")).not.toBeNull()
expect(queryByLabelText("Clone Repository")).toBeNull()
})
it("still toggles the section when the header label is clicked", () => {
const { getByText } = renderWithIntl(
<SidebarSectionHeader
section="folders"
expanded
onToggle={onToggle}
onOpenFolder={onOpenFolder}
onCloneRepository={onCloneRepository}
/>
)
fireEvent.click(getByText("Folders"))
expect(onToggle).toHaveBeenCalledWith("folders")
})
})
describe("SidebarSectionHeader action gating by section", () => {
it("offers only New chat on the chats section, never the folder actions", () => {
// Pass the folder callbacks too: they must be gated by `section`, not merely
// by callback presence.
const { getByLabelText, queryByLabelText } = renderWithIntl(
<SidebarSectionHeader
section="chats"
expanded
onToggle={onToggle}
onNewChat={onNewChat}
onOpenFolder={onOpenFolder}
onCloneRepository={onCloneRepository}
/>
)
expect(getByLabelText("New chat")).not.toBeNull()
expect(queryByLabelText("Open Folder")).toBeNull()
expect(queryByLabelText("Clone Repository")).toBeNull()
})
it("offers no action buttons on the pinned section", () => {
const { queryByLabelText } = renderWithIntl(
<SidebarSectionHeader
section="pinned"
expanded
onToggle={onToggle}
onNewChat={onNewChat}
onOpenFolder={onOpenFolder}
onCloneRepository={onCloneRepository}
/>
)
expect(queryByLabelText("New chat")).toBeNull()
expect(queryByLabelText("Open Folder")).toBeNull()
expect(queryByLabelText("Clone Repository")).toBeNull()
})
})