Skip to content

Commit

Permalink
Define MockVaadin.tearDown() when UI.access{} throws; test for follow…
Browse files Browse the repository at this point in the history
…-up MockVaadin.tearDown() not affected
  • Loading branch information
mvysny committed Aug 13, 2024
1 parent b20c82a commit 5c76f04
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicReference
import java.util.concurrent.locks.ReentrantReadWriteLock
import javax.servlet.http.Cookie
import java.util.concurrent.ExecutionException
import kotlin.concurrent.read
import kotlin.concurrent.thread
import kotlin.concurrent.write
Expand Down Expand Up @@ -149,6 +150,22 @@ internal fun DynaNodeGroup.mockVaadinTest() {
expect(1, "detach should be called exactly once") { detachCalled }
expect(1, "detach should be called exactly once") { vldetachCalled }
}

test("tearDown() runs UI.access{} blocks") {
var called = 0
UI.getCurrent().access { called++ }
expect(0) { called }
MockVaadin.tearDown()
expect(1) { called }
}

test("when UI.access{} throws, follow-up setup() shouldn't be affected") {
UI.getCurrent().access { throw RuntimeException("Simulated") }
expectThrows<ExecutionException>("Simulated") {
MockVaadin.tearDown()
}
MockVaadin.setup()
}
}

group("proper mocking") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ public object MockVaadin {
}
check(!VaadinMeta.isCompatibilityMode)

// disable the Page.reload() detection if tearDown() was not called.
lastUILocation.remove()

// initialize servlet if necessary
if (!servlet.isInitialized) {
val ctx: ServletContext = MockVaadinHelper.createMockContext()
servlet.init(FakeServletConfig(ctx))
Expand Down Expand Up @@ -131,44 +135,57 @@ public object MockVaadin {
* should you forget to call [setup] properly.
*
* You don't have to call this function though; [setup] will overwrite any current UI/Session instances with a fresh ones.
*
* Any exceptions thrown by listeners such as UI detach listener, or session/service destroy listeners, or scheduled calls
* to [UI.access] will be propagated and thrown by this function.
*/
@JvmStatic
public fun tearDown() {
clearVaadinInstances(false)
try {
clearVaadinInstances(false)
} finally {
lastUILocation.remove()
}
val service: VaadinService? = VaadinService.getCurrent()
if (service != null) {
service.fireServiceDestroyListeners(ServiceDestroyEvent(service))
VaadinService.setCurrent(null)
}
lastUILocation.remove()
}

private fun clearVaadinInstances(fireUIDetach: Boolean) {
closeCurrentUI(fireUIDetach)
closeCurrentSession()
CurrentInstance.set(VaadinRequest::class.java, null)
CurrentInstance.set(VaadinResponse::class.java, null)
strongRefReq.remove()
strongRefRes.remove()
try {
closeCurrentUI(fireUIDetach)
closeCurrentSession()
} finally {
CurrentInstance.set(VaadinRequest::class.java, null)
CurrentInstance.set(VaadinResponse::class.java, null)
strongRefReq.remove()
strongRefRes.remove()
}
}

/**
* Closes current session if [VaadinSession.getCurrent] is not null.
*/
private fun closeCurrentSession() {
val session: VaadinSession? = VaadinSession.getCurrent()
strongRefSession.remove()
if (session != null) {
val service: VaadinService = VaadinService.getCurrent()
service.fireSessionDestroy(session)
VaadinSession.setCurrent(null)
// service destroys session via session.access(); we need to run that action now.
currentlyClosingSession.set(true)
runUIQueue(session = session)
currentlyClosingSession.set(false)
try {
runUIQueue(session = session)
} finally {
currentlyClosingSession.set(false)
}
}
strongRefSession.remove()
}

private val currentlyClosingSession: ThreadLocal<Boolean> = object : ThreadLocal<Boolean>() {
override fun initialValue(): Boolean = false
}
private val currentlyClosingSession: ThreadLocal<Boolean> = ThreadLocal.withInitial { false }

/**
* Change & call [setup] to set a different browser.
Expand Down

0 comments on commit 5c76f04

Please sign in to comment.