A nano project to start a Vaadin project. Perfect for Micro-UIs packed as fat jar in a docker image.
The target of this project is a minimal rampup time for a first hello world. Why we need one more HelloWorld? Well, the answer is quite easy. If you have to try something out, or you want to make a small POC to present something, there is no time and budget to create a demo project. You don´t want to copy paste all small things together. Here you will get a Nano-Project that will give you all in a second.
Clone the repo and start editing the class BasicTestUI or BasicTestUIRunner.
Nothing more.
This project will not use any additional maven plugin or technology. Core Kotlin and the Vaadin Dependencies are all that you need to put a Vaadin app into a Servlet-container.
Here we are using the plain meecrowave as Servlet-Container. http://openwebbeans.apache.org/meecrowave/index.html
As mentioned before, there is not additional technology involved. No DI to wire all things together.
But let´s start from the beginning.
The class BasicTestUIRunner will ramp up the Container and
holds the Servlet- and UI- class as inner static classes.
Here all the basic stuff is done. The start will init. a ServletContainer at port 8080.
If you want to use a random port, use randomHttpPort() instead of httpPort = 8080
The WebApp will deployed as ROOT.war.
object BasicTestUIRunner {
@JvmStatic
fun main(args: Array<String>) {
Meecrowave(object : Meecrowave.Builder() {
init {
// randomHttpPort();
httpPort = 8080
isTomcatScanning = true
isTomcatAutoSetup = false
isHttp2 = true
}
})
.bake()
.await()
}
}The Servlet itself will only bind the UI Class to the Vaadin Servlet.
@WebServlet("/*")
@VaadinServletConfiguration(productionMode = false, ui = MyUI::class)
class MyProjectServlet : VaadinServlet()The UI itself will hold the graphical elements.
@PreserveOnRefresh
@Push
class MyUI : UI() {
override fun init(request: VaadinRequest) {
content = BasicTestUI()
}
}After this you can start the app invoking the main-method.
The UI itself is quite easy. There is only a button you can click. For every click, the counter will be increased.
class BasicTestUI : Composite() {
private val button = Button()
private val label = Label()
private var counter = 0
init {
label.id = LABEL_ID
label.value = counter.toString()
button.id = BUTTON_ID
button.caption = BUTTON_ID
button.addClickListener { e -> label.value = (++counter).toString() }
compositionRoot = VerticalLayout(button, label)
}
companion object {
// read http://vaadin.com/testing for more infos
@JvmField val BUTTON_ID = buttonID().apply(BasicTestUI::class.java, "buttonID")
@JvmField val LABEL_ID = buttonID().apply(BasicTestUI::class.java, "labelID")
}
}For testing the Vaadin app, the Open Source project Testbench-NG is used. This is a jUnit5 / Webdriver - manager AddOn for the Selenium and Testbench projects. To read more about it, plase have a look at
https://github.com/vaadin-developer/vaadin-testbench-ng The lates version of Testbench NG is :
The next step is to create a PageObject for the UI. This can be done straight forward.
class BasicTestPageObject(webDriver: WebDriver, containerInfo: ContainerInfo)
: AbstractVaadinPageObject(webDriver, containerInfo) {
fun button(): ButtonElement {
return btn().id(BasicTestUI.BUTTON_ID)
}
fun counterLabel(): LabelElement {
return label().id(BasicTestUI.LABEL_ID)
}
}Now we can start writing logical tests. One could be
@VaadinWebUnitTest
internal class BasicUnitTest {
@Test
fun test001(pageObject: BasicTestPageObject) {
pageObject.loadPage()
Assertions.assertEquals("0", pageObject.counterLabel().text)
pageObject.button().click()
Assertions.assertEquals("1", pageObject.counterLabel().text)
pageObject.screenshot()
}
}This project will give you the basic config for MutationTesting as well. Invoke the maven target pitest:mutationCoverage to create the report. The report itself will be under target/pit-reports
Happy Coding.
if you have any questions: ping me on Twitter https://twitter.com/SvenRuppert or via mail.
