@@ -1943,6 +1943,126 @@ Future<void> testMain() async {
19431943 hideKeyboard ();
19441944 });
19451945
1946+ test ('Supports composition changes with shift arrow selection in Japanese IME' , () {
1947+ final HybridTextEditing testTextEditing = HybridTextEditing ();
1948+ final GlobalTextEditingStrategySpy editingStrategy = GlobalTextEditingStrategySpy (
1949+ testTextEditing,
1950+ );
1951+
1952+ showKeyboard (inputType: 'text' );
1953+ editingStrategy.composingText = 'へんかん' ;
1954+ sendFrameworkMessage (
1955+ codec.encodeMethodCall (
1956+ const MethodCall ('TextInput.setEditingState' , < String , dynamic > {
1957+ 'text' : 'へんかん' ,
1958+ 'selectionBase' : 4 ,
1959+ 'selectionExtent' : 4 ,
1960+ 'composingBase' : 0 ,
1961+ 'composingExtent' : 4 ,
1962+ }),
1963+ ),
1964+ );
1965+ checkInputEditingState (textEditing! .strategy.domElement, 'へんかん' , 4 , 4 );
1966+
1967+ // text composition is started
1968+ sendFrameworkMessage (
1969+ codec.encodeMethodCall (
1970+ const MethodCall ('TextInput.setEditingState' , < String , dynamic > {
1971+ 'text' : '変換' ,
1972+ 'selectionBase' : 0 ,
1973+ 'selectionExtent' : 2 ,
1974+ 'composingBase' : 0 ,
1975+ 'composingExtent' : 2 ,
1976+ }),
1977+ ),
1978+ );
1979+ checkInputEditingState (textEditing! .strategy.domElement, '変換' , 0 , 2 );
1980+
1981+ // shift + ←
1982+ sendFrameworkMessage (
1983+ codec.encodeMethodCall (
1984+ const MethodCall ('TextInput.setEditingState' , < String , dynamic > {
1985+ 'text' : '変化ん' ,
1986+ 'selectionBase' : 0 ,
1987+ 'selectionExtent' : 2 ,
1988+ 'composingBase' : - 1 ,
1989+ 'composingExtent' : - 1 ,
1990+ }),
1991+ ),
1992+ );
1993+ checkInputEditingState (textEditing! .strategy.domElement, '変化ん' , 0 , 2 );
1994+
1995+ // shift + ←
1996+ sendFrameworkMessage (
1997+ codec.encodeMethodCall (
1998+ const MethodCall ('TextInput.setEditingState' , < String , dynamic > {
1999+ 'text' : '変かん' ,
2000+ 'selectionBase' : 0 ,
2001+ 'selectionExtent' : 1 ,
2002+ 'composingBase' : - 1 ,
2003+ 'composingExtent' : - 1 ,
2004+ }),
2005+ ),
2006+ );
2007+ checkInputEditingState (textEditing! .strategy.domElement, '変かん' , 0 , 1 );
2008+
2009+ // shift + ←
2010+ sendFrameworkMessage (
2011+ codec.encodeMethodCall (
2012+ const MethodCall ('TextInput.setEditingState' , < String , dynamic > {
2013+ 'text' : 'へんかん' ,
2014+ 'selectionBase' : 0 ,
2015+ 'selectionExtent' : 1 ,
2016+ 'composingBase' : - 1 ,
2017+ 'composingExtent' : - 1 ,
2018+ }),
2019+ ),
2020+ );
2021+ checkInputEditingState (textEditing! .strategy.domElement, 'へんかん' , 0 , 1 );
2022+
2023+ // shift + →
2024+ sendFrameworkMessage (
2025+ codec.encodeMethodCall (
2026+ const MethodCall ('TextInput.setEditingState' , < String , dynamic > {
2027+ 'text' : '変かん' ,
2028+ 'selectionBase' : 0 ,
2029+ 'selectionExtent' : 1 ,
2030+ 'composingBase' : - 1 ,
2031+ 'composingExtent' : - 1 ,
2032+ }),
2033+ ),
2034+ );
2035+ checkInputEditingState (textEditing! .strategy.domElement, '変かん' , 0 , 1 );
2036+
2037+ // shift + →
2038+ sendFrameworkMessage (
2039+ codec.encodeMethodCall (
2040+ const MethodCall ('TextInput.setEditingState' , < String , dynamic > {
2041+ 'text' : '変化ん' ,
2042+ 'selectionBase' : 0 ,
2043+ 'selectionExtent' : 2 ,
2044+ 'composingBase' : - 1 ,
2045+ 'composingExtent' : - 1 ,
2046+ }),
2047+ ),
2048+ );
2049+ checkInputEditingState (textEditing! .strategy.domElement, '変化ん' , 0 , 2 );
2050+
2051+ // shift + →
2052+ sendFrameworkMessage (
2053+ codec.encodeMethodCall (
2054+ const MethodCall ('TextInput.setEditingState' , < String , dynamic > {
2055+ 'text' : '変換' ,
2056+ 'selectionBase' : 0 ,
2057+ 'selectionExtent' : 2 ,
2058+ 'composingBase' : 0 ,
2059+ 'composingExtent' : 2 ,
2060+ }),
2061+ ),
2062+ );
2063+ checkInputEditingState (textEditing! .strategy.domElement, '変換' , 0 , 2 );
2064+ });
2065+
19462066 test ('Supports deletion at inverted selection' , () async {
19472067 final MethodCall setClient = MethodCall ('TextInput.setClient' , < dynamic > [
19482068 123 ,
0 commit comments