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

chore: Make polymer templates dependency optional #1590

Merged
merged 1 commit into from
Dec 30, 2022
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 @@ -13,6 +13,7 @@ import com.github.mvysny.dynatest.DynaTest
import java.net.URL
import java.util.*
import kotlin.test.expect
import com.vaadin.flow.component.button.Button

class AllTests : DynaTest({

Expand Down Expand Up @@ -70,5 +71,9 @@ class AllTests : DynaTest({
shortcutsTestBatch()
}

test("Component.isTemplate does not fail without polymer templates dependency") {
expect(false) { Button("foo").isTemplate }
}


})
2 changes: 2 additions & 0 deletions vaadin-testbench-unit-shared/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@
<groupId>com.vaadin</groupId>
<artifactId>flow-polymer-template</artifactId>
<version>${vaadin.version}</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,8 @@ internal fun HasElement.setChildComponentToSlot(slotName: String, component: Com
element.appendChild(component.element)
}
}

internal fun isPolymerTemplate(component: Component): Boolean {
return polymerTemplateClass != null
&& polymerTemplateClass.isAssignableFrom(component.javaClass);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ package com.vaadin.testbench.unit.internal
import java.util.function.Predicate
import com.vaadin.flow.component.Component
import com.vaadin.flow.component.HasStyle
import com.vaadin.flow.component.HasTheme
import com.vaadin.flow.component.HasValue
import com.vaadin.flow.component.UI
import com.vaadin.flow.component.dialog.Dialog
import com.vaadin.flow.component.polymertemplate.PolymerTemplate
import com.vaadin.flow.router.InternalServerError

/**
Expand Down Expand Up @@ -190,7 +188,7 @@ fun <T: Component> Component._find(clazz: Class<T>, block: SearchSpec<T>.()->Uni
// if there's a PolymerTemplate, warn that UI Unit Testing can't really locate components in there:
// https://github.com/mvysny/karibu-testing/tree/master/karibu-testing-v10#polymer-templates
// fixes https://github.com/mvysny/karibu-testing/issues/35
val hasPolymerTemplates: Boolean = _walkAll().any { it is PolymerTemplate<*> }
val hasPolymerTemplates: Boolean = hasPolymerTemplates() && _walkAll().any { isPolymerTemplate(it) }
if (hasPolymerTemplates) {
message = "$message\nWarning: UI Unit Testing is not able to look up components from inside of PolymerTemplate. Please see https://github.com/mvysny/karibu-testing/tree/master/karibu-testing-v10#polymer-templates for more details."
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
*/
package com.vaadin.testbench.unit.internal

import java.lang.reflect.Method
import com.vaadin.flow.component.Component
import com.vaadin.flow.component.UI
import com.vaadin.flow.component.contextmenu.MenuItemBase
import com.vaadin.flow.component.dialog.Dialog
import com.vaadin.flow.component.grid.Grid
import com.vaadin.flow.component.littemplate.LitTemplate
import com.vaadin.flow.component.menubar.MenuBar
import com.vaadin.flow.component.polymertemplate.PolymerTemplate
import java.lang.reflect.Method

/**
* If you need to hook into the testing lifecycle (e.g. you need to wait for any async operations to finish),
Expand Down Expand Up @@ -80,11 +80,13 @@ interface TestingLifecycleHook {
// also include component.children: https://github.com/mvysny/karibu-testing/issues/76
(component.children.toList() + component.subMenu.items).distinct()
}

component is MenuBar -> {
// don't include virtual children since that would make the MenuItems appear two times.
component.children.toList()
}
component is PolymerTemplate<*> -> {

component.isTemplate -> {
// don't include virtual children since those will include nested components.
// however, those components are only they are only "shallow shells" of components constructed
// server-side - almost none of their properties are transferred to the server-side.
Expand All @@ -93,11 +95,13 @@ interface TestingLifecycleHook {
// See https://github.com/mvysny/karibu-testing/tree/master/karibu-testing-v10#polymer-templates--lit-templates
component.children.toList()
}

component.javaClass.name == "com.vaadin.flow.component.grid.ColumnGroup" -> {
// don't include virtual children since that would include the header/footer components
// which would clash with Grid.Column later on
component.children.toList()
}

component is Grid.Column<*> -> {
// don't include virtual children since that would include the header/footer components
// which would clash with Grid.Column later on
Expand All @@ -108,14 +112,19 @@ interface TestingLifecycleHook {
else -> (component.children.toList() + component._getVirtualChildren()).distinct()
}


companion object {
/**
* A default lifecycle hook that simply runs default implementations of the hook functions.
*/
val default: TestingLifecycleHook get() = object : TestingLifecycleHook {}
val default: TestingLifecycleHook
get() = object : TestingLifecycleHook {}
}
}

val Component.isTemplate: Boolean
get() = this is LitTemplate || isPolymerTemplate(this)

/**
* If you need to hook into the testing lifecycle (e.g. you need to wait for any async operations to finish),
* set your custom implementation here. See [TestingLifecycleHook] for more info on
Expand All @@ -125,9 +134,11 @@ var testingLifecycleHook: TestingLifecycleHook = TestingLifecycleHook.default

private val _ConfirmDialog_Class: Class<*>? = try {
Class.forName("com.vaadin.flow.component.confirmdialog.ConfirmDialog")
} catch (e: ClassNotFoundException) { null }
} catch (e: ClassNotFoundException) {
null
}
private val _ConfirmDialog_isOpened: Method? =
_ConfirmDialog_Class?.getMethod("isOpened")
_ConfirmDialog_Class?.getMethod("isOpened")

/**
* Checks whether given [component] is a dialog and needs to be removed from the UI.
Expand All @@ -138,7 +149,10 @@ private fun isDialogAndNeedsRemoval(component: Component): Boolean {
return true
}
// also support ConfirmDialog. But be careful - this is a Pro component and may not be on classpath.
if (_ConfirmDialog_Class != null && _ConfirmDialog_isOpened != null && _ConfirmDialog_Class.isInstance(component) && !(_ConfirmDialog_isOpened.invoke(component) as Boolean)) {
if (_ConfirmDialog_Class != null && _ConfirmDialog_isOpened != null && _ConfirmDialog_Class.isInstance(
component
) && !(_ConfirmDialog_isOpened.invoke(component) as Boolean)
) {
return true
}
return false
Expand All @@ -154,6 +168,6 @@ fun cleanupDialogs() {
// modal dialog within the UI. This is probably related to the "server-side
// modality curtain" feature. Also see https://github.com/mvysny/karibu-testing/issues/102
UI.getCurrent().walk()
.filter { isDialogAndNeedsRemoval(it) }
.forEach { it.element.removeFromParent() }
.filter { isDialogAndNeedsRemoval(it) }
.forEach { it.element.removeFromParent() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,13 @@ val Servlet.isInitialized: Boolean get() = servletConfig != null

internal fun Class<*>.hasCustomToString(): Boolean =
getMethod("toString").declaringClass != java.lang.Object::class.java

internal val polymerTemplateClass =
try {
Class.forName("com.vaadin.flow.component.polymertemplate.PolymerTemplate")
} catch (ex: ClassNotFoundException) {
null
}

internal fun hasPolymerTemplates() : Boolean = polymerTemplateClass != null

Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright (C) 2022 Vaadin Ltd
*
* This program is available under Commercial Vaadin Developer License
* 4.0 (CVDLv4).
*
*
* For the full License, see <https://vaadin.com/license/cvdl-4.0>.
*/

package com.vaadin.testbench.unit.internal

import kotlin.test.expect
import com.vaadin.flow.component.Tag
import com.vaadin.flow.component.button.Button
import com.vaadin.flow.component.littemplate.LitTemplate
import com.vaadin.flow.component.polymertemplate.PolymerTemplate
import com.vaadin.flow.component.polymertemplate.TemplateParser
import com.vaadin.flow.server.VaadinService
import com.vaadin.flow.templatemodel.TemplateModel
import com.github.mvysny.dynatest.DynaTest
import org.jsoup.nodes.Element

class AllTests : DynaTest({

beforeEach { MockVaadin.setup() }
afterEach { MockVaadin.tearDown() }


test("Component.isTemplate") {
expect(false) { Button("foo").isTemplate }
expect(true) { MyLitTemplate().isTemplate }
expect(true) { MyPolymerTemplate().isTemplate }
}

})

internal interface MyModel : TemplateModel
internal class MyTemplateParser : TemplateParser {
override fun getTemplateContent(
clazz: Class<out PolymerTemplate<*>>?,
tag: String?,
service: VaadinService?
): TemplateParser.TemplateData {
return TemplateParser.TemplateData("", Element(tag))
}

}
@Tag("my-polymer")
internal class MyPolymerTemplate : PolymerTemplate<MyModel>(MyTemplateParser()) {

}
@Tag("my-lit")
internal class MyLitTemplate : LitTemplate()