@@ -204,6 +204,70 @@ public void itAnnouncesRouteNameWhenAddingNewRoute() {
204204 assertEquals (sentences .get (0 ).toString (), "new_node2" );
205205 }
206206
207+ @ Test
208+ public void itIgnoresUnfocusableNodeDuringHitTest () {
209+ AccessibilityViewEmbedder mockViewEmbedder = mock (AccessibilityViewEmbedder .class );
210+ AccessibilityManager mockManager = mock (AccessibilityManager .class );
211+ View mockRootView = mock (View .class );
212+ Context context = mock (Context .class );
213+ when (mockRootView .getContext ()).thenReturn (context );
214+ when (context .getPackageName ()).thenReturn ("test" );
215+ AccessibilityBridge accessibilityBridge =
216+ setUpBridge (mockRootView , mockManager , mockViewEmbedder );
217+ ViewParent mockParent = mock (ViewParent .class );
218+ when (mockRootView .getParent ()).thenReturn (mockParent );
219+ when (mockManager .isEnabled ()).thenReturn (true );
220+ when (mockManager .isTouchExplorationEnabled ()).thenReturn (true );
221+
222+ TestSemanticsNode root = new TestSemanticsNode ();
223+ root .id = 0 ;
224+ root .left = 0 ;
225+ root .top = 0 ;
226+ root .bottom = 20 ;
227+ root .right = 20 ;
228+ TestSemanticsNode ignored = new TestSemanticsNode ();
229+ ignored .id = 1 ;
230+ ignored .addFlag (AccessibilityBridge .Flag .SCOPES_ROUTE );
231+ ignored .left = 0 ;
232+ ignored .top = 0 ;
233+ ignored .bottom = 20 ;
234+ ignored .right = 20 ;
235+ root .children .add (ignored );
236+ TestSemanticsNode child = new TestSemanticsNode ();
237+ child .id = 2 ;
238+ child .label = "label" ;
239+ child .left = 0 ;
240+ child .top = 0 ;
241+ child .bottom = 20 ;
242+ child .right = 20 ;
243+ root .children .add (child );
244+ TestSemanticsUpdate testSemanticsUpdate = root .toUpdate ();
245+ accessibilityBridge .updateSemantics (testSemanticsUpdate .buffer , testSemanticsUpdate .strings );
246+
247+ ArgumentCaptor <AccessibilityEvent > eventCaptor =
248+ ArgumentCaptor .forClass (AccessibilityEvent .class );
249+ verify (mockParent , times (2 ))
250+ .requestSendAccessibilityEvent (eq (mockRootView ), eventCaptor .capture ());
251+ AccessibilityEvent event = eventCaptor .getAllValues ().get (0 );
252+ assertEquals (event .getEventType (), AccessibilityEvent .TYPE_WINDOW_STATE_CHANGED );
253+
254+ // Synthesize an accessibility hit test event.
255+ MotionEvent mockEvent = mock (MotionEvent .class );
256+ when (mockEvent .getX ()).thenReturn (10.0f );
257+ when (mockEvent .getY ()).thenReturn (10.0f );
258+ when (mockEvent .getAction ()).thenReturn (MotionEvent .ACTION_HOVER_ENTER );
259+ boolean hit = accessibilityBridge .onAccessibilityHoverEvent (mockEvent );
260+
261+ assertEquals (hit , true );
262+
263+ eventCaptor = ArgumentCaptor .forClass (AccessibilityEvent .class );
264+ verify (mockParent , times (3 ))
265+ .requestSendAccessibilityEvent (eq (mockRootView ), eventCaptor .capture ());
266+ event = eventCaptor .getAllValues ().get (2 );
267+ assertEquals (event .getEventType (), AccessibilityEvent .TYPE_VIEW_HOVER_ENTER );
268+ assertEquals (accessibilityBridge .getHoveredObjectId (), 2 );
269+ }
270+
207271 @ Test
208272 public void itAnnouncesRouteNameWhenRemoveARoute () {
209273 AccessibilityViewEmbedder mockViewEmbedder = mock (AccessibilityViewEmbedder .class );
0 commit comments