test(core): Add tests for SmartDeleteHandler

Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
This commit is contained in:
Myzel394 2024-07-25 23:17:28 +02:00
parent 358f5b4582
commit 6cb9532e6e
No known key found for this signature in database
GPG Key ID: DEC4AAB876F73185
2 changed files with 183 additions and 4 deletions

View File

@ -3,12 +3,24 @@ package app.myzel394.numberhub.core.ui.common.textfield
import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.TextRange
import app.myzel394.numberhub.core.base.Token import app.myzel394.numberhub.core.base.Token
// Smartly delete tokens /** Smartly delete tokens
* @param value the current value of the text field
* @param selection the current selection of the text field - Assumed to be a valid selection
*/
data class SmartDeleteHandler( data class SmartDeleteHandler(
private val value: String, private val value: String,
private val selection: TextRange, private val selection: TextRange,
) { ) {
/**
* Calculate the range to delete based on the current selection.
*
* @return the range to delete - [Inclusive, Exclusive]
*/
fun calculateDeleteRange(): TextRange { fun calculateDeleteRange(): TextRange {
if (value == "") {
return TextRange(0, 0)
}
if (isSelectionARange()) { if (isSelectionARange()) {
return selection return selection
} }
@ -30,14 +42,20 @@ data class SmartDeleteHandler(
return if (rightBracketRelativeToLeftPosition == null) { return if (rightBracketRelativeToLeftPosition == null) {
// 1+2(+5|+6 // 1+2(+5|+6
TextRange(leftBracketPosition + 1, position) TextRange((leftBracketPosition + 1).coerceAtMost(position), position)
} else { } else {
// 1+2(6)+5|+6 // 1+2(6)+5|+6
TextRange(takeNextIfIsOperator(rightBracketRelativeToLeftPosition + 1), position) TextRange(
takeNextIfIsOperator(rightBracketRelativeToLeftPosition + 1).coerceAtMost(
position,
),
position,
)
} }
} }
return TextRange(leftBracketPosition + 1, findClosingParen(leftBracketPosition)); val end = findClosingParen(leftBracketPosition)
return TextRange((leftBracketPosition + 1).coerceAtMost(end), end);
} }
private fun takeNextIfIsOperator(position: Int): Int { private fun takeNextIfIsOperator(position: Int): Int {

View File

@ -0,0 +1,161 @@
package app.myzel394.numberhub.core.ui
import androidx.compose.ui.text.TextRange
import app.myzel394.numberhub.core.ui.common.textfield.SmartDeleteHandler
import org.junit.Test
class SmartDeleteHandlerTest {
@Test
fun `test simple delete`() {
assertDeleteRange(
"1+2",
TextRange(2, 2),
TextRange(0, 2),
)
}
@Test
fun `test brackets, position in between`() {
assertDeleteRange(
"1+(2+3)",
TextRange(4, 4),
TextRange(3, 6),
)
}
@Test
fun `test brackets, position at the end`() {
assertDeleteRange(
"1+(2+3)",
TextRange(6, 6),
TextRange(3, 6),
)
}
@Test
fun `test brackets, position at the start`() {
assertDeleteRange(
"1+(2+3)",
TextRange(3, 3),
TextRange(3, 6),
)
}
@Test
fun `test brackets, but position outside`() {
assertDeleteRange(
"1+(2+3)",
TextRange(1, 1),
TextRange(0, 1),
)
}
@Test
fun `test brackets, but cursor outside right of it`() {
assertDeleteRange(
"1+(2+3)54",
TextRange(8, 8),
TextRange(7, 8),
)
}
@Test
fun `test brackets, but cursor outside right of it, should go to the operator`() {
assertDeleteRange(
"1+(2+3)×54",
TextRange(9, 9),
TextRange(8, 9),
)
}
@Test
fun `test nested brackets, inside the nested one`() {
assertDeleteRange(
"1+(2+(3+4))",
TextRange(8, 8),
TextRange(6, 9),
)
}
@Test
fun `test nested brackets, inside the outside one`() {
assertDeleteRange(
"1+(2+(3+4))",
TextRange(4, 4),
TextRange(3, 10),
)
}
@Test
fun `test nested empty brackets`() {
assertDeleteRange(
"1+(2+())",
TextRange(4, 4),
TextRange(3, 7),
)
}
@Test
fun `test pure empty nested brackets`() {
assertDeleteRange(
"1+((()))",
TextRange(5, 5),
TextRange(5, 5),
)
}
@Test
fun `test empty string`() {
assertDeleteRange(
"",
TextRange(0, 0),
TextRange(0, 0),
)
}
@Test
fun `test single character with cursor ar 0,0`() {
assertDeleteRange(
"1",
TextRange(0, 0),
TextRange(0, 0),
)
}
@Test
fun `test single bracket with cursor at 0,0`() {
assertDeleteRange(
"(",
TextRange(0, 0),
TextRange(0, 0),
)
}
@Test
fun `test nested brackets with operators`() {
assertDeleteRange(
"1+(2*(3+4))",
TextRange(8, 8),
TextRange(6, 9),
)
}
@Test
fun `test selection range spanning multiple tokens`() {
assertDeleteRange(
"1+(2+3)*4",
TextRange(2, 6),
TextRange(2, 6),
)
}
private fun assertDeleteRange(input: String, selection: TextRange, expected: TextRange) {
val smartDeleteHandler =
SmartDeleteHandler(input, selection)
val actual = smartDeleteHandler.calculateDeleteRange()
assert(expected == actual) {
"Expected: $expected, actual: $actual"
}
}
}