-
Notifications
You must be signed in to change notification settings - Fork 451
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into renovate/all
- Loading branch information
Showing
5 changed files
with
252 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/RaiseAccumulateSpec.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package arrow.core.raise | ||
|
||
import arrow.core.NonEmptyList | ||
import arrow.core.left | ||
import arrow.core.nonEmptyListOf | ||
import io.kotest.core.spec.style.StringSpec | ||
import io.kotest.matchers.shouldBe | ||
|
||
class RaiseAccumulateSpec : StringSpec({ | ||
"RaiseAccumulate takes precedence over extension function" { | ||
either<NonEmptyList<String>, Int> { | ||
zipOrAccumulate( | ||
{ ensure(false) { "false" } }, | ||
{ mapOrAccumulate(1..2) { ensure(false) { "$it: IsFalse" } } } | ||
) { _, _ -> 1 } | ||
} shouldBe nonEmptyListOf("false", "1: IsFalse", "2: IsFalse").left() | ||
} | ||
}) |
99 changes: 99 additions & 0 deletions
99
arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/CopyTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package arrow.optics.plugin | ||
|
||
import org.junit.jupiter.api.Test | ||
|
||
// from https://kotlinlang.slack.com/archives/C5UPMM0A0/p1688822411819599 | ||
// and https://github.com/overfullstack/my-lab/blob/master/arrow/src/test/kotlin/ga/overfullstack/optics/OpticsLab.kt | ||
|
||
val copyCode = """ | ||
@optics data class Person(val name: String, val age: Int, val address: Address) { | ||
companion object | ||
} | ||
@optics data class Address(val street: Street, val city: City, val coordinates: List<Int>) { | ||
companion object | ||
} | ||
@optics data class Street(val name: String, val number: Int?) { | ||
companion object | ||
} | ||
@optics data class City(val name: String, val country: String) { | ||
companion object | ||
} | ||
fun Person.moveToAmsterdamCopy(): Person = copy { | ||
Person.address.city.name set "Amsterdam" | ||
Person.address.city.country set "Netherlands" | ||
Person.address .coordinates set listOf(2, 3) | ||
} | ||
fun Person.moveToAmsterdamInside(): Person = copy { | ||
inside(Person.address.city) { | ||
City.name set "Amsterdam" | ||
City.country set "Netherlands" | ||
} | ||
} | ||
val me = | ||
Person( | ||
"Gopal", | ||
99, | ||
Address(Street("Kotlinstraat", 1), City("Hilversum", "Netherlands"), listOf(1, 2)) | ||
) | ||
""" | ||
|
||
class CopyTest { | ||
@Test | ||
fun `code compiles`() { | ||
""" | ||
|package PersonTest | ||
|$imports | ||
|$copyCode | ||
""".compilationSucceeds() | ||
} | ||
|
||
@Test | ||
fun `birthday increments`() { | ||
""" | ||
|package PersonTest | ||
|$imports | ||
|$copyCode | ||
|val meAfterBirthdayParty = Person.age.modify(me) { it + 1 } | ||
|val r = Person.age.get(meAfterBirthdayParty) | ||
""".evals("r" to 100) | ||
} | ||
|
||
@Test | ||
fun `moving to another city`() { | ||
""" | ||
|package PersonTest | ||
|$imports | ||
|$copyCode | ||
|val newAddress = | ||
| Address(Street("Kotlinplein", null), City("Amsterdam", "Netherlands"), listOf(1, 2)) | ||
|val meAfterMoving = Person.address.set(me, newAddress) | ||
|val r = Person.address.get(meAfterMoving).street.name | ||
""".evals("r" to "Kotlinplein") | ||
} | ||
|
||
@Test | ||
fun `optics composition`() { | ||
""" | ||
|package PersonTest | ||
|$imports | ||
|$copyCode | ||
|val personCity: Lens<Person, String> = Person.address compose Address.city compose City.name | ||
|val meAtTheCapital = personCity.set(me, "Amsterdam") | ||
|val r = meAtTheCapital.address.city.name | ||
""".evals("r" to "Amsterdam") | ||
} | ||
|
||
@Test | ||
fun `optics copy to modify multiple fields`() { | ||
""" | ||
|package PersonTest | ||
|$imports | ||
|$copyCode | ||
|val meAfterMoving = me.moveToAmsterdamInside() | ||
|val r = meAfterMoving.address.city.name | ||
""".evals("r" to "Amsterdam") | ||
} | ||
} |
111 changes: 111 additions & 0 deletions
111
arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/CopyTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package arrow.optics | ||
|
||
import io.kotest.core.spec.style.StringSpec | ||
import io.kotest.matchers.shouldBe | ||
|
||
// from https://kotlinlang.slack.com/archives/C5UPMM0A0/p1688822411819599 | ||
// and https://github.com/overfullstack/my-lab/blob/master/arrow/src/test/kotlin/ga/overfullstack/optics/OpticsLab.kt | ||
|
||
data class Person(val name: String, val age: Int, val address: Address) { | ||
companion object { | ||
val name: Lens<Person, String> = Lens( | ||
get = { it.name }, | ||
set = { p, x -> p.copy(name = x) } | ||
) | ||
val age: Lens<Person, Int> = Lens( | ||
get = { it.age }, | ||
set = { p, x -> p.copy(age = x) } | ||
) | ||
val address: Lens<Person, Address> = Lens( | ||
get = { it.address }, | ||
set = { p, x -> p.copy(address = x) } | ||
) | ||
} | ||
} | ||
data class Address(val street: Street, val city: City, val coordinates: List<Int>) { | ||
companion object { | ||
val city: Lens<Address, City> = Lens( | ||
get = { it.city }, | ||
set = { a, x -> a.copy(city = x) } | ||
) | ||
val coordinates: Lens<Address, List<Int>> = Lens( | ||
get = { it.coordinates }, | ||
set = { a, x -> a.copy(coordinates = x) } | ||
) | ||
} | ||
} | ||
data class Street(val name: String, val number: Int?) | ||
data class City(val name: String, val country: String) { | ||
companion object { | ||
val name: Lens<City, String> = Lens( | ||
get = { it.name }, | ||
set = { c, x -> c.copy(name = x) } | ||
) | ||
val country: Lens<City, String> = Lens( | ||
get = { it.country }, | ||
set = { c, x -> c.copy(country = x) } | ||
) | ||
} | ||
} | ||
|
||
fun Person.moveToAmsterdamCopy(): Person = copy { | ||
Person.address + Address.city + City.name set "Amsterdam" | ||
Person.address + Address.city + City.country set "Netherlands" | ||
Person.address + Address.coordinates set listOf(2, 3) | ||
} | ||
|
||
fun Person.moveToAmsterdamInside(): Person = copy { | ||
inside(Person.address + Address.city) { | ||
City.name set "Amsterdam" | ||
City.country set "Netherlands" | ||
} | ||
} | ||
|
||
class CopyTest : StringSpec({ | ||
"optics" { | ||
val me = | ||
Person( | ||
"Gopal", | ||
99, | ||
Address(Street("Kotlinstraat", 1), City("Hilversum", "Netherlands"), listOf(1, 2)) | ||
) | ||
|
||
Person.name.get(me) shouldBe "Gopal" | ||
|
||
val meAfterBirthdayParty = Person.age.modify(me) { it + 1 } | ||
Person.age.get(meAfterBirthdayParty) shouldBe 100 | ||
|
||
val newAddress = | ||
Address(Street("Kotlinplein", null), City("Amsterdam", "Netherlands"), listOf(1, 2)) | ||
val meAfterMoving = Person.address.set(me, newAddress) | ||
Person.address.get(meAfterMoving) shouldBe newAddress | ||
} | ||
|
||
"optics composition" { | ||
val personCity: Lens<Person, String> = Person.address compose Address.city compose City.name | ||
|
||
val me = | ||
Person( | ||
"Alejandro", | ||
35, | ||
Address(Street("Kotlinstraat", 1), City("Hilversum", "Netherlands"), listOf(1, 2)) | ||
) | ||
|
||
personCity.get(me) shouldBe "Hilversum" | ||
val meAtTheCapital = personCity.set(me, "Amsterdam") | ||
meAtTheCapital.address.city.name shouldBe "Amsterdam" | ||
} | ||
|
||
"optics copy to modify multiple fields" { | ||
val me = | ||
Person( | ||
"Alejandro", | ||
35, | ||
Address(Street("Kotlinstraat", 1), City("Hilversum", "Netherlands"), listOf(1, 2)) | ||
) | ||
val meAfterMoving1 = me.moveToAmsterdamInside() | ||
val meAfterMoving2 = me.moveToAmsterdamInside() | ||
meAfterMoving1 shouldBe meAfterMoving2 | ||
meAfterMoving1.address.city.name shouldBe "Amsterdam" | ||
} | ||
}) |