Flutter Engine
The Flutter Engine
Classes | Public Member Functions | Package Attributes | List of all members
io.flutter.plugin.editing.TextInputPluginTest Class Reference

Classes

interface  EventHandler
 
class  TestAfm
 
class  TestImm
 

Public Member Functions

void setUp ()
 
void textInputPlugin_RequestsReattachOnCreation () throws JSONException
 
void setTextInputEditingState_doesNotInvokeUpdateEditingState ()
 
void setTextInputEditingState_willNotThrowWithoutSetTextInputClient ()
 
void setTextInputEditingState_doesNotInvokeUpdateEditingStateWithDeltas ()
 
void textEditingDelta_TestUpdateEditingValueWithDeltasIsNotInvokedWhenDeltaModelDisabled () throws NullPointerException
 
void textEditingDelta_TestUpdateEditingValueIsNotInvokedWhenDeltaModelEnabled () throws NullPointerException
 
void textEditingDelta_TestDeltaIsCreatedWhenComposingTextSetIsInserting () throws NullPointerException
 
void textEditingDelta_TestDeltaIsCreatedWhenComposingTextSetIsDeleting () throws NullPointerException
 
void textEditingDelta_TestDeltaIsCreatedWhenComposingTextSetIsReplacing () throws NullPointerException
 
void inputConnectionAdaptor_RepeatFilter () throws NullPointerException
 
void setTextInputEditingState_doesNotRestartWhenTextIsIdentical ()
 
void setTextInputEditingState_alwaysSetEditableWhenDifferent ()
 
void setTextInputEditingState_restartsIMEOnlyWhenFrameworkChangesComposingRegion ()
 
void TextEditState_throwsOnInvalidStatesReceived ()
 
void setTextInputEditingState_nullInputMethodSubtype ()
 
void clearTextInputClient_alwaysRestartsImm ()
 
void destroy_clearTextInputMethodHandler ()
 
void inputConnection_createsActionFromEnter () throws JSONException
 
void inputConnection_respondsToKeyEvents_textInputTypeNone () throws JSONException
 
void inputConnection_finishComposingTextUpdatesIMM () throws JSONException
 
void inputConnection_textInputTypeNone ()
 
void showTextInput_textInputTypeNone ()
 
void inputConnection_textInputTypeMultilineAndSuggestionsDisabled ()
 
void autofill_enabledByDefault ()
 
void autofill_canBeDisabled ()
 
void autofill_hintText ()
 
void autofill_onProvideVirtualViewStructure ()
 
void autofill_onProvideVirtualViewStructure_singular_textfield ()
 
void autofill_testLifeCycle ()
 
void autofill_testAutofillUpdatesTheFramework ()
 
void autofill_doesNotCrashAfterClearClientCall ()
 
void autofill_testSetTextIpnutClientUpdatesSideFields ()
 
void respondsToInputChannelMessages ()
 
void sendAppPrivateCommand_dataIsEmpty () throws JSONException
 
void sendAppPrivateCommand_hasData () throws JSONException
 
void ime_windowInsetsSync_notLaidOutBehindNavigation_excludesNavigationBars ()
 
void ime_windowInsetsSync_laidOutBehindNavigation_includesNavigationBars ()
 
void lastWindowInsets_updatedOnSecondOnProgressCall ()
 

Package Attributes

FlutterJNI mockFlutterJni
 
FlutterLoader mockFlutterLoader
 

Detailed Description

Definition at line 89 of file TextInputPluginTest.java.

Member Function Documentation

◆ autofill_canBeDisabled()

void io.flutter.plugin.editing.TextInputPluginTest.autofill_canBeDisabled ( )
inline

Definition at line 1451 of file TextInputPluginTest.java.

1451 {
1452 if (Build.VERSION.SDK_INT < API_LEVELS.API_26) {
1453 return;
1454 }
1455 FlutterView testView = new FlutterView(ctx);
1456 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
1457 TextInputPlugin textInputPlugin =
1458 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1459 final TextInputChannel.Configuration.Autofill autofill =
1460 new TextInputChannel.Configuration.Autofill(
1461 "1", new String[] {}, null, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1462
1463 final TextInputChannel.Configuration config =
1464 new TextInputChannel.Configuration(
1465 false,
1466 false,
1467 true,
1468 true,
1469 false,
1470 TextInputChannel.TextCapitalization.NONE,
1471 null,
1472 null,
1473 null,
1474 null,
1475 null,
1476 null);
1477
1478 textInputPlugin.setTextInputClient(0, config);
1479
1480 final ViewStructure viewStructure = mock(ViewStructure.class);
1481
1482 textInputPlugin.onProvideAutofillVirtualStructure(viewStructure, 0);
1483
1484 verify(viewStructure, times(0)).newChild(anyInt());
1485 }
static SkISize times(const SkISize &size, float factor)
FlutterTextInputPlugin * textInputPlugin
def Build(configs, env, options)
Definition: build.py:232

◆ autofill_doesNotCrashAfterClearClientCall()

void io.flutter.plugin.editing.TextInputPluginTest.autofill_doesNotCrashAfterClearClientCall ( )
inline

Definition at line 1909 of file TextInputPluginTest.java.

1909 {
1910 if (Build.VERSION.SDK_INT < API_LEVELS.API_26) {
1911 return;
1912 }
1913 FlutterView testView = new FlutterView(ctx);
1914 TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
1915 TextInputPlugin textInputPlugin =
1916 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1917 // Set up an autofill scenario with 2 fields.
1918 final TextInputChannel.Configuration.Autofill autofillConfig =
1919 new TextInputChannel.Configuration.Autofill(
1920 "1",
1921 new String[] {"HINT1"},
1922 "placeholder1",
1923 new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1924 final TextInputChannel.Configuration config =
1925 new TextInputChannel.Configuration(
1926 false,
1927 false,
1928 true,
1929 true,
1930 false,
1931 TextInputChannel.TextCapitalization.NONE,
1932 null,
1933 null,
1934 null,
1935 autofillConfig,
1936 null,
1937 null);
1938
1939 textInputPlugin.setTextInputClient(0, config);
1940 textInputPlugin.setTextInputEditingState(
1941 testView, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1943
1944 final SparseArray<AutofillValue> autofillValues = new SparseArray();
1945 autofillValues.append("1".hashCode(), AutofillValue.forText("focused field"));
1946 autofillValues.append("2".hashCode(), AutofillValue.forText("unfocused field"));
1947
1948 // Autofill both fields.
1949 textInputPlugin.autofill(autofillValues);
1950
1951 verify(textInputChannel, never()).updateEditingStateWithTag(anyInt(), any());
1952 verify(textInputChannel, never())
1953 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
1954 }
SIT bool any(const Vec< 1, T > &x)
Definition: SkVx.h:530

◆ autofill_enabledByDefault()

void io.flutter.plugin.editing.TextInputPluginTest.autofill_enabledByDefault ( )
inline

Definition at line 1391 of file TextInputPluginTest.java.

1391 {
1392 if (Build.VERSION.SDK_INT < API_LEVELS.API_26) {
1393 return;
1394 }
1395 FlutterView testView = new FlutterView(ctx);
1396 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
1397 TextInputPlugin textInputPlugin =
1398 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1399 final TextInputChannel.Configuration.Autofill autofill =
1400 new TextInputChannel.Configuration.Autofill(
1401 "1", new String[] {}, null, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1402
1403 final TextInputChannel.Configuration config =
1404 new TextInputChannel.Configuration(
1405 false,
1406 false,
1407 true,
1408 true,
1409 false,
1410 TextInputChannel.TextCapitalization.NONE,
1411 null,
1412 null,
1413 null,
1414 autofill,
1415 null,
1416 null);
1417
1418 textInputPlugin.setTextInputClient(
1419 0,
1420 new TextInputChannel.Configuration(
1421 false,
1422 false,
1423 true,
1424 true,
1425 false,
1426 TextInputChannel.TextCapitalization.NONE,
1427 null,
1428 null,
1429 null,
1430 autofill,
1431 null,
1432 new TextInputChannel.Configuration[] {config}));
1433
1434 final ViewStructure viewStructure = mock(ViewStructure.class);
1435 final ViewStructure[] children = {mock(ViewStructure.class), mock(ViewStructure.class)};
1436
1437 when(viewStructure.newChild(anyInt()))
1438 .thenAnswer(invocation -> children[(int) invocation.getArgument(0)]);
1439
1440 textInputPlugin.onProvideAutofillVirtualStructure(viewStructure, 0);
1441
1442 verify(viewStructure).newChild(0);
1443
1444 verify(children[0]).setAutofillId(any(), eq("1".hashCode()));
1445 // The flutter application sends an empty hint list, don't set hints.
1446 verify(children[0], never()).setAutofillHints(aryEq(new String[] {}));
1447 verify(children[0]).setDimens(anyInt(), anyInt(), anyInt(), anyInt(), gt(0), gt(0));
1448 }
static bool eq(const SkM44 &a, const SkM44 &b, float tol)
Definition: M44Test.cpp:18

◆ autofill_hintText()

void io.flutter.plugin.editing.TextInputPluginTest.autofill_hintText ( )
inline

Definition at line 1488 of file TextInputPluginTest.java.

1488 {
1489 if (Build.VERSION.SDK_INT < API_LEVELS.API_26) {
1490 return;
1491 }
1492 FlutterView testView = new FlutterView(ctx);
1493 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
1494 TextInputPlugin textInputPlugin =
1495 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1496 final TextInputChannel.Configuration.Autofill autofill =
1497 new TextInputChannel.Configuration.Autofill(
1498 "1",
1499 new String[] {},
1500 "placeholder",
1501 new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1502
1503 final TextInputChannel.Configuration config =
1504 new TextInputChannel.Configuration(
1505 false,
1506 false,
1507 true,
1508 true,
1509 false,
1510 TextInputChannel.TextCapitalization.NONE,
1511 null,
1512 null,
1513 null,
1514 autofill,
1515 null,
1516 null);
1517
1518 textInputPlugin.setTextInputClient(0, config);
1519
1520 final ViewStructure viewStructure = mock(ViewStructure.class);
1521 final ViewStructure[] children = {mock(ViewStructure.class), mock(ViewStructure.class)};
1522
1523 when(viewStructure.newChild(anyInt()))
1524 .thenAnswer(invocation -> children[(int) invocation.getArgument(0)]);
1525
1526 textInputPlugin.onProvideAutofillVirtualStructure(viewStructure, 0);
1527 verify(children[0]).setHint("placeholder");
1528 }

◆ autofill_onProvideVirtualViewStructure()

void io.flutter.plugin.editing.TextInputPluginTest.autofill_onProvideVirtualViewStructure ( )
inline

Definition at line 1533 of file TextInputPluginTest.java.

1533 {
1534 if (Build.VERSION.SDK_INT < API_LEVELS.API_26) {
1535 return;
1536 }
1537 FlutterView testView = getTestView();
1538 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
1539 TextInputPlugin textInputPlugin =
1540 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1541 final TextInputChannel.Configuration.Autofill autofill1 =
1542 new TextInputChannel.Configuration.Autofill(
1543 "1",
1544 new String[] {"HINT1"},
1545 "placeholder1",
1546 new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1547 final TextInputChannel.Configuration.Autofill autofill2 =
1548 new TextInputChannel.Configuration.Autofill(
1549 "2",
1550 new String[] {"HINT2", "EXTRA"},
1551 null,
1552 new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1553
1554 final TextInputChannel.Configuration config1 =
1555 new TextInputChannel.Configuration(
1556 false,
1557 false,
1558 true,
1559 true,
1560 false,
1561 TextInputChannel.TextCapitalization.NONE,
1562 null,
1563 null,
1564 null,
1565 autofill1,
1566 null,
1567 null);
1568 final TextInputChannel.Configuration config2 =
1569 new TextInputChannel.Configuration(
1570 false,
1571 false,
1572 true,
1573 true,
1574 false,
1575 TextInputChannel.TextCapitalization.NONE,
1576 null,
1577 null,
1578 null,
1579 autofill2,
1580 null,
1581 null);
1582
1583 textInputPlugin.setTextInputClient(
1584 0,
1585 new TextInputChannel.Configuration(
1586 false,
1587 false,
1588 true,
1589 true,
1590 false,
1591 TextInputChannel.TextCapitalization.NONE,
1592 null,
1593 null,
1594 null,
1595 autofill1,
1596 null,
1597 new TextInputChannel.Configuration[] {config1, config2}));
1598
1599 final ViewStructure viewStructure = mock(ViewStructure.class);
1600 final ViewStructure[] children = {mock(ViewStructure.class), mock(ViewStructure.class)};
1601
1602 when(viewStructure.newChild(anyInt()))
1603 .thenAnswer(invocation -> children[(int) invocation.getArgument(0)]);
1604
1605 textInputPlugin.onProvideAutofillVirtualStructure(viewStructure, 0);
1606
1607 verify(viewStructure).newChild(0);
1608 verify(viewStructure).newChild(1);
1609
1610 verify(children[0]).setAutofillId(any(), eq("1".hashCode()));
1611 verify(children[0]).setAutofillHints(aryEq(new String[] {"HINT1"}));
1612 verify(children[0]).setDimens(anyInt(), anyInt(), anyInt(), anyInt(), gt(0), gt(0));
1613 verify(children[0]).setHint("placeholder1");
1614
1615 verify(children[1]).setAutofillId(any(), eq("2".hashCode()));
1616 verify(children[1]).setAutofillHints(aryEq(new String[] {"HINT2", "EXTRA"}));
1617 verify(children[1]).setDimens(anyInt(), anyInt(), anyInt(), anyInt(), gt(0), gt(0));
1618 verify(children[1], times(0)).setHint(any());
1619 }

◆ autofill_onProvideVirtualViewStructure_singular_textfield()

void io.flutter.plugin.editing.TextInputPluginTest.autofill_onProvideVirtualViewStructure_singular_textfield ( )
inline

Definition at line 1624 of file TextInputPluginTest.java.

1624 {
1625 if (Build.VERSION.SDK_INT < API_LEVELS.API_26) {
1626 return;
1627 }
1628 // Migrate to ActivityScenario by following https://github.com/robolectric/robolectric/pull/4736
1629 FlutterView testView = getTestView();
1630 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
1631 TextInputPlugin textInputPlugin =
1632 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1633 final TextInputChannel.Configuration.Autofill autofill =
1634 new TextInputChannel.Configuration.Autofill(
1635 "1",
1636 new String[] {"HINT1"},
1637 "placeholder",
1638 new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1639
1640 // Autofill should still work without AutofillGroup.
1641 textInputPlugin.setTextInputClient(
1642 0,
1643 new TextInputChannel.Configuration(
1644 false,
1645 false,
1646 true,
1647 true,
1648 false,
1649 TextInputChannel.TextCapitalization.NONE,
1650 null,
1651 null,
1652 null,
1653 autofill,
1654 null,
1655 null));
1656
1657 final ViewStructure viewStructure = mock(ViewStructure.class);
1658 final ViewStructure[] children = {mock(ViewStructure.class)};
1659
1660 when(viewStructure.newChild(anyInt()))
1661 .thenAnswer(invocation -> children[(int) invocation.getArgument(0)]);
1662
1663 textInputPlugin.onProvideAutofillVirtualStructure(viewStructure, 0);
1664
1665 verify(viewStructure).newChild(0);
1666
1667 verify(children[0]).setAutofillId(any(), eq("1".hashCode()));
1668 verify(children[0]).setAutofillHints(aryEq(new String[] {"HINT1"}));
1669 verify(children[0]).setHint("placeholder");
1670 // Verifies that the child has a non-zero size.
1671 verify(children[0]).setDimens(anyInt(), anyInt(), anyInt(), anyInt(), gt(0), gt(0));
1672 }

◆ autofill_testAutofillUpdatesTheFramework()

void io.flutter.plugin.editing.TextInputPluginTest.autofill_testAutofillUpdatesTheFramework ( )
inline

Definition at line 1812 of file TextInputPluginTest.java.

1812 {
1813 if (Build.VERSION.SDK_INT < API_LEVELS.API_26) {
1814 return;
1815 }
1816
1817 TestAfm testAfm = Shadow.extract(ctx.getSystemService(AutofillManager.class));
1818 FlutterView testView = getTestView();
1819 TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
1820 TextInputPlugin textInputPlugin =
1821 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1822
1823 // Set up an autofill scenario with 2 fields.
1824 final TextInputChannel.Configuration.Autofill autofill1 =
1825 new TextInputChannel.Configuration.Autofill(
1826 "1",
1827 new String[] {"HINT1"},
1828 null,
1829 new TextInputChannel.TextEditState("field 1", 0, 0, -1, -1));
1830 final TextInputChannel.Configuration.Autofill autofill2 =
1831 new TextInputChannel.Configuration.Autofill(
1832 "2",
1833 new String[] {"HINT2", "EXTRA"},
1834 null,
1835 new TextInputChannel.TextEditState("field 2", 0, 0, -1, -1));
1836
1837 final TextInputChannel.Configuration config1 =
1838 new TextInputChannel.Configuration(
1839 false,
1840 false,
1841 true,
1842 true,
1843 false,
1844 TextInputChannel.TextCapitalization.NONE,
1845 null,
1846 null,
1847 null,
1848 autofill1,
1849 null,
1850 null);
1851 final TextInputChannel.Configuration config2 =
1852 new TextInputChannel.Configuration(
1853 false,
1854 false,
1855 true,
1856 true,
1857 false,
1858 TextInputChannel.TextCapitalization.NONE,
1859 null,
1860 null,
1861 null,
1862 autofill2,
1863 null,
1864 null);
1865
1866 final TextInputChannel.Configuration autofillConfiguration =
1867 new TextInputChannel.Configuration(
1868 false,
1869 false,
1870 true,
1871 true,
1872 false,
1873 TextInputChannel.TextCapitalization.NONE,
1874 null,
1875 null,
1876 null,
1877 autofill1,
1878 null,
1879 new TextInputChannel.Configuration[] {config1, config2});
1880
1881 textInputPlugin.setTextInputClient(0, autofillConfiguration);
1882 textInputPlugin.setTextInputEditingState(
1883 testView, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1884
1885 final SparseArray<AutofillValue> autofillValues = new SparseArray();
1886 autofillValues.append("1".hashCode(), AutofillValue.forText("focused field"));
1887 autofillValues.append("2".hashCode(), AutofillValue.forText("unfocused field"));
1888
1889 // Autofill both fields.
1890 textInputPlugin.autofill(autofillValues);
1891
1892 // Verify the Editable has been updated.
1893 assertTrue(textInputPlugin.getEditable().toString().equals("focused field"));
1894
1895 // The autofill value of the focused field is sent via updateEditingState.
1896 verify(textInputChannel, times(1))
1897 .updateEditingState(anyInt(), eq("focused field"), eq(13), eq(13), eq(-1), eq(-1));
1898
1899 final ArgumentCaptor<HashMap> mapCaptor = ArgumentCaptor.forClass(HashMap.class);
1900
1901 verify(textInputChannel, times(1)).updateEditingStateWithTag(anyInt(), mapCaptor.capture());
1902 final TextInputChannel.TextEditState editState =
1903 (TextInputChannel.TextEditState) mapCaptor.getValue().get("2");
1904 assertEquals(editState.text, "unfocused field");
1905 }

◆ autofill_testLifeCycle()

void io.flutter.plugin.editing.TextInputPluginTest.autofill_testLifeCycle ( )
inline

Definition at line 1676 of file TextInputPluginTest.java.

1676 {
1677 if (Build.VERSION.SDK_INT < API_LEVELS.API_26) {
1678 return;
1679 }
1680
1681 TestAfm testAfm = Shadow.extract(ctx.getSystemService(AutofillManager.class));
1682 FlutterView testView = getTestView();
1683 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
1684 TextInputPlugin textInputPlugin =
1685 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1686
1687 // Set up an autofill scenario with 2 fields.
1688 final TextInputChannel.Configuration.Autofill autofill1 =
1689 new TextInputChannel.Configuration.Autofill(
1690 "1",
1691 new String[] {"HINT1"},
1692 "placeholder1",
1693 new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1694 final TextInputChannel.Configuration.Autofill autofill2 =
1695 new TextInputChannel.Configuration.Autofill(
1696 "2",
1697 new String[] {"HINT2", "EXTRA"},
1698 null,
1699 new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1700
1701 final TextInputChannel.Configuration config1 =
1702 new TextInputChannel.Configuration(
1703 false,
1704 false,
1705 true,
1706 true,
1707 false,
1708 TextInputChannel.TextCapitalization.NONE,
1709 null,
1710 null,
1711 null,
1712 autofill1,
1713 null,
1714 null);
1715 final TextInputChannel.Configuration config2 =
1716 new TextInputChannel.Configuration(
1717 false,
1718 false,
1719 true,
1720 true,
1721 false,
1722 TextInputChannel.TextCapitalization.NONE,
1723 null,
1724 null,
1725 null,
1726 autofill2,
1727 null,
1728 null);
1729
1730 // Set client. This should call notifyViewExited on the FlutterView if the previous client is
1731 // also eligible for autofill.
1732 final TextInputChannel.Configuration autofillConfiguration =
1733 new TextInputChannel.Configuration(
1734 false,
1735 false,
1736 true,
1737 true,
1738 false,
1739 TextInputChannel.TextCapitalization.NONE,
1740 null,
1741 null,
1742 null,
1743 autofill1,
1744 null,
1745 new TextInputChannel.Configuration[] {config1, config2});
1746
1747 textInputPlugin.setTextInputClient(0, autofillConfiguration);
1748
1749 // notifyViewExited should not be called as this is the first client we set.
1750 assertEquals(testAfm.empty, testAfm.exitId);
1751
1752 // The framework updates the text, call notifyValueChanged.
1753 textInputPlugin.setTextInputEditingState(
1754 testView, new TextInputChannel.TextEditState("new text", -1, -1, -1, -1));
1755 assertEquals("new text", testAfm.changeString);
1756 assertEquals("1".hashCode(), testAfm.changeVirtualId);
1757
1758 // The input method updates the text, call notifyValueChanged.
1759 testAfm.resetStates();
1760 final KeyboardManager mockKeyboardManager = mock(KeyboardManager.class);
1761 InputConnectionAdaptor adaptor =
1762 new InputConnectionAdaptor(
1763 testView,
1764 0,
1765 mock(TextInputChannel.class),
1766 mockKeyboardManager,
1767 (ListenableEditingState) textInputPlugin.getEditable(),
1768 new EditorInfo());
1769 adaptor.commitText("input from IME ", 1);
1770
1771 assertEquals("input from IME new text", testAfm.changeString);
1772 assertEquals("1".hashCode(), testAfm.changeVirtualId);
1773
1774 // notifyViewExited should be called on the previous client.
1775 testAfm.resetStates();
1776 textInputPlugin.setTextInputClient(
1777 1,
1778 new TextInputChannel.Configuration(
1779 false,
1780 false,
1781 true,
1782 true,
1783 false,
1784 TextInputChannel.TextCapitalization.NONE,
1785 null,
1786 null,
1787 null,
1788 null,
1789 null,
1790 null));
1791
1792 assertEquals("1".hashCode(), testAfm.exitId);
1793
1794 // TextInputPlugin#clearTextInputClient calls notifyViewExited.
1795 testAfm.resetStates();
1796 textInputPlugin.setTextInputClient(3, autofillConfiguration);
1797 assertEquals(testAfm.empty, testAfm.exitId);
1799 assertEquals("1".hashCode(), testAfm.exitId);
1800
1801 // TextInputPlugin#destroy calls notifyViewExited.
1802 testAfm.resetStates();
1803 textInputPlugin.setTextInputClient(4, autofillConfiguration);
1804 assertEquals(testAfm.empty, testAfm.exitId);
1805 textInputPlugin.destroy();
1806 assertEquals("1".hashCode(), testAfm.exitId);
1807 }

◆ autofill_testSetTextIpnutClientUpdatesSideFields()

void io.flutter.plugin.editing.TextInputPluginTest.autofill_testSetTextIpnutClientUpdatesSideFields ( )
inline

Definition at line 1958 of file TextInputPluginTest.java.

1958 {
1959 if (Build.VERSION.SDK_INT < API_LEVELS.API_26) {
1960 return;
1961 }
1962
1963 TestAfm testAfm = Shadow.extract(ctx.getSystemService(AutofillManager.class));
1964 FlutterView testView = getTestView();
1965 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
1966 TextInputPlugin textInputPlugin =
1967 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1968
1969 // Set up an autofill scenario with 2 fields.
1970 final TextInputChannel.Configuration.Autofill autofill1 =
1971 new TextInputChannel.Configuration.Autofill(
1972 "1",
1973 new String[] {"HINT1"},
1974 "null",
1975 new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1976 final TextInputChannel.Configuration.Autofill autofill2 =
1977 new TextInputChannel.Configuration.Autofill(
1978 "2",
1979 new String[] {"HINT2", "EXTRA"},
1980 "null",
1981 new TextInputChannel.TextEditState(
1982 "Unfocused fields need love like everything does", 0, 0, -1, -1));
1983
1984 final TextInputChannel.Configuration config1 =
1985 new TextInputChannel.Configuration(
1986 false,
1987 false,
1988 true,
1989 true,
1990 false,
1991 TextInputChannel.TextCapitalization.NONE,
1992 null,
1993 null,
1994 null,
1995 autofill1,
1996 null,
1997 null);
1998 final TextInputChannel.Configuration config2 =
1999 new TextInputChannel.Configuration(
2000 false,
2001 false,
2002 true,
2003 true,
2004 false,
2005 TextInputChannel.TextCapitalization.NONE,
2006 null,
2007 null,
2008 null,
2009 autofill2,
2010 null,
2011 null);
2012
2013 final TextInputChannel.Configuration autofillConfiguration =
2014 new TextInputChannel.Configuration(
2015 false,
2016 false,
2017 true,
2018 true,
2019 false,
2020 TextInputChannel.TextCapitalization.NONE,
2021 null,
2022 null,
2023 null,
2024 autofill1,
2025 null,
2026 new TextInputChannel.Configuration[] {config1, config2});
2027
2028 textInputPlugin.setTextInputClient(0, autofillConfiguration);
2029
2030 // notifyValueChanged should be called for unfocused fields.
2031 assertEquals("2".hashCode(), testAfm.changeVirtualId);
2032 assertEquals("Unfocused fields need love like everything does", testAfm.changeString);
2033 }

◆ clearTextInputClient_alwaysRestartsImm()

void io.flutter.plugin.editing.TextInputPluginTest.clearTextInputClient_alwaysRestartsImm ( )
inline

Definition at line 1134 of file TextInputPluginTest.java.

1134 {
1135 // Initialize a general TextInputPlugin.
1136 InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
1137 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
1138 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
1139 View testView = new View(ctx);
1140 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
1141 TextInputPlugin textInputPlugin =
1142 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1143 textInputPlugin.setTextInputClient(
1144 0,
1145 new TextInputChannel.Configuration(
1146 false,
1147 false,
1148 true,
1149 true,
1150 false,
1151 TextInputChannel.TextCapitalization.NONE,
1152 null,
1153 null,
1154 null,
1155 null,
1156 null,
1157 null));
1158 // There's a pending restart since we initialized the text input client. Flush that now.
1159 textInputPlugin.setTextInputEditingState(
1160 testView, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1161 assertEquals(1, testImm.getRestartCount(testView));
1162
1163 // A restart is always forced when calling clearTextInputClient().
1165 assertEquals(2, testImm.getRestartCount(testView));
1166 }

◆ destroy_clearTextInputMethodHandler()

void io.flutter.plugin.editing.TextInputPluginTest.destroy_clearTextInputMethodHandler ( )
inline

Definition at line 1169 of file TextInputPluginTest.java.

1169 {
1170 View testView = new View(ctx);
1171 TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
1172 TextInputPlugin textInputPlugin =
1173 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1174 verify(textInputChannel, times(1)).setTextInputMethodHandler(isNotNull());
1175 textInputPlugin.destroy();
1176 verify(textInputChannel, times(1)).setTextInputMethodHandler(isNull());
1177 }

◆ ime_windowInsetsSync_laidOutBehindNavigation_includesNavigationBars()

void io.flutter.plugin.editing.TextInputPluginTest.ime_windowInsetsSync_laidOutBehindNavigation_includesNavigationBars ( )
inline

Definition at line 2220 of file TextInputPluginTest.java.

2220 {
2221 FlutterView testView = spy(getTestView());
2222 when(testView.getWindowSystemUiVisibility())
2223 .thenReturn(
2224 View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
2225
2226 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
2227 TextInputPlugin textInputPlugin =
2228 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
2229 ImeSyncDeferringInsetsCallback imeSyncCallback = textInputPlugin.getImeSyncCallback();
2230 FlutterEngine flutterEngine = spy(new FlutterEngine(ctx, mockFlutterLoader, mockFlutterJni));
2231 FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
2232 when(flutterEngine.getRenderer()).thenReturn(flutterRenderer);
2233 testView.attachToFlutterEngine(flutterEngine);
2234
2235 WindowInsetsAnimation animation = mock(WindowInsetsAnimation.class);
2236 when(animation.getTypeMask()).thenReturn(WindowInsets.Type.ime());
2237
2238 List<WindowInsetsAnimation> animationList = new ArrayList();
2239 animationList.add(animation);
2240
2241 ArgumentCaptor<FlutterRenderer.ViewportMetrics> viewportMetricsCaptor =
2242 ArgumentCaptor.forClass(FlutterRenderer.ViewportMetrics.class);
2243
2244 WindowInsets.Builder builder = new WindowInsets.Builder();
2245
2246 // Set the initial insets and verify that they were set and the bottom view inset is correct
2247 imeSyncCallback.getInsetsListener().onApplyWindowInsets(testView, builder.build());
2248
2249 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2250 assertEquals(0, viewportMetricsCaptor.getValue().viewInsetBottom);
2251
2252 // Call onPrepare and set the lastWindowInsets - these should be stored for the end of the
2253 // animation instead of being applied immediately
2254 imeSyncCallback.getAnimationCallback().onPrepare(animation);
2255 builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 100));
2256 builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, 0));
2257 imeSyncCallback.getInsetsListener().onApplyWindowInsets(testView, builder.build());
2258
2259 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2260 assertEquals(0, viewportMetricsCaptor.getValue().viewInsetBottom);
2261
2262 // Call onStart and apply new insets - these should be ignored completely
2263 imeSyncCallback.getAnimationCallback().onStart(animation, null);
2264 builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 50));
2265 builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, 40));
2266 imeSyncCallback.getInsetsListener().onApplyWindowInsets(testView, builder.build());
2267
2268 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2269 assertEquals(0, viewportMetricsCaptor.getValue().viewInsetBottom);
2270
2271 // Progress the animation and ensure that the navigation bar insets have not been
2272 // subtracted from the IME insets
2273 builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 25));
2274 builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, 40));
2275 imeSyncCallback.getAnimationCallback().onProgress(builder.build(), animationList);
2276
2277 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2278 assertEquals(25, viewportMetricsCaptor.getValue().viewInsetBottom);
2279
2280 builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 50));
2281 builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, 40));
2282 imeSyncCallback.getAnimationCallback().onProgress(builder.build(), animationList);
2283
2284 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2285 assertEquals(50, viewportMetricsCaptor.getValue().viewInsetBottom);
2286
2287 // End the animation and ensure that the bottom insets match the lastWindowInsets that we set
2288 // during onPrepare
2289 imeSyncCallback.getAnimationCallback().onEnd(animation);
2290
2291 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2292 assertEquals(100, viewportMetricsCaptor.getValue().viewInsetBottom);
2293 }
void add(sk_sp< SkIDChangeListener > listener) SK_EXCLUDES(fMutex)

◆ ime_windowInsetsSync_notLaidOutBehindNavigation_excludesNavigationBars()

void io.flutter.plugin.editing.TextInputPluginTest.ime_windowInsetsSync_notLaidOutBehindNavigation_excludesNavigationBars ( )
inline

Definition at line 2141 of file TextInputPluginTest.java.

2141 {
2142 FlutterView testView = spy(getTestView());
2143 when(testView.getWindowSystemUiVisibility()).thenReturn(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
2144
2145 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
2146 TextInputPlugin textInputPlugin =
2147 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
2148 ImeSyncDeferringInsetsCallback imeSyncCallback = textInputPlugin.getImeSyncCallback();
2149 FlutterEngine flutterEngine = spy(new FlutterEngine(ctx, mockFlutterLoader, mockFlutterJni));
2150 FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
2151 when(flutterEngine.getRenderer()).thenReturn(flutterRenderer);
2152 testView.attachToFlutterEngine(flutterEngine);
2153
2154 WindowInsetsAnimation animation = mock(WindowInsetsAnimation.class);
2155 when(animation.getTypeMask()).thenReturn(WindowInsets.Type.ime());
2156
2157 List<WindowInsetsAnimation> animationList = new ArrayList();
2158 animationList.add(animation);
2159
2160 ArgumentCaptor<FlutterRenderer.ViewportMetrics> viewportMetricsCaptor =
2161 ArgumentCaptor.forClass(FlutterRenderer.ViewportMetrics.class);
2162
2163 WindowInsets.Builder builder = new WindowInsets.Builder();
2164
2165 // Set the initial insets and verify that they were set and the bottom view inset is correct
2166 imeSyncCallback.getInsetsListener().onApplyWindowInsets(testView, builder.build());
2167
2168 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2169 assertEquals(0, viewportMetricsCaptor.getValue().viewInsetBottom);
2170
2171 // Call onPrepare and set the lastWindowInsets - these should be stored for the end of the
2172 // animation instead of being applied immediately
2173 imeSyncCallback.getAnimationCallback().onPrepare(animation);
2174 builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 100));
2175 builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, 0));
2176 imeSyncCallback.getInsetsListener().onApplyWindowInsets(testView, builder.build());
2177
2178 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2179 assertEquals(0, viewportMetricsCaptor.getValue().viewInsetBottom);
2180
2181 // Call onStart and apply new insets - these should be ignored completely
2182 imeSyncCallback.getAnimationCallback().onStart(animation, null);
2183 builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 50));
2184 builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, 40));
2185 imeSyncCallback.getInsetsListener().onApplyWindowInsets(testView, builder.build());
2186
2187 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2188 assertEquals(0, viewportMetricsCaptor.getValue().viewInsetBottom);
2189
2190 // Progress the animation and ensure that the navigation bar insets have been subtracted
2191 // from the IME insets
2192 builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 25));
2193 builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, 40));
2194 imeSyncCallback.getAnimationCallback().onProgress(builder.build(), animationList);
2195
2196 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2197 assertEquals(0, viewportMetricsCaptor.getValue().viewInsetBottom);
2198
2199 builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 50));
2200 builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, 40));
2201 imeSyncCallback.getAnimationCallback().onProgress(builder.build(), animationList);
2202
2203 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2204 assertEquals(10, viewportMetricsCaptor.getValue().viewInsetBottom);
2205
2206 // End the animation and ensure that the bottom insets match the lastWindowInsets that we set
2207 // during onPrepare
2208 imeSyncCallback.getAnimationCallback().onEnd(animation);
2209
2210 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2211 assertEquals(100, viewportMetricsCaptor.getValue().viewInsetBottom);
2212 }

◆ inputConnection_createsActionFromEnter()

void io.flutter.plugin.editing.TextInputPluginTest.inputConnection_createsActionFromEnter ( ) throws JSONException
inline

Definition at line 1238 of file TextInputPluginTest.java.

1238 {
1239 verifyInputConnection(TextInputChannel.TextInputType.TEXT);
1240 }

◆ inputConnection_finishComposingTextUpdatesIMM()

void io.flutter.plugin.editing.TextInputPluginTest.inputConnection_finishComposingTextUpdatesIMM ( ) throws JSONException
inline

Definition at line 1249 of file TextInputPluginTest.java.

1249 {
1250 ShadowBuild.setManufacturer("samsung");
1251 InputMethodSubtype inputMethodSubtype =
1252 new InputMethodSubtype(0, 0, /*locale=*/ "en", "", "", false, false);
1253 Settings.Secure.putString(
1254 ctx.getContentResolver(),
1255 Settings.Secure.DEFAULT_INPUT_METHOD,
1256 "com.sec.android.inputmethod/.SamsungKeypad");
1257 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
1258 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
1259 FlutterJNI mockFlutterJni = mock(FlutterJNI.class);
1260 View testView = new View(ctx);
1261 DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJni, mock(AssetManager.class)));
1262 TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
1263 TextInputPlugin textInputPlugin =
1264 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1265 textInputPlugin.setTextInputClient(
1266 0,
1267 new TextInputChannel.Configuration(
1268 false,
1269 false,
1270 true,
1271 true,
1272 false,
1273 TextInputChannel.TextCapitalization.NONE,
1274 new TextInputChannel.InputType(TextInputChannel.TextInputType.TEXT, false, false),
1275 null,
1276 null,
1277 null,
1278 null,
1279 null));
1280 // There's a pending restart since we initialized the text input client. Flush that now.
1281 textInputPlugin.setTextInputEditingState(
1282 testView, new TextInputChannel.TextEditState("text", 0, 0, -1, -1));
1283 InputConnection connection =
1284 textInputPlugin.createInputConnection(
1285 testView, mock(KeyboardManager.class), new EditorInfo());
1286
1287 connection.requestCursorUpdates(
1288 InputConnection.CURSOR_UPDATE_MONITOR | InputConnection.CURSOR_UPDATE_IMMEDIATE);
1289
1290 connection.finishComposingText();
1291
1292 assertEquals(-1, testImm.getLastCursorAnchorInfo().getComposingTextStart());
1293 assertEquals(0, testImm.getLastCursorAnchorInfo().getComposingText().length());
1294 }

◆ inputConnection_respondsToKeyEvents_textInputTypeNone()

void io.flutter.plugin.editing.TextInputPluginTest.inputConnection_respondsToKeyEvents_textInputTypeNone ( ) throws JSONException
inline

Definition at line 1243 of file TextInputPluginTest.java.

1243 {
1244 verifyInputConnection(TextInputChannel.TextInputType.NONE);
1245 }

◆ inputConnection_textInputTypeMultilineAndSuggestionsDisabled()

void io.flutter.plugin.editing.TextInputPluginTest.inputConnection_textInputTypeMultilineAndSuggestionsDisabled ( )
inline

Definition at line 1354 of file TextInputPluginTest.java.

1354 {
1355 // Regression test for https://github.com/flutter/flutter/issues/71679.
1356 View testView = new View(ctx);
1357 DartExecutor dartExecutor = mock(DartExecutor.class);
1358 TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
1359 TextInputPlugin textInputPlugin =
1360 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1361 textInputPlugin.setTextInputClient(
1362 0,
1363 new TextInputChannel.Configuration(
1364 false,
1365 false,
1366 false, // Disable suggestions.
1367 true,
1368 false,
1369 TextInputChannel.TextCapitalization.NONE,
1370 new TextInputChannel.InputType(TextInputChannel.TextInputType.MULTILINE, false, false),
1371 null,
1372 null,
1373 null,
1374 null,
1375 null));
1376
1377 EditorInfo editorInfo = new EditorInfo();
1378 InputConnection connection =
1379 textInputPlugin.createInputConnection(testView, mock(KeyboardManager.class), editorInfo);
1380
1381 assertEquals(
1382 editorInfo.inputType,
1383 InputType.TYPE_CLASS_TEXT
1384 | InputType.TYPE_TEXT_FLAG_MULTI_LINE
1385 | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
1386 | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
1387 }

◆ inputConnection_textInputTypeNone()

void io.flutter.plugin.editing.TextInputPluginTest.inputConnection_textInputTypeNone ( )
inline

Definition at line 1297 of file TextInputPluginTest.java.

1297 {
1298 View testView = new View(ctx);
1299 DartExecutor dartExecutor = mock(DartExecutor.class);
1300 TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
1301 TextInputPlugin textInputPlugin =
1302 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1303 textInputPlugin.setTextInputClient(
1304 0,
1305 new TextInputChannel.Configuration(
1306 false,
1307 false,
1308 true,
1309 true,
1310 false,
1311 TextInputChannel.TextCapitalization.NONE,
1312 new TextInputChannel.InputType(TextInputChannel.TextInputType.NONE, false, false),
1313 null,
1314 null,
1315 null,
1316 null,
1317 null));
1318
1319 InputConnection connection =
1320 textInputPlugin.createInputConnection(
1321 testView, mock(KeyboardManager.class), new EditorInfo());
1322 assertNotNull(connection);
1323 }

◆ inputConnectionAdaptor_RepeatFilter()

void io.flutter.plugin.editing.TextInputPluginTest.inputConnectionAdaptor_RepeatFilter ( ) throws NullPointerException
inline

Definition at line 823 of file TextInputPluginTest.java.

823 {
824 // Initialize a general TextInputPlugin.
825 InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
826 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
827 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
828 View testView = new View(ctx);
829 EditorInfo outAttrs = new EditorInfo();
830 outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE;
831 TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
832 TextInputPlugin textInputPlugin =
833 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
834
835 // Change InputTarget to FRAMEWORK_CLIENT.
836 textInputPlugin.setTextInputClient(
837 0,
838 new TextInputChannel.Configuration(
839 false,
840 false,
841 true,
842 true,
843 false,
844 TextInputChannel.TextCapitalization.NONE,
845 new TextInputChannel.InputType(TextInputChannel.TextInputType.TEXT, false, false),
846 null,
847 null,
848 null,
849 null,
850 null));
851
852 // There's a pending restart since we initialized the text input client. Flush that now.
853 textInputPlugin.setTextInputEditingState(
854 testView, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
855 verify(textInputChannel, times(0))
856 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
857
858 InputConnectionAdaptor inputConnectionAdaptor =
859 (InputConnectionAdaptor)
860 textInputPlugin.createInputConnection(testView, mock(KeyboardManager.class), outAttrs);
861
862 inputConnectionAdaptor.beginBatchEdit();
863 verify(textInputChannel, times(0))
864 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
865 inputConnectionAdaptor.setComposingText("I do not fear computers. I fear the lack of them.", 1);
866 verify(textInputChannel, times(0))
867 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
868 inputConnectionAdaptor.endBatchEdit();
869 verify(textInputChannel, times(1))
870 .updateEditingState(
871 anyInt(),
872 eq("I do not fear computers. I fear the lack of them."),
873 eq(49),
874 eq(49),
875 eq(0),
876 eq(49));
877
878 inputConnectionAdaptor.beginBatchEdit();
879
880 verify(textInputChannel, times(1))
881 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
882
883 inputConnectionAdaptor.endBatchEdit();
884
885 verify(textInputChannel, times(1))
886 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
887
888 inputConnectionAdaptor.beginBatchEdit();
889
890 verify(textInputChannel, times(1))
891 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
892
893 inputConnectionAdaptor.setSelection(3, 4);
894 assertEquals(Selection.getSelectionStart(textInputPlugin.getEditable()), 3);
895 assertEquals(Selection.getSelectionEnd(textInputPlugin.getEditable()), 4);
896
897 verify(textInputChannel, times(1))
898 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
899
900 verify(textInputChannel, times(1))
901 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
902
903 inputConnectionAdaptor.endBatchEdit();
904
905 verify(textInputChannel, times(1))
906 .updateEditingState(
907 anyInt(),
908 eq("I do not fear computers. I fear the lack of them."),
909 eq(3),
910 eq(4),
911 eq(0),
912 eq(49));
913 }

◆ lastWindowInsets_updatedOnSecondOnProgressCall()

void io.flutter.plugin.editing.TextInputPluginTest.lastWindowInsets_updatedOnSecondOnProgressCall ( )
inline

Definition at line 2301 of file TextInputPluginTest.java.

2301 {
2302 FlutterView testView = spy(getTestView());
2303 when(testView.getWindowSystemUiVisibility()).thenReturn(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
2304
2305 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
2306 TextInputPlugin textInputPlugin =
2307 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
2308 ImeSyncDeferringInsetsCallback imeSyncCallback = textInputPlugin.getImeSyncCallback();
2309 FlutterEngine flutterEngine = spy(new FlutterEngine(ctx, mockFlutterLoader, mockFlutterJni));
2310 FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
2311 when(flutterEngine.getRenderer()).thenReturn(flutterRenderer);
2312 testView.attachToFlutterEngine(flutterEngine);
2313
2314 WindowInsetsAnimation imeAnimation = mock(WindowInsetsAnimation.class);
2315 when(imeAnimation.getTypeMask()).thenReturn(WindowInsets.Type.ime());
2316 WindowInsetsAnimation navigationBarAnimation = mock(WindowInsetsAnimation.class);
2317 when(navigationBarAnimation.getTypeMask()).thenReturn(WindowInsets.Type.navigationBars());
2318
2319 List<WindowInsetsAnimation> animationList = new ArrayList();
2320 animationList.add(imeAnimation);
2321 animationList.add(navigationBarAnimation);
2322
2323 ArgumentCaptor<FlutterRenderer.ViewportMetrics> viewportMetricsCaptor =
2324 ArgumentCaptor.forClass(FlutterRenderer.ViewportMetrics.class);
2325
2326 WindowInsets.Builder builder = new WindowInsets.Builder();
2327
2328 // Set the initial insets and verify that they were set and the bottom view padding is correct
2329 builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 1000));
2330 builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, 100));
2331 imeSyncCallback.getInsetsListener().onApplyWindowInsets(testView, builder.build());
2332
2333 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2334 assertEquals(100, viewportMetricsCaptor.getValue().viewPaddingBottom);
2335
2336 // Call onPrepare and set the lastWindowInsets - these should be stored for the end of the
2337 // animation instead of being applied immediately
2338 imeSyncCallback.getAnimationCallback().onPrepare(imeAnimation);
2339 builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 0));
2340 builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, 100));
2341 imeSyncCallback.getInsetsListener().onApplyWindowInsets(testView, builder.build());
2342
2343 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2344 assertEquals(100, viewportMetricsCaptor.getValue().viewPaddingBottom);
2345
2346 // Call onPrepare again and apply new insets - these should overrite lastWindowInsets
2347 imeSyncCallback.getAnimationCallback().onPrepare(navigationBarAnimation);
2348 builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 0));
2349 builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, 0));
2350 imeSyncCallback.getInsetsListener().onApplyWindowInsets(testView, builder.build());
2351
2352 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2353 assertEquals(100, viewportMetricsCaptor.getValue().viewPaddingBottom);
2354
2355 // Progress the animation and ensure that the navigation bar insets have not been
2356 // subtracted from the IME insets
2357 builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 500));
2358 builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, 0));
2359 imeSyncCallback.getAnimationCallback().onProgress(builder.build(), animationList);
2360
2361 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2362 assertEquals(0, viewportMetricsCaptor.getValue().viewPaddingBottom);
2363
2364 builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 250));
2365 builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, 0));
2366 imeSyncCallback.getAnimationCallback().onProgress(builder.build(), animationList);
2367
2368 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2369 assertEquals(0, viewportMetricsCaptor.getValue().viewPaddingBottom);
2370
2371 // End the animation and ensure that the bottom insets match the lastWindowInsets that we set
2372 // during onPrepare
2373 imeSyncCallback.getAnimationCallback().onEnd(imeAnimation);
2374
2375 verify(flutterRenderer, atLeast(1)).setViewportMetrics(viewportMetricsCaptor.capture());
2376 assertEquals(0, viewportMetricsCaptor.getValue().viewPaddingBottom);
2377 }

◆ respondsToInputChannelMessages()

void io.flutter.plugin.editing.TextInputPluginTest.respondsToInputChannelMessages ( )
inline

Definition at line 2045 of file TextInputPluginTest.java.

2045 {
2046 ArgumentCaptor<BinaryMessenger.BinaryMessageHandler> binaryMessageHandlerCaptor =
2047 ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class);
2048 DartExecutor mockBinaryMessenger = mock(DartExecutor.class);
2049 TextInputChannel.TextInputMethodHandler mockHandler =
2050 mock(TextInputChannel.TextInputMethodHandler.class);
2051 TextInputChannel textInputChannel = new TextInputChannel(mockBinaryMessenger);
2052
2053 textInputChannel.setTextInputMethodHandler(mockHandler);
2054
2055 verify(mockBinaryMessenger, times(1))
2056 .setMessageHandler(any(String.class), binaryMessageHandlerCaptor.capture());
2057
2058 BinaryMessenger.BinaryMessageHandler binaryMessageHandler =
2059 binaryMessageHandlerCaptor.getValue();
2060
2061 sendToBinaryMessageHandler(binaryMessageHandler, "TextInput.requestAutofill", null);
2062 verify(mockHandler, times(1)).requestAutofill();
2063
2064 sendToBinaryMessageHandler(binaryMessageHandler, "TextInput.finishAutofillContext", true);
2065 verify(mockHandler, times(1)).finishAutofillContext(true);
2066
2067 sendToBinaryMessageHandler(binaryMessageHandler, "TextInput.finishAutofillContext", false);
2068 verify(mockHandler, times(1)).finishAutofillContext(false);
2069 }

◆ sendAppPrivateCommand_dataIsEmpty()

void io.flutter.plugin.editing.TextInputPluginTest.sendAppPrivateCommand_dataIsEmpty ( ) throws JSONException
inline

Definition at line 2074 of file TextInputPluginTest.java.

2074 {
2075 ArgumentCaptor<BinaryMessenger.BinaryMessageHandler> binaryMessageHandlerCaptor =
2076 ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class);
2077 DartExecutor mockBinaryMessenger = mock(DartExecutor.class);
2078 TextInputChannel textInputChannel = new TextInputChannel(mockBinaryMessenger);
2079
2080 EventHandler mockEventHandler = mock(EventHandler.class);
2081 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
2082 testImm.setEventHandler(mockEventHandler);
2083
2084 View testView = new View(ctx);
2085 TextInputPlugin textInputPlugin =
2086 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
2087
2088 verify(mockBinaryMessenger, times(1))
2089 .setMessageHandler(any(String.class), binaryMessageHandlerCaptor.capture());
2090
2091 JSONObject arguments = new JSONObject();
2092 arguments.put("action", "actionCommand");
2093 arguments.put("data", "");
2094
2095 BinaryMessenger.BinaryMessageHandler binaryMessageHandler =
2096 binaryMessageHandlerCaptor.getValue();
2097 sendToBinaryMessageHandler(binaryMessageHandler, "TextInput.sendAppPrivateCommand", arguments);
2098 verify(mockEventHandler, times(1))
2099 .sendAppPrivateCommand(any(View.class), eq("actionCommand"), eq(null));
2100 }

◆ sendAppPrivateCommand_hasData()

void io.flutter.plugin.editing.TextInputPluginTest.sendAppPrivateCommand_hasData ( ) throws JSONException
inline

Definition at line 2105 of file TextInputPluginTest.java.

2105 {
2106 ArgumentCaptor<BinaryMessenger.BinaryMessageHandler> binaryMessageHandlerCaptor =
2107 ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class);
2108 DartExecutor mockBinaryMessenger = mock(DartExecutor.class);
2109 TextInputChannel textInputChannel = new TextInputChannel(mockBinaryMessenger);
2110
2111 EventHandler mockEventHandler = mock(EventHandler.class);
2112 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
2113 testImm.setEventHandler(mockEventHandler);
2114
2115 View testView = new View(ctx);
2116 TextInputPlugin textInputPlugin =
2117 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
2118
2119 verify(mockBinaryMessenger, times(1))
2120 .setMessageHandler(any(String.class), binaryMessageHandlerCaptor.capture());
2121
2122 JSONObject arguments = new JSONObject();
2123 arguments.put("action", "actionCommand");
2124 arguments.put("data", "actionData");
2125
2126 ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
2127 BinaryMessenger.BinaryMessageHandler binaryMessageHandler =
2128 binaryMessageHandlerCaptor.getValue();
2129 sendToBinaryMessageHandler(binaryMessageHandler, "TextInput.sendAppPrivateCommand", arguments);
2130 verify(mockEventHandler, times(1))
2131 .sendAppPrivateCommand(any(View.class), eq("actionCommand"), bundleCaptor.capture());
2132 assertEquals("actionData", bundleCaptor.getValue().getCharSequence("data"));
2133 }

◆ setTextInputEditingState_alwaysSetEditableWhenDifferent()

void io.flutter.plugin.editing.TextInputPluginTest.setTextInputEditingState_alwaysSetEditableWhenDifferent ( )
inline

Definition at line 954 of file TextInputPluginTest.java.

954 {
955 // Initialize a general TextInputPlugin.
956 InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
957 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
958 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
959 View testView = new View(ctx);
960 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
961 TextInputPlugin textInputPlugin =
962 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
963 textInputPlugin.setTextInputClient(
964 0,
965 new TextInputChannel.Configuration(
966 false,
967 false,
968 true,
969 true,
970 false,
971 TextInputChannel.TextCapitalization.NONE,
972 null,
973 null,
974 null,
975 null,
976 null,
977 null));
978 // There's a pending restart since we initialized the text input client. Flush that now. With
979 // changed text, we should
980 // always set the Editable contents.
981 textInputPlugin.setTextInputEditingState(
982 testView, new TextInputChannel.TextEditState("hello", 0, 0, -1, -1));
983 assertEquals(1, testImm.getRestartCount(testView));
984 assertTrue(textInputPlugin.getEditable().toString().equals("hello"));
985
986 // No pending restart, set Editable contents anyways.
987 textInputPlugin.setTextInputEditingState(
988 testView, new TextInputChannel.TextEditState("Shibuyawoo", 0, 0, -1, -1));
989 assertEquals(1, testImm.getRestartCount(testView));
990 assertTrue(textInputPlugin.getEditable().toString().equals("Shibuyawoo"));
991 }

◆ setTextInputEditingState_doesNotInvokeUpdateEditingState()

void io.flutter.plugin.editing.TextInputPluginTest.setTextInputEditingState_doesNotInvokeUpdateEditingState ( )
inline

Definition at line 148 of file TextInputPluginTest.java.

148 {
149 // Initialize a general TextInputPlugin.
150 InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
151 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
152 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
153 View testView = new View(ctx);
154 TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
155 TextInputPlugin textInputPlugin =
156 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
157 textInputPlugin.setTextInputClient(
158 0,
159 new TextInputChannel.Configuration(
160 false,
161 false,
162 true,
163 true,
164 false,
165 TextInputChannel.TextCapitalization.NONE,
166 null,
167 null,
168 null,
169 null,
170 null,
171 null));
172
173 textInputPlugin.setTextInputEditingState(
174 testView, new TextInputChannel.TextEditState("initial input from framework", 0, 0, -1, -1));
175 assertTrue(textInputPlugin.getEditable().toString().equals("initial input from framework"));
176
177 verify(textInputChannel, times(0))
178 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
179
180 textInputPlugin.setTextInputEditingState(
181 testView,
182 new TextInputChannel.TextEditState("more update from the framework", 1, 2, -1, -1));
183
184 assertTrue(textInputPlugin.getEditable().toString().equals("more update from the framework"));
185 verify(textInputChannel, times(0))
186 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
187 }

◆ setTextInputEditingState_doesNotInvokeUpdateEditingStateWithDeltas()

void io.flutter.plugin.editing.TextInputPluginTest.setTextInputEditingState_doesNotInvokeUpdateEditingStateWithDeltas ( )
inline

Definition at line 207 of file TextInputPluginTest.java.

207 {
208 // Initialize a general TextInputPlugin.
209 InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
210 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
211 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
212 View testView = new View(ctx);
213 TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
214 TextInputPlugin textInputPlugin =
215 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
216 textInputPlugin.setTextInputClient(
217 0,
218 new TextInputChannel.Configuration(
219 false,
220 false,
221 true,
222 true,
223 true, // Enable delta model.
224 TextInputChannel.TextCapitalization.NONE,
225 null,
226 null,
227 null,
228 null,
229 null,
230 null));
231
232 textInputPlugin.setTextInputEditingState(
233 testView,
234 new TextInputChannel.TextEditState("receiving initial input from framework", 0, 0, -1, -1));
235 assertTrue(
236 textInputPlugin.getEditable().toString().equals("receiving initial input from framework"));
237
238 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
239
240 textInputPlugin.setTextInputEditingState(
241 testView,
242 new TextInputChannel.TextEditState(
243 "receiving more updates from the framework", 1, 2, -1, -1));
244
245 assertTrue(
247 .getEditable()
248 .toString()
249 .equals("receiving more updates from the framework"));
250 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
251 }
bool equals(SkDrawable *a, SkDrawable *b)

◆ setTextInputEditingState_doesNotRestartWhenTextIsIdentical()

void io.flutter.plugin.editing.TextInputPluginTest.setTextInputEditingState_doesNotRestartWhenTextIsIdentical ( )
inline

Definition at line 916 of file TextInputPluginTest.java.

916 {
917 // Initialize a general TextInputPlugin.
918 InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
919 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
920 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
921 View testView = new View(ctx);
922 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
923 TextInputPlugin textInputPlugin =
924 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
925 textInputPlugin.setTextInputClient(
926 0,
927 new TextInputChannel.Configuration(
928 false,
929 false,
930 true,
931 true,
932 false,
933 TextInputChannel.TextCapitalization.NONE,
934 null,
935 null,
936 null,
937 null,
938 null,
939 null));
940 // There's a pending restart since we initialized the text input client. Flush that now.
941 textInputPlugin.setTextInputEditingState(
942 testView, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
943
944 // Move the cursor.
945 assertEquals(1, testImm.getRestartCount(testView));
946 textInputPlugin.setTextInputEditingState(
947 testView, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
948
949 // Verify that we haven't restarted the input.
950 assertEquals(1, testImm.getRestartCount(testView));
951 }

◆ setTextInputEditingState_nullInputMethodSubtype()

void io.flutter.plugin.editing.TextInputPluginTest.setTextInputEditingState_nullInputMethodSubtype ( )
inline

Definition at line 1104 of file TextInputPluginTest.java.

1104 {
1105 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
1106 testImm.setCurrentInputMethodSubtype(null);
1107
1108 View testView = new View(ctx);
1109 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
1110 TextInputPlugin textInputPlugin =
1111 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1112 textInputPlugin.setTextInputClient(
1113 0,
1114 new TextInputChannel.Configuration(
1115 false,
1116 false,
1117 true,
1118 true,
1119 false,
1120 TextInputChannel.TextCapitalization.NONE,
1121 null,
1122 null,
1123 null,
1124 null,
1125 null,
1126 null));
1127 // There's a pending restart since we initialized the text input client. Flush that now.
1128 textInputPlugin.setTextInputEditingState(
1129 testView, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1130 assertEquals(1, testImm.getRestartCount(testView));
1131 }

◆ setTextInputEditingState_restartsIMEOnlyWhenFrameworkChangesComposingRegion()

void io.flutter.plugin.editing.TextInputPluginTest.setTextInputEditingState_restartsIMEOnlyWhenFrameworkChangesComposingRegion ( )
inline

Definition at line 1001 of file TextInputPluginTest.java.

1001 {
1002 // Initialize a TextInputPlugin that needs to be always restarted.
1003 InputMethodSubtype inputMethodSubtype =
1004 new InputMethodSubtype(0, 0, /*locale=*/ "en", "", "", false, false);
1005 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
1006 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
1007 View testView = new View(ctx);
1008 TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
1009 TextInputPlugin textInputPlugin =
1010 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1011 textInputPlugin.setTextInputClient(
1012 0,
1013 new TextInputChannel.Configuration(
1014 false,
1015 false,
1016 true,
1017 true,
1018 false,
1019 TextInputChannel.TextCapitalization.NONE,
1020 new TextInputChannel.InputType(TextInputChannel.TextInputType.TEXT, false, false),
1021 null,
1022 null,
1023 null,
1024 null,
1025 null));
1026 // There's a pending restart since we initialized the text input client. Flush that now.
1027 textInputPlugin.setTextInputEditingState(
1028 testView, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
1029 assertEquals(1, testImm.getRestartCount(testView));
1030 InputConnection connection =
1031 textInputPlugin.createInputConnection(
1032 testView, mock(KeyboardManager.class), new EditorInfo());
1033 connection.setComposingText("POWERRRRR", 1);
1034
1035 textInputPlugin.setTextInputEditingState(
1036 testView, new TextInputChannel.TextEditState("UNLIMITED POWERRRRR", 0, 0, 10, 19));
1037 // Does not restart since the composing text is not changed.
1038 assertEquals(1, testImm.getRestartCount(testView));
1039
1040 connection.finishComposingText();
1041 // Does not restart since the composing text is committed by the IME.
1042 assertEquals(1, testImm.getRestartCount(testView));
1043
1044 // Does not restart since the composing text is changed by the IME.
1045 connection.setComposingText("POWERRRRR", 1);
1046 assertEquals(1, testImm.getRestartCount(testView));
1047
1048 // The framework tries to commit the composing region.
1049 textInputPlugin.setTextInputEditingState(
1050 testView, new TextInputChannel.TextEditState("POWERRRRR", 0, 0, -1, -1));
1051
1052 // Verify that we've restarted the input.
1053 assertEquals(2, testImm.getRestartCount(testView));
1054 }

◆ setTextInputEditingState_willNotThrowWithoutSetTextInputClient()

void io.flutter.plugin.editing.TextInputPluginTest.setTextInputEditingState_willNotThrowWithoutSetTextInputClient ( )
inline

Definition at line 190 of file TextInputPluginTest.java.

190 {
191 // Initialize a general TextInputPlugin.
192 InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
193 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
194 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
195 View testView = new View(ctx);
196 TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
197 TextInputPlugin textInputPlugin =
198 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
199
200 // Here's no textInputPlugin.setTextInputClient()
201 textInputPlugin.setTextInputEditingState(
202 testView, new TextInputChannel.TextEditState("initial input from framework", 0, 0, -1, -1));
203 assertTrue(textInputPlugin.getEditable().toString().equals("initial input from framework"));
204 }

◆ setUp()

void io.flutter.plugin.editing.TextInputPluginTest.setUp ( )
inline

Definition at line 95 of file TextInputPluginTest.java.

95 {
96 MockitoAnnotations.openMocks(this);
97 when(mockFlutterJni.isAttached()).thenReturn(true);
98 }

◆ showTextInput_textInputTypeNone()

void io.flutter.plugin.editing.TextInputPluginTest.showTextInput_textInputTypeNone ( )
inline

Definition at line 1326 of file TextInputPluginTest.java.

1326 {
1327 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
1328 View testView = new View(ctx);
1329 DartExecutor dartExecutor = mock(DartExecutor.class);
1330 TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
1331 TextInputPlugin textInputPlugin =
1332 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
1333 textInputPlugin.setTextInputClient(
1334 0,
1335 new TextInputChannel.Configuration(
1336 false,
1337 false,
1338 true,
1339 true,
1340 false,
1341 TextInputChannel.TextCapitalization.NONE,
1342 new TextInputChannel.InputType(TextInputChannel.TextInputType.NONE, false, false),
1343 null,
1344 null,
1345 null,
1346 null,
1347 null));
1348
1350 assertEquals(testImm.isSoftInputVisible(), false);
1351 }

◆ textEditingDelta_TestDeltaIsCreatedWhenComposingTextSetIsDeleting()

void io.flutter.plugin.editing.TextInputPluginTest.textEditingDelta_TestDeltaIsCreatedWhenComposingTextSetIsDeleting ( ) throws NullPointerException
inline

Definition at line 605 of file TextInputPluginTest.java.

606 {
607 // Initialize a general TextInputPlugin.
608 InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
609 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
610 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
611 View testView = new View(ctx);
612 EditorInfo outAttrs = new EditorInfo();
613 outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE;
614 TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
615 TextInputPlugin textInputPlugin =
616 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
617 CharSequence newText = "I do not fear computers. I fear the lack of them.";
618 final TextEditingDelta expectedDelta =
619 new TextEditingDelta(
620 newText, 0, 49, "I do not fear computers. I fear the lack of them", 48, 48, 0, 48);
621
622 // Change InputTarget to FRAMEWORK_CLIENT.
623 textInputPlugin.setTextInputClient(
624 0,
625 new TextInputChannel.Configuration(
626 false,
627 false,
628 true,
629 true,
630 true, // Enable delta model.
631 TextInputChannel.TextCapitalization.NONE,
632 new TextInputChannel.InputType(TextInputChannel.TextInputType.TEXT, false, false),
633 null,
634 null,
635 null,
636 null,
637 null));
638
639 // There's a pending restart since we initialized the text input client. Flush that now.
640 textInputPlugin.setTextInputEditingState(
641 testView, new TextInputChannel.TextEditState(newText.toString(), 49, 49, 0, 49));
642 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
643 assertEquals(
644 0,
645 ((ListenableEditingState) textInputPlugin.getEditable())
646 .extractBatchTextEditingDeltas()
647 .size());
648
649 InputConnection inputConnection =
650 textInputPlugin.createInputConnection(testView, mock(KeyboardManager.class), outAttrs);
651
652 inputConnection.beginBatchEdit();
653 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
654 inputConnection.setComposingText("I do not fear computers. I fear the lack of them", 48);
655 final ArrayList<TextEditingDelta> actualDeltas =
656 ((ListenableEditingState) textInputPlugin.getEditable()).extractBatchTextEditingDeltas();
657 final TextEditingDelta delta = actualDeltas.get(1);
658 System.out.println(delta.getDeltaText());
659 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
660 inputConnection.endBatchEdit();
661
662 assertEquals(
663 0,
664 ((ListenableEditingState) textInputPlugin.getEditable())
665 .extractBatchTextEditingDeltas()
666 .size());
667
668 // Verify delta is what we expect.
669 assertEquals(expectedDelta.getOldText(), delta.getOldText());
670 assertEquals(expectedDelta.getDeltaText(), delta.getDeltaText());
671 assertEquals(expectedDelta.getDeltaStart(), delta.getDeltaStart());
672 assertEquals(expectedDelta.getDeltaEnd(), delta.getDeltaEnd());
673 assertEquals(expectedDelta.getNewSelectionStart(), delta.getNewSelectionStart());
674 assertEquals(expectedDelta.getNewSelectionEnd(), delta.getNewSelectionEnd());
675 assertEquals(expectedDelta.getNewComposingStart(), delta.getNewComposingStart());
676 assertEquals(expectedDelta.getNewComposingEnd(), delta.getNewComposingEnd());
677
678 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
679
680 inputConnection.beginBatchEdit();
681
682 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
683
684 inputConnection.endBatchEdit();
685
686 assertEquals(
687 0,
688 ((ListenableEditingState) textInputPlugin.getEditable())
689 .extractBatchTextEditingDeltas()
690 .size());
691
692 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
693
694 inputConnection.beginBatchEdit();
695
696 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
697
698 // Selection changes so this will trigger an update to the framework through
699 // updateEditingStateWithDeltas after the batch edit has completed and notified all listeners
700 // of the editing state.
701 inputConnection.setSelection(3, 4);
702 assertEquals(Selection.getSelectionStart(textInputPlugin.getEditable()), 3);
703 assertEquals(Selection.getSelectionEnd(textInputPlugin.getEditable()), 4);
704
705 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
706
707 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
708
709 inputConnection.endBatchEdit();
710
711 verify(textInputChannel, times(2)).updateEditingStateWithDeltas(anyInt(), any());
712 }

◆ textEditingDelta_TestDeltaIsCreatedWhenComposingTextSetIsInserting()

void io.flutter.plugin.editing.TextInputPluginTest.textEditingDelta_TestDeltaIsCreatedWhenComposingTextSetIsInserting ( ) throws NullPointerException
inline

Definition at line 496 of file TextInputPluginTest.java.

497 {
498 // Initialize a general TextInputPlugin.
499 InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
500 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
501 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
502 View testView = new View(ctx);
503 EditorInfo outAttrs = new EditorInfo();
504 outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE;
505 TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
506 TextInputPlugin textInputPlugin =
507 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
508 CharSequence newText = "I do not fear computers. I fear the lack of them.";
509 final TextEditingDelta expectedDelta =
510 new TextEditingDelta("", 0, 0, newText, newText.length(), newText.length(), 0, 49);
511
512 // Change InputTarget to FRAMEWORK_CLIENT.
513 textInputPlugin.setTextInputClient(
514 0,
515 new TextInputChannel.Configuration(
516 false,
517 false,
518 true,
519 true,
520 true, // Enable delta model.
521 TextInputChannel.TextCapitalization.NONE,
522 new TextInputChannel.InputType(TextInputChannel.TextInputType.TEXT, false, false),
523 null,
524 null,
525 null,
526 null,
527 null));
528
529 // There's a pending restart since we initialized the text input client. Flush that now.
530 textInputPlugin.setTextInputEditingState(
531 testView, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
532 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
533 assertEquals(
534 0,
535 ((ListenableEditingState) textInputPlugin.getEditable())
536 .extractBatchTextEditingDeltas()
537 .size());
538
539 InputConnection inputConnection =
540 textInputPlugin.createInputConnection(testView, mock(KeyboardManager.class), outAttrs);
541
542 inputConnection.beginBatchEdit();
543 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
544 inputConnection.setComposingText(newText, newText.length());
545 final ArrayList<TextEditingDelta> actualDeltas =
546 ((ListenableEditingState) textInputPlugin.getEditable()).extractBatchTextEditingDeltas();
547 assertEquals(2, actualDeltas.size());
548 final TextEditingDelta delta = actualDeltas.get(1);
549 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
550 inputConnection.endBatchEdit();
551
552 assertEquals(
553 0,
554 ((ListenableEditingState) textInputPlugin.getEditable())
555 .extractBatchTextEditingDeltas()
556 .size());
557
558 // Verify delta is what we expect.
559 assertEquals(expectedDelta.getOldText(), delta.getOldText());
560 assertEquals(expectedDelta.getDeltaText(), delta.getDeltaText());
561 assertEquals(expectedDelta.getDeltaStart(), delta.getDeltaStart());
562 assertEquals(expectedDelta.getDeltaEnd(), delta.getDeltaEnd());
563 assertEquals(expectedDelta.getNewSelectionStart(), delta.getNewSelectionStart());
564 assertEquals(expectedDelta.getNewSelectionEnd(), delta.getNewSelectionEnd());
565 assertEquals(expectedDelta.getNewComposingStart(), delta.getNewComposingStart());
566 assertEquals(expectedDelta.getNewComposingEnd(), delta.getNewComposingEnd());
567
568 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
569
570 inputConnection.beginBatchEdit();
571
572 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
573
574 inputConnection.endBatchEdit();
575
576 assertEquals(
577 0,
578 ((ListenableEditingState) textInputPlugin.getEditable())
579 .extractBatchTextEditingDeltas()
580 .size());
581
582 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
583
584 inputConnection.beginBatchEdit();
585
586 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
587
588 // Selection changes so this will trigger an update to the framework through
589 // updateEditingStateWithDeltas after the batch edit has completed and notified all listeners
590 // of the editing state.
591 inputConnection.setSelection(3, 4);
592 assertEquals(Selection.getSelectionStart(textInputPlugin.getEditable()), 3);
593 assertEquals(Selection.getSelectionEnd(textInputPlugin.getEditable()), 4);
594
595 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
596
597 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
598
599 inputConnection.endBatchEdit();
600
601 verify(textInputChannel, times(2)).updateEditingStateWithDeltas(anyInt(), any());
602 }

◆ textEditingDelta_TestDeltaIsCreatedWhenComposingTextSetIsReplacing()

void io.flutter.plugin.editing.TextInputPluginTest.textEditingDelta_TestDeltaIsCreatedWhenComposingTextSetIsReplacing ( ) throws NullPointerException
inline

Definition at line 715 of file TextInputPluginTest.java.

716 {
717 // Initialize a general TextInputPlugin.
718 InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
719 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
720 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
721 View testView = new View(ctx);
722 EditorInfo outAttrs = new EditorInfo();
723 outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE;
724 TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
725 TextInputPlugin textInputPlugin =
726 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
727 CharSequence newText = "helfo";
728 final TextEditingDelta expectedDelta = new TextEditingDelta(newText, 0, 5, "hello", 5, 5, 0, 5);
729
730 // Change InputTarget to FRAMEWORK_CLIENT.
731 textInputPlugin.setTextInputClient(
732 0,
733 new TextInputChannel.Configuration(
734 false,
735 false,
736 true,
737 true,
738 true, // Enable delta model.
739 TextInputChannel.TextCapitalization.NONE,
740 new TextInputChannel.InputType(TextInputChannel.TextInputType.TEXT, false, false),
741 null,
742 null,
743 null,
744 null,
745 null));
746
747 // There's a pending restart since we initialized the text input client. Flush that now.
748 textInputPlugin.setTextInputEditingState(
749 testView, new TextInputChannel.TextEditState(newText.toString(), 5, 5, 0, 5));
750 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
751 assertEquals(
752 0,
753 ((ListenableEditingState) textInputPlugin.getEditable())
754 .extractBatchTextEditingDeltas()
755 .size());
756
757 InputConnection inputConnection =
758 textInputPlugin.createInputConnection(testView, mock(KeyboardManager.class), outAttrs);
759
760 inputConnection.beginBatchEdit();
761 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
762 inputConnection.setComposingText("hello", 5);
763 final ArrayList<TextEditingDelta> actualDeltas =
764 ((ListenableEditingState) textInputPlugin.getEditable()).extractBatchTextEditingDeltas();
765 final TextEditingDelta delta = actualDeltas.get(1);
766 System.out.println(delta.getDeltaText());
767 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
768 inputConnection.endBatchEdit();
769
770 assertEquals(
771 0,
772 ((ListenableEditingState) textInputPlugin.getEditable())
773 .extractBatchTextEditingDeltas()
774 .size());
775
776 // Verify delta is what we expect.
777 assertEquals(expectedDelta.getOldText(), delta.getOldText());
778 assertEquals(expectedDelta.getDeltaText(), delta.getDeltaText());
779 assertEquals(expectedDelta.getDeltaStart(), delta.getDeltaStart());
780 assertEquals(expectedDelta.getDeltaEnd(), delta.getDeltaEnd());
781 assertEquals(expectedDelta.getNewSelectionStart(), delta.getNewSelectionStart());
782 assertEquals(expectedDelta.getNewSelectionEnd(), delta.getNewSelectionEnd());
783 assertEquals(expectedDelta.getNewComposingStart(), delta.getNewComposingStart());
784 assertEquals(expectedDelta.getNewComposingEnd(), delta.getNewComposingEnd());
785
786 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
787
788 inputConnection.beginBatchEdit();
789
790 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
791
792 inputConnection.endBatchEdit();
793
794 assertEquals(
795 0,
796 ((ListenableEditingState) textInputPlugin.getEditable())
797 .extractBatchTextEditingDeltas()
798 .size());
799
800 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
801
802 inputConnection.beginBatchEdit();
803
804 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
805
806 // Selection changes so this will trigger an update to the framework through
807 // updateEditingStateWithDeltas after the batch edit has completed and notified all listeners
808 // of the editing state.
809 inputConnection.setSelection(3, 4);
810 assertEquals(Selection.getSelectionStart(textInputPlugin.getEditable()), 3);
811 assertEquals(Selection.getSelectionEnd(textInputPlugin.getEditable()), 4);
812
813 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
814
815 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
816
817 inputConnection.endBatchEdit();
818
819 verify(textInputChannel, times(2)).updateEditingStateWithDeltas(anyInt(), any());
820 }

◆ textEditingDelta_TestUpdateEditingValueIsNotInvokedWhenDeltaModelEnabled()

void io.flutter.plugin.editing.TextInputPluginTest.textEditingDelta_TestUpdateEditingValueIsNotInvokedWhenDeltaModelEnabled ( ) throws NullPointerException
inline

Definition at line 367 of file TextInputPluginTest.java.

368 {
369 // Initialize a general TextInputPlugin.
370 InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
371 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
372 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
373 View testView = new View(ctx);
374 EditorInfo outAttrs = new EditorInfo();
375 outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE;
376 TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
377 TextInputPlugin textInputPlugin =
378 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
379 CharSequence newText = "I do not fear computers. I fear the lack of them.";
380 final TextEditingDelta expectedDelta =
381 new TextEditingDelta("", 0, 0, newText, newText.length(), newText.length(), 0, 49);
382
383 // Change InputTarget to FRAMEWORK_CLIENT.
384 textInputPlugin.setTextInputClient(
385 0,
386 new TextInputChannel.Configuration(
387 false,
388 false,
389 true,
390 true,
391 true, // Enable delta model.
392 TextInputChannel.TextCapitalization.NONE,
393 new TextInputChannel.InputType(TextInputChannel.TextInputType.TEXT, false, false),
394 null,
395 null,
396 null,
397 null,
398 null));
399
400 // There's a pending restart since we initialized the text input client. Flush that now.
401 textInputPlugin.setTextInputEditingState(
402 testView, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
403 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
404 verify(textInputChannel, times(0))
405 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
406 assertEquals(
407 0,
408 ((ListenableEditingState) textInputPlugin.getEditable())
409 .extractBatchTextEditingDeltas()
410 .size());
411
412 InputConnection inputConnection =
413 textInputPlugin.createInputConnection(testView, mock(KeyboardManager.class), outAttrs);
414
415 inputConnection.beginBatchEdit();
416 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
417 verify(textInputChannel, times(0))
418 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
419 inputConnection.setComposingText(newText, newText.length());
420 final ArrayList<TextEditingDelta> actualDeltas =
421 ((ListenableEditingState) textInputPlugin.getEditable()).extractBatchTextEditingDeltas();
422 assertEquals(2, actualDeltas.size());
423 final TextEditingDelta delta = actualDeltas.get(1);
424 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
425 verify(textInputChannel, times(0))
426 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
427 inputConnection.endBatchEdit();
428
429 assertEquals(
430 0,
431 ((ListenableEditingState) textInputPlugin.getEditable())
432 .extractBatchTextEditingDeltas()
433 .size());
434
435 // Verify delta is what we expect.
436 assertEquals(expectedDelta.getOldText(), delta.getOldText());
437 assertEquals(expectedDelta.getDeltaText(), delta.getDeltaText());
438 assertEquals(expectedDelta.getDeltaStart(), delta.getDeltaStart());
439 assertEquals(expectedDelta.getDeltaEnd(), delta.getDeltaEnd());
440 assertEquals(expectedDelta.getNewSelectionStart(), delta.getNewSelectionStart());
441 assertEquals(expectedDelta.getNewSelectionEnd(), delta.getNewSelectionEnd());
442 assertEquals(expectedDelta.getNewComposingStart(), delta.getNewComposingStart());
443 assertEquals(expectedDelta.getNewComposingEnd(), delta.getNewComposingEnd());
444
445 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
446 verify(textInputChannel, times(0))
447 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
448
449 inputConnection.beginBatchEdit();
450
451 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
452 verify(textInputChannel, times(0))
453 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
454
455 inputConnection.endBatchEdit();
456
457 assertEquals(
458 0,
459 ((ListenableEditingState) textInputPlugin.getEditable())
460 .extractBatchTextEditingDeltas()
461 .size());
462
463 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
464 verify(textInputChannel, times(0))
465 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
466
467 inputConnection.beginBatchEdit();
468
469 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
470 verify(textInputChannel, times(0))
471 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
472
473 // Selection changes so this will trigger an update to the framework through
474 // updateEditingStateWithDeltas after the batch edit has completed and notified all listeners
475 // of the editing state.
476 inputConnection.setSelection(3, 4);
477 assertEquals(Selection.getSelectionStart(textInputPlugin.getEditable()), 3);
478 assertEquals(Selection.getSelectionEnd(textInputPlugin.getEditable()), 4);
479
480 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
481 verify(textInputChannel, times(0))
482 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
483
484 verify(textInputChannel, times(1)).updateEditingStateWithDeltas(anyInt(), any());
485 verify(textInputChannel, times(0))
486 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
487
488 inputConnection.endBatchEdit();
489
490 verify(textInputChannel, times(2)).updateEditingStateWithDeltas(anyInt(), any());
491 verify(textInputChannel, times(0))
492 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
493 }

◆ textEditingDelta_TestUpdateEditingValueWithDeltasIsNotInvokedWhenDeltaModelDisabled()

void io.flutter.plugin.editing.TextInputPluginTest.textEditingDelta_TestUpdateEditingValueWithDeltasIsNotInvokedWhenDeltaModelDisabled ( ) throws NullPointerException
inline

Definition at line 254 of file TextInputPluginTest.java.

255 {
256 // Initialize a general TextInputPlugin.
257 InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
258 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
259 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
260 View testView = new View(ctx);
261 EditorInfo outAttrs = new EditorInfo();
262 outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE;
263 TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
264 TextInputPlugin textInputPlugin =
265 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
266 CharSequence newText = "I do not fear computers. I fear the lack of them.";
267
268 // Change InputTarget to FRAMEWORK_CLIENT.
269 textInputPlugin.setTextInputClient(
270 0,
271 new TextInputChannel.Configuration(
272 false,
273 false,
274 true,
275 true,
276 false, // Delta model is disabled.
277 TextInputChannel.TextCapitalization.NONE,
278 new TextInputChannel.InputType(TextInputChannel.TextInputType.TEXT, false, false),
279 null,
280 null,
281 null,
282 null,
283 null));
284
285 // There's a pending restart since we initialized the text input client. Flush that now.
286 textInputPlugin.setTextInputEditingState(
287 testView, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
288 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
289 verify(textInputChannel, times(0))
290 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
291 assertEquals(
292 0,
293 ((ListenableEditingState) textInputPlugin.getEditable())
294 .extractBatchTextEditingDeltas()
295 .size());
296
297 InputConnection inputConnection =
298 textInputPlugin.createInputConnection(testView, mock(KeyboardManager.class), outAttrs);
299
300 inputConnection.beginBatchEdit();
301 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
302 verify(textInputChannel, times(0))
303 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
304 inputConnection.setComposingText(newText, newText.length());
305 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
306 verify(textInputChannel, times(0))
307 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
308 inputConnection.endBatchEdit();
309
310 assertEquals(
311 0,
312 ((ListenableEditingState) textInputPlugin.getEditable())
313 .extractBatchTextEditingDeltas()
314 .size());
315
316 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
317 verify(textInputChannel, times(1))
318 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
319
320 inputConnection.beginBatchEdit();
321
322 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
323 verify(textInputChannel, times(1))
324 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
325
326 inputConnection.endBatchEdit();
327
328 assertEquals(
329 0,
330 ((ListenableEditingState) textInputPlugin.getEditable())
331 .extractBatchTextEditingDeltas()
332 .size());
333
334 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
335 verify(textInputChannel, times(1))
336 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
337
338 inputConnection.beginBatchEdit();
339
340 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
341 verify(textInputChannel, times(1))
342 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
343
344 // Selection changes so this will trigger an update to the framework through
345 // updateEditingStateWithDeltas after the batch edit has completed and notified all listeners
346 // of the editing state.
347 inputConnection.setSelection(3, 4);
348 assertEquals(Selection.getSelectionStart(textInputPlugin.getEditable()), 3);
349 assertEquals(Selection.getSelectionEnd(textInputPlugin.getEditable()), 4);
350
351 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
352 verify(textInputChannel, times(1))
353 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
354
355 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
356 verify(textInputChannel, times(1))
357 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
358
359 inputConnection.endBatchEdit();
360
361 verify(textInputChannel, times(0)).updateEditingStateWithDeltas(anyInt(), any());
362 verify(textInputChannel, times(2))
363 .updateEditingState(anyInt(), any(), anyInt(), anyInt(), anyInt(), anyInt());
364 }

◆ TextEditState_throwsOnInvalidStatesReceived()

void io.flutter.plugin.editing.TextInputPluginTest.TextEditState_throwsOnInvalidStatesReceived ( )
inline

Definition at line 1057 of file TextInputPluginTest.java.

1057 {
1058 // Index OOB:
1059 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("", 0, -9, -1, -1));
1060 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("", -9, 0, -1, -1));
1061 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("", 0, 1, -1, -1));
1062 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("", 1, 0, -1, -1));
1063 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("Text", 0, 0, 1, 5));
1064 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("Text", 0, 0, 5, 1));
1065 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("Text", 0, 0, 5, 5));
1066
1067 // Invalid Selections:
1068 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("", -1, -2, -1, -1));
1069 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("", -2, -1, -1, -1));
1070 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("", -9, -9, -1, -1));
1071
1072 // Invalid Composing Ranges:
1073 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("Text", 0, 0, -9, -1));
1074 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("Text", 0, 0, -1, -9));
1075 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("Text", 0, 0, -9, -9));
1076 assertThrows(IndexOutOfBoundsException.class, () -> new TextEditState("Text", 0, 0, 2, 1));
1077
1078 // Valid values (does not throw):
1079 // Nothing selected/composing:
1080 TextEditState state = new TextEditState("", -1, -1, -1, -1);
1081 assertEquals("", state.text);
1082 assertEquals(-1, state.selectionStart);
1083 assertEquals(-1, state.selectionEnd);
1084 assertEquals(-1, state.composingStart);
1085 assertEquals(-1, state.composingEnd);
1086 // Collapsed selection.
1087 state = new TextEditState("x", 0, 0, 0, 1);
1088 assertEquals(0, state.selectionStart);
1089 assertEquals(0, state.selectionEnd);
1090 // Reversed Selection.
1091 state = new TextEditState("REEEE", 4, 2, -1, -1);
1092 assertEquals(4, state.selectionStart);
1093 assertEquals(2, state.selectionEnd);
1094 // A collapsed selection and composing range.
1095 state = new TextEditState("text", 0, 0, 0, 0);
1096 assertEquals("text", state.text);
1097 assertEquals(0, state.selectionStart);
1098 assertEquals(0, state.selectionEnd);
1099 assertEquals(0, state.composingStart);
1100 assertEquals(0, state.composingEnd);
1101 }
AtkStateType state

◆ textInputPlugin_RequestsReattachOnCreation()

void io.flutter.plugin.editing.TextInputPluginTest.textInputPlugin_RequestsReattachOnCreation ( ) throws JSONException
inline

Definition at line 126 of file TextInputPluginTest.java.

126 {
127 // Initialize a general TextInputPlugin.
128 InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
129 TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
130 testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
131 View testView = new View(ctx);
132
133 FlutterJNI mockFlutterJni = mock(FlutterJNI.class);
134 DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJni, mock(AssetManager.class)));
135 TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
136 TextInputPlugin textInputPlugin =
137 new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
138
139 ArgumentCaptor<String> channelCaptor = ArgumentCaptor.forClass(String.class);
140 ArgumentCaptor<ByteBuffer> bufferCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
141
142 verify(dartExecutor, times(1)).send(channelCaptor.capture(), bufferCaptor.capture(), isNull());
143 assertEquals("flutter/textinput", channelCaptor.getValue());
144 verifyMethodCall(bufferCaptor.getValue(), "TextInputClient.requestExistingInputState", null);
145 }

Member Data Documentation

◆ mockFlutterJni

FlutterJNI io.flutter.plugin.editing.TextInputPluginTest.mockFlutterJni
package

Definition at line 91 of file TextInputPluginTest.java.

◆ mockFlutterLoader

FlutterLoader io.flutter.plugin.editing.TextInputPluginTest.mockFlutterLoader
package

Definition at line 92 of file TextInputPluginTest.java.


The documentation for this class was generated from the following file: