test(mobile): cover AltGr native keyboard ownership

This commit is contained in:
Neil
2026-09-05 22:22:47 -07:00
parent 7fe19f20ee
commit ea79923f2e
3 changed files with 56 additions and 1 deletions
@@ -0,0 +1,23 @@
package expo.modules.hardwarekeyboard;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowKeyCharacterMap;
@Implements(KeyCharacterMap.class)
public class HardwareKeyboardAlternateCharacterMap extends ShadowKeyCharacterMap {
@Implementation
protected static char nativeGetCharacter(long pointer, int keyCode, int metaState) {
if (keyCode != KeyEvent.KEYCODE_Q) return '\u0000';
boolean shifted = (metaState & KeyEvent.META_SHIFT_ON) != 0;
if ((metaState & KeyEvent.META_ALT_ON) != 0) return shifted ? '#' : '@';
return shifted ? 'Q' : 'q';
}
@Implementation
protected static char nativeGetDisplayLabel(long pointer, int keyCode) {
return keyCode == KeyEvent.KEYCODE_Q ? 'Q' : '\u0000';
}
}
@@ -0,0 +1,32 @@
package expo.modules.hardwarekeyboard
import android.view.KeyEvent
import org.junit.Assert.*
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [28], manifest = Config.NONE, shadows = [HardwareKeyboardAlternateCharacterMap::class])
class HardwareKeyboardAlternateLayoutTest {
@Test fun synthesizedAltGrKeepsNativeTextAndNeverClaimsARelease() {
for (shift in listOf(0, KeyEvent.META_SHIFT_ON)) {
val fixture = HardwareKeyboardNativeBoundaryTest.Fixture()
val meta = KeyEvent.META_CTRL_ON or KeyEvent.META_ALT_ON or shift
assertFalse(fixture.key(KeyEvent.KEYCODE_Q, meta = meta))
assertEquals("first", fixture.input.text.toString())
assertTrue(fixture.context.events.isEmpty())
assertFalse(fixture.key(KeyEvent.KEYCODE_Q, KeyEvent.ACTION_UP, meta = meta))
}
}
@Test fun ordinaryCtrlStillCapturesTheLogicalKeyAndFieldBoundary() {
val fixture = HardwareKeyboardNativeBoundaryTest.Fixture()
assertTrue(fixture.key(KeyEvent.KEYCODE_Q, meta = KeyEvent.META_CTRL_ON))
assertEquals("q", fixture.lastKey()["key"])
assertEquals("first", (fixture.lastKey()["fieldBoundary"] as Map<*, *>)["text"])
assertEquals("", fixture.input.text.toString())
assertTrue(fixture.key(KeyEvent.KEYCODE_Q, KeyEvent.ACTION_UP))
}
}
@@ -19,7 +19,7 @@ import org.robolectric.annotation.Config
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [28], manifest = Config.NONE)
class HardwareKeyboardNativeBoundaryTest {
private class Fixture {
internal class Fixture {
val context = HardwareKeyboardRecordingContext(RuntimeEnvironment.getApplication()).also {
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(it)
}