You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
5.0 KiB

package com.keylesspalace.tusky
import android.text.Spannable
import com.keylesspalace.tusky.util.highlightSpans
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
class SpanUtilsTest {
@Test
fun matchesMixedSpans() {
val input = "one #one two: @two three : https://thr.ee/meh?foo=bar&wat=@at#hmm four #four five @five"
val inputSpannable = FakeSpannable(input)
highlightSpans(inputSpannable, 0xffffff)
val spans = inputSpannable.spans
Assert.assertEquals(5, spans.size)
}
@Test
fun doesntMergeAdjacentURLs() {
val firstURL = "http://first.thing"
val secondURL = "https://second.thing"
val inputSpannable = FakeSpannable("$firstURL $secondURL")
highlightSpans(inputSpannable, 0xffffff)
val spans = inputSpannable.spans
Assert.assertEquals(2, spans.size)
Assert.assertEquals(firstURL.length, spans[0].end - spans[0].start)
Assert.assertEquals(secondURL.length, spans[1].end - spans[1].start)
}
@RunWith(Parameterized::class)
class MatchingTests(private val thingToHighlight: String) {
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun data(): Iterable<Any> {
return listOf(
"@mention",
"#tag",
"https://thr.ee/meh?foo=bar&wat=@at#hmm",
"http://thr.ee/meh?foo=bar&wat=@at#hmm"
)
}
}
@Test
fun matchesSpanAtStart() {
val inputSpannable = FakeSpannable(thingToHighlight)
highlightSpans(inputSpannable, 0xffffff)
val spans = inputSpannable.spans
Assert.assertEquals(1, spans.size)
Assert.assertEquals(thingToHighlight.length, spans[0].end - spans[0].start)
}
@Test
fun matchesSpanNotAtStart() {
val inputSpannable = FakeSpannable(" $thingToHighlight")
highlightSpans(inputSpannable, 0xffffff)
val spans = inputSpannable.spans
Assert.assertEquals(1, spans.size)
Assert.assertEquals(thingToHighlight.length, spans[0].end - spans[0].start)
}
@Test
fun doesNotMatchSpanEmbeddedInText() {
val inputSpannable = FakeSpannable("aa${thingToHighlight}aa")
highlightSpans(inputSpannable, 0xffffff)
val spans = inputSpannable.spans
Assert.assertTrue(spans.isEmpty())
}
@Test
fun doesNotMatchSpanEmbeddedInAnotherSpan() {
val inputSpannable = FakeSpannable("@aa${thingToHighlight}aa")
highlightSpans(inputSpannable, 0xffffff)
val spans = inputSpannable.spans
Assert.assertEquals(1, spans.size)
}
@Test
fun spansDoNotOverlap() {
val begin = "@begin"
val end = "#end"
val inputSpannable = FakeSpannable("$begin $thingToHighlight $end")
highlightSpans(inputSpannable, 0xffffff)
val spans = inputSpannable.spans
Assert.assertEquals(3, spans.size)
val middleSpan = spans.single { span -> span.start > 0 && span.end < inputSpannable.lastIndex }
Assert.assertEquals(begin.length + 1, middleSpan.start)
Assert.assertEquals(inputSpannable.length - end.length - 1, middleSpan.end)
}
}
class FakeSpannable(private val text: String) : Spannable {
val spans = mutableListOf<BoundedSpan>()
override fun setSpan(what: Any?, start: Int, end: Int, flags: Int) {
spans.add(BoundedSpan(what, start, end))
}
override fun <T : Any> getSpans(start: Int, end: Int, type: Class<T>): Array<T> {
return spans.filter { it.start >= start && it.end <= end && type.isInstance(it)}
.map { it.span }
.toTypedArray() as Array<T>
}
override fun removeSpan(what: Any?) {
spans.removeIf { span -> span.span == what}
}
override fun toString(): String {
return text
}
override val length: Int
get() = text.length
class BoundedSpan(val span: Any?, val start: Int, val end: Int)
override fun nextSpanTransition(start: Int, limit: Int, type: Class<*>?): Int {
throw NotImplementedError()
}
override fun getSpanEnd(tag: Any?): Int {
throw NotImplementedError()
}
override fun getSpanFlags(tag: Any?): Int {
throw NotImplementedError()
}
override fun get(index: Int): Char {
throw NotImplementedError()
}
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence {
throw NotImplementedError()
}
override fun getSpanStart(tag: Any?): Int {
throw NotImplementedError()
}
}
}