All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlinx.jupyter.test.repl.ReplWithTestResolverTests.kt Maven / Gradle / Ivy

package org.jetbrains.kotlinx.jupyter.test.repl

import io.kotest.matchers.collections.shouldContain
import io.kotest.matchers.collections.shouldContainAll
import io.kotest.matchers.collections.shouldHaveAtLeastSize
import io.kotest.matchers.collections.shouldHaveSize
import io.kotest.matchers.collections.shouldNotContain
import io.kotest.matchers.ints.shouldBeGreaterThan
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldStartWith
import org.jetbrains.kotlinx.jupyter.api.JSON
import org.jetbrains.kotlinx.jupyter.api.MimeTypedResult
import org.jetbrains.kotlinx.jupyter.api.MimeTypes
import org.jetbrains.kotlinx.jupyter.test.TestDisplayHandler
import org.jetbrains.kotlinx.jupyter.test.assertUnit
import org.jetbrains.kotlinx.jupyter.test.displayValue
import org.jetbrains.kotlinx.jupyter.test.rawValue
import org.jetbrains.kotlinx.jupyter.test.renderedValue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertTimeout
import org.junit.jupiter.api.parallel.Execution
import org.junit.jupiter.api.parallel.ExecutionMode
import java.time.Duration
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue

@Execution(ExecutionMode.SAME_THREAD)
class ReplWithTestResolverTests : AbstractSingleReplTest() {
    private val displays = mutableListOf()
    private val displayHandler = TestDisplayHandler(displays)
    override val repl = makeReplWithTestResolver(displayHandler)

    @Test
    fun testLetsPlot() {
        val code1 = "%use lets-plot"
        val code2 =
            """letsPlot(mapOf("cat" to listOf("a", "b")))"""

        val res1 = eval(code1)
        assertEquals(2, displays.count())
        displays.clear()
        assertUnit(res1.renderedValue)
        eval(code2)
        assertEquals(1, displays.count())
        val mime = displays[0] as? MimeTypedResult
        assertNotNull(mime)
        assertEquals(1, mime.size)
        assertEquals(MimeTypes.HTML, mime.entries.first().key)
    }

    @Test
    fun testDataframe() {
        eval("SessionOptions.resolveSources = true")

        val res =
            eval(
                """
                %use dataframe
                
                val name by column()
                val height by column()
                
                dataFrameOf(name, height)(
                    "Bill", 135,
                    "Mark", 160
                )
                """.trimIndent(),
            )

        val value = res.renderedValue
        assertTrue(value is MimeTypedResult)

        val html = value[MimeTypes.HTML]!!
        assertTrue(html.contains("Bill"))

        res.metadata.newSources.shouldHaveAtLeastSize(3)
    }

    @Test
    fun testSerialization() {
        val serialized =
            eval(
                """
                %use serialization
                
                @Serializable
                class C(val x: Int)
                
                Json.encodeToString(C(42))
                """.trimIndent(),
            )

        val expectedJson = """{"x":42}"""
        serialized.rawValue shouldBe expectedJson
        serialized.renderedValue shouldBe JSON(expectedJson)
    }

    @Test
    fun testNullableErasure() {
        eval(
            """
            val a: Int? = 3
            val b: String? = a.toString()
            """.trimIndent(),
        )
        val code2 = "a + 2 + b.toInt()"
        val res = eval(code2).renderedValue
        assertEquals(8, res)
    }

    @Test
    fun testKlaxonClasspathDoesntLeak() {
        val res =
            eval(
                """
                @file:DependsOn("src/test/testData/klaxon-2.1.8.jar")
                import com.beust.klaxon.*
                
                class Person (val name: String, var age: Int = 23)
                val klaxon = Klaxon()
                val parseRes = klaxon.parse(""${'"'}
                    {
                      "name": "John Smith"
                    }
                    ""${'"'})
                parseRes?.age
                """.trimIndent(),
            )
        assertEquals(23, res.renderedValue)
    }

    @Test
    fun testLibNewClasspath() {
        val res =
            eval(
                """
                %use lets-plot
                """.trimIndent(),
            )

        with(res.metadata) {
            assertTrue(newClasspath.size >= 10)
            assertTrue(newImports.size >= 5)
            assertTrue("org.jetbrains.letsPlot.*" in newImports)
        }
    }

    @Test
    fun testLibraryCompletion() {
        complete("%u|").sortedMatches() shouldBe listOf("use", "useLatestDescriptors")
        complete("%use kot|").sortedMatches() shouldContainAll listOf("kotlin-dl")
        with(complete("%use dataframe(0.8.0-|)").sortedMatches()) {
            shouldHaveAtLeastSize(10)
            shouldContain("0.8.0-rc-1")
        }
        complete("%use lets-plot, data|").sortedMatches() shouldBe listOf("dataframe")
        with(complete("%use kotlin-dl(|").matches()) {
            last() shouldBe "0.1.1"

            // Pre-release version should appear after release version
            indexOf("0.3.0-alpha-1") shouldBeGreaterThan indexOf("0.3.0")
        }

        // Value should be cached, and all these requests should not take much time
        assertTimeout(Duration.ofSeconds(20)) {
            for (i in 1..10000) {
                complete("%use kmath(|").matches() shouldHaveAtLeastSize 5
            }
        }
    }

    @Test
    fun testLibraryCompletionWithParams() {
        complete("%use kotlin-dl(|)").matches() shouldHaveAtLeastSize 5
        complete("%use kotlin-dl(|v =)").matches() shouldBe listOf("v")
        complete("%use kotlin-dl(v =|").matches().apply {
            shouldHaveAtLeastSize(5)
            shouldNotContain("v")
        }
        complete("%use kotlin-dl(a =|").matches() shouldHaveSize 0

        complete("%use lets-plot(v = |").matches() shouldContain "4.9.2"
        complete("%use lets-plot(v = |, js").matches() shouldContain "4.9.2"
    }

    @Test
    fun testTextRenderersOnRealData() {
        val result =
            eval(
                """
                notebook.textRenderersProcessor.registerDefaultRenderers()
                val text = java.io.File("src/test/testData/textRenderers/textData.txt").readText()
                "".toRegex().findAll(text).toList()
                """.trimIndent(),
            )

        val html = (result.displayValue as MimeTypedResult)["text/plain"]!!
        html shouldStartWith "ArrayList[MatcherMatchResult("
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy