1f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir/* 2f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir * Copyright (C) 2017 The Android Open Source Project 3f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir * 4f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir * Licensed under the Apache License, Version 2.0 (the "License"); 5f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir * you may not use this file except in compliance with the License. 6f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir * You may obtain a copy of the License at 7f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir * 8f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir * http://www.apache.org/licenses/LICENSE-2.0 9f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir * 10f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir * Unless required by applicable law or agreed to in writing, software 11f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir * distributed under the License is distributed on an "AS IS" BASIS, 12f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir * See the License for the specific language governing permissions and 14f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir * limitations under the License. 15f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir */ 16f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirpackage android.support.text.emoji.widget; 17f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 18f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static junit.framework.Assert.assertSame; 19f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static junit.framework.TestCase.assertNotNull; 20f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 21f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.hamcrest.Matchers.arrayWithSize; 22f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.hamcrest.Matchers.instanceOf; 23f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.junit.Assert.assertEquals; 24f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.junit.Assert.assertThat; 25f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.mockito.Matchers.any; 26f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.mockito.Matchers.anyInt; 27f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.mockito.Matchers.anyObject; 28f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.mockito.Matchers.same; 29f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.mockito.Mockito.mock; 30f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.mockito.Mockito.never; 31f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.mockito.Mockito.reset; 32f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.mockito.Mockito.times; 33f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.mockito.Mockito.verify; 34f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.mockito.Mockito.withSettings; 35f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 36f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport android.support.test.filters.SmallTest; 37f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport android.support.test.runner.AndroidJUnit4; 38f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport android.support.text.emoji.EmojiSpan; 39f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport android.text.Editable; 40f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport android.text.SpanWatcher; 41f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport android.text.Spannable; 42f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport android.text.Spanned; 43f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport android.text.TextWatcher; 44f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport android.text.style.QuoteSpan; 45f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 46f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport junit.framework.Assert; 47f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 48f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport org.junit.Before; 49f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport org.junit.Test; 50f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport org.junit.runner.RunWith; 51f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 52f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir@SmallTest 53f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir@RunWith(AndroidJUnit4.class) 54f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirpublic class SpannableBuilderTest { 55f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 56f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir private TextWatcher mWatcher; 57f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir private Class mClass; 58f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 59f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir @Before 60f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir public void setup() { 61f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir mWatcher = mock(TextWatcher.class, withSettings().extraInterfaces(SpanWatcher.class)); 62f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir mClass = mWatcher.getClass(); 63f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 64f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 65f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir @Test 66f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir public void testConstructor() { 67f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir new SpannableBuilder(mClass); 68f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 69f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir new SpannableBuilder(mClass, "abc"); 70f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 71f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir new SpannableBuilder(mClass, "abc", 0, 3); 72f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 73f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // test spannable copying? do I need it? 74f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 75f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 76f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir @Test 77f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir public void testSubSequence() { 78f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final SpannableBuilder spannable = new SpannableBuilder(mClass, "abc"); 79f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final QuoteSpan span1 = mock(QuoteSpan.class); 80f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final QuoteSpan span2 = mock(QuoteSpan.class); 81f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.setSpan(span1, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 82f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.setSpan(span2, 2, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 83f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 84f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final CharSequence subsequence = spannable.subSequence(0, 1); 85f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertNotNull(subsequence); 86f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertThat(subsequence, instanceOf(SpannableBuilder.class)); 87f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 88f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final QuoteSpan[] spans = spannable.getSpans(0, 1, QuoteSpan.class); 89f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertThat(spans, arrayWithSize(1)); 90f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertSame(spans[0], span1); 91f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 92f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 93f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir @Test 94f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir public void testSetAndGetSpan() { 95f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final SpannableBuilder spannable = new SpannableBuilder(mClass, "abcde"); 96f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.setSpan(mWatcher, 1, 2, Spanned.SPAN_INCLUSIVE_INCLUSIVE); 97f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 98f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // getSpans should return the span 99f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir Object[] spans = spannable.getSpans(0, spannable.length(), mClass); 100f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertNotNull(spans); 101f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertThat(spans, arrayWithSize(1)); 102f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertSame(mWatcher, spans[0]); 103f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 104f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // span attributes should be correct 105f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertEquals(1, spannable.getSpanStart(mWatcher)); 106f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertEquals(2, spannable.getSpanEnd(mWatcher)); 107f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertEquals(Spanned.SPAN_INCLUSIVE_INCLUSIVE, spannable.getSpanFlags(mWatcher)); 108f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 109f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // should remove the span 110f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.removeSpan(mWatcher); 111f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spans = spannable.getSpans(0, spannable.length(), QuoteSpan.class); 112f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertNotNull(spans); 113f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertThat(spans, arrayWithSize(0)); 114f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 115f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 116f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir @Test 117f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir public void testNextSpanTransition() { 118f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final SpannableBuilder spannable = new SpannableBuilder(mClass, "abcde"); 119f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.setSpan(mWatcher, 1, 2, Spanned.SPAN_INCLUSIVE_INCLUSIVE); 120f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final int start = spannable.nextSpanTransition(0, spannable.length(), mClass); 121f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir Assert.assertEquals(1, start); 122f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 123f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 124f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir @Test 125f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir public void testBlocksSpanCallbacks_forEmojiSpans() { 126f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final EmojiSpan span = mock(EmojiSpan.class); 127f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final SpannableBuilder spannable = new SpannableBuilder(mClass, "123456"); 128f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.setSpan(mWatcher, 0, spannable.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); 129f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.setSpan(span, 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 130f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir reset(mWatcher); 131f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 132f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.delete(0, 3); 133f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 134f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // verify that characters are deleted 135f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertEquals("456", spannable.toString()); 136f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // verify EmojiSpan is deleted 137f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir EmojiSpan[] spans = spannable.getSpans(0, spannable.length(), EmojiSpan.class); 138f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertThat(spans, arrayWithSize(0)); 139f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 140f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // verify the call to span callbacks are blocked 141f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify((SpanWatcher) mWatcher, never()).onSpanRemoved(any(Spannable.class), 142f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir same(span), anyInt(), anyInt()); 143f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify((SpanWatcher) mWatcher, never()).onSpanAdded(any(Spannable.class), 144f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir same(span), anyInt(), anyInt()); 145f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify((SpanWatcher) mWatcher, never()).onSpanChanged(any(Spannable.class), 146f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir same(span), anyInt(), anyInt(), anyInt(), anyInt()); 147f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 148f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // verify the call to TextWatcher callbacks are called 149f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify(mWatcher, times(1)).beforeTextChanged(any(CharSequence.class), anyInt(), 150f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir anyInt(), anyInt()); 151f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify(mWatcher, times(1)).onTextChanged(any(CharSequence.class), anyInt(), anyInt(), 152f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir anyInt()); 153f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify(mWatcher, times(1)).afterTextChanged(any(Editable.class)); 154f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 155f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 156f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir @Test 157f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir public void testDoesNotBlockSpanCallbacks_forNonEmojiSpans() { 158f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final QuoteSpan span = mock(QuoteSpan.class); 159f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final SpannableBuilder spannable = new SpannableBuilder(mClass, "123456"); 160f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.setSpan(mWatcher, 0, spannable.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); 161f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.setSpan(span, 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 162f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir reset(mWatcher); 163f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 164f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.delete(0, 3); 165f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 166f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // verify that characters are deleted 167f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertEquals("456", spannable.toString()); 168f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // verify QuoteSpan is deleted 169f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir QuoteSpan[] spans = spannable.getSpans(0, spannable.length(), QuoteSpan.class); 170f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertThat(spans, arrayWithSize(0)); 171f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 172f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // verify the call to span callbacks are not blocked 173f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify((SpanWatcher) mWatcher, times(1)).onSpanRemoved(any(Spannable.class), 174f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir anyObject(), anyInt(), anyInt()); 175f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 176f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // verify the call to TextWatcher callbacks are called 177f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify(mWatcher, times(1)).beforeTextChanged(any(CharSequence.class), anyInt(), anyInt(), 178f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir anyInt()); 179f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify(mWatcher, times(1)).onTextChanged(any(CharSequence.class), anyInt(), anyInt(), 180f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir anyInt()); 181f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify(mWatcher, times(1)).afterTextChanged(any(Editable.class)); 182f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 183f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 184f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir @Test 185f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir public void testDoesNotBlockSpanCallbacksForOtherWatchers() { 186f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final TextWatcher textWatcher = mock(TextWatcher.class); 187f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final SpanWatcher spanWatcher = mock(SpanWatcher.class); 188f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 189f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final EmojiSpan span = mock(EmojiSpan.class); 190f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir final SpannableBuilder spannable = new SpannableBuilder(mClass, "123456"); 191f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.setSpan(textWatcher, 0, spannable.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); 192f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.setSpan(spanWatcher, 0, spannable.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); 193f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.setSpan(span, 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 194f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir reset(textWatcher); 195f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 196f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir spannable.delete(0, 3); 197f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 198f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // verify that characters are deleted 199f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertEquals("456", spannable.toString()); 200f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // verify EmojiSpan is deleted 201f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir EmojiSpan[] spans = spannable.getSpans(0, spannable.length(), EmojiSpan.class); 202f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir assertThat(spans, arrayWithSize(0)); 203f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 204f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // verify the call to span callbacks are blocked 205f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify(spanWatcher, times(1)).onSpanRemoved(any(Spannable.class), same(span), 206f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir anyInt(), anyInt()); 207f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 208f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir // verify the call to TextWatcher callbacks are called 209f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify(textWatcher, times(1)).beforeTextChanged(any(CharSequence.class), anyInt(), 210f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir anyInt(), anyInt()); 211f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify(textWatcher, times(1)).onTextChanged(any(CharSequence.class), anyInt(), anyInt(), 212f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir anyInt()); 213f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir verify(textWatcher, times(1)).afterTextChanged(any(Editable.class)); 214f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 215f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir} 216