@@ -252,6 +252,93 @@ describe('TalkDetail Integration', () => {
252252 } ) ;
253253 } ) ;
254254
255+ describe ( 'Speaker Filter Interaction' , ( ) => {
256+ it ( 'user can click speaker to search by speaker name' , async ( ) => {
257+ ( useTalks as ReturnType < typeof vi . fn > ) . mockReturnValue ( {
258+ talks : [ mockTalk ] ,
259+ loading : false ,
260+ error : null
261+ } ) ;
262+
263+ renderIntegration (
264+ < Routes >
265+ < Route path = "/talk/:id" element = { < TalkDetail /> } />
266+ </ Routes > ,
267+ {
268+ initialPath : '/talk/test-123'
269+ }
270+ ) ;
271+
272+ // Click speaker button
273+ const speakerButton = screen . getByText ( 'Alice Smith' ) ;
274+ fireEvent . click ( speakerButton ) ;
275+
276+ // Speaker button should show active state (query set to speaker name)
277+ await waitFor ( ( ) => {
278+ expect ( speakerButton ) . toHaveClass ( 'bg-blue-500' , 'text-white' ) ;
279+ } ) ;
280+ } ) ;
281+
282+ it ( 'user can toggle speaker filter off by clicking again' , async ( ) => {
283+ ( useTalks as ReturnType < typeof vi . fn > ) . mockReturnValue ( {
284+ talks : [ mockTalk ] ,
285+ loading : false ,
286+ error : null
287+ } ) ;
288+
289+ // Start with query set to speaker name
290+ renderIntegration (
291+ < Routes >
292+ < Route path = "/talk/:id" element = { < TalkDetail /> } />
293+ </ Routes > ,
294+ {
295+ initialPath : '/talk/test-123' ,
296+ initialParams : new URLSearchParams ( 'query=Alice Smith' )
297+ }
298+ ) ;
299+
300+ const speakerButton = screen . getByText ( 'Alice Smith' ) ;
301+ expect ( speakerButton ) . toHaveClass ( 'bg-blue-500' , 'text-white' ) ;
302+
303+ // Click to remove filter
304+ fireEvent . click ( speakerButton ) ;
305+
306+ // Button should return to inactive state
307+ await waitFor ( ( ) => {
308+ expect ( speakerButton ) . not . toHaveClass ( 'bg-blue-500' ) ;
309+ } ) ;
310+ } ) ;
311+
312+ it ( 'clicking a different speaker replaces the current query' , async ( ) => {
313+ ( useTalks as ReturnType < typeof vi . fn > ) . mockReturnValue ( {
314+ talks : [ mockTalk ] ,
315+ loading : false ,
316+ error : null
317+ } ) ;
318+
319+ // Start with query set to first speaker
320+ renderIntegration (
321+ < Routes >
322+ < Route path = "/talk/:id" element = { < TalkDetail /> } />
323+ </ Routes > ,
324+ {
325+ initialPath : '/talk/test-123' ,
326+ initialParams : new URLSearchParams ( 'query=Alice Smith' )
327+ }
328+ ) ;
329+
330+ // Click the other speaker
331+ const bobButton = screen . getByText ( 'Bob Jones' ) ;
332+ fireEvent . click ( bobButton ) ;
333+
334+ // Bob should become active, Alice inactive
335+ await waitFor ( ( ) => {
336+ expect ( bobButton ) . toHaveClass ( 'bg-blue-500' , 'text-white' ) ;
337+ } ) ;
338+ expect ( screen . getByText ( 'Alice Smith' ) ) . not . toHaveClass ( 'bg-blue-500' ) ;
339+ } ) ;
340+ } ) ;
341+
255342 describe ( 'Conference Filter Interaction' , ( ) => {
256343 it ( 'user can click conference to apply filter' , async ( ) => {
257344 ( useTalks as ReturnType < typeof vi . fn > ) . mockReturnValue ( {
0 commit comments