---
title: "KeyInjectionScope"
description: "The receiver scope of the key input injection lambda from [performKeyInput].

All sequences and patterns of key input can be expressed using the two fundamental methods of
this API - [keyDown] and [keyUp]. All other injection functions are provided as abstractions
built on top of these two methods in order to improve test code readability/maintainability and
decrease development time.

The entire event injection state is shared between all `perform.*Input` methods, meaning you can
continue an unfinished key input sequence in a subsequent invocation of [performKeyInput] or
[performMultiModalInput].

All events sent by these methods are batched together and sent as a whole after [performKeyInput]
has executed its code block.

When a key is held down - i.e. the virtual clock is forwarded whilst the key is pressed down,
repeat key down events will be sent. In a fashion consistent with Android's implementation, the
first repeat key event will be sent after a key has been held down for 500ms. Subsequent repeat
events will be sent at 50ms intervals, until the key is released or another key is pressed down.

The sending of repeat key events is handled as an implicit side-effect of [advanceEventTime],
which is called within the injection scope. As such, no repeat key events will be sent if
[MainTestClock.advanceTimeBy] is used to advance the time."
type: "interface"
---

<div class='type'>Interface</div>


<a id='references'></a>

<div class='sourceset sourceset-common'>Common</div>



```kotlin
@JvmDefaultWithCompatibility
interface KeyInjectionScope : InjectionScope
```


The receiver scope of the key input injection lambda from `performKeyInput`.

All sequences and patterns of key input can be expressed using the two fundamental methods of
this API - `keyDown` and `keyUp`. All other injection functions are provided as abstractions
built on top of these two methods in order to improve test code readability/maintainability and
decrease development time.

The entire event injection state is shared between all `perform.*Input` methods, meaning you can
continue an unfinished key input sequence in a subsequent invocation of `performKeyInput` or
`performMultiModalInput`.

All events sent by these methods are batched together and sent as a whole after `performKeyInput`
has executed its code block.

When a key is held down - i.e. the virtual clock is forwarded whilst the key is pressed down,
repeat key down events will be sent. In a fashion consistent with Android's implementation, the
first repeat key event will be sent after a key has been held down for 500ms. Subsequent repeat
events will be sent at 50ms intervals, until the key is released or another key is pressed down.

The sending of repeat key events is handled as an implicit side-effect of `advanceEventTime`,
which is called within the injection scope. As such, no repeat key events will be sent if
`MainTestClock.advanceTimeBy` is used to advance the time.


## Properties

<div class='sourceset sourceset-common'>Common</div>


```kotlin
val isCapsLockOn: Boolean
```


Indicates whether caps lock is on or not.

Note that this reflects the state of the injected input only, it does not correspond to the
state of an actual keyboard attached to the device on which a test is run



<div class='sourceset sourceset-common'>Common</div>


```kotlin
val isNumLockOn: Boolean
```


Indicates whether num lock is on or not.

Note that this reflects the state of the injected input only, it does not correspond to the
state of an actual keyboard attached to the device on which a test is run



<div class='sourceset sourceset-common'>Common</div>


```kotlin
val isScrollLockOn: Boolean
```


Indicates whether scroll lock is on or not.

Note that this reflects the state of the injected input only, it does not correspond to the
state of an actual keyboard attached to the device on which a test is run



## Functions

```kotlin
fun keyDown(key: Key)
```


Sends a key down event for the given `key`.

If the given key is already down, an `IllegalStateException` will be thrown.

#### Parameters

| | |
| --- | --- |
| key | The key to be pressed down. |



```kotlin
fun keyUp(key: Key)
```


Sends a key up event for the given `key`.

If the given key is already up, an `IllegalStateException` will be thrown.

#### Parameters

| | |
| --- | --- |
| key | The key to be released. |



```kotlin
fun isKeyDown(key: Key): Boolean
```


Checks if the given `key` is down.

#### Parameters

| | |
| --- | --- |
| key | The key to be checked. |


#### Returns

| | |
| --- | --- |
|  | true if the given `key` is pressed down, false otherwise. |




## Code Examples

### keyInputClick
```kotlin
fun keyInputClick() {
    var counter = 0
    val focusRequester = FocusRequester()
    lateinit var inputModeManager: InputModeManager
    composeTestRule.setContent {
        inputModeManager = LocalInputModeManager.current
        BasicText(
            "ClickableText",
            modifier =
                Modifier.testTag("myClickable").focusRequester(focusRequester).clickable {
                    counter++
                },
        )
    }
    composeTestRule.runOnIdle {
        inputModeManager.requestInputMode(Keyboard)
        focusRequester.requestFocus()
    }
    composeTestRule.onNodeWithTag("myClickable").performKeyInput { keyDown(Key.Enter) }
    composeTestRule.runOnIdle { assert(counter == 0) }
    composeTestRule.onNodeWithTag("myClickable").performKeyInput { keyUp(Key.Enter) }
    composeTestRule.runOnIdle { assert(counter == 1) }
}
```

