/* * Copyright (C) 2015 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.android.talkback; import android.annotation.TargetApi; import android.graphics.Typeface; import android.os.Build; import android.text.SpannableString; import android.text.Spanned; import android.text.TextPaint; import android.text.style.CharacterStyle; import android.text.style.StyleSpan; import android.text.style.URLSpan; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricGradleTestRunner; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertEquals; import com.android.talkback.FeedbackFragment; import com.android.talkback.FeedbackItem; import com.android.talkback.FeedbackProcessingUtils; /** * Tests for FeedbackProcessingUtils */ @Config( constants = BuildConfig.class, sdk = 21) @TargetApi(Build.VERSION_CODES.LOLLIPOP) @RunWith(RobolectricGradleTestRunner.class) public class FeedbackProcessingUtilsTest { @Test public void splitText_shouldNotAlterOrigin() { int numberOfFragment = 2; int size = numberOfFragment * FeedbackProcessingUtils.maxUtteranceLength; String originText = ""; for (int i = 0; i < size/2; i++) { originText += "i "; } FeedbackFragment fragment = new FeedbackFragment(originText, null); FeedbackItem item = new FeedbackItem(); item.addFragment(fragment); FeedbackProcessingUtils.splitLongText(item); StringBuilder processedBuffer = new StringBuilder(); assertTrue("Expended fragment size should larger than original ", item.getFragments().size() > numberOfFragment); for (FeedbackFragment processedFragment : item.getFragments()) { assertTrue("Length is smaller than max length", processedFragment.getText().length() < FeedbackProcessingUtils.maxUtteranceLength); processedBuffer.append(processedFragment.getText()); } assertEquals(processedBuffer.toString().length(), originText.length()); assertEquals("Processed content should be the same as original one", processedBuffer.toString(), originText); } @Test public void addFormattingCharacteristics_noSpans() { final String testString = "The quick brown fox jumps over the lazy dog!"; FeedbackFragment fragment = new FeedbackFragment(testString, null); fragment.addEarcon(R.raw.bold); FeedbackItem feedback = new FeedbackItem(); feedback.addFragment(fragment); FeedbackProcessingUtils.addFormattingCharacteristics(feedback); assertEquals(1, feedback.getFragments().size()); assertFragment(feedback, 0, testString, true); } @Test public void addFormattingCharacteristics_preserveExistingFeedback() { // Indices: 4----9 final String testSring = "The QUICK brown fox jumps over the lazy dog!"; SpannableString spannableString = new SpannableString(testSring); spannableString.setSpan(new StyleSpan(Typeface.ITALIC), 4, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); FeedbackFragment fragment = new FeedbackFragment(spannableString, null); fragment.addEarcon(R.raw.bold); FeedbackItem feedback = new FeedbackItem(); feedback.addFragment(fragment); FeedbackProcessingUtils.addFormattingCharacteristics(feedback); assertEquals(3, feedback.getFragments().size()); assertFragment(feedback, 0, "The ", true /* hasEarcon */); // Existing earcon! assertFragment(feedback, 1, "QUICK", true); // New earcon. assertFragment(feedback, 2, " brown fox jumps over the lazy dog!", false); } @Test public void addFormattingCharacteristics_styleSpans() { // Indices: 4----9 20--------30 final String testSring = "The QUICK brown fox JUMPS OVER the lazy dog!"; SpannableString spannableString = new SpannableString(testSring); spannableString.setSpan(new StyleSpan(Typeface.ITALIC), 4, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 20, 30, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); FeedbackItem feedback = new FeedbackItem(); feedback.addFragment(new FeedbackFragment(spannableString, null)); FeedbackProcessingUtils.addFormattingCharacteristics(feedback); assertEquals(5, feedback.getFragments().size()); assertFragment(feedback, 0, "The ", false /* hasEarcon */); assertFragment(feedback, 1, "QUICK", true); assertFragment(feedback, 2, " brown fox ", false); assertFragment(feedback, 3, "JUMPS OVER", true); assertFragment(feedback, 4, " the lazy dog!", false); } @Test public void addFormattingCharacteristics_nonOverlappingSpans() { // Indices: 4----9 20--------30 final String testSring = "The QUICK brown fox JUMPS OVER the lazy dog!"; SpannableString spannableString = new SpannableString(testSring); spannableString.setSpan(new StyleSpan(Typeface.ITALIC), 4, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString.setSpan(new URLSpan("https://www.google.com"), 20, 30, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); FeedbackItem feedback = new FeedbackItem(); feedback.addFragment(new FeedbackFragment(spannableString, null)); FeedbackProcessingUtils.addFormattingCharacteristics(feedback); assertEquals(5, feedback.getFragments().size()); assertFragment(feedback, 0, "The ", false /* hasEarcon */); assertFragment(feedback, 1, "QUICK", true); assertFragment(feedback, 2, " brown fox ", false); assertFragment(feedback, 3, "JUMPS OVER", true); assertFragment(feedback, 4, " the lazy dog!", false); } @Test public void addFormattingCharacteristics_overlappingSpans() { // StyleSpan: 4--------------19 // URLSpan: 10------------------30 final String testSring = "The QUICK BROWN FOX JUMPS OVER the lazy dog!"; SpannableString spannableString = new SpannableString(testSring); spannableString.setSpan(new StyleSpan(Typeface.ITALIC), 4, 19, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString.setSpan(new URLSpan("https://www.google.com"), 10, 30, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); FeedbackItem feedback = new FeedbackItem(); feedback.addFragment(new FeedbackFragment(spannableString, null)); FeedbackProcessingUtils.addFormattingCharacteristics(feedback); assertEquals(5, feedback.getFragments().size()); assertFragment(feedback, 0, "The ", false /* hasEarcon */); assertFragment(feedback, 1, "QUICK ", true); assertFragment(feedback, 2, "BROWN FOX", true); assertFragment(feedback, 3, " JUMPS OVER", true); assertFragment(feedback, 4, " the lazy dog!", false); } @Test public void addFormattingCharacteristics_manySpans() { // Span 1: 0---4 // Span 2: 3---------------19 // Span 3: 26--30 // Span 4: 26------34 // Span 5: 30-------39 // BLOCKS: |--||--------------|......|---|---|----|.... final String testSring = "The QUICK BROWN FOX JUMPS OVER the lazy dog!"; SpannableString spannableString = new SpannableString(testSring); spannableString.setSpan(new StyleSpan(Typeface.ITALIC), 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString.setSpan(new StyleSpan(Typeface.BOLD), 3, 19, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString.setSpan(new URLSpan("https://www.google.com"), 26, 30, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString.setSpan(new StyleSpan(Typeface.ITALIC), 26, 34, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 30, 39, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); FeedbackItem feedback = new FeedbackItem(); feedback.addFragment(new FeedbackFragment(spannableString, null)); FeedbackProcessingUtils.addFormattingCharacteristics(feedback); assertEquals(8, feedback.getFragments().size()); assertFragment(feedback, 0, "The", true /* hasEarcon */); assertFragment(feedback, 1, " ", true); assertFragment(feedback, 2, "QUICK BROWN FOX", true); assertFragment(feedback, 3, " JUMPS ", false); assertFragment(feedback, 4, "OVER", true); assertFragment(feedback, 5, " the", true); assertFragment(feedback, 6, " lazy", true); assertFragment(feedback, 7, " dog!", false); } @Test public void addFormattingCharacteristics_extraneousSpans() { // Span 1: 0---4 // Span 2 (extra): 3---------------19 // Span 3 (extra): 26--30 // Span 4 (extra): 26------34 // Span 5: 30-------39 // BLOCKS: |---|.........................|--------|.... final String testSring = "The QUICK BROWN FOX JUMPS OVER the lazy dog!"; SpannableString spannableString = new SpannableString(testSring); spannableString.setSpan(new StyleSpan(Typeface.ITALIC), 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString.setSpan(new FakeSpan(), 3, 19, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString.setSpan(new FakeSpan(), 26, 30, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString.setSpan(new FakeSpan(), 26, 34, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 30, 39, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); FeedbackItem feedback = new FeedbackItem(); feedback.addFragment(new FeedbackFragment(spannableString, null)); FeedbackProcessingUtils.addFormattingCharacteristics(feedback); assertEquals(4, feedback.getFragments().size()); assertFragment(feedback, 0, "The ", true /* hasEarcon */); assertFragment(feedback, 1, "QUICK BROWN FOX JUMPS OVER", false); assertFragment(feedback, 2, " the lazy", true); assertFragment(feedback, 3, " dog!", false); } private void assertFragment(FeedbackItem feedback, int fragmentIndex, String text, boolean hasEarcon) { FeedbackFragment fragment = feedback.getFragments().get(fragmentIndex); assertEquals(text, fragment.getText().toString()); if (hasEarcon) { assertTrue(0 != fragment.getEarcons().size()); } else { assertTrue(0 == fragment.getEarcons().size()); } } private static class FakeSpan extends CharacterStyle { public FakeSpan() {} @Override public void updateDrawState(TextPaint tp) {} } }