Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Functional tests: assert file existence #134

Merged
merged 6 commits into from
Jan 13, 2024
Merged
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 @@ -3,6 +3,7 @@ package dev.adamko.dokkatoo.utils
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths
import kotlin.io.path.readText
import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
Expand Down Expand Up @@ -183,7 +184,7 @@ private class TestProjectFileProvidedDelegate(
private val filePath: String,
) : ReadWriteProperty<Any?, String> {
override fun getValue(thisRef: Any?, property: KProperty<*>): String =
project.projectDir.resolve(filePath).toFile().readText()
project.projectDir.resolve(filePath).readText()

override fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
project.createFile(filePath, value)
Expand All @@ -195,7 +196,7 @@ class TestProjectFileDelegate(
private val filePath: String,
) : ReadWriteProperty<ProjectDirectoryScope, String> {
override fun getValue(thisRef: ProjectDirectoryScope, property: KProperty<*>): String =
thisRef.projectDir.resolve(filePath).toFile().readText()
thisRef.projectDir.resolve(filePath).readText()

override fun setValue(thisRef: ProjectDirectoryScope, property: KProperty<*>, value: String) {
thisRef.createFile(filePath, value)
Expand Down
46 changes: 39 additions & 7 deletions modules/dokkatoo-plugin/src/testFixtures/kotlin/fileTree.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,45 @@ import java.nio.file.Path
// based on https://gist.github.com/mfwgenerics/d1ec89eb80c95da9d542a03b49b5e15b
// context: https://kotlinlang.slack.com/archives/C0B8MA7FA/p1676106647658099

fun Path.toTreeString(): String = toFile().toTreeString()

fun File.toTreeString(): String = when {
isDirectory -> name + "/\n" + buildTreeString(this)
fun Path.toTreeString(
fileFilter: FileFilter = FileFilter { true },
): String =
toFile().toTreeString(fileFilter = fileFilter)


fun File.toTreeString(
fileFilter: FileFilter = FileFilter { true },
): String = when {
isDirectory -> name + "/\n" + buildTreeString(dir = this, fileFilter = fileFilter)
else -> name
}


/**
* Optionally include/exclude files. Directories will always be included.
*/
fun interface FileFilter {
operator fun invoke(file: File): Boolean
}


private fun FileFilter.matches(file: File): Boolean =
if (file.isDirectory) {
// don't include directories that have no matches
file.walk().any { it.isFile && invoke(it) }
} else {
invoke(file)
}


private fun buildTreeString(
dir: File,
fileFilter: FileFilter = FileFilter { true },
margin: String = "",
): String {
val entries = dir.listDirectoryEntries()
.filter { file -> fileFilter.matches(file) }

return entries.joinToString("\n") { entry ->
val (currentPrefix, nextPrefix) = when (entry) {
Expand All @@ -30,10 +57,10 @@ private fun buildTreeString(

if (entry.isDirectory) {
append("/")
if (entry.countDirectoryEntries() > 0) {
if (entry.countDirectoryEntries(fileFilter) > 0) {
append("\n")
}
append(buildTreeString(entry, margin + nextPrefix))
append(buildTreeString(entry, fileFilter, margin + nextPrefix))
}
}
}
Expand All @@ -43,8 +70,13 @@ private fun File.listDirectoryEntries(): Sequence<File> =
walkTopDown().maxDepth(1).filter { it != this@listDirectoryEntries }


private fun File.countDirectoryEntries(): Int =
listDirectoryEntries().count()
private fun File.countDirectoryEntries(
fileFilter: FileFilter,
): Int =
listDirectoryEntries()
.filter { file -> fileFilter.matches(file) }
.count()


private data class PrefixPair(
/** The current entry should be prefixed with this */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import io.kotest.assertions.withClue
import io.kotest.core.spec.style.FunSpec
import io.kotest.inspectors.shouldForAll
import io.kotest.matchers.file.shouldBeAFile
import io.kotest.matchers.paths.shouldBeAFile
import io.kotest.matchers.sequences.shouldNotBeEmpty
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain
import io.kotest.matchers.string.shouldNotContain
import kotlin.io.path.readText

class KotlinMultiplatformFunctionalTest : FunSpec({

Expand Down Expand Up @@ -44,19 +45,27 @@ class KotlinMultiplatformFunctionalTest : FunSpec({
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()
}

test("and dokka_parameters.json is generated") {
project.projectDir.resolve("build/dokka/html/dokka_parameters.json")
.shouldBeAFile()
project.projectDir
.resolve("build/dokka/")
.toTreeString { it.extension == "html" } shouldBe /* language=text */ """
¦dokka/
¦└── html/
¦ ├── index.html
¦ ├── test/
¦ │ └── com.project/
¦ │ ├── index.html
¦ │ ├── goodbye.html
¦ │ └── -hello/
¦ │ ├── say-hello.html
¦ │ ├── index.html
¦ │ └── -hello.html
¦ └── navigation.html
""".trimMargin("¦")
}

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()
project.projectDir.resolve("build/dokka/html/test/package-list").toFile().shouldBeAFile()
project.projectDir.resolve("build/dokka/html/test/package-list").readText()
.sortLines()
.shouldContain( /* language=text */ """
|${'$'}dokka.format:html-v1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import io.kotest.inspectors.shouldForAll
import io.kotest.matchers.collections.shouldBeIn
import io.kotest.matchers.collections.shouldContainAll
import io.kotest.matchers.file.shouldBeAFile
import io.kotest.matchers.paths.shouldBeAFile
import io.kotest.matchers.paths.shouldNotExist
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldBeEmpty
import io.kotest.matchers.string.shouldContain
import io.kotest.matchers.string.shouldNotContain
import kotlin.io.path.readText
import org.gradle.testkit.runner.TaskOutcome.*

class MultiModuleFunctionalTest : FunSpec({
Expand All @@ -30,48 +31,64 @@ class MultiModuleFunctionalTest : FunSpec({
test("expect build is successful") {
output shouldContain "BUILD SUCCESSFUL"
}
}

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

context("expect HTML site is generated") {

test("with expected HTML files") {
project.file("subproject/build/dokka/html/index.html").shouldBeAFile()
project.file("subproject/build/dokka/html/com/project/hello/Hello.html")
.shouldBeAFile()
}

test("and dokka_parameters.json is generated") {
project.file("subproject/build/dokka/html/dokka_parameters.json")
.shouldBeAFile()
}
context("expect HTML site is generated") {

test("with expected HTML files") {
project.projectDir
.resolve("build/dokka/html/")
.toTreeString { it.extension == "html" } shouldBe /* language=text */ """
¦html/
¦├── subproject-hello/
¦│ ├── index.html
¦│ ├── com.project.hello/
¦│ │ ├── index.html
¦│ │ └── -hello/
¦│ │ ├── say-hello.html
¦│ │ ├── index.html
¦│ │ └── -hello.html
¦│ └── navigation.html
¦├── index.html
¦├── subproject-goodbye/
¦│ ├── index.html
¦│ ├── com.project.goodbye/
¦│ │ ├── index.html
¦│ │ └── -goodbye/
¦│ │ ├── say-hello.html
¦│ │ ├── index.html
¦│ │ └── -goodbye.html
¦│ └── navigation.html
¦└── navigation.html""".trimMargin("¦")
}

test("with element-list") {
project.file("build/dokka/html/package-list").shouldBeAFile()
project.file("build/dokka/html/package-list").toFile().readText()
.shouldContain( /* language=text */ """
|${'$'}dokka.format:html-v1
|${'$'}dokka.linkExtension:html
|
|module:subproject-hello
|com.project.hello
|module:subproject-goodbye
|com.project.goodbye
""".trimMargin()
)
test("with element-list") {
project.file("build/dokka/html/package-list").toFile().shouldBeAFile()
project.file("build/dokka/html/package-list").readText()
.shouldContain( /* language=text */ """
|${'$'}dokka.format:html-v1
|${'$'}dokka.linkExtension:html
|
|module:subproject-hello
|com.project.hello
|module:subproject-goodbye
|com.project.goodbye
""".trimMargin()
)
}
}
}
}
}

context("Gradle caching") {
Expand Down Expand Up @@ -231,7 +248,8 @@ class MultiModuleFunctionalTest : FunSpec({
.build {

test("expect HelloAgain HTML file exists") {
helloAgainIndexHtml.shouldBeAFile()
// convert to file, workaround https://github.com/kotest/kotest/issues/3825
helloAgainIndexHtml.toFile().shouldBeAFile()
}

test("expect :subproject-goodbye tasks are up-to-date, because no files changed") {
Expand Down
Loading