fix(ui): fit quest board dialogs on screen
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
package games.dmg.spigotquestboard;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Clock;
|
||||
@@ -16,6 +19,144 @@ import org.junit.jupiter.api.Test;
|
||||
final class QuestBoardDialogUiTest {
|
||||
private static final Instant NOW = Instant.parse("2026-09-05T03:00:00Z");
|
||||
|
||||
@Test
|
||||
void dashboardUsesCompactDedicatedNavigableScreens() {
|
||||
RecordingCreator creator = new RecordingCreator(false);
|
||||
QuestBoardDialogUi ui = new QuestBoardDialogUi(
|
||||
creator, now -> List.of(creator.quest(NOW)), Clock.fixed(NOW, ZoneOffset.UTC)
|
||||
);
|
||||
|
||||
QuestBoardDialogSpec specification = ui.specification(mock(Player.class));
|
||||
|
||||
assertEquals(420, specification.maximumBodyWidth());
|
||||
assertEquals(List.of("Browse quests", "Create quest", "Pending claims"),
|
||||
specification.dashboardActions());
|
||||
assertEquals(1, specification.questEntries().size());
|
||||
org.junit.jupiter.api.Assertions.assertTrue(
|
||||
specification.questEntries().getFirst().hasBackAction()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void dedicatedScreensKeepContentSeparateAndProvideBackNavigation() {
|
||||
RecordingCreator creator = new RecordingCreator(false);
|
||||
QuestBoardDialogUi ui = new QuestBoardDialogUi(
|
||||
creator, now -> List.of(creator.quest(NOW)), null, null, player ->
|
||||
new ClaimCollectionResult(0, 0), Clock.fixed(NOW, ZoneOffset.UTC)
|
||||
);
|
||||
|
||||
QuestBoardDialogSpec specification = ui.specification(mock(Player.class));
|
||||
|
||||
assertEquals("Choose what you want to do.", specification.dashboard().message());
|
||||
assertTrue(specification.browse().message().contains("Select a quest"));
|
||||
assertTrue(specification.create().message().contains("reward in your main hand"));
|
||||
assertEquals("No pending claims.", specification.claims().message());
|
||||
assertFalse(specification.dashboard().hasBackAction());
|
||||
assertTrue(specification.browse().hasBackAction());
|
||||
assertTrue(specification.create().hasBackAction());
|
||||
assertTrue(specification.claims().hasBackAction());
|
||||
assertTrue(specification.questEntries().stream().allMatch(
|
||||
QuestBoardDialogSpec.QuestEntry::hasBackAction
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
void questDetailsShowRequiredContentAndRouteAvailableActions() {
|
||||
RecordingCreator creator = new RecordingCreator(false);
|
||||
Quest quest = creator.quest(NOW);
|
||||
Player issuer = mock(Player.class);
|
||||
when(issuer.getUniqueId()).thenReturn(quest.issuerId());
|
||||
QuestBoardDialogUi ui = new QuestBoardDialogUi(
|
||||
creator, now -> List.of(quest), new RecordingCompleter(), new RecordingCanceller(),
|
||||
null, Clock.fixed(NOW, ZoneOffset.UTC)
|
||||
);
|
||||
|
||||
QuestBoardDialogSpec specification = ui.specification(issuer);
|
||||
QuestBoardDialogSpec.QuestEntry entry = specification.questEntries().getFirst();
|
||||
|
||||
assertTrue(entry.message().contains("64 × STONE"));
|
||||
assertTrue(entry.message().contains("Reward: 1 × DIAMOND"));
|
||||
assertTrue(entry.message().contains("Issuer: Issuer"));
|
||||
assertTrue(entry.message().contains("Time remaining: 7d"));
|
||||
assertEquals(
|
||||
List.of(QuestBoardDialogSpec.Route.COMPLETE, QuestBoardDialogSpec.Route.CANCEL),
|
||||
entry.actions().stream().map(QuestBoardDialogSpec.Action::route).toList()
|
||||
);
|
||||
assertTrue(entry.actions().stream().allMatch(
|
||||
action -> quest.id().toString().equals(action.questId())
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
void dashboardCreationAndClaimsDeclareTheirActionRoutesAndInputs() {
|
||||
RecordingCreator creator = new RecordingCreator(false);
|
||||
QuestBoardDialogUi ui = new QuestBoardDialogUi(
|
||||
creator, now -> List.of(), null, null, player ->
|
||||
new ClaimCollectionResult(0, 0), Clock.fixed(NOW, ZoneOffset.UTC)
|
||||
);
|
||||
|
||||
QuestBoardDialogSpec specification = ui.specification(mock(Player.class));
|
||||
|
||||
assertEquals(
|
||||
List.of(
|
||||
QuestBoardDialogSpec.Route.OPEN_BROWSE,
|
||||
QuestBoardDialogSpec.Route.OPEN_CREATE,
|
||||
QuestBoardDialogSpec.Route.OPEN_CLAIMS
|
||||
),
|
||||
specification.dashboard().actions().stream()
|
||||
.map(QuestBoardDialogSpec.Action::route)
|
||||
.toList()
|
||||
);
|
||||
assertEquals(List.of("requested_material", "requested_quantity"),
|
||||
specification.create().inputs().stream()
|
||||
.map(QuestBoardDialogSpec.Input::key)
|
||||
.toList());
|
||||
assertEquals(QuestBoardDialogSpec.Route.SUBMIT_CREATE,
|
||||
specification.create().actions().getFirst().route());
|
||||
assertEquals(QuestBoardDialogSpec.Route.COLLECT,
|
||||
specification.claims().actions().getFirst().route());
|
||||
}
|
||||
|
||||
@Test
|
||||
void largeQuestCollectionsRemainIndividualNavigableEntries() {
|
||||
RecordingCreator creator = new RecordingCreator(false);
|
||||
List<Quest> quests = java.util.stream.IntStream.range(0, 250)
|
||||
.mapToObj(index -> new Quest(
|
||||
new UUID(0, index + 100L), new UUID(0, index + 1L), "Issuer " + index,
|
||||
"STONE", index + 1, List.of(new EscrowItem("DIAMOND", 1, null)),
|
||||
NOW, NOW.plusSeconds(604800)
|
||||
))
|
||||
.toList();
|
||||
QuestBoardDialogUi ui = new QuestBoardDialogUi(
|
||||
creator, now -> quests, Clock.fixed(NOW, ZoneOffset.UTC)
|
||||
);
|
||||
|
||||
QuestBoardDialogSpec specification = ui.specification(mock(Player.class));
|
||||
|
||||
assertEquals(250, specification.questEntries().size());
|
||||
assertTrue(specification.questEntries().stream().allMatch(
|
||||
QuestBoardDialogSpec.QuestEntry::hasBackAction
|
||||
));
|
||||
assertFalse(specification.browse().message().contains(quests.getLast().id().toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonIssuersCannotReceiveCancellationRoutes() {
|
||||
RecordingCreator creator = new RecordingCreator(false);
|
||||
Player player = mock(Player.class);
|
||||
when(player.getUniqueId()).thenReturn(UUID.randomUUID());
|
||||
QuestBoardDialogUi ui = new QuestBoardDialogUi(
|
||||
creator, now -> List.of(creator.quest(NOW)), new RecordingCompleter(),
|
||||
new RecordingCanceller(), Clock.fixed(NOW, ZoneOffset.UTC)
|
||||
);
|
||||
|
||||
QuestBoardDialogSpec.QuestEntry entry = ui.specification(player)
|
||||
.questEntries().getFirst();
|
||||
|
||||
assertEquals(List.of(QuestBoardDialogSpec.Route.COMPLETE),
|
||||
entry.actions().stream().map(QuestBoardDialogSpec.Action::route).toList());
|
||||
}
|
||||
|
||||
@Test
|
||||
void disabledPlayerCommandsDoNotGateBoardUiGateways() throws Exception {
|
||||
PlayerCommandSettings settings = new PlayerCommandSettings(
|
||||
|
||||
Reference in New Issue
Block a user