A automação de testes de navegação por foco garante que a entrega de apps ofereça uma experiência do usuário consistente e previsível em teclados físicos, botões direcionais e ferramentas de acessibilidade. O Compose oferece APIs de teste integradas para simular a entrada de teclas e verificar os estados de foco.
Configurar testes de foco
Para criar testes de foco, use createComposeRule() da biblioteca de testes do
Compose:
@RunWith(AndroidJUnit4::class) class FocusNavigationTest { @get:Rule val composeTestRule = createComposeRule()
Verificar os alvos de foco
Para verificar se um elemento da interface pode receber foco, clique nele ou
solicite o foco e, em seguida, confirme o estado usando assertIsFocused() e
assertIsNotFocused().
@Test fun interactiveElement_isFocusTarget() { composeTestRule.setContent { AppTheme { CardListScreen() } } val firstCard = composeTestRule.onNodeWithTag("card_1") val secondCard = composeTestRule.onNodeWithTag("card_2") // Focus the first element firstCard.performClick() firstCard.assertIsFocused() secondCard.assertIsNotFocused() }
Testar a transição de foco unidimensional
Simule as teclas Tab e Shift+Tab
usando performKeyInput para verificar se o foco avança pela interface
na ordem de exibição. Como prática recomendada,
verifique a navegação para frente (Key.Tab) e para trás
(Key.Tab com Key.ShiftLeft pressionado) para garantir a integridade da travessia
bidirecional:
@Test fun tabKey_navigatesInAppearanceOrder() { composeTestRule.setContent { AppTheme { CardListScreen() } } val firstCard = composeTestRule.onNodeWithTag("card_1") val secondCard = composeTestRule.onNodeWithTag("card_2") val thirdCard = composeTestRule.onNodeWithTag("card_3") firstCard.performClick() firstCard.assertIsFocused() // Press Tab -> Moves to second card firstCard.performKeyInput { pressKey(Key.Tab) } secondCard.assertIsFocused() firstCard.assertIsNotFocused() // Press Tab -> Moves to third card secondCard.performKeyInput { pressKey(Key.Tab) } thirdCard.assertIsFocused() // Press Shift + Tab -> Moves backward to second card thirdCard.performKeyInput { withKeyDown(Key.ShiftLeft) { pressKey(Key.Tab) } } secondCard.assertIsFocused() }
Testar a travessia direcional bidimensional
Simule as teclas de seta ou as teclas direcionais do botão direcional usando Key.DirectionDown,
Key.DirectionUp, Key.DirectionRight e Key.DirectionLeft.
@Test fun arrowKeys_moveFocusTwoDimensionallyWithoutWrap() { composeTestRule.setContent { AppTheme { GridLayoutScreen() } } val topLeftButton = composeTestRule.onNodeWithTag("btn_top_left") val bottomLeftButton = composeTestRule.onNodeWithTag("btn_bottom_left") topLeftButton.performClick() topLeftButton.assertIsFocused() // Down arrow moves focus downward to bottom-left button topLeftButton.performKeyInput { pressKey(Key.DirectionDown) } bottomLeftButton.assertIsFocused() // Directional keys do not wrap around: pressing Down on bottom element stays focused bottomLeftButton.performKeyInput { pressKey(Key.DirectionDown) } bottomLeftButton.assertIsFocused() }
Testar o comportamento de foco do campo de texto
Verifique se os campos de texto de linha única avançam o foco em Tab, enquanto os campos de texto multilinha mantêm o foco:
@Test fun textField_handlesTabAccordingToLineLimits() { composeTestRule.setContent { AppTheme { FormScreen() } } val singleLineNode = composeTestRule.onNodeWithTag("single_line_field") val multiLineNode = composeTestRule.onNodeWithTag("multi_line_field") val submitButtonNode = composeTestRule.onNodeWithTag("submit_button") // Single-line field advances focus on Tab singleLineNode.performClick() singleLineNode.assertIsFocused() singleLineNode.performKeyInput { pressKey(Key.Tab) } multiLineNode.assertIsFocused() // Multi-line field keeps focus and inserts '\t' multiLineNode.performKeyInput { pressKey(Key.Tab) } multiLineNode.assertIsFocused() submitButtonNode.assertIsNotFocused() // Shift + Tab escapes multi-line field to previous target multiLineNode.performKeyInput { withKeyDown(Key.ShiftLeft) { pressKey(Key.Tab) } } singleLineNode.assertIsFocused() }
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Metas de foco
- Ordem de apresentação do foco
- Foco em campos de texto
- Agrupar alvos de foco