package com.vtence.molecule.middlewares; import com.vtence.molecule.Application; import com.vtence.molecule.Request; import com.vtence.molecule.Response; import com.vtence.molecule.lib.FlashHash; import com.vtence.molecule.session.Session; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutionException; import static com.vtence.molecule.testing.ResponseAssert.assertThat; import static java.util.Collections.emptyMap; import static org.hamcrest.Matchers.aMapWithSize; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; public class FlashTest { Flash flash = new Flash(); Request request = new Request(); Response response = new Response(); Session session = new Session(); @Rule public ExpectedException error = ExpectedException.none(); @Before public void storeEmptyFlash() { session.put(FlashHash.class, new HashMap<>()); session.bind(request); } @Test public void createsFlashHashFromSessionValues() throws Throwable { flashes().put("greeting", "Hello"); flashes().put("farewell", "Goodbye"); flash.connectTo(this::printFlashContent); flash.handle(request, response); assertNoError(); assertThat(response).hasBodyText("{greeting=Hello, farewell=Goodbye}"); } @Test public void complainsIfNoSessionFound() throws Throwable { Session.unbind(request); error.expect(IllegalStateException.class); flash.handle(request, response); } @Test public void createsFreshFlashHashWhenNoneExists() throws Throwable { session.clear(); flash.connectTo(this::printFlashContent); flash.handle(request, response); assertNoError(); assertThat(response).hasBodyText("{}"); } @Test public void storesFreshFlashEntriesInSessionWhenDoneAndForgetAboutOldEntries() throws Throwable { flashes().put("greeting", "Hello"); Map<String, String> freshValues = new HashMap<>(); freshValues.put("farewell", "Goodbye"); flash.connectTo(writeToFlash(freshValues)); flash.handle(request, response); assertThat("old flashes", flashes(), nullValue()); response.done(); assertNoError(); assertThat("fresh flashes count", flashes(), aMapWithSize(1)); assertThat("fresh flashes", flashes(), hasEntry("farewell", "Goodbye")); } @Test public void doesNotWriteEmptyFlashToSession() throws Throwable { flash.connectTo(writeToFlash(emptyMap())); flash.handle(request, response); response.done(); assertNoError(); assertThat("done flashes", flashes(), nullValue()); } @Test public void unbindsFlashFromRequestOnceDone() throws Throwable { flash.handle(request, response); response.done(); assertNoError(); assertThat("flash", FlashHash.get(request), nullValue()); } @Test public void unbindsFlashFromRequestWhenExceptionOccurs() throws Throwable { flash.connectTo(crashWith(new Exception("Internal error!"))); error.expectMessage("Internal error!"); try { flash.handle(request, response); } finally { assertThat("flash", FlashHash.get(request), nullValue()); } } @Test public void unbindsFlashFromRequestInCaseOfDeferredErrorAsWell() throws Throwable { flash.handle(request, response); response.done(new Exception("Internal error!")); assertThat("flash", FlashHash.get(request), nullValue()); } @Test public void complainsIfSessionRemovedDuringProcessing() throws Throwable { flash.connectTo((request, response) -> Session.unbind(request)); error.expect(IllegalStateException.class); response.done(); flash.handle(request, response); awaitCompletion(); } private Application crashWith(Exception error) { return (request, response) -> { throw error; }; } private Application writeToFlash(Map<String, String> values) { return (request, response) -> { FlashHash flash = FlashHash.get(request); assertThat("request flash", flash, notNullValue()); flash.putAll(values); }; } private void printFlashContent(Request request, Response response) throws Exception { FlashHash flash = FlashHash.get(request); assertThat("request flash", flash, notNullValue()); response.done(flash.toMap().toString()); } private Map<String, String> flashes() { return session.get(FlashHash.class); } private void assertNoError() throws Throwable { awaitCompletion(); } private void awaitCompletion() throws Throwable { try { response.await(); } catch (ExecutionException e) { throw e.getCause(); } } }