Automatyzacja testów nawigacji z użyciem fokusu zapewnia spójne i przewidywalne działanie aplikacji na klawiaturach sprzętowych, padach kierunkowych i narzędziach ułatwień dostępu. Compose udostępnia wbudowane interfejsy API do testowania, które symulują wprowadzanie danych za pomocą klawiszy i weryfikują stany zaznaczenia.
Konfigurowanie testów skupienia
Aby napisać testy zaznaczenia, użyj createComposeRule() z biblioteki testowej Compose:
@RunWith(AndroidJUnit4::class) class FocusNavigationTest { @get:Rule val composeTestRule = createComposeRule()
Sprawdzanie celów ostrości
Możesz sprawdzić, czy element interfejsu może zostać zaznaczony, klikając go lub żądając zaznaczenia, a następnie potwierdzając jego stan za pomocą assertIsFocused() i 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() }
Testowanie jednowymiarowego przechodzenia fokusu
Zasymuluj naciśnięcie klawiszy Tab i Shift+Tab za pomocą performKeyInput, aby sprawdzić, czy zaznaczenie przesuwa się po interfejsie w kolejności wyświetlania. Zalecamy sprawdzenie zarówno nawigacji do przodu (Key.Tab), jak i do tyłu (Key.Tab z przytrzymanym klawiszem Key.ShiftLeft), aby upewnić się, że nawigacja działa prawidłowo w obu kierunkach:
@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() }
Testowanie dwuwymiarowej nawigacji kierunkowej
Symuluj klawisze strzałek lub klawisze kierunkowe pada kierunkowego za pomocą klawiszy Key.DirectionDown, Key.DirectionUp, Key.DirectionRight i 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() }
Testowanie zachowania zaznaczenia pola tekstowego
Sprawdź, czy po naciśnięciu klawisza Tab fokus przechodzi do następnego pola tekstowego, jeśli jest ono jednowierszowe, lub pozostaje w tym samym polu, jeśli jest ono wielowierszowe:
@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() }
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy język JavaScript jest wyłączony.
- Cele skupienia
- Kolejność przechodzenia między elementami
- Ustawianie kursora w polach tekstowych
- Cele skupienia grupy