package org.tessell.tests.model.commands; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import org.junit.Test; import org.tessell.dispatch.client.util.OutstandingDispatchAsync; import org.tessell.dispatch.client.util.StubOutstandingDispatchAsync; import org.tessell.dispatch.shared.Action; import org.tessell.dispatch.shared.Result; import org.tessell.model.commands.DispatchUiCommand; import org.tessell.tests.model.validation.rules.AbstractRuleTest; public class DispatchUiCommandTest extends AbstractRuleTest { final StubOutstandingDispatchAsync async = new StubOutstandingDispatchAsync(); @Test public void activeIsTrueThenFalseWhenRpcIsSuccessful() { DummyUiCommand command = new DummyUiCommand(async); assertThat(command.active().get(), is(FALSE)); assertThat(async.hasAnyOutstanding(), is(false)); command.execute(); assertThat(command.active().get(), is(TRUE)); assertThat(async.hasAnyOutstanding(), is(true)); async.getCalls().get(0).onSuccess(null); assertThat(command.active().get(), is(FALSE)); assertThat(async.hasAnyOutstanding(), is(false)); } @Test public void activeIsTrueThenFalseWhenRpcFails() { DummyUiCommand command = new DummyUiCommand(async); assertThat(command.active().get(), is(FALSE)); assertThat(async.hasAnyOutstanding(), is(false)); command.execute(); assertThat(command.active().get(), is(TRUE)); assertThat(async.hasAnyOutstanding(), is(true)); async.getCalls().get(0).onFailure(null); assertThat(command.active().get(), is(FALSE)); assertThat(async.hasAnyOutstanding(), is(false)); } @Test public void allowsReExecution() { DummyUiCommand command = new DummyUiCommand(async); // initial execute is fine command.execute(); assertThat(command.createActionCalls, is(1)); command.execute(); assertThat(command.createActionCalls, is(2)); // when the first response finally comes back async.getCalls().get(0).onSuccess(null); // it calls onResult assertThat(command.onResultCalls, is(1)); // but it could tell it was a stale result assertThat(command.hasNewerAction, is(true)); // but not out of order assertThat(command.hasNewerResult, is(false)); // note that the command is still active assertThat(command.active().get(), is(true)); // and when the second response comes back async.getCalls().get(1).onSuccess(null); // it also calls onResult assertThat(command.onResultCalls, is(2)); // and this result was not stale assertThat(command.hasNewerAction, is(false)); // nor out of order assertThat(command.hasNewerResult, is(false)); } @Test public void handlesOutOfOrderResponses() { DummyUiCommand command = new DummyUiCommand(async); // initial execute is fine command.execute(); assertThat(command.createActionCalls, is(1)); command.execute(); assertThat(command.createActionCalls, is(2)); // now the 2nd request completes first async.getCalls().get(1).onSuccessOutOfOrder(null); // it calls onResult assertThat(command.onResultCalls, is(1)); // and it was not a stale result assertThat(command.hasNewerAction, is(false)); // nor out of order (yet) assertThat(command.hasNewerResult, is(false)); // we consider the command no longer active? assertThat(command.active().get(), is(false)); // and now the 1st request is responded to async.getCalls().get(0).onSuccess(null); // it also calls onResult assertThat(command.onResultCalls, is(2)); // but it could tell is was stale assertThat(command.hasNewerAction, is(true)); // and also out of order assertThat(command.hasNewerResult, is(true)); } @Test public void activeIsSetFalseBeforeOnResultIsRan() { DummyUiCommand command = new DummyUiCommand(async); command.execute(); async.getCalls().get(0).onSuccess(null); assertThat(command.wasActiveInOnResult, is(false)); } /** Fails depending on the instance variable {@code fail}. */ private final class DummyUiCommand extends DispatchUiCommand<Action<Result>, Result> { private int createActionCalls = 0; private int onResultCalls = 0; private boolean hasNewerAction = false; private boolean hasNewerResult = false; private boolean wasActiveInOnResult; public DummyUiCommand(OutstandingDispatchAsync async) { super(async); } @Override protected Action<Result> createAction() { createActionCalls++; return new Action<Result>() { }; } @Override protected void onResult() { hasNewerAction = hasNewerActionBeenSent(); hasNewerResult = hasNewerResultBeenReceived(); wasActiveInOnResult = active().get(); onResultCalls++; } } }