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>
<version>1.7.30</version>
</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>
<build>

View File

@ -12,13 +12,12 @@ data class Dependency(
val name: String,
val groupId: String,
val artifactId: String,
val version: String,
val version: Version,
val default: Boolean,
val category: Category,
val scope: Scope,
val logger: String?,
val repository: String?,
val versionKey: String,
val repository: Repository?,
)
data class Repository(val name: String, val url: String)
@ -30,7 +29,7 @@ data class Project(
val basePackage: String,
val inputs: List<Input>,
val dependencies: List<Dependency>,
val repositories: List<Repository>,
val repositories: Collection<Repository>,
)
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(
val dependencies: List<Dependency>,
val inputs: List<Input>,
val repositories: List<Repository>,
)
class Config {
@ -23,22 +22,29 @@ class Config {
@Suppress("UNCHECKED_CAST")
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")
.map { (name, values) ->
val versionKey: String = values["version"] ?: 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(
name,
values["groupId"],
values["artifactId"],
version,
values.getOrElse("default", false),
values.getEnumOrElse("category", Category.Other),
values.getEnumOrElse("scope", Scope.Compile),
values["logger"],
values["repository"],
versionKey
name = name,
groupId = values["groupId"],
artifactId = values["artifactId"],
version = Version(versionKey, version),
default = values.getOrElse("default", false),
category = values.getEnumOrElse("category", Category.Other),
scope = values.getEnumOrElse("scope", Scope.Compile),
logger = values["logger"],
repository = repo,
)
}
@ -47,11 +53,6 @@ class Config {
Input(name, values["display"], values["default"])
}
val repositories = cfg.configMap("repositories")
.map { (name, values) ->
Repository(name, values["url"])
}
return StarterConfig(dependencies, inputs, repositories)
return StarterConfig(dependencies, inputs)
}
}

View File

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

View File

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

View File

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