फ़ोकस नेविगेशन की सुविधा की जांच करना

फ़ोकस नेविगेशन टेस्ट को अपने-आप होने की सुविधा के साथ सेट अप करने से, यह पक्का किया जा सकता है कि आपका ऐप्लिकेशन, हार्डवेयर कीबोर्ड, डी-पैड, और सुलभता टूल पर एक जैसा और अनुमानित यूज़र एक्सपीरियंस दे. Compose में, पहले से मौजूद टेस्टिंग एपीआई उपलब्ध होते हैं. इनकी मदद से, मुख्य इनपुट को सिम्युलेट किया जा सकता है और फ़ोकस की स्थितियों की पुष्टि की जा सकती है.

फ़ोकस टेस्ट सेट अप करना

फ़ोकस टेस्ट लिखने के लिए, Compose टेस्टिंग लाइब्रेरी से createComposeRule() का इस्तेमाल करें:

@RunWith(AndroidJUnit4::class)
class FocusNavigationTest {
    @get:Rule
    val composeTestRule = createComposeRule()

फ़ोकस किए गए टारगेट की पुष्टि करना

यह पुष्टि की जा सकती है कि किसी यूज़र इंटरफ़ेस (यूआई) एलिमेंट पर फ़ोकस किया जा सकता है या नहीं. इसके लिए, उस पर क्लिक करें या फ़ोकस करने का अनुरोध करें. इसके बाद, assertIsFocused() और 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()
}

एक डाइमेंशन में फ़ोकस ट्रैवर्सल की जांच करना

Tab और Shift+Tab कुंजियों को दबाने की कार्रवाई को performKeyInput का इस्तेमाल करके सिम्युलेट करें. इससे यह पुष्टि की जा सकेगी कि फ़ोकस, यूज़र इंटरफ़ेस (यूआई) में दिखने के क्रम के हिसाब से आगे बढ़ता है. सबसे सही तरीके के तौर पर, आगे बढ़ने के लिए नेविगेशन (Key.Tab) और पीछे जाने के लिए नेविगेशन (Key.Tab को दबाकर रखें Key.ShiftLeft) की पुष्टि करें. इससे यह पक्का किया जा सकेगा कि दोनों तरह के नेविगेशन सही तरीके से काम कर रहे हैं:

@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()
}

दो डाइमेंशन में दिशा के हिसाब से ट्रैवर्स करने की सुविधा की जांच करना

Key.DirectionDown, Key.DirectionUp, Key.DirectionRight, और 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()
}

टेक्स्ट फ़ील्ड पर फ़ोकस करने के तरीके की जांच करना

पुष्टि करें कि एक लाइन वाले टेक्स्ट फ़ील्ड में, फ़ोकस Tab पर चला जाता है. वहीं, कई लाइन वाले टेक्स्ट फ़ील्ड में फ़ोकस बना रहता है:

@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()
}