mirror of
https://github.com/androidx/media.git
synced 2025-05-06 23:20:42 +08:00
Add {Relative,Absolute}SizeSpan support to SpannedSubject
I'll use this in TtmlDecoderTest PiperOrigin-RevId: 289091526
This commit is contained in:
parent
d24188f663
commit
b562e8687b
@ -24,9 +24,11 @@ import android.graphics.Typeface;
|
||||
import android.text.Layout.Alignment;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.AbsoluteSizeSpan;
|
||||
import android.text.style.AlignmentSpan;
|
||||
import android.text.style.BackgroundColorSpan;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
import android.text.style.StrikethroughSpan;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.text.style.TypefaceSpan;
|
||||
@ -422,6 +424,88 @@ public final class SpannedSubject extends Subject {
|
||||
hasNoSpansOfTypeBetween(TypefaceSpan.class, start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the subject has a {@link AbsoluteSizeSpan} from {@code start} to {@code end}.
|
||||
*
|
||||
* <p>The size is asserted in a follow-up method call on the return {@link AbsoluteSized} object.
|
||||
*
|
||||
* @param start The start of the expected span.
|
||||
* @param end The end of the expected span.
|
||||
* @return A {@link AbsoluteSized} object to assert on the size of the matching spans.
|
||||
*/
|
||||
@CheckResult
|
||||
public AbsoluteSized hasAbsoluteSizeSpanBetween(int start, int end) {
|
||||
if (actual == null) {
|
||||
failWithoutActual(simpleFact("Spanned must not be null"));
|
||||
return ALREADY_FAILED_ABSOLUTE_SIZED;
|
||||
}
|
||||
|
||||
List<AbsoluteSizeSpan> absoluteSizeSpans =
|
||||
findMatchingSpans(start, end, AbsoluteSizeSpan.class);
|
||||
if (absoluteSizeSpans.isEmpty()) {
|
||||
failWithExpectedSpan(
|
||||
start, end, AbsoluteSizeSpan.class, actual.toString().substring(start, end));
|
||||
return ALREADY_FAILED_ABSOLUTE_SIZED;
|
||||
}
|
||||
return check("AbsoluteSizeSpan (start=%s,end=%s)", start, end)
|
||||
.about(absoluteSizeSpans(actual))
|
||||
.that(absoluteSizeSpans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the subject has no {@link AbsoluteSizeSpan}s on any of the text between {@code
|
||||
* start} and {@code end}.
|
||||
*
|
||||
* <p>This fails even if the start and end indexes don't exactly match.
|
||||
*
|
||||
* @param start The start index to start searching for spans.
|
||||
* @param end The end index to stop searching for spans.
|
||||
*/
|
||||
public void hasNoAbsoluteSizeSpanBetween(int start, int end) {
|
||||
hasNoSpansOfTypeBetween(AbsoluteSizeSpan.class, start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the subject has a {@link RelativeSizeSpan} from {@code start} to {@code end}.
|
||||
*
|
||||
* <p>The size is asserted in a follow-up method call on the return {@link RelativeSized} object.
|
||||
*
|
||||
* @param start The start of the expected span.
|
||||
* @param end The end of the expected span.
|
||||
* @return A {@link RelativeSized} object to assert on the size of the matching spans.
|
||||
*/
|
||||
@CheckResult
|
||||
public RelativeSized hasRelativeSizeSpanBetween(int start, int end) {
|
||||
if (actual == null) {
|
||||
failWithoutActual(simpleFact("Spanned must not be null"));
|
||||
return ALREADY_FAILED_RELATIVE_SIZED;
|
||||
}
|
||||
|
||||
List<RelativeSizeSpan> relativeSizeSpans =
|
||||
findMatchingSpans(start, end, RelativeSizeSpan.class);
|
||||
if (relativeSizeSpans.isEmpty()) {
|
||||
failWithExpectedSpan(
|
||||
start, end, RelativeSizeSpan.class, actual.toString().substring(start, end));
|
||||
return ALREADY_FAILED_RELATIVE_SIZED;
|
||||
}
|
||||
return check("RelativeSizeSpan (start=%s,end=%s)", start, end)
|
||||
.about(relativeSizeSpans(actual))
|
||||
.that(relativeSizeSpans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the subject has no {@link RelativeSizeSpan}s on any of the text between {@code
|
||||
* start} and {@code end}.
|
||||
*
|
||||
* <p>This fails even if the start and end indexes don't exactly match.
|
||||
*
|
||||
* @param start The start index to start searching for spans.
|
||||
* @param end The end index to stop searching for spans.
|
||||
*/
|
||||
public void hasNoRelativeSizeSpanBetween(int start, int end) {
|
||||
hasNoSpansOfTypeBetween(RelativeSizeSpan.class, start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the subject has a {@link RubySpan} from {@code start} to {@code end}.
|
||||
*
|
||||
@ -817,6 +901,105 @@ public final class SpannedSubject extends Subject {
|
||||
}
|
||||
}
|
||||
|
||||
/** Allows assertions about the absolute size of a span. */
|
||||
public interface AbsoluteSized {
|
||||
|
||||
/**
|
||||
* Checks that at least one of the matched spans has the expected {@code size}.
|
||||
*
|
||||
* @param size The expected size.
|
||||
* @return A {@link WithSpanFlags} object for optional additional assertions on the flags.
|
||||
*/
|
||||
AndSpanFlags withAbsoluteSize(int size);
|
||||
}
|
||||
|
||||
private static final AbsoluteSized ALREADY_FAILED_ABSOLUTE_SIZED =
|
||||
size -> ALREADY_FAILED_AND_FLAGS;
|
||||
|
||||
private static Factory<AbsoluteSizeSpansSubject, List<AbsoluteSizeSpan>> absoluteSizeSpans(
|
||||
Spanned actualSpanned) {
|
||||
return (FailureMetadata metadata, List<AbsoluteSizeSpan> spans) ->
|
||||
new AbsoluteSizeSpansSubject(metadata, spans, actualSpanned);
|
||||
}
|
||||
|
||||
private static final class AbsoluteSizeSpansSubject extends Subject implements AbsoluteSized {
|
||||
|
||||
private final List<AbsoluteSizeSpan> actualSpans;
|
||||
private final Spanned actualSpanned;
|
||||
|
||||
private AbsoluteSizeSpansSubject(
|
||||
FailureMetadata metadata, List<AbsoluteSizeSpan> actualSpans, Spanned actualSpanned) {
|
||||
super(metadata, actualSpans);
|
||||
this.actualSpans = actualSpans;
|
||||
this.actualSpanned = actualSpanned;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AndSpanFlags withAbsoluteSize(int size) {
|
||||
List<Integer> matchingSpanFlags = new ArrayList<>();
|
||||
List<Integer> spanSizes = new ArrayList<>();
|
||||
|
||||
for (AbsoluteSizeSpan span : actualSpans) {
|
||||
spanSizes.add(span.getSize());
|
||||
if (span.getSize() == size) {
|
||||
matchingSpanFlags.add(actualSpanned.getSpanFlags(span));
|
||||
}
|
||||
}
|
||||
|
||||
check("absoluteSize").that(spanSizes).containsExactly(size);
|
||||
return check("flags").about(spanFlags()).that(matchingSpanFlags);
|
||||
}
|
||||
}
|
||||
|
||||
/** Allows assertions about the relative size of a span. */
|
||||
public interface RelativeSized {
|
||||
/**
|
||||
* Checks that at least one of the matched spans has the expected {@code sizeChange}.
|
||||
*
|
||||
* @param sizeChange The expected size change.
|
||||
* @return A {@link WithSpanFlags} object for optional additional assertions on the flags.
|
||||
*/
|
||||
AndSpanFlags withSizeChange(float sizeChange);
|
||||
}
|
||||
|
||||
private static final RelativeSized ALREADY_FAILED_RELATIVE_SIZED =
|
||||
sizeChange -> ALREADY_FAILED_AND_FLAGS;
|
||||
|
||||
private static Factory<RelativeSizeSpansSubject, List<RelativeSizeSpan>> relativeSizeSpans(
|
||||
Spanned actualSpanned) {
|
||||
return (FailureMetadata metadata, List<RelativeSizeSpan> spans) ->
|
||||
new RelativeSizeSpansSubject(metadata, spans, actualSpanned);
|
||||
}
|
||||
|
||||
private static final class RelativeSizeSpansSubject extends Subject implements RelativeSized {
|
||||
|
||||
private final List<RelativeSizeSpan> actualSpans;
|
||||
private final Spanned actualSpanned;
|
||||
|
||||
private RelativeSizeSpansSubject(
|
||||
FailureMetadata metadata, List<RelativeSizeSpan> actualSpans, Spanned actualSpanned) {
|
||||
super(metadata, actualSpans);
|
||||
this.actualSpans = actualSpans;
|
||||
this.actualSpanned = actualSpanned;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AndSpanFlags withSizeChange(float size) {
|
||||
List<Integer> matchingSpanFlags = new ArrayList<>();
|
||||
List<Float> spanSizes = new ArrayList<>();
|
||||
|
||||
for (RelativeSizeSpan span : actualSpans) {
|
||||
spanSizes.add(span.getSizeChange());
|
||||
if (span.getSizeChange() == size) {
|
||||
matchingSpanFlags.add(actualSpanned.getSpanFlags(span));
|
||||
}
|
||||
}
|
||||
|
||||
check("sizeChange").that(spanSizes).containsExactly(size);
|
||||
return check("flags").about(spanFlags()).that(matchingSpanFlags);
|
||||
}
|
||||
}
|
||||
|
||||
/** Allows assertions about a span's ruby text and its position. */
|
||||
public interface RubyText {
|
||||
|
||||
|
@ -26,10 +26,12 @@ import android.graphics.Typeface;
|
||||
import android.text.Layout.Alignment;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.AbsoluteSizeSpan;
|
||||
import android.text.style.AlignmentSpan;
|
||||
import android.text.style.AlignmentSpan.Standard;
|
||||
import android.text.style.BackgroundColorSpan;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
import android.text.style.StrikethroughSpan;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.text.style.TypefaceSpan;
|
||||
@ -489,6 +491,118 @@ public class SpannedSubjectTest {
|
||||
checkHasNoSpanFails(new TypefaceSpan("courier"), SpannedSubject::hasNoTypefaceSpanBetween);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void absoluteSizeSpan_success() {
|
||||
SpannableString spannable =
|
||||
createSpannable(new AbsoluteSizeSpan(/* size= */ 5), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
|
||||
assertThat(spannable)
|
||||
.hasAbsoluteSizeSpanBetween(SPAN_START, SPAN_END)
|
||||
.withAbsoluteSize(5)
|
||||
.andFlags(Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void absoluteSizeSpan_wrongIndex() {
|
||||
checkHasSpanFailsDueToIndexMismatch(
|
||||
new AbsoluteSizeSpan(/* size= */ 5), SpannedSubject::hasAbsoluteSizeSpanBetween);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void absoluteSizeSpan_wrongSize() {
|
||||
SpannableString spannable = createSpannable(new AbsoluteSizeSpan(/* size= */ 5));
|
||||
|
||||
AssertionError expected =
|
||||
expectFailure(
|
||||
whenTesting ->
|
||||
whenTesting
|
||||
.that(spannable)
|
||||
.hasAbsoluteSizeSpanBetween(SPAN_START, SPAN_END)
|
||||
.withAbsoluteSize(4));
|
||||
|
||||
assertThat(expected).factValue("value of").contains("absoluteSize");
|
||||
assertThat(expected).factValue("expected").contains("4");
|
||||
assertThat(expected).factValue("but was").contains("5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void absoluteSizeSpan_wrongFlags() {
|
||||
checkHasSpanFailsDueToFlagMismatch(
|
||||
new AbsoluteSizeSpan(/* size= */ 5),
|
||||
(subject, start, end) ->
|
||||
subject.hasAbsoluteSizeSpanBetween(start, end).withAbsoluteSize(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noAbsoluteSizeSpan_success() {
|
||||
SpannableString spannable =
|
||||
createSpannableWithUnrelatedSpanAnd(new AbsoluteSizeSpan(/* size= */ 5));
|
||||
|
||||
assertThat(spannable).hasNoAbsoluteSizeSpanBetween(UNRELATED_SPAN_START, UNRELATED_SPAN_END);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noAbsoluteSizeSpan_failure() {
|
||||
checkHasNoSpanFails(
|
||||
new AbsoluteSizeSpan(/* size= */ 5), SpannedSubject::hasNoAbsoluteSizeSpanBetween);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void relativeSizeSpan_success() {
|
||||
SpannableString spannable =
|
||||
createSpannable(
|
||||
new RelativeSizeSpan(/* proportion= */ 5), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
|
||||
assertThat(spannable)
|
||||
.hasRelativeSizeSpanBetween(SPAN_START, SPAN_END)
|
||||
.withSizeChange(5)
|
||||
.andFlags(Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void relativeSizeSpan_wrongIndex() {
|
||||
checkHasSpanFailsDueToIndexMismatch(
|
||||
new RelativeSizeSpan(/* proportion= */ 5), SpannedSubject::hasRelativeSizeSpanBetween);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void relativeSizeSpan_wrongSize() {
|
||||
SpannableString spannable = createSpannable(new RelativeSizeSpan(/* proportion= */ 5));
|
||||
|
||||
AssertionError expected =
|
||||
expectFailure(
|
||||
whenTesting ->
|
||||
whenTesting
|
||||
.that(spannable)
|
||||
.hasRelativeSizeSpanBetween(SPAN_START, SPAN_END)
|
||||
.withSizeChange(4));
|
||||
|
||||
assertThat(expected).factValue("value of").contains("sizeChange");
|
||||
assertThat(expected).factValue("expected").contains("4");
|
||||
assertThat(expected).factValue("but was").contains("5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void relativeSizeSpan_wrongFlags() {
|
||||
checkHasSpanFailsDueToFlagMismatch(
|
||||
new RelativeSizeSpan(/* proportion= */ 5),
|
||||
(subject, start, end) -> subject.hasRelativeSizeSpanBetween(start, end).withSizeChange(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noRelativeSizeSpan_success() {
|
||||
SpannableString spannable =
|
||||
createSpannableWithUnrelatedSpanAnd(new RelativeSizeSpan(/* proportion= */ 5));
|
||||
|
||||
assertThat(spannable).hasNoRelativeSizeSpanBetween(UNRELATED_SPAN_START, UNRELATED_SPAN_END);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noRelativeSizeSpan_failure() {
|
||||
checkHasNoSpanFails(
|
||||
new RelativeSizeSpan(/* proportion= */ 5), SpannedSubject::hasNoRelativeSizeSpanBetween);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rubySpan_success() {
|
||||
SpannableString spannable =
|
||||
|
Loading…
x
Reference in New Issue
Block a user