123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka/* 223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * Copyright (C) 2016 The Android Open Source Project 323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * 423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * Licensed under the Apache License, Version 2.0 (the "License"); 523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * you may not use this file except in compliance with the License. 623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * You may obtain a copy of the License at 723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * 823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * http://www.apache.org/licenses/LICENSE-2.0 923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * 1023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * Unless required by applicable law or agreed to in writing, software 1123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * distributed under the License is distributed on an "AS IS" BASIS, 1223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * See the License for the specific language governing permissions and 1423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * limitations under the License. 1523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka */ 1623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 1723a67678e3848e2465518769236139e6cafac2eeSeigo Nonakapackage android.text.method; 1823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 1923a67678e3848e2465518769236139e6cafac2eeSeigo Nonakaimport android.app.Activity; 2023a67678e3848e2465518769236139e6cafac2eeSeigo Nonakaimport android.test.suitebuilder.annotation.SmallTest; 2123a67678e3848e2465518769236139e6cafac2eeSeigo Nonakaimport android.test.suitebuilder.annotation.Suppress; 2223a67678e3848e2465518769236139e6cafac2eeSeigo Nonakaimport android.text.InputType; 2323a67678e3848e2465518769236139e6cafac2eeSeigo Nonakaimport android.text.method.BaseKeyListener; 2423a67678e3848e2465518769236139e6cafac2eeSeigo Nonakaimport android.text.method.KeyListenerTestCase; 2523a67678e3848e2465518769236139e6cafac2eeSeigo Nonakaimport android.view.KeyEvent; 2623a67678e3848e2465518769236139e6cafac2eeSeigo Nonakaimport android.widget.EditText; 2723a67678e3848e2465518769236139e6cafac2eeSeigo Nonakaimport android.widget.TextView.BufferType; 2823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 2923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka/** 3023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * Test forward delete key handling of {@link android.text.method.BaseKeyListener}. 3123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka * 32132039ae89cfad501cd14fbb3819901151ae1890Seigo Nonaka * Only contains edge cases. For normal cases, see {@see android.text.method.cts.ForwardDeleteTest}. 33132039ae89cfad501cd14fbb3819901151ae1890Seigo Nonaka * TODO: introduce test cases for surrogate pairs and replacement span. 3423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka */ 3523a67678e3848e2465518769236139e6cafac2eeSeigo Nonakapublic class ForwardDeleteTest extends KeyListenerTestCase { 3623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka private static final BaseKeyListener mKeyListener = new BaseKeyListener() { 3723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka public int getInputType() { 3823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka return InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL; 3923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka } 4023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka }; 4123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 4223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Sync the state to the TextView and call onKeyDown with KEYCODE_FORWARD_DEL key event. 4323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Then update the state to the result of TextView. 4423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka private void forwardDelete(final EditorState state, int modifiers) { 4523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka mActivity.runOnUiThread(new Runnable() { 4623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka public void run() { 4723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka mTextView.setText(state.mText, BufferType.EDITABLE); 4823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka mTextView.setKeyListener(mKeyListener); 4923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd); 5023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka } 5123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka }); 5223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka mInstrumentation.waitForIdleSync(); 5323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka assertTrue(mTextView.hasWindowFocus()); 5423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 5523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_FORWARD_DEL, modifiers); 5623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka mActivity.runOnUiThread(new Runnable() { 5723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka public void run() { 5823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent); 5923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka } 6023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka }); 6123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka mInstrumentation.waitForIdleSync(); 6223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 6323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.mText = mTextView.getText(); 6423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.mSelectionStart = mTextView.getSelectionStart(); 6523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.mSelectionEnd = mTextView.getSelectionEnd(); 6623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka } 6723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 6823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka @SmallTest 6923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka public void testCombiningEnclosingKeycaps() { 7023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka EditorState state = new EditorState(); 7123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 7223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // multiple COMBINING ENCLOSING KEYCAP 7323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| '1' U+20E3 U+20E3"); 7423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 7523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 7623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 7723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Isolated COMBINING ENCLOSING KEYCAP 7823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+20E3"); 7923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 8023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 8123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 8223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Isolated multiple COMBINING ENCLOSING KEYCAP 8323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+20E3 U+20E3"); 8423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 8523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 8623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka } 8723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 8823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka @SmallTest 8923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka public void testVariationSelector() { 9023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka EditorState state = new EditorState(); 9123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 9223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Isolated variation selectors 9323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+FE0F"); 9423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 9523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 9623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 9723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+E0100"); 9823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 9923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 10023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 10123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Isolated multiple variation selectors 10223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+FE0F U+FE0F"); 10323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 10423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 10523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 10623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+FE0F U+E0100"); 10723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 10823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 10923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 11023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+E0100 U+FE0F"); 11123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 11223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 11323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 11423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+E0100 U+E0100"); 11523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 11623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 11723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 11823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Multiple variation selectors 11923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| '#' U+FE0F U+FE0F"); 12023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 12123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 12223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 12323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| '#' U+FE0F U+E0100"); 12423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 12523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 12623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 12723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+845B U+E0100 U+FE0F"); 12823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 12923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 13023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 13123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+845B U+E0100 U+E0100"); 13223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 13323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 13423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka } 13523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 13623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka @SmallTest 13723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka public void testEmojiZeroWidthJoinerSequence() { 13823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka EditorState state = new EditorState(); 13923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 140328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka // U+200D is ZERO WIDTH JOINER. 141328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka state.setByString("| U+1F441 U+200D U+1F5E8"); 142328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka forwardDelete(state, 0); 143328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka state.assertEquals("|"); 144328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka 145328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka state.setByString("| U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468"); 146328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka forwardDelete(state, 0); 147328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka state.assertEquals("|"); 148328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka 14923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // End with ZERO WIDTH JOINER 15023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F441 U+200D"); 15123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 15223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 15323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 15423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Start with ZERO WIDTH JOINER 15523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+200D U+1F5E8"); 15623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 15723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F5E8"); 15823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 15923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 16023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 16123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Multiple ZERO WIDTH JOINER 16223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F441 U+200D U+200D U+1F5E8"); 16323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 16423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F5E8"); 16523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 16623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 16723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 16823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Isolated ZERO WIDTH JOINER 16923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+200D"); 17023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 17123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 17223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 17323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Isolated multiple ZERO WIDTH JOINER 17423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+200D U+200D"); 17523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 17623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 17723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka } 17823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 17923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka @SmallTest 18023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka public void testFlags() { 18123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka EditorState state = new EditorState(); 18223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 18323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Isolated regional indicator symbol 18423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F1FA"); 18523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 18623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 18723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 18823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Odd numbered regional indicator symbols 18923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F1FA U+1F1F8 U+1F1FA"); 19023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 19123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F1FA"); 19223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 19323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 19423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka } 19523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 19623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka @SmallTest 19723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka public void testEmojiModifier() { 19823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka EditorState state = new EditorState(); 19923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 200328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka // U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2. 201328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka state.setByString("| U+1F466 U+1F3FB"); 202328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka forwardDelete(state, 0); 203328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka state.assertEquals("|"); 204328251a1d756463ad5f0dedcdf8a5b613387f8dcSeigo Nonaka 20523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Isolated emoji modifier 20623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F3FB"); 20723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 20823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 20923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 21023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Isolated multiple emoji modifier 21123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F3FB U+1F3FB"); 21223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 21323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F3FB"); 21423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 21523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 21623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 21723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Multiple emoji modifiers 21823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F466 U+1F3FB U+1F3FB"); 21923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 22023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F3FB"); 22123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 22223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 22323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka } 22423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 22523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka @SmallTest 22623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka public void testMixedEdgeCases() { 22723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka EditorState state = new EditorState(); 22823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 22923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // COMBINING ENCLOSING KEYCAP + variation selector 23023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| '1' U+20E3 U+FE0F"); 23123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 23223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 23323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 23423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Variation selector + COMBINING ENCLOSING KEYCAP 23523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+2665 U+FE0F U+20E3"); 23623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 23723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 23823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 23923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // COMBINING ENCLOSING KEYCAP + ending with ZERO WIDTH JOINER 24023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| '1' U+20E3 U+200D"); 24123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 24223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 24323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 24423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // COMBINING ENCLOSING KEYCAP + ZERO WIDTH JOINER 24523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| '1' U+20E3 U+200D U+1F5E8"); 24623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 24723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F5E8 "); 24823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 24923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Start with ZERO WIDTH JOINER + COMBINING ENCLOSING KEYCAP 25023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+200D U+20E3"); 25123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 25223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 25323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 25423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // ZERO WIDTH JOINER + COMBINING ENCLOSING KEYCAP 25523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F441 U+200D U+20E3"); 25623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 25723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 25823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 25923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // COMBINING ENCLOSING KEYCAP + regional indicator symbol 26023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| '1' U+20E3 U+1F1FA"); 26123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 26223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F1FA"); 26323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 26423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 26523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 26623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Regional indicator symbol + COMBINING ENCLOSING KEYCAP 26723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F1FA U+20E3"); 26823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 26923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 27023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 27123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // COMBINING ENCLOSING KEYCAP + emoji modifier 27223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| '1' U+20E3 U+1F3FB"); 27323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 27423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F3FB"); 27523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 27623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Emoji modifier + COMBINING ENCLOSING KEYCAP 27723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F466 U+1F3FB U+20E3"); 27823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 27923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 28023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 28123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Variation selector + end with ZERO WIDTH JOINER 28223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+2665 U+FE0F U+200D"); 28323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 28423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 28523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 28623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Variation selector + ZERO WIDTH JOINER 28723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F469 U+200D U+2764 U+FE0F U+200D U+1F469"); 28823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 28923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 29023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 29123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Start with ZERO WIDTH JOINER + variation selector 29223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+200D U+FE0F"); 29323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 29423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 29523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 29623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // ZERO WIDTH JOINER + variation selector 29723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F469 U+200D U+FE0F"); 29823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 29923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 30023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 30123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Variation selector + regional indicator symbol 30223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+2665 U+FE0F U+1F1FA"); 30323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 30423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F1FA"); 30523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 30623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 30723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 30823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Regional indicator symbol + variation selector 30923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F1FA U+FE0F"); 31023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 31123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 31223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 31323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Variation selector + emoji modifier 31423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+2665 U+FE0F U+1F3FB"); 31523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 31623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F3FB"); 31723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 31823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Emoji modifier + variation selector 31923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F466 U+1F3FB U+FE0F"); 32023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 32123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 32223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 32323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Start with ZERO WIDTH JOINER + regional indicator symbol 32423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+200D U+1F1FA"); 32523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 32623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F1FA"); 32723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 32823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 32923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 33023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // ZERO WIDTH JOINER + regional indicator symbol 33123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F469 U+200D U+1F1FA"); 33223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 33323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F1FA"); 33423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 33523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Regional indicator symbol + end with ZERO WIDTH JOINER 33623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F1FA U+200D"); 33723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 33823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 33923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 34023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Regional indicator symbol + ZERO WIDTH JOINER 34123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F1FA U+200D U+1F469"); 34223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 34323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F469"); 34423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 34523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 34623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 34723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Start with ZERO WIDTH JOINER + emoji modifier 34823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+200D U+1F3FB"); 34923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 35023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F3FB"); 35123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 35223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // ZERO WIDTH JOINER + emoji modifier 35323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F469 U+200D U+1F3FB"); 35423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 35523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F3FB"); 35623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 35723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Emoji modifier + end with ZERO WIDTH JOINER 35823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F466 U+1F3FB U+200D"); 35923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 36023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 36123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 36223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Emoji modifier + ZERO WIDTH JOINER 36323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F466 U+1F3FB U+200D U+1F469"); 36423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 36523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F469"); 36623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 36723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 36823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 36923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Regional indicator symbol + emoji modifier 37023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F1FA U+1F3FB"); 37123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 37223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F3FB"); 37323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 37423a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 37523a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka 37623a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka // Emoji modifier + regional indicator symbol 37723a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.setByString("| U+1F466 U+1F3FB U+1F1FA"); 37823a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 37923a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("| U+1F1FA"); 38023a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka forwardDelete(state, 0); 38123a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka state.assertEquals("|"); 38223a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka } 38323a67678e3848e2465518769236139e6cafac2eeSeigo Nonaka} 384