1
0

Refactor models + add tests

This commit is contained in:
Hubert Van De Walle 2020-10-06 21:40:12 +02:00
parent 6c0d17299e
commit bb5e955318
8 changed files with 159 additions and 27 deletions

13
pom.xml
View File

@ -57,6 +57,19 @@
<artifactId>slf4j-simple</artifactId> <artifactId>slf4j-simple</artifactId>
<version>1.7.30</version> <version>1.7.30</version>
</dependency> </dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.17.2</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -12,13 +12,12 @@ data class Dependency(
val name: String, val name: String,
val groupId: String, val groupId: String,
val artifactId: String, val artifactId: String,
val version: String, val version: Version,
val default: Boolean, val default: Boolean,
val category: Category, val category: Category,
val scope: Scope, val scope: Scope,
val logger: String?, val logger: String?,
val repository: String?, val repository: Repository?,
val versionKey: String,
) )
data class Repository(val name: String, val url: String) data class Repository(val name: String, val url: String)
@ -30,7 +29,7 @@ data class Project(
val basePackage: String, val basePackage: String,
val inputs: List<Input>, val inputs: List<Input>,
val dependencies: List<Dependency>, val dependencies: List<Dependency>,
val repositories: List<Repository>, val repositories: Collection<Repository>,
) )
data class Version(val name: String, val value: String) data class Version(val name: String, val value: String)

View File

@ -8,7 +8,6 @@ import com.electronwill.nightconfig.core.Config as NightConfig
data class StarterConfig( data class StarterConfig(
val dependencies: List<Dependency>, val dependencies: List<Dependency>,
val inputs: List<Input>, val inputs: List<Input>,
val repositories: List<Repository>,
) )
class Config { class Config {
@ -23,22 +22,29 @@ class Config {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val versions = cfg.get<UnmodifiableConfig>("versions").valueMap() as Map<String, String> val versions = cfg.get<UnmodifiableConfig>("versions").valueMap() as Map<String, String>
val repositories = cfg.configMap("repositories")
.map { (name, values) ->
Repository(name, values["url"])
}
val dependencies = cfg.configMap("dependencies") val dependencies = cfg.configMap("dependencies")
.map { (name, values) -> .map { (name, values) ->
val versionKey: String = values["version"] ?: name val versionKey: String = values["version"] ?: name
val version = versions[versionKey] ?: error("Missing version for $name") val version = versions[versionKey] ?: error("Missing version for $name")
val repositoryName: String? = values["repository"]
val repo = repositoryName?.let { repoName -> repositories.find { it.name == repoName } }
Dependency( Dependency(
name, name = name,
values["groupId"], groupId = values["groupId"],
values["artifactId"], artifactId = values["artifactId"],
version, version = Version(versionKey, version),
values.getOrElse("default", false), default = values.getOrElse("default", false),
values.getEnumOrElse("category", Category.Other), category = values.getEnumOrElse("category", Category.Other),
values.getEnumOrElse("scope", Scope.Compile), scope = values.getEnumOrElse("scope", Scope.Compile),
values["logger"], logger = values["logger"],
values["repository"], repository = repo,
versionKey
) )
} }
@ -47,11 +53,6 @@ class Config {
Input(name, values["display"], values["default"]) Input(name, values["display"], values["default"])
} }
val repositories = cfg.configMap("repositories") return StarterConfig(dependencies, inputs)
.map { (name, values) ->
Repository(name, values["url"])
}
return StarterConfig(dependencies, inputs, repositories)
} }
} }

View File

@ -37,7 +37,7 @@ class DepAsXmlPebbleFunction : PebbleFunction {
|${startTag("dependency")} |${startTag("dependency")}
| ${tag("groupId", dep.groupId)} | ${tag("groupId", dep.groupId)}
| ${tag("artifactId", dep.artifactId)} | ${tag("artifactId", dep.artifactId)}
| ${tag("version", dep.version)} | ${tag("version", dep.version.value)}
|${endTag("dependency")} |${endTag("dependency")}
""".trimMargin() """.trimMargin()

View File

@ -38,9 +38,7 @@ class ZipRouteSupplier(
if (basePackage.contains("/") || basePackage.contains("..")) { if (basePackage.contains("/") || basePackage.contains("..")) {
Response.badRequest() Response.badRequest()
} else { } else {
val repositories = conf.repositories val repositories = deps.mapNotNull { it.repository }.toSet()
.filter { repo -> repo.name in deps.mapNotNull { it.repository } }
val project = Project(projectName, basePackage, inputs, deps, repositories) val project = Project(projectName, basePackage, inputs, deps, repositories)
val outputStream = projectZip.createZip(project) val outputStream = projectZip.createZip(project)

View File

@ -14,7 +14,7 @@ class PomTemplate(private val engine: PebbleEngine) : Template {
"dependencies" to project.dependencies.sortedBy { it.scope }, "dependencies" to project.dependencies.sortedBy { it.scope },
"repositories" to project.repositories, "repositories" to project.repositories,
"kotlinxSerialization" to project.dependencies.any { it.name == "kotlinx-serialization" }, "kotlinxSerialization" to project.dependencies.any { it.name == "kotlinx-serialization" },
"versions" to project.dependencies.map { Version(name = it.versionKey, value = it.version) }.toSet() "versions" to project.dependencies.map { it.version }.toSet()
) )
project.inputs.forEach { project.inputs.forEach {

View File

@ -8,7 +8,7 @@
<dependency> <dependency>
<groupId>{{ dep.groupId }}</groupId> <groupId>{{ dep.groupId }}</groupId>
<artifactId>{{ dep.artifactId }}</artifactId> <artifactId>{{ dep.artifactId }}</artifactId>
<version>{{ "${" }}{{ dep.versionKey }}{{ ".version}" }}</version> <version>{{ "${" }}{{ dep.version.name }}{{ ".version}" }}</version>
{% if dep.scope == "Test" %} {% if dep.scope == "Test" %}
<scope>test</scope> <scope>test</scope>
{% endif %} {% endif %}

View File

@ -0,0 +1,121 @@
package starter.templates
import org.assertj.core.api.Assertions.assertThat
import org.intellij.lang.annotations.Language
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.koin.dsl.koinApplication
import org.w3c.dom.Node
import org.w3c.dom.NodeList
import starter.Project
import starter.config.StarterConfig
import starter.modules.mainModule
import starter.modules.pebbleModule
import starter.modules.templateModule
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.xpath.XPathConstants
import javax.xml.xpath.XPathFactory
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
internal class PomTemplateTest {
private val koin = koinApplication {
modules(mainModule, pebbleModule, templateModule)
}.koin
private val pomTemplate = koin.get<PomTemplate>()
private val conf = koin.get<StarterConfig>()
private val project = Project(
name = "Test",
basePackage = "org.test",
inputs = conf.inputs,
dependencies = conf.dependencies,
repositories = conf.dependencies.mapNotNull { it.repository }.toSet()
)
private val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
private val xPath = XPathFactory.newInstance().newXPath()
// region xml utils
private fun String.extract(expression: String): String {
val doc = docBuilder.parse(this.byteInputStream())
xPath.compile(expression).evaluate(doc, XPathConstants.NODESET)
return xPath.compile(expression).evaluate(doc)
}
private fun <T> String.extractAll(expression: String, mapper: (Node) -> T): List<T> {
val doc = docBuilder.parse(this.byteInputStream())
val res = xPath.compile(expression).evaluate(doc, XPathConstants.NODESET) as NodeList
return res.asList().map(mapper)
}
private fun NodeList.asList(): List<Node> = (0 until length).map { item(it) }
// endregion
@Test
fun javaVersion() {
val xml = pomTemplate.render(project)
assertThat(xml.extract("/project/properties/java.version"))
.isEqualTo(project.inputs.find { it.name == "javaVersion" }?.value)
println(xml)
}
@Test
fun dependencies() {
val xml = pomTemplate.render(project)
val deps = xml.extractAll("/project/dependencies/dependency") {
val map = it.childNodes.asList()
.filter { it.nodeType == Node.ELEMENT_NODE }
.associate { it.nodeName to it.firstChild.nodeValue }
Triple(map["groupId"]!!, map["artifactId"]!!, map["version"]!!)
}.filterNot { it.second == "kotlin-stdlib-jdk8" }
println(deps.joinToString("\n"))
val expectedDependencies = project.dependencies
.map { Triple(it.groupId, it.artifactId, "\${" + it.version.name + ".version}") }
assertThat(expectedDependencies).containsExactlyInAnyOrderElementsOf(deps)
}
@Test
fun versions() {
val xml = pomTemplate.render(project)
val versions = xml.extractAll("/project/properties") {
it.childNodes.asList()
.filter { it.nodeType == Node.ELEMENT_NODE }
.filter { it.nodeName.endsWith(".version") }
.filterNot { it.nodeName in listOf("java.version", "kotlin.version") }
.associate { it.nodeName.substringBefore(".version") to it.firstChild.nodeValue }
}.first()
val expected = project.dependencies.associate { it.version.name to it.version.value }
assertThat(versions).containsExactlyInAnyOrderEntriesOf(expected)
println(versions)
}
@Test
fun kotlinxSerialization() {
val xml = pomTemplate.render(project)
@Language("XPath")
val kotlinMavenPlugin = "/project/build/plugins/plugin[artifactId='kotlin-maven-plugin']"
val kotlinxPlugin = "$kotlinMavenPlugin/configuration/compilerPlugins/plugin"
assertThat(xml.extract(kotlinxPlugin))
.isEqualTo("kotlinx-serialization")
val kotlinxPluginDep = "$kotlinMavenPlugin/dependencies/dependency/artifactId"
assertThat(xml.extract(kotlinxPluginDep))
.isEqualTo("kotlin-maven-serialization")
}
}