diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c17bf78..9db3a2e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,6 +14,7 @@ ktor = "2.3.11" vanniktech-maven-publish = "0.28.0" jetbrains-compose = "1.6.10" ksp = "1.9.23-1.0.20" +truth = "1.4.2" [libraries] anvil-annotations = { module = "com.squareup.anvil:annotations", version.ref = "anvil" } @@ -33,7 +34,7 @@ ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "kto ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" } ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" } ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" } - +truth = { module = "com.google.truth:truth", version.ref = "truth" } #### Kotlin analysis #### diff --git a/owners/owners-github-codeowners/build.gradle.kts b/owners/owners-github-codeowners/build.gradle.kts index 224d54f..4527a13 100644 --- a/owners/owners-github-codeowners/build.gradle.kts +++ b/owners/owners-github-codeowners/build.gradle.kts @@ -11,14 +11,7 @@ dependencies { implementation(libs.kotlin.compiler.embeddable) implementation(project(":invert-models")) implementation(project(":invert-gradle-plugin")) - testImplementation(libs.kotlin.test) - testImplementation("com.google.truth:truth:1.0.1") - val junit5 = "5.3.1" - testImplementation("org.junit.jupiter:junit-jupiter-api:$junit5") - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$junit5") - val spek = "2.0.7" - testImplementation("org.spekframework.spek2:spek-dsl-jvm:$spek") - testRuntimeOnly("org.spekframework.spek2:spek-runner-junit5:$spek") - testImplementation(kotlin("reflect")) + testImplementation(libs.truth) + testImplementation(libs.kotlin.test) } diff --git a/owners/owners-github-codeowners/src/test/kotlin/com/github/pgreze/kowners/CodeOwnershipTest.kt b/owners/owners-github-codeowners/src/test/kotlin/com/github/pgreze/kowners/CodeOwnershipTest.kt index 86e0523..78432e8 100644 --- a/owners/owners-github-codeowners/src/test/kotlin/com/github/pgreze/kowners/CodeOwnershipTest.kt +++ b/owners/owners-github-codeowners/src/test/kotlin/com/github/pgreze/kowners/CodeOwnershipTest.kt @@ -1,56 +1,52 @@ package com.github.pgreze.kowners -import org.spekframework.spek2.Spek -import org.spekframework.spek2.style.specification.describe +import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertFails import kotlin.test.assertNull -class CodeOwnershipTest : Spek({ +class CodeOwnershipTest { - describe("Codeowners comment") { - it("returns null") { - assertNull("# A comment".parseCodeOwnersLine()) - } + @Test + fun `Codeowners comment`() { + assertNull("# A comment".parseCodeOwnersLine()) } - describe("Empty Codeowners line") { - it("returns null") { - assertNull("".parseCodeOwnersLine()) - } + @Test + fun `Empty Codeowners line`() { + assertNull("".parseCodeOwnersLine()) } - describe("Simple Codeowners line") { - it("returns correct value for 1 owner") { - val expected = CodeOwnership( - pattern = Pattern("docs/"), - owners = listOf("@me") - ) - assertEquals(expected, "docs/ @me".parseCodeOwnersLine()) - } - - it("returns correct value for multiple owners") { - val expected = CodeOwnership( - pattern = Pattern("docs/"), - owners = listOf("@me", "@org/team-name") - ) - assertEquals(expected, "docs/ @me @org/team-name".parseCodeOwnersLine()) - } + @Test + fun `Simple Codeowners line - returns correct value for 1 owner`() { + val expected = CodeOwnership( + pattern = Pattern("docs/"), + owners = listOf("@me") + ) + assertEquals(expected, "docs/ @me".parseCodeOwnersLine()) } - describe("Codeowners line with escaped space") { - it("returns correct value") { - val expected = CodeOwnership( - pattern = Pattern("docs/\\ hello"), - owners = listOf("@me") - ) - assertEquals(expected, "docs/\\ hello @me".parseCodeOwnersLine()) - } + @Test + fun `Simple Codeowners line - returns correct value for multiple owners`() { + val expected = CodeOwnership( + pattern = Pattern("docs/"), + owners = listOf("@me", "@org/team-name") + ) + assertEquals(expected, "docs/ @me @org/team-name".parseCodeOwnersLine()) } - describe("Codeowners line with invalid owners") { - it("returns correct message for no owner") { - assertFails("No owner in line: docs/") { "docs/".parseCodeOwnersLine() } - } + @Test + fun `Codeowners line with escaped space - returns correct value`() { + val expected = CodeOwnership( + pattern = Pattern("docs/\\ hello"), + owners = listOf("@me") + ) + assertEquals(expected, "docs/\\ hello @me".parseCodeOwnersLine()) } -}) + + @Test + fun `Codeowners line with invalid owners returns correct message for no owner`() { + assertFails("No owner in line: docs/") { "docs/".parseCodeOwnersLine() } + } + +} diff --git a/owners/owners-github-codeowners/src/test/kotlin/com/github/pgreze/kowners/OwnersResolverTest.kt b/owners/owners-github-codeowners/src/test/kotlin/com/github/pgreze/kowners/OwnersResolverTest.kt index 1bbca70..63e0175 100644 --- a/owners/owners-github-codeowners/src/test/kotlin/com/github/pgreze/kowners/OwnersResolverTest.kt +++ b/owners/owners-github-codeowners/src/test/kotlin/com/github/pgreze/kowners/OwnersResolverTest.kt @@ -1,12 +1,12 @@ package com.github.pgreze.kowners import com.google.common.truth.Truth.assertThat -import org.spekframework.spek2.Spek -import org.spekframework.spek2.style.specification.describe +import org.junit.Test -class OwnersResolverTest : Spek({ +class OwnersResolverTest { - describe("docs/sample project") { + @Test + fun `docs-sample project`() { val ownersResolver = CODEOWNERS.split("\n") .filter(String::isNotEmpty) .parseCodeOwners() @@ -16,11 +16,9 @@ class OwnersResolverTest : Spek({ .map { it to ownersResolver.resolveOwnership(it) } .toMap() - it("resolve all owners") { - assertThat(fileToOwners).isEqualTo(FILE_TO_OWNER) - } + assertThat(fileToOwners).isEqualTo(FILE_TO_OWNER) } -}) +} private const val CODEOWNERS = """ *.md charlie diff --git a/owners/owners-github-codeowners/src/test/kotlin/com/github/pgreze/kowners/PatternTest.kt b/owners/owners-github-codeowners/src/test/kotlin/com/github/pgreze/kowners/PatternTest.kt index 63fd2c1..f032ee9 100644 --- a/owners/owners-github-codeowners/src/test/kotlin/com/github/pgreze/kowners/PatternTest.kt +++ b/owners/owners-github-codeowners/src/test/kotlin/com/github/pgreze/kowners/PatternTest.kt @@ -1,169 +1,147 @@ package com.github.pgreze.kowners -import org.spekframework.spek2.Spek -import org.spekframework.spek2.style.specification.describe +import org.junit.Test import kotlin.test.assertFalse import kotlin.test.assertTrue -class PatternTest : Spek({ +class PatternTest { - describe("single patterns") { + @Test + fun `single patterns - single pattern`() { + // If a separator is at the end, it can only match a folder + val pattern = Pattern("docs/") - context("single pattern") { - // If a separator is at the end, it can only match a folder - val pattern = Pattern("docs/") + // match a single directory + assertTrue(pattern.matches("docs")) + assertTrue(pattern.matches("docs/")) - it("match a single directory") { - assertTrue(pattern.matches("docs")) - assertTrue(pattern.matches("docs/")) - } + // match a sub-file + assertTrue(pattern.matches("docs/item")) - it("match a sub-file") { - assertTrue(pattern.matches("docs/item")) - } - } + } - context("root based pattern") { - val pattern = Pattern("/docs") + @Test + fun `single patterns - root based pattern`() { + val pattern = Pattern("/docs") - it("match a single file") { - assertTrue(pattern.matches("docs")) - assertTrue(pattern.matches("docs/")) - } + // match a single file + assertTrue(pattern.matches("docs")) + assertTrue(pattern.matches("docs/")) - it("not match a sub-file") { - assertFalse(pattern.matches("/item/docs/")) - } - } - context("sub-tree pattern") { - val pattern = Pattern("hello/world") + // not match a sub-file + assertFalse(pattern.matches("/item/docs/")) - it("match only root folder") { - assertTrue(pattern.matches("hello/world")) - assertTrue(pattern.matches("/hello/world")) - } + } - it("not match as a sub-folder") { - assertFalse(pattern.matches("/root/hello/world")) - } - } + @Test + fun `single patterns - sub-tree pattern`() { + val pattern = Pattern("hello/world") + + // match only root folder + assertTrue(pattern.matches("hello/world")) + assertTrue(pattern.matches("/hello/world")) + + // not match as a sub-folder + assertFalse(pattern.matches("/root/hello/world")) } - // An asterisk "*" matches anything except a slash. - // The character "?" matches any one character except a slash. - describe("wildcard patterns") { + @Test + fun `wildcard patterns - extension based`() { + val pattern = Pattern("*.txt") - context("extension based") { - val pattern = Pattern("*.txt") + // match a single file + assertTrue(pattern.matches("file.txt")) + // match a sub-file + assertTrue(pattern.matches("docs/file.txt")) + // match a deep hierarchy + assertTrue(pattern.matches("docs/file.txt/rtfm")) + } - it("match a single file") { - assertTrue(pattern.matches("file.txt")) - } - it("match a sub-file") { - assertTrue(pattern.matches("docs/file.txt")) - } - it("match a deep hierarchy") { - assertTrue(pattern.matches("docs/file.txt/rtfm")) - } - } - context("any name") { - val pattern = Pattern("docs/*") - - it("not match a non folder") { - assertFalse(pattern.matches("docs")) - } - it("match a sub-file") { - assertTrue(pattern.matches("docs/file")) - } - it("not match a deep hierarchy") { - assertTrue(pattern.matches("docs/sub/file.txt")) - } - } + @Test + fun `wildcard patterns - any name`() { + val pattern = Pattern("docs/*") - context("partial name") { - val pattern = Pattern("/core_*") - - it("match a single file") { - assertTrue(pattern.matches("core_")) - assertTrue(pattern.matches("core_ui/")) - assertTrue(pattern.matches("core_ui.txt")) - } - it("match a sub-file") { - assertTrue(pattern.matches("core_ui/file.txt")) - } - it("not match a deep hierarchy") { - assertFalse(pattern.matches("/tmp/core_ui/file.txt")) - } - } + // not match a non folder + assertFalse(pattern.matches("docs")) + // match a sub-file + assertTrue(pattern.matches("docs/file")) + // not match a deep hierarchy + assertTrue(pattern.matches("docs/sub/file.txt")) + } + + + @Test + fun `wildcard patterns - partial name`() { + val pattern = Pattern("/core_*") + + // match a single file + assertTrue(pattern.matches("core_")) + assertTrue(pattern.matches("core_ui/")) + assertTrue(pattern.matches("core_ui.txt")) + // match a sub-file + assertTrue(pattern.matches("core_ui/file.txt")) + // not match a deep hierarchy + assertFalse(pattern.matches("/tmp/core_ui/file.txt")) } - describe("double wildcard patterns") { + @Test + fun `wildcard patterns - double wildcard patterns`() { // Equals to the same pattern without **/ - describe("prefixed pattern") { + // prefixed pattern + run { val pattern = Pattern("**/docs") - it("match root folder") { - assertTrue(pattern.matches("docs")) - } - it("match a deep hierarchy") { - assertTrue(pattern.matches("my/docs/")) - assertTrue(pattern.matches("my/docs/file.txt")) - } + // match root folder + assertTrue(pattern.matches("docs")) + // match a deep hierarchy + assertTrue(pattern.matches("my/docs/")) + assertTrue(pattern.matches("my/docs/file.txt")) } - describe("suffixed pattern") { + run { + // describe("suffixed pattern val pattern = Pattern("docs/**") - it("not match a non folder") { - assertFalse(pattern.matches("docs")) - } - it("match a sub-file") { - assertTrue(pattern.matches("docs/file")) - assertTrue(pattern.matches("docs/file.txt")) - } - it("match a deep hierarchy") { - assertTrue(pattern.matches("docs/sub/file.txt")) - } + // not match a non folder + assertFalse(pattern.matches("docs")) + // match a sub-file + assertTrue(pattern.matches("docs/file")) + assertTrue(pattern.matches("docs/file.txt")) + // match a deep hierarchy + assertTrue(pattern.matches("docs/sub/file.txt")) } - describe("inside a pattern") { + run { + // describe("inside a pattern val pattern = Pattern("a/**/b") - it("match 0 depth hierarchy") { - assertTrue(pattern.matches("a/b")) - } - it("match n depth hierarchy") { - assertTrue(pattern.matches("a/x/b")) - assertTrue(pattern.matches("a/x/y/b")) - } - it("match sub-tree") { - assertTrue(pattern.matches("a/x/b/y")) - assertTrue(pattern.matches("a/x/y/b/z/x")) - } - it("not match hierarchy inside other folders") { - assertFalse(pattern.matches("x/a/b/y")) - assertFalse(pattern.matches("X/a/y/b/Z")) - } + // match 0 depth hierarchy + assertTrue(pattern.matches("a/b")) + // match n depth hierarchy + assertTrue(pattern.matches("a/x/b")) + assertTrue(pattern.matches("a/x/y/b")) + // match sub-tree + assertTrue(pattern.matches("a/x/b/y")) + assertTrue(pattern.matches("a/x/y/b/z/x")) + // not match hierarchy inside other folders + assertFalse(pattern.matches("x/a/b/y")) + assertFalse(pattern.matches("X/a/y/b/Z")) } - } - describe("range patterns") { + run { - context("partial name") { + // partial name val pattern = Pattern("/core_[a-zA-Z]") - - it("match a single file") { - assertTrue(pattern.matches("core_a")) - assertTrue(pattern.matches("core_b/")) - assertTrue(pattern.matches("core_Z")) - } - it("match a sub-file") { - assertTrue(pattern.matches("core_a/file.txt")) - } + // match a single file + assertTrue(pattern.matches("core_a")) + assertTrue(pattern.matches("core_b/")) + assertTrue(pattern.matches("core_Z")) + // match a sub-file + assertTrue(pattern.matches("core_a/file.txt")) } } -}) +}