11import { render , screen } from "@testing-library/react" ;
2- import { describe , expect , it } from "vitest" ;
2+ import userEvent from "@testing-library/user-event" ;
3+ import { describe , expect , it , vi } from "vitest" ;
34import type { V0ServerJson } from "@/generated/types.gen" ;
45import { Servers } from "../servers" ;
56
7+ const mockOnClearSearch = vi . fn ( ) ;
8+
69const mockServers : V0ServerJson [ ] = [
710 {
811 name : "aws-nova-canvas" ,
@@ -27,7 +30,14 @@ const mockServers: V0ServerJson[] = [
2730describe ( "Servers" , ( ) => {
2831 describe ( "grid mode" , ( ) => {
2932 it ( "displays servers in grid layout" , ( ) => {
30- render ( < Servers servers = { mockServers } viewMode = "grid" searchQuery = "" /> ) ;
33+ render (
34+ < Servers
35+ servers = { mockServers }
36+ viewMode = "grid"
37+ searchQuery = ""
38+ onClearSearch = { mockOnClearSearch }
39+ /> ,
40+ ) ;
3141
3242 expect ( screen . getByText ( "aws-nova-canvas" ) ) . toBeVisible ( ) ;
3343 expect ( screen . getByText ( "google-applications" ) ) . toBeVisible ( ) ;
@@ -36,7 +46,12 @@ describe("Servers", () => {
3646
3747 it ( "displays grid container" , ( ) => {
3848 const { container } = render (
39- < Servers servers = { mockServers } viewMode = "grid" searchQuery = "" /> ,
49+ < Servers
50+ servers = { mockServers }
51+ viewMode = "grid"
52+ searchQuery = ""
53+ onClearSearch = { mockOnClearSearch }
54+ /> ,
4055 ) ;
4156
4257 const grid = container . querySelector ( ".grid" ) ;
@@ -46,15 +61,29 @@ describe("Servers", () => {
4661
4762 describe ( "list mode" , ( ) => {
4863 it ( "displays servers in table layout" , ( ) => {
49- render ( < Servers servers = { mockServers } viewMode = "list" searchQuery = "" /> ) ;
64+ render (
65+ < Servers
66+ servers = { mockServers }
67+ viewMode = "list"
68+ searchQuery = ""
69+ onClearSearch = { mockOnClearSearch }
70+ /> ,
71+ ) ;
5072
5173 expect ( screen . getByText ( "aws-nova-canvas" ) ) . toBeVisible ( ) ;
5274 expect ( screen . getByText ( "google-applications" ) ) . toBeVisible ( ) ;
5375 expect ( screen . getByText ( "azure-mcp" ) ) . toBeVisible ( ) ;
5476 } ) ;
5577
5678 it ( "displays table headers" , ( ) => {
57- render ( < Servers servers = { mockServers } viewMode = "list" searchQuery = "" /> ) ;
79+ render (
80+ < Servers
81+ servers = { mockServers }
82+ viewMode = "list"
83+ searchQuery = ""
84+ onClearSearch = { mockOnClearSearch }
85+ /> ,
86+ ) ;
5887
5988 expect ( screen . getByText ( "Server" ) ) . toBeVisible ( ) ;
6089 expect ( screen . getByText ( "About" ) ) . toBeVisible ( ) ;
@@ -64,7 +93,12 @@ describe("Servers", () => {
6493 describe ( "search functionality" , ( ) => {
6594 it ( "filters servers by name" , ( ) => {
6695 render (
67- < Servers servers = { mockServers } viewMode = "grid" searchQuery = "aws" /> ,
96+ < Servers
97+ servers = { mockServers }
98+ viewMode = "grid"
99+ searchQuery = "aws"
100+ onClearSearch = { mockOnClearSearch }
101+ /> ,
68102 ) ;
69103
70104 expect ( screen . getByText ( "aws-nova-canvas" ) ) . toBeVisible ( ) ;
@@ -74,7 +108,12 @@ describe("Servers", () => {
74108
75109 it ( "filters servers by title" , ( ) => {
76110 render (
77- < Servers servers = { mockServers } viewMode = "grid" searchQuery = "google" /> ,
111+ < Servers
112+ servers = { mockServers }
113+ viewMode = "grid"
114+ searchQuery = "google"
115+ onClearSearch = { mockOnClearSearch }
116+ /> ,
78117 ) ;
79118
80119 expect ( screen . getByText ( "google-applications" ) ) . toBeVisible ( ) ;
@@ -87,6 +126,7 @@ describe("Servers", () => {
87126 servers = { mockServers }
88127 viewMode = "grid"
89128 searchQuery = "workspace"
129+ onClearSearch = { mockOnClearSearch }
90130 /> ,
91131 ) ;
92132
@@ -96,7 +136,12 @@ describe("Servers", () => {
96136
97137 it ( "is case insensitive" , ( ) => {
98138 render (
99- < Servers servers = { mockServers } viewMode = "grid" searchQuery = "AWS" /> ,
139+ < Servers
140+ servers = { mockServers }
141+ viewMode = "grid"
142+ searchQuery = "AWS"
143+ onClearSearch = { mockOnClearSearch }
144+ /> ,
100145 ) ;
101146
102147 expect ( screen . getByText ( "aws-nova-canvas" ) ) . toBeVisible ( ) ;
@@ -108,26 +153,93 @@ describe("Servers", () => {
108153 servers = { mockServers }
109154 viewMode = "grid"
110155 searchQuery = "nonexistent"
156+ onClearSearch = { mockOnClearSearch }
111157 /> ,
112158 ) ;
113159
160+ expect ( screen . getByText ( "No results found" ) ) . toBeVisible ( ) ;
114161 expect (
115- screen . getByText ( 'No servers found matching "nonexistent"' ) ,
162+ screen . getByText ( / c o u l d n ' t f i n d a n y s e r v e r s m a t c h i n g " n o n e x i s t e n t " / ) ,
116163 ) . toBeVisible ( ) ;
117164 } ) ;
165+
166+ it ( "shows clear search button when search has no matches" , async ( ) => {
167+ const user = userEvent . setup ( ) ;
168+ const onClearSearch = vi . fn ( ) ;
169+
170+ render (
171+ < Servers
172+ servers = { mockServers }
173+ viewMode = "grid"
174+ searchQuery = "nonexistent"
175+ onClearSearch = { onClearSearch }
176+ /> ,
177+ ) ;
178+
179+ const clearButton = screen . getByRole ( "button" , { name : / c l e a r s e a r c h / i } ) ;
180+ expect ( clearButton ) . toBeVisible ( ) ;
181+
182+ await user . click ( clearButton ) ;
183+ expect ( onClearSearch ) . toHaveBeenCalledTimes ( 1 ) ;
184+ } ) ;
118185 } ) ;
119186
120187 describe ( "empty state" , ( ) => {
121188 it ( "shows no servers message when list is empty" , ( ) => {
122- render ( < Servers servers = { [ ] } viewMode = "grid" searchQuery = "" /> ) ;
189+ render (
190+ < Servers
191+ servers = { [ ] }
192+ viewMode = "grid"
193+ searchQuery = ""
194+ onClearSearch = { mockOnClearSearch }
195+ /> ,
196+ ) ;
123197
124198 expect ( screen . getByText ( "No servers available" ) ) . toBeVisible ( ) ;
199+ expect (
200+ screen . getByText ( / n o M C P s e r v e r s i n t h e c a t a l o g y e t / i) ,
201+ ) . toBeVisible ( ) ;
125202 } ) ;
126203
127204 it ( "shows no servers message in list mode" , ( ) => {
128- render ( < Servers servers = { [ ] } viewMode = "list" searchQuery = "" /> ) ;
205+ render (
206+ < Servers
207+ servers = { [ ] }
208+ viewMode = "list"
209+ searchQuery = ""
210+ onClearSearch = { mockOnClearSearch }
211+ /> ,
212+ ) ;
129213
130214 expect ( screen . getByText ( "No servers available" ) ) . toBeVisible ( ) ;
131215 } ) ;
216+
217+ it ( "displays illustration in empty state" , ( ) => {
218+ const { container } = render (
219+ < Servers
220+ servers = { [ ] }
221+ viewMode = "grid"
222+ searchQuery = ""
223+ onClearSearch = { mockOnClearSearch }
224+ /> ,
225+ ) ;
226+
227+ expect ( container . querySelector ( "svg" ) ) . toBeInTheDocument ( ) ;
228+ } ) ;
229+
230+ it ( "does not show clear search button when no servers and no search" , ( ) => {
231+ render (
232+ < Servers
233+ servers = { [ ] }
234+ viewMode = "grid"
235+ searchQuery = ""
236+ onClearSearch = { mockOnClearSearch }
237+ /> ,
238+ ) ;
239+
240+ expect (
241+ screen . queryByRole ( "button" , { name : / c l e a r s e a r c h / i } ) ,
242+ ) . not . toBeInTheDocument ( ) ;
243+ } ) ;
132244 } ) ;
133245} ) ;
0 commit comments