@@ -177,4 +177,161 @@ describe('Dropdown', () => {
177177
178178 expect ( mockEv . preventDefault ) . toHaveBeenCalledTimes ( 2 ) ;
179179 } ) ;
180+
181+ it ( 'TabTransparentDropdown handles focus in' , ( ) => {
182+ const component = renderer . create ( < TestContainer >
183+ < Dropdown toggle = { < button > show more</ button > } >
184+ < DropdownList >
185+ < DropdownItem onClick = { ( ) => null } message = 'i18n:highlighting:dropdown:delete' />
186+ </ DropdownList >
187+ </ Dropdown >
188+ </ TestContainer > ) ;
189+
190+ // Find the dropdown focus wrapper div
191+ const focusWrapper = component . root . findAll (
192+ ( el ) => el . props . className && el . props . className . includes ( 'dropdown-focus-wrapper' )
193+ ) [ 0 ] ;
194+
195+ // Initially, focus-within should not be present
196+ expect ( focusWrapper . props . className ) . not . toContain ( 'focus-within' ) ;
197+
198+ // Simulate focus in
199+ renderer . act ( ( ) => {
200+ focusWrapper . props . onFocus ( ) ;
201+ } ) ;
202+
203+ // After focus in, focus-within should be present
204+ const updatedFocusWrapper = component . root . findAll (
205+ ( el ) => el . props . className && el . props . className . includes ( 'dropdown-focus-wrapper' )
206+ ) [ 0 ] ;
207+ expect ( updatedFocusWrapper . props . className ) . toContain ( 'focus-within' ) ;
208+ } ) ;
209+
210+ it ( 'TabTransparentDropdown handles focus out when focus moves outside' , ( ) => {
211+ const component = renderer . create ( < TestContainer >
212+ < Dropdown toggle = { < button > show more</ button > } >
213+ < DropdownList >
214+ < DropdownItem onClick = { ( ) => null } message = 'i18n:highlighting:dropdown:delete' />
215+ </ DropdownList >
216+ </ Dropdown >
217+ </ TestContainer > ) ;
218+
219+ // Find the dropdown focus wrapper div
220+ const focusWrapper = component . root . findAll (
221+ ( el ) => el . props . className && el . props . className . includes ( 'dropdown-focus-wrapper' )
222+ ) [ 0 ] ;
223+
224+ // Simulate focus in first
225+ renderer . act ( ( ) => {
226+ focusWrapper . props . onFocus ( ) ;
227+ } ) ;
228+
229+ // Verify focus-within is present
230+ let updatedFocusWrapper = component . root . findAll (
231+ ( el ) => el . props . className && el . props . className . includes ( 'dropdown-focus-wrapper' )
232+ ) [ 0 ] ;
233+ expect ( updatedFocusWrapper . props . className ) . toContain ( 'focus-within' ) ;
234+
235+ // Simulate focus out to an element outside the dropdown (relatedTarget is outside)
236+ renderer . act ( ( ) => {
237+ const outsideElement = document ?. createElement ( 'div' ) ;
238+ focusWrapper . props . onBlur ( {
239+ currentTarget : {
240+ contains : jest . fn ( ) . mockReturnValue ( false ) ,
241+ } ,
242+ relatedTarget : outsideElement ,
243+ } ) ;
244+ } ) ;
245+
246+ // After focus out, focus-within should be removed
247+ updatedFocusWrapper = component . root . findAll (
248+ ( el ) => el . props . className && el . props . className . includes ( 'dropdown-focus-wrapper' )
249+ ) [ 0 ] ;
250+ expect ( updatedFocusWrapper . props . className ) . not . toContain ( 'focus-within' ) ;
251+ } ) ;
252+
253+ it ( 'TabTransparentDropdown handles focus out when relatedTarget is null' , ( ) => {
254+ const component = renderer . create ( < TestContainer >
255+ < Dropdown toggle = { < button > show more</ button > } >
256+ < DropdownList >
257+ < DropdownItem onClick = { ( ) => null } message = 'i18n:highlighting:dropdown:delete' />
258+ </ DropdownList >
259+ </ Dropdown >
260+ </ TestContainer > ) ;
261+
262+ // Find the dropdown focus wrapper div
263+ const focusWrapper = component . root . findAll (
264+ ( el ) => el . props . className && el . props . className . includes ( 'dropdown-focus-wrapper' )
265+ ) [ 0 ] ;
266+
267+ // Simulate focus in first
268+ renderer . act ( ( ) => {
269+ focusWrapper . props . onFocus ( ) ;
270+ } ) ;
271+
272+ // Verify focus-within is present
273+ let updatedFocusWrapper = component . root . findAll (
274+ ( el ) => el . props . className && el . props . className . includes ( 'dropdown-focus-wrapper' )
275+ ) [ 0 ] ;
276+ expect ( updatedFocusWrapper . props . className ) . toContain ( 'focus-within' ) ;
277+
278+ // Simulate focus out with null relatedTarget (focus moved to browser UI or another app)
279+ renderer . act ( ( ) => {
280+ focusWrapper . props . onBlur ( {
281+ currentTarget : {
282+ contains : jest . fn ( ) ,
283+ } ,
284+ relatedTarget : null ,
285+ } ) ;
286+ } ) ;
287+
288+ // After focus out with null relatedTarget, focus-within should be removed
289+ updatedFocusWrapper = component . root . findAll (
290+ ( el ) => el . props . className && el . props . className . includes ( 'dropdown-focus-wrapper' )
291+ ) [ 0 ] ;
292+ expect ( updatedFocusWrapper . props . className ) . not . toContain ( 'focus-within' ) ;
293+ } ) ;
294+
295+ it ( 'TabTransparentDropdown maintains focus when moving within the dropdown' , ( ) => {
296+ const component = renderer . create ( < TestContainer >
297+ < Dropdown toggle = { < button > show more</ button > } >
298+ < DropdownList >
299+ < DropdownItem onClick = { ( ) => null } message = 'i18n:highlighting:dropdown:delete' />
300+ </ DropdownList >
301+ </ Dropdown >
302+ </ TestContainer > ) ;
303+
304+ // Find the dropdown focus wrapper div
305+ const focusWrapper = component . root . findAll (
306+ ( el ) => el . props . className && el . props . className . includes ( 'dropdown-focus-wrapper' )
307+ ) [ 0 ] ;
308+
309+ // Simulate focus in first
310+ renderer . act ( ( ) => {
311+ focusWrapper . props . onFocus ( ) ;
312+ } ) ;
313+
314+ // Verify focus-within is present
315+ let updatedFocusWrapper = component . root . findAll (
316+ ( el ) => el . props . className && el . props . className . includes ( 'dropdown-focus-wrapper' )
317+ ) [ 0 ] ;
318+ expect ( updatedFocusWrapper . props . className ) . toContain ( 'focus-within' ) ;
319+
320+ // Simulate focus moving to another element within the dropdown (relatedTarget is inside)
321+ renderer . act ( ( ) => {
322+ const insideElement = document ?. createElement ( 'div' ) ;
323+ focusWrapper . props . onBlur ( {
324+ currentTarget : {
325+ contains : jest . fn ( ) . mockReturnValue ( true ) ,
326+ } ,
327+ relatedTarget : insideElement ,
328+ } ) ;
329+ } ) ;
330+
331+ // Focus-within should still be present because focus is still within the dropdown
332+ updatedFocusWrapper = component . root . findAll (
333+ ( el ) => el . props . className && el . props . className . includes ( 'dropdown-focus-wrapper' )
334+ ) [ 0 ] ;
335+ expect ( updatedFocusWrapper . props . className ) . toContain ( 'focus-within' ) ;
336+ } ) ;
180337} ) ;
0 commit comments