mvysny / karibu-testing

Vaadin Server-Side Browserless Containerless Unit Testing
Apache License 2.0
111 stars 14 forks source link

Running notification tests on Vaadin 23.0.10 and 23.1.0.rc1+ fails #113

Closed mvysny closed 2 years ago

mvysny commented 2 years ago

The following exception is thrown:

Trying to detach an element from parent that does not have it.
java.lang.IllegalArgumentException: Trying to detach an element from parent that does not have it.
    at com.vaadin.flow.dom.impl.AbstractNodeStateProvider.removeChild(AbstractNodeStateProvider.java:125)
    at com.vaadin.flow.dom.Node.removeChild(Node.java:377)
    at com.vaadin.flow.dom.Element.removeFromParent(Element.java:515)
    at com.vaadin.flow.component.notification.Notification.removeAutoAdded(Notification.java:218)
    at com.vaadin.flow.component.notification.Notification.lambda$initBaseElementsAndListeners$9b1b5227$1(Notification.java:208)
    at com.vaadin.flow.component.ComponentEventBus.fireEventForListener(ComponentEventBus.java:206)
    at com.vaadin.flow.component.ComponentEventBus.fireEvent(ComponentEventBus.java:195)
    at com.vaadin.flow.component.Component.fireEvent(Component.java:378)
    at com.vaadin.flow.component.ComponentUtil.fireEvent(ComponentUtil.java:401)
    at com.vaadin.flow.component.ComponentUtil.onComponentDetach(ComponentUtil.java:263)
    at java.base/java.util.Optional.ifPresent(Optional.java:183)
    at com.vaadin.flow.internal.nodefeature.ComponentMapping.onDetach(ComponentMapping.java:109)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
    at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
    at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
    at com.vaadin.flow.internal.StateNode.forEachFeature(StateNode.java:358)
    at com.vaadin.flow.internal.StateNode.fireDetachListeners(StateNode.java:856)
    at com.vaadin.flow.internal.StateNode.onDetach(StateNode.java:342)
    at com.vaadin.flow.internal.StateNode.setParent(StateNode.java:281)
    at com.vaadin.flow.internal.nodefeature.NodeFeature.detatchPotentialChild(NodeFeature.java:97)
    at com.vaadin.flow.internal.nodefeature.StateNodeNodeList.remove(StateNodeNodeList.java:67)
    at com.vaadin.flow.internal.nodefeature.ElementChildrenList.remove(ElementChildrenList.java:54)
    at com.vaadin.flow.dom.impl.AbstractNodeStateProvider.removeChild(AbstractNodeStateProvider.java:128)
    at com.vaadin.flow.dom.Node.removeChild(Node.java:377)
    at com.vaadin.flow.component.HasComponents.lambda$remove$0(HasComponents.java:98)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
    at com.vaadin.flow.component.HasComponents.remove(HasComponents.java:98)
    at com.github.mvysny.kaributools.ComponentUtilsKt.removeFromParent(ComponentUtils.kt:80)
    at com.github.mvysny.kaributesting.v10.NotificationsKt.clearNotifications(Notifications.kt:51)
    at com.github.mvysny.kaributesting.v10.NotificationsKt.expectNotifications(Notifications.kt:37)
    at com.github.mvysny.kaributesting.v10.NotificationsTestKt$notificationsTests$5.invoke(NotificationsTest.kt:47)
    at com.github.mvysny.kaributesting.v10.NotificationsTestKt$notificationsTests$5.invoke(NotificationsTest.kt:45)
    at com.github.mvysny.dynatest.engine.DynaNodeTestDescriptor$runTest$1.invoke(DynaTestEngine.kt:226)
    at com.github.mvysny.dynatest.engine.DynaNodeTestDescriptor$runTest$1.invoke(DynaTestEngine.kt:226)
    at com.github.mvysny.dynatest.engine.DynaNodeTestDescriptor.runBlock(DynaTestEngine.kt:216)
    at com.github.mvysny.dynatest.engine.DynaNodeTestDescriptor.runTest(DynaTestEngine.kt:226)
    at com.github.mvysny.dynatest.engine.DynaTestEngine.execute$runAllTests(DynaTestEngine.kt:126)
    at com.github.mvysny.dynatest.engine.DynaTestEngine.execute$runAllTests(DynaTestEngine.kt:122)
    at com.github.mvysny.dynatest.engine.DynaTestEngine.execute$runAllTests(DynaTestEngine.kt:122)
    at com.github.mvysny.dynatest.engine.DynaTestEngine.execute$runAllTests(DynaTestEngine.kt:122)
    at com.github.mvysny.dynatest.engine.DynaTestEngine.execute$runAllTests(DynaTestEngine.kt:122)
    at com.github.mvysny.dynatest.engine.DynaTestEngine.execute(DynaTestEngine.kt:137)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at com.sun.proxy.$Proxy2.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

\me: investigate :)

mvysny commented 2 years ago

No idea what's going on. The Notifications use some clever deferredJob/.beforeClientResponse() combo to attach itself for some reason (see the Notification constructor for more details). However, Karibu-Testing is running those blocks from MockVaadin.clientRoundtrip() so everything should work correctly. And it does in Vaadin 23.0.9 and 23.1.0.beta2; however once you upgrade to Vaadin 23.0.10 and 23.1.0.rc1 then notifications will break for some reason.

Artur- commented 2 years ago

Related to https://github.com/vaadin/flow-components/pull/3154 ?

mvysny commented 2 years ago

Thank you, let me investigate

mvysny commented 2 years ago

The workaround is to only consider notifications which are opened. The https://github.com/vaadin/flow-components/pull/3154 looks innocent in this case... no idea. Implementing workaround.