Skip to content

Commit 08151d5

Browse files
Operators: lowercase uppercase capitalize (#67)
* operators draft * create separate class for unwrap strategy * fix bug * add tests for operators * add tests for StringUnwrapStrategy
1 parent 599aa09 commit 08151d5

File tree

8 files changed

+369
-0
lines changed

8 files changed

+369
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package string
2+
3+
import operation.StandardLogicOperation
4+
5+
object Capitalize : StandardLogicOperation, StringUnwrapStrategy {
6+
override fun evaluateLogic(expression: Any?, data: Any?): Any? =
7+
unwrapValueAsString(expression)?.replaceFirstChar { it.uppercase() }
8+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package string
2+
3+
import operation.StandardLogicOperation
4+
5+
object Lowercase : StandardLogicOperation, StringUnwrapStrategy {
6+
override fun evaluateLogic(expression: Any?, data: Any?): Any? = unwrapValueAsString(expression)?.lowercase()
7+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package string
2+
3+
import operation.StandardLogicOperation
4+
import utils.asList
5+
6+
7+
internal interface StringUnwrapStrategy {
8+
fun unwrapValueAsString(wrappedValue: Any?): String? =
9+
with(wrappedValue.asList) {
10+
if (size <= 1) {
11+
(firstOrNull() as? String)
12+
} else null
13+
}
14+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package string
2+
3+
import operation.StandardLogicOperation
4+
5+
object Uppercase : StandardLogicOperation, StringUnwrapStrategy {
6+
override fun evaluateLogic(expression: Any?, data: Any?): Any? = unwrapValueAsString(expression)?.uppercase()
7+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package string
2+
3+
import JsonLogicResult.Failure
4+
import JsonLogicResult.Success
5+
import TestInput
6+
import io.kotest.core.spec.style.FunSpec
7+
import io.kotest.datatest.withData
8+
import io.kotest.matchers.shouldBe
9+
10+
class CapitalizeTest : FunSpec({
11+
val operatorName = "capitalize"
12+
val logicEngine = JsonLogicEngine.Builder().addStandardOperation(operatorName, Capitalize).build()
13+
14+
withData(
15+
nameFn = { input -> "Should evaluated ${input.expression} with given ${input.data} result in ${input.result}" },
16+
ts = listOf(
17+
TestInput(
18+
expression = mapOf(operatorName to "banana"),
19+
result = Success("Banana")
20+
),
21+
TestInput(
22+
expression = mapOf(operatorName to ""),
23+
result = Success("")
24+
),
25+
TestInput(
26+
expression = mapOf(operatorName to " "),
27+
result = Success(" ")
28+
),
29+
TestInput(
30+
expression = mapOf(operatorName to "123"),
31+
result = Success("123")
32+
),
33+
TestInput(
34+
expression = mapOf(operatorName to "Test"),
35+
result = Success("Test")
36+
),
37+
TestInput(
38+
expression = mapOf(operatorName to "TEST ME!"),
39+
result = Success("TEST ME!")
40+
),
41+
TestInput(
42+
expression = mapOf(operatorName to mapOf("var" to "key")),
43+
data = mapOf("key" to "apple"),
44+
result = Success("Apple")
45+
),
46+
TestInput(
47+
expression = mapOf(operatorName to mapOf("var" to "key")),
48+
result = Failure.NullResult
49+
),
50+
TestInput(
51+
expression = mapOf(operatorName to 1.3),
52+
result = Failure.NullResult
53+
),
54+
TestInput(
55+
expression = mapOf(operatorName to null),
56+
result = Failure.NullResult
57+
),
58+
TestInput(
59+
expression = mapOf(operatorName to true),
60+
result = Failure.NullResult
61+
),
62+
TestInput(
63+
expression = mapOf(operatorName to emptyList<Any>()),
64+
result = Failure.NullResult
65+
),
66+
)
67+
// given
68+
) { testInput: TestInput ->
69+
// when
70+
val evaluationResult = logicEngine.evaluate(testInput.expression, testInput.data)
71+
72+
// then
73+
evaluationResult shouldBe testInput.result
74+
}
75+
})
76+
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package string
2+
3+
import JsonLogicResult.Failure
4+
import JsonLogicResult.Success
5+
import TestInput
6+
import io.kotest.core.spec.style.FunSpec
7+
import io.kotest.datatest.withData
8+
import io.kotest.matchers.shouldBe
9+
10+
class LowercaseTest : FunSpec({
11+
val operatorName = "lowercase"
12+
val logicEngine = JsonLogicEngine.Builder().addStandardOperation(operatorName, Lowercase).build()
13+
14+
withData(
15+
nameFn = { input -> "Should evaluated ${input.expression} with given ${input.data} result in ${input.result}" },
16+
ts = listOf(
17+
TestInput(
18+
expression = mapOf(operatorName to "banana"),
19+
result = Success("banana")
20+
),
21+
TestInput(
22+
expression = mapOf(operatorName to ""),
23+
result = Success("")
24+
),
25+
TestInput(
26+
expression = mapOf(operatorName to " "),
27+
result = Success(" ")
28+
),
29+
TestInput(
30+
expression = mapOf(operatorName to "123"),
31+
result = Success("123")
32+
),
33+
TestInput(
34+
expression = mapOf(operatorName to "Test"),
35+
result = Success("test")
36+
),
37+
TestInput(
38+
expression = mapOf(operatorName to "TEST ME!"),
39+
result = Success("test me!")
40+
),
41+
TestInput(
42+
expression = mapOf(operatorName to mapOf("var" to "key")),
43+
data = mapOf("key" to "APPLE"),
44+
result = Success("apple")
45+
),
46+
TestInput(
47+
expression = mapOf(operatorName to mapOf("var" to "key")),
48+
result = Failure.NullResult
49+
),
50+
TestInput(
51+
expression = mapOf(operatorName to 1.3),
52+
result = Failure.NullResult
53+
),
54+
TestInput(
55+
expression = mapOf(operatorName to null),
56+
result = Failure.NullResult
57+
),
58+
TestInput(
59+
expression = mapOf(operatorName to true),
60+
result = Failure.NullResult
61+
),
62+
TestInput(
63+
expression = mapOf(operatorName to emptyList<Any>()),
64+
result = Failure.NullResult
65+
),
66+
)
67+
// given
68+
) { testInput: TestInput ->
69+
// when
70+
val evaluationResult = logicEngine.evaluate(testInput.expression, testInput.data)
71+
72+
// then
73+
evaluationResult shouldBe testInput.result
74+
}
75+
})
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package string
2+
3+
import io.kotest.core.spec.style.BehaviorSpec
4+
import io.kotest.matchers.shouldBe
5+
6+
class StringUnwrapStrategyTest : BehaviorSpec({
7+
val strategyImplementation: StringUnwrapStrategy = object : StringUnwrapStrategy {}
8+
9+
given("A list with one string") {
10+
val wrappedValue = listOf("test")
11+
`when`("unwrapped") {
12+
val unwrapResult = strategyImplementation.unwrapValueAsString(wrappedValue)
13+
then("should be string") {
14+
unwrapResult shouldBe "test"
15+
}
16+
}
17+
}
18+
19+
given("A string") {
20+
val wrappedValue = "apple"
21+
`when`("unwrapped") {
22+
val unwrapResult = strategyImplementation.unwrapValueAsString(wrappedValue)
23+
then("should be string") {
24+
unwrapResult shouldBe "apple"
25+
}
26+
}
27+
}
28+
29+
given("A list of strings") {
30+
val wrappedValue = listOf("apple", "banana")
31+
`when`("unwrapped") {
32+
val unwrapResult = strategyImplementation.unwrapValueAsString(wrappedValue)
33+
then("should not be unwrapped") {
34+
unwrapResult shouldBe null
35+
}
36+
}
37+
}
38+
39+
given("A non-decimal double") {
40+
val wrappedValue = listOf(2.0)
41+
`when`("unwrapped") {
42+
val unwrapResult = strategyImplementation.unwrapValueAsString(wrappedValue)
43+
then("should not be unwrapped") {
44+
unwrapResult shouldBe null
45+
}
46+
}
47+
}
48+
49+
given("A double") {
50+
val wrappedValue = listOf(2.51)
51+
`when`("unwrapped") {
52+
val unwrapResult = strategyImplementation.unwrapValueAsString(wrappedValue)
53+
then("should not be unwrapped") {
54+
unwrapResult shouldBe null
55+
}
56+
}
57+
}
58+
given("An empty list") {
59+
val wrappedValue = emptyList<String>()
60+
`when`("unwrapped") {
61+
val unwrapResult = strategyImplementation.unwrapValueAsString(wrappedValue)
62+
then("should not be unwrapped") {
63+
unwrapResult shouldBe null
64+
}
65+
}
66+
}
67+
68+
given("A boolean value") {
69+
val wrappedValue = listOf(false)
70+
`when`("unwrapped") {
71+
val unwrapResult = strategyImplementation.unwrapValueAsString(wrappedValue)
72+
then("should not be unwrapped") {
73+
unwrapResult shouldBe null
74+
}
75+
}
76+
}
77+
78+
given("A null") {
79+
val wrappedValue = listOf(null)
80+
`when`("unwrapped") {
81+
val unwrapResult = strategyImplementation.unwrapValueAsString(wrappedValue)
82+
then("should not be unwrapped") {
83+
unwrapResult shouldBe null
84+
}
85+
}
86+
}
87+
88+
given("A nested list items") {
89+
val wrappedValue = listOf(listOf(listOf("banana", "apple", "pineapple")))
90+
`when`("unwrapped") {
91+
val unwrapResult = strategyImplementation.unwrapValueAsString(wrappedValue)
92+
then("should not be unwrapped") {
93+
unwrapResult shouldBe null
94+
}
95+
}
96+
}
97+
98+
given("A nested lists items") {
99+
val wrappedValue = listOf(true, listOf(listOf("banana")), listOf(2.0))
100+
`when`("unwrapped") {
101+
val unwrapResult = strategyImplementation.unwrapValueAsString(wrappedValue)
102+
then("should not be unwrapped") {
103+
unwrapResult shouldBe null
104+
}
105+
}
106+
}
107+
})
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package string
2+
3+
import JsonLogicResult.Failure
4+
import JsonLogicResult.Success
5+
import TestInput
6+
import io.kotest.core.spec.style.FunSpec
7+
import io.kotest.datatest.withData
8+
import io.kotest.matchers.shouldBe
9+
10+
class UppercaseTest : FunSpec({
11+
val operatorName = "uppercase"
12+
val logicEngine = JsonLogicEngine.Builder().addStandardOperation(operatorName, Uppercase).build()
13+
14+
withData(
15+
nameFn = { input -> "Should evaluated ${input.expression} with given ${input.data} result in ${input.result}" },
16+
ts = listOf(
17+
TestInput(
18+
expression = mapOf(operatorName to "banana"),
19+
result = Success("BANANA")
20+
),
21+
TestInput(
22+
expression = mapOf(operatorName to ""),
23+
result = Success("")
24+
),
25+
TestInput(
26+
expression = mapOf(operatorName to " "),
27+
result = Success(" ")
28+
),
29+
TestInput(
30+
expression = mapOf(operatorName to "123"),
31+
result = Success("123")
32+
),
33+
TestInput(
34+
expression = mapOf(operatorName to "Test"),
35+
result = Success("TEST")
36+
),
37+
TestInput(
38+
expression = mapOf(operatorName to "TEST ME!"),
39+
result = Success("TEST ME!")
40+
),
41+
TestInput(
42+
expression = mapOf(operatorName to mapOf("var" to "key")),
43+
data = mapOf("key" to "apple"),
44+
result = Success("APPLE")
45+
),
46+
TestInput(
47+
expression = mapOf(operatorName to mapOf("var" to "key")),
48+
result = Failure.NullResult
49+
),
50+
TestInput(
51+
expression = mapOf(operatorName to 1.3),
52+
result = Failure.NullResult
53+
),
54+
TestInput(
55+
expression = mapOf(operatorName to null),
56+
result = Failure.NullResult
57+
),
58+
TestInput(
59+
expression = mapOf(operatorName to true),
60+
result = Failure.NullResult
61+
),
62+
TestInput(
63+
expression = mapOf(operatorName to emptyList<Any>()),
64+
result = Failure.NullResult
65+
),
66+
)
67+
// given
68+
) { testInput: TestInput ->
69+
// when
70+
val evaluationResult = logicEngine.evaluate(testInput.expression, testInput.data)
71+
72+
// then
73+
evaluationResult shouldBe testInput.result
74+
}
75+
})

0 commit comments

Comments
 (0)