Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,6 @@ class GradleProjectTest(
}


///**
// * Load a project from the [GradleProjectTest.dokkaSrcIntegrationTestProjectsDir]
// */
//fun gradleKtsProjectIntegrationTest(
// testProjectName: String,
// build: GradleProjectTest.() -> Unit,
//): GradleProjectTest =
// GradleProjectTest(
// baseDir = GradleProjectTest.dokkaSrcIntegrationTestProjectsDir,
// testProjectName = testProjectName,
// ).apply(build)


/**
* Builder for testing a Gradle project that uses Kotlin script DSL and creates default
* `settings.gradle.kts` and `gradle.properties` files.
Expand All @@ -85,10 +72,10 @@ fun gradleKtsProjectTest(
settingsGradleKts = """
|rootProject.name = "test"
|
|@Suppress("UnstableApiUsage")
|dependencyResolutionManagement {
|pluginManagement {
| repositories {
| mavenCentral()
| gradlePluginPortal()
| maven(file("$testMavenRepoRelativePath")) {
| mavenContent {
| includeGroup("dev.adamko.dokkatoo")
Expand All @@ -98,10 +85,10 @@ fun gradleKtsProjectTest(
| }
|}
|
|pluginManagement {
|@Suppress("UnstableApiUsage")
|dependencyResolutionManagement {
| repositories {
| mavenCentral()
| gradlePluginPortal()
| maven(file("$testMavenRepoRelativePath")) {
| mavenContent {
| includeGroup("dev.adamko.dokkatoo")
Expand Down Expand Up @@ -158,6 +145,8 @@ fun gradleGroovyProjectTest(
gradleProperties = """
|kotlin.mpp.stability.nowarn=true
|org.gradle.cache=true
|org.gradle.daemon=false
|
""".trimMargin()

build()
Expand Down Expand Up @@ -241,12 +230,16 @@ fun ProjectDirectoryScope.findFiles(matcher: (File) -> Boolean): Sequence<File>

/** Set the content of `settings.gradle.kts` */
@delegate:Language("kts")
var ProjectDirectoryScope.settingsGradleKts: String by TestProjectFileDelegate("settings.gradle.kts")
var ProjectDirectoryScope.settingsGradleKts: String by TestProjectFileDelegate(
/* language=text */ "settings.gradle.kts"
)


/** Set the content of `build.gradle.kts` */
@delegate:Language("kts")
var ProjectDirectoryScope.buildGradleKts: String by TestProjectFileDelegate("build.gradle.kts")
var ProjectDirectoryScope.buildGradleKts: String by TestProjectFileDelegate(
/* language=text */ "build.gradle.kts"
)


/** Set the content of `settings.gradle` */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,95 +13,119 @@ import io.kotest.matchers.string.shouldNotContain

class KotlinMultiplatformFunctionalTest : FunSpec({

context("when dokkatoo generates all formats") {
val project = initKotlinMultiplatformProject()

project.runner
.addArguments(
"clean",
":dokkatooGeneratePublicationHtml",
"--stacktrace",
)
.forwardOutput()
.build {
test("expect build is successful") {
output shouldContain "BUILD SUCCESSFUL"
}
}
val kotlinVersionsToTest = listOf(
"1.8.22",
"1.9.10",
"1.9.20-dev-9102",
)

test("expect all dokka workers are successful") {
project
.findFiles { it.name == "dokka-worker.log" }
.shouldBeSingleton { dokkaWorkerLog ->
dokkaWorkerLog.shouldBeAFile()
dokkaWorkerLog.readText().shouldNotContainAnyOf(
"[ERROR]",
"[WARN]",
)
}
}
for (kotlinVersion in kotlinVersionsToTest) {
testKotlinMultiplatformProject(kotlinVersion)
}
})

context("expect HTML site is generated") {

test("with expected HTML files") {
project.projectDir.resolve("build/dokka/html/index.html").shouldBeAFile()
project.projectDir.resolve("build/dokka/html/com/project/hello/Hello.html")
.shouldBeAFile()
}
private fun FunSpec.testKotlinMultiplatformProject(
kotlinVersion: String,
): Unit = context("when dokkatoo generates all formats for Kotlin v$kotlinVersion project") {
val project = initKotlinMultiplatformProject(kotlinVersion)

test("and dokka_parameters.json is generated") {
project.projectDir.resolve("build/dokka/html/dokka_parameters.json")
.shouldBeAFile()
project.runner
.addArguments(
"clean",
":dokkatooGeneratePublicationHtml",
"--stacktrace",
)
.forwardOutput()
.build {
test("expect build is successful") {
output shouldContain "BUILD SUCCESSFUL"
}
}

test("with element-list") {
project.projectDir.resolve("build/dokka/html/test/package-list").shouldBeAFile()
project.projectDir.resolve("build/dokka/html/test/package-list").toFile().readText()
.sortLines()
.shouldContain( /* language=text */ """
|${'$'}dokka.format:html-v1
|${'$'}dokka.linkExtension:html
|${'$'}dokka.location:com.project////PointingToDeclaration/test/com.project/index.html
|${'$'}dokka.location:com.project//goodbye/#kotlinx.serialization.json.JsonObject/PointingToDeclaration/test/com.project/goodbye.html
|${'$'}dokka.location:com.project/Hello///PointingToDeclaration/test/com.project/-hello/index.html
|${'$'}dokka.location:com.project/Hello/Hello/#/PointingToDeclaration/test/com.project/-hello/-hello.html
|${'$'}dokka.location:com.project/Hello/sayHello/#kotlinx.serialization.json.JsonObject/PointingToDeclaration/test/com.project/-hello/say-hello.html
|com.project
""".trimMargin()
)
test("expect all dokka workers are successful") {
project
.findFiles { it.name == "dokka-worker.log" }
.shouldBeSingleton { dokkaWorkerLog ->
dokkaWorkerLog.shouldBeAFile()
dokkaWorkerLog.readText().shouldNotContainAnyOf(
"[ERROR]",
"[WARN]",
)
}
}

test("expect no 'unknown class' message in HTML files") {
val htmlFiles = project.projectDir.toFile()
.resolve("build/dokka/html")
.walk()
.filter { it.isFile && it.extension == "html" }
context("expect HTML site is generated") {

htmlFiles.shouldNotBeEmpty()
test("with expected HTML files") {
project.projectDir.resolve("build/dokka/html/index.html").shouldBeAFile()
project.projectDir.resolve("build/dokka/html/com/project/hello/Hello.html")
.shouldBeAFile()
}

htmlFiles.forEach { htmlFile ->
val relativePath = htmlFile.relativeTo(project.projectDir.toFile())
withClue("$relativePath should not contain Error class: unknown class") {
htmlFile.useLines { lines ->
lines.shouldForAll { line -> line.shouldNotContain("Error class: unknown class") }
}
test("and dokka_parameters.json is generated") {
project.projectDir.resolve("build/dokka/html/dokka_parameters.json")
.shouldBeAFile()
}

test("with element-list") {
project.projectDir.resolve("build/dokka/html/test/package-list").shouldBeAFile()
project.projectDir.resolve("build/dokka/html/test/package-list").toFile().readText()
.sortLines()
.shouldContain( /* language=text */ """
|${'$'}dokka.format:html-v1
|${'$'}dokka.linkExtension:html
|${'$'}dokka.location:com.project////PointingToDeclaration/test/com.project/index.html
|${'$'}dokka.location:com.project//goodbye/#kotlinx.serialization.json.JsonObject/PointingToDeclaration/test/com.project/goodbye.html
|${'$'}dokka.location:com.project/Hello///PointingToDeclaration/test/com.project/-hello/index.html
|${'$'}dokka.location:com.project/Hello/Hello/#/PointingToDeclaration/test/com.project/-hello/-hello.html
|${'$'}dokka.location:com.project/Hello/sayHello/#kotlinx.serialization.json.JsonObject/PointingToDeclaration/test/com.project/-hello/say-hello.html
|com.project
""".trimMargin()
)
}

test("expect no 'unknown class' message in HTML files") {
val htmlFiles = project.projectDir.toFile()
.resolve("build/dokka/html")
.walk()
.filter { it.isFile && it.extension == "html" }

htmlFiles.shouldNotBeEmpty()

htmlFiles.forEach { htmlFile ->
val relativePath = htmlFile.relativeTo(project.projectDir.toFile())
withClue("$relativePath should not contain Error class: unknown class") {
htmlFile.useLines { lines ->
lines.shouldForAll { line -> line.shouldNotContain("Error class: unknown class") }
}
}
}
}
}
})
}


private fun initKotlinMultiplatformProject(
kotlinVersion: String,
config: GradleProjectTest.() -> Unit = {},
): GradleProjectTest {
return gradleKtsProjectTest("kotlin-multiplatform-project") {
return gradleKtsProjectTest("kotlin-multiplatform-project-v$kotlinVersion") {

settingsGradleKts = settingsGradleKts.replace(
"""
|pluginManagement {
| repositories {
""".trimMargin(),
"""
|pluginManagement {
| repositories {
| maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap")
""".trimMargin(),
)
settingsGradleKts += """
|
|dependencyResolutionManagement {
|
| repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
|
| repositories {
Expand Down Expand Up @@ -131,14 +155,40 @@ private fun initKotlinMultiplatformProject(
| }
| filter { includeGroup("com.yarnpkg") }
| }
| maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap")
|
| // workaround for https://youtrack.jetbrains.com/issue/KT-51379
| exclusiveContent {
| forRepository {
| ivy("https://download.jetbrains.com/kotlin/native/builds") {
| name = "Kotlin Native"
| patternLayout {
| listOf(
| "macos-x86_64",
| "macos-aarch64",
| "osx-x86_64",
| "osx-aarch64",
| "linux-x86_64",
| "windows-x86_64",
| ).forEach { os ->
| listOf("dev", "releases").forEach { stage ->
artifact("${'$'}stage/[revision]/${'$'}os/[artifact]-[revision].[ext]")
| }
| }
| }
| metadataSources { artifact() }
| }
| }
| filter { includeModuleByRegex(".*", ".*kotlin-native-prebuilt.*") }
| }
| }
|}
|
""".trimMargin()

buildGradleKts = """
|plugins {
| kotlin("multiplatform") version "1.8.22"
| kotlin("multiplatform") version "$kotlinVersion"
| id("dev.adamko.dokkatoo") version "${DokkatooConstants.DOKKATOO_VERSION}"
|}
|
Expand All @@ -147,6 +197,11 @@ private fun initKotlinMultiplatformProject(
| js(IR) {
| browser()
| }
| linuxX64()
| macosX64()
| macosArm64()
| iosX64()
| mingwX64()
|
| sourceSets {
| commonMain {
Expand Down Expand Up @@ -212,34 +267,30 @@ private fun initKotlinMultiplatformProject(
)
}

dir("src/jvmMain/kotlin/") {
createKotlinFile(
"goodbyeJvm.kt",
"""
|package com.project
|
|import kotlinx.serialization.json.JsonObject
|
|/** JVM implementation - prints `goodbye` and [json] to the console */
|actual fun goodbye(json: JsonObject) = println("[JVM] goodbye ${'$'}json")
|
""".trimMargin()
)
}
listOf(
"jvm",
"js",
"linuxX64",
"macosX64",
"macosArm64",
"iosX64",
"mingwX64",
).forEach { target ->

dir("src/jsMain/kotlin/") {
createKotlinFile(
"goodbyeJs.kt",
"""
dir("src/${target}Main/kotlin/") {
createKotlinFile(
"goodbye_${target}.kt",
"""
|package com.project
|
|import kotlinx.serialization.json.JsonObject
|
|/** JS implementation - prints `goodbye` and [json] to the console */
|actual fun goodbye(json: JsonObject) = println("[JS] goodbye ${'$'}json")
|/** $target implementation - prints `goodbye` and [json] to the console */
|actual fun goodbye(json: JsonObject) = println("[target] goodbye ${'$'}json")
|
""".trimMargin()
)
)
}
}

config()
Expand Down