From 5a0cf32494e62607885f941dcbf452317bcc9f03 Mon Sep 17 00:00:00 2001 From: Matthew Trew Date: Wed, 27 Aug 2025 15:56:32 +0200 Subject: [PATCH 1/4] Load gameboard question limit from config --- .../uk/ac/cam/cl/dtg/isaac/api/Constants.java | 5 ---- .../dtg/isaac/api/managers/GameManager.java | 24 ++++++++++++------- .../uk/ac/cam/cl/dtg/segue/api/Constants.java | 2 ++ .../api/AbstractIsaacIntegrationTest.java | 2 +- .../isaac/api/managers/GameManagerTest.java | 11 ++++++++- .../segue-integration-test-config.yaml | 2 ++ 6 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/main/java/uk/ac/cam/cl/dtg/isaac/api/Constants.java b/src/main/java/uk/ac/cam/cl/dtg/isaac/api/Constants.java index c9aa4771bb..3787c93aa5 100644 --- a/src/main/java/uk/ac/cam/cl/dtg/isaac/api/Constants.java +++ b/src/main/java/uk/ac/cam/cl/dtg/isaac/api/Constants.java @@ -65,11 +65,6 @@ public final class Constants { public static final Set SEARCHABLE_DOC_TYPES = ImmutableSet.of( QUESTION_TYPE, FAST_TRACK_QUESTION_TYPE, CONCEPT_TYPE, TOPIC_SUMMARY_PAGE_TYPE, BOOK_INDEX_TYPE, BOOK_DETAIL_TYPE, PAGE_TYPE, EVENT_TYPE); - /* - * Game specific variables. - */ - public static final int GAME_BOARD_TARGET_SIZE = 10; - public enum CompletionState { ALL_CORRECT, ALL_ATTEMPTED, ALL_INCORRECT, IN_PROGRESS, NOT_ATTEMPTED; diff --git a/src/main/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManager.java b/src/main/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManager.java index 990b33a317..c0076032b5 100644 --- a/src/main/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManager.java +++ b/src/main/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManager.java @@ -60,6 +60,8 @@ import jakarta.annotation.Nullable; import jakarta.validation.constraints.NotNull; +import uk.ac.cam.cl.dtg.util.AbstractConfigLoader; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -87,6 +89,7 @@ public class GameManager { private static final float DEFAULT_QUESTION_PASS_MARK = 75; private static final int MAX_QUESTIONS_TO_SEARCH = 20; + private static int questionLimit; private final GameboardPersistenceManager gameboardPersistenceManager; private final Random randomGenerator; @@ -109,7 +112,8 @@ public class GameManager { @Inject public GameManager(final GitContentManager contentManager, final GameboardPersistenceManager gameboardPersistenceManager, final MapperFacade mapper, - final QuestionManager questionManager) { + final QuestionManager questionManager, + final AbstractConfigLoader properties) { this.contentManager = contentManager; this.gameboardPersistenceManager = gameboardPersistenceManager; this.questionManager = questionManager; @@ -117,6 +121,8 @@ public GameManager(final GitContentManager contentManager, this.randomGenerator = new Random(); this.mapper = mapper; + + GameManager.questionLimit = Integer.parseInt(properties.getProperty(GAMEBOARD_QUESTION_LIMIT)); } /** @@ -995,7 +1001,7 @@ private List getSelectedGameboardQuestions(final GameFilter gameF Set gameboardReadyQuestions = Sets.newHashSet(); List completedQuestions = Lists.newArrayList(); // choose the gameboard questions to include. - while (gameboardReadyQuestions.size() < GAME_BOARD_TARGET_SIZE && !selectionOfGameboardQuestions.isEmpty()) { + while (gameboardReadyQuestions.size() < questionLimit && !selectionOfGameboardQuestions.isEmpty()) { for (GameboardItem gameboardItem : selectionOfGameboardQuestions) { CompletionState questionState; try { @@ -1015,12 +1021,12 @@ private List getSelectedGameboardQuestions(final GameFilter gameF } // stop inner loop if we have reached our target - if (gameboardReadyQuestions.size() == GAME_BOARD_TARGET_SIZE) { + if (gameboardReadyQuestions.size() == questionLimit) { break; } } - if (gameboardReadyQuestions.size() == GAME_BOARD_TARGET_SIZE) { + if (gameboardReadyQuestions.size() == questionLimit) { break; } @@ -1032,11 +1038,11 @@ private List getSelectedGameboardQuestions(final GameFilter gameF } // Try and make up the difference with completed ones if we haven't reached our target size - if (gameboardReadyQuestions.size() < GAME_BOARD_TARGET_SIZE && !completedQuestions.isEmpty()) { + if (gameboardReadyQuestions.size() < questionLimit && !completedQuestions.isEmpty()) { for (GameboardItem completedQuestion : completedQuestions) { - if (gameboardReadyQuestions.size() < GAME_BOARD_TARGET_SIZE) { + if (gameboardReadyQuestions.size() < questionLimit) { gameboardReadyQuestions.add(completedQuestion); - } else if (gameboardReadyQuestions.size() == GAME_BOARD_TARGET_SIZE) { + } else if (gameboardReadyQuestions.size() == questionLimit) { break; } } @@ -1373,9 +1379,9 @@ private void validateGameboard(final GameboardDTO gameboardDTO) throws InvalidGa "Your gameboard must not contain illegal characters e.g. spaces"); } - if (gameboardDTO.getContents().size() > Constants.GAME_BOARD_TARGET_SIZE) { + if (gameboardDTO.getContents().size() > questionLimit) { throw new InvalidGameboardException(String.format("Your gameboard must not contain more than %s questions", - GAME_BOARD_TARGET_SIZE)); + questionLimit)); } if (gameboardDTO.getGameFilter() == null || !validateFilterQuery(gameboardDTO.getGameFilter())) { diff --git a/src/main/java/uk/ac/cam/cl/dtg/segue/api/Constants.java b/src/main/java/uk/ac/cam/cl/dtg/segue/api/Constants.java index 0f6743c965..c2ca274452 100644 --- a/src/main/java/uk/ac/cam/cl/dtg/segue/api/Constants.java +++ b/src/main/java/uk/ac/cam/cl/dtg/segue/api/Constants.java @@ -588,6 +588,8 @@ public static SchoolInfoStatus get(final boolean schoolIdProvided, final boolean public static final String ASSOCIATION_TOKEN_FIELDNAME = "token"; + public static final String GAMEBOARD_QUESTION_LIMIT = "GAMEBOARD_QUESTION_LIMIT"; + public static final String GROUP_FK = "groupId"; public static final String ASSIGNMENT_FK = "assignmentId"; public static final String ASSIGNMENT_DUEDATE = "dueDate"; diff --git a/src/test/java/uk/ac/cam/cl/dtg/isaac/api/AbstractIsaacIntegrationTest.java b/src/test/java/uk/ac/cam/cl/dtg/isaac/api/AbstractIsaacIntegrationTest.java index ef618bcd32..ed59cca875 100644 --- a/src/test/java/uk/ac/cam/cl/dtg/isaac/api/AbstractIsaacIntegrationTest.java +++ b/src/test/java/uk/ac/cam/cl/dtg/isaac/api/AbstractIsaacIntegrationTest.java @@ -290,7 +290,7 @@ public static void setUpClass() throws Exception { IAssignmentPersistenceManager assignmentPersistenceManager = new PgAssignmentPersistenceManager(postgresSqlDb, mapperFacade); GameboardPersistenceManager gameboardPersistenceManager = new GameboardPersistenceManager(postgresSqlDb, contentManager, mapperFacade, contentMapper); - gameManager = new GameManager(contentManager, gameboardPersistenceManager, mapperFacade, questionManager); + gameManager = new GameManager(contentManager, gameboardPersistenceManager, mapperFacade, questionManager, properties); groupManager = new GroupManager(pgUserGroupPersistenceManager, userAccountManager, gameManager, mapperFacade); userAssociationManager = new UserAssociationManager(pgAssociationDataManager, userAccountManager, groupManager); PgTransactionManager pgTransactionManager = new PgTransactionManager(postgresSqlDb); diff --git a/src/test/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManagerTest.java b/src/test/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManagerTest.java index 33d1c89744..fb2dbcd7a5 100644 --- a/src/test/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManagerTest.java +++ b/src/test/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManagerTest.java @@ -35,6 +35,8 @@ import uk.ac.cam.cl.dtg.segue.dao.content.ContentManagerException; import uk.ac.cam.cl.dtg.segue.dao.content.GitContentManager; import uk.ac.cam.cl.dtg.segue.dao.content.GitContentManager.BooleanSearchClause; +import uk.ac.cam.cl.dtg.util.AbstractConfigLoader; +import uk.ac.cam.cl.dtg.util.YamlLoader; import java.util.Collections; import java.util.List; @@ -44,6 +46,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.powermock.api.easymock.PowerMock.replay; +import static uk.ac.cam.cl.dtg.segue.api.Constants.*; @RunWith(PowerMockRunner.class) @@ -55,6 +58,7 @@ public class GameManagerTest { private GameboardPersistenceManager dummyGameboardPersistenceManager; private MapperFacade dummyMapper; private QuestionManager dummyQuestionManager; + private AbstractConfigLoader dummyConfigLoader; @Before public void setUp() { @@ -62,6 +66,10 @@ public void setUp() { this.dummyGameboardPersistenceManager = PowerMock.createMock(GameboardPersistenceManager.class); this.dummyMapper = PowerMock.createMock(MapperFacade.class); this.dummyQuestionManager = PowerMock.createMock(QuestionManager.class); + this.dummyConfigLoader = PowerMock.createMock(YamlLoader.class); + + EasyMock.expect(dummyConfigLoader.getProperty(GAMEBOARD_QUESTION_LIMIT)).andStubReturn("30"); + replay(dummyConfigLoader); } @Test @@ -73,7 +81,8 @@ public void getNextQuestionsForFilter_appliesExclusionFilterForDeprecatedQuestio this.dummyContentManager, this.dummyGameboardPersistenceManager, this.dummyMapper, - this.dummyQuestionManager + this.dummyQuestionManager, + this.dummyConfigLoader ); // configure the mock GitContentManager to record the filters that are sent to it by getNextQuestionsForFilter() diff --git a/src/test/resources/segue-integration-test-config.yaml b/src/test/resources/segue-integration-test-config.yaml index bbe3f93fa8..b1b522944d 100644 --- a/src/test/resources/segue-integration-test-config.yaml +++ b/src/test/resources/segue-integration-test-config.yaml @@ -22,6 +22,8 @@ HIDE_REGRESSION_TEST_CONTENT: "false" MAX_CONTENT_CACHE_TIME: "0" LOGGING_ENABLED: "true" RESTRICTED_SIGNUP_EMAIL_REGEX: .*@(isaacphysics|adacomputerscience)\.org +GAMEBOARD_QUESTION_LIMIT: "30" +# # ETL ETL_HOSTNAME: localhost ETL_PORT: "8090" From 0868b5e0732ab68da1b08890006f1169319fd019 Mon Sep 17 00:00:00 2001 From: Matthew Trew Date: Tue, 2 Sep 2025 13:52:28 +0100 Subject: [PATCH 2/4] Restore default generated gameboard size --- .../dtg/isaac/api/managers/GameManager.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManager.java b/src/main/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManager.java index c0076032b5..0f7ee8665e 100644 --- a/src/main/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManager.java +++ b/src/main/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManager.java @@ -25,7 +25,6 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import uk.ac.cam.cl.dtg.isaac.api.Constants; import uk.ac.cam.cl.dtg.isaac.dao.GameboardPersistenceManager; import uk.ac.cam.cl.dtg.isaac.dos.AudienceContext; import uk.ac.cam.cl.dtg.isaac.dos.GameboardContentDescriptor; @@ -89,7 +88,8 @@ public class GameManager { private static final float DEFAULT_QUESTION_PASS_MARK = 75; private static final int MAX_QUESTIONS_TO_SEARCH = 20; - private static int questionLimit; + private static final int GAMEBOARD_QUESTIONS_DEFAULT = 10; + private static int gameboardQuestionsLimit; private final GameboardPersistenceManager gameboardPersistenceManager; private final Random randomGenerator; @@ -122,7 +122,7 @@ public GameManager(final GitContentManager contentManager, this.mapper = mapper; - GameManager.questionLimit = Integer.parseInt(properties.getProperty(GAMEBOARD_QUESTION_LIMIT)); + GameManager.gameboardQuestionsLimit = Integer.parseInt(properties.getProperty(GAMEBOARD_QUESTION_LIMIT)); } /** @@ -1001,7 +1001,7 @@ private List getSelectedGameboardQuestions(final GameFilter gameF Set gameboardReadyQuestions = Sets.newHashSet(); List completedQuestions = Lists.newArrayList(); // choose the gameboard questions to include. - while (gameboardReadyQuestions.size() < questionLimit && !selectionOfGameboardQuestions.isEmpty()) { + while (gameboardReadyQuestions.size() < GAMEBOARD_QUESTIONS_DEFAULT && !selectionOfGameboardQuestions.isEmpty()) { for (GameboardItem gameboardItem : selectionOfGameboardQuestions) { CompletionState questionState; try { @@ -1021,12 +1021,12 @@ private List getSelectedGameboardQuestions(final GameFilter gameF } // stop inner loop if we have reached our target - if (gameboardReadyQuestions.size() == questionLimit) { + if (gameboardReadyQuestions.size() == GAMEBOARD_QUESTIONS_DEFAULT) { break; } } - if (gameboardReadyQuestions.size() == questionLimit) { + if (gameboardReadyQuestions.size() == GAMEBOARD_QUESTIONS_DEFAULT) { break; } @@ -1038,11 +1038,11 @@ private List getSelectedGameboardQuestions(final GameFilter gameF } // Try and make up the difference with completed ones if we haven't reached our target size - if (gameboardReadyQuestions.size() < questionLimit && !completedQuestions.isEmpty()) { + if (gameboardReadyQuestions.size() < GAMEBOARD_QUESTIONS_DEFAULT && !completedQuestions.isEmpty()) { for (GameboardItem completedQuestion : completedQuestions) { - if (gameboardReadyQuestions.size() < questionLimit) { + if (gameboardReadyQuestions.size() < GAMEBOARD_QUESTIONS_DEFAULT) { gameboardReadyQuestions.add(completedQuestion); - } else if (gameboardReadyQuestions.size() == questionLimit) { + } else if (gameboardReadyQuestions.size() == GAMEBOARD_QUESTIONS_DEFAULT) { break; } } @@ -1379,9 +1379,9 @@ private void validateGameboard(final GameboardDTO gameboardDTO) throws InvalidGa "Your gameboard must not contain illegal characters e.g. spaces"); } - if (gameboardDTO.getContents().size() > questionLimit) { + if (gameboardDTO.getContents().size() > gameboardQuestionsLimit) { throw new InvalidGameboardException(String.format("Your gameboard must not contain more than %s questions", - questionLimit)); + gameboardQuestionsLimit)); } if (gameboardDTO.getGameFilter() == null || !validateFilterQuery(gameboardDTO.getGameFilter())) { From 02c48b460ecf338c9b130038c7462b761b33c61d Mon Sep 17 00:00:00 2001 From: Matthew Trew Date: Fri, 12 Sep 2025 16:08:56 +0100 Subject: [PATCH 3/4] Add tests for gameboard question limit --- .../api/AbstractIsaacIntegrationTest.java | 3 + .../cam/cl/dtg/isaac/api/CookieJarFilter.java | 33 +++++++ .../cl/dtg/isaac/api/GameboardsFacadeIT.java | 94 +++++++++++++++++++ .../api/IsaacIntegrationTestWithREST.java | 38 ++++++-- 4 files changed, 159 insertions(+), 9 deletions(-) create mode 100644 src/test/java/uk/ac/cam/cl/dtg/isaac/api/CookieJarFilter.java create mode 100644 src/test/java/uk/ac/cam/cl/dtg/isaac/api/GameboardsFacadeIT.java diff --git a/src/test/java/uk/ac/cam/cl/dtg/isaac/api/AbstractIsaacIntegrationTest.java b/src/test/java/uk/ac/cam/cl/dtg/isaac/api/AbstractIsaacIntegrationTest.java index ed59cca875..96652e6da3 100644 --- a/src/test/java/uk/ac/cam/cl/dtg/isaac/api/AbstractIsaacIntegrationTest.java +++ b/src/test/java/uk/ac/cam/cl/dtg/isaac/api/AbstractIsaacIntegrationTest.java @@ -17,6 +17,7 @@ import org.testcontainers.utility.MountableFile; import uk.ac.cam.cl.dtg.isaac.api.managers.AssignmentManager; import uk.ac.cam.cl.dtg.isaac.api.managers.EventBookingManager; +import uk.ac.cam.cl.dtg.isaac.api.managers.FastTrackManger; import uk.ac.cam.cl.dtg.isaac.api.managers.GameManager; import uk.ac.cam.cl.dtg.isaac.api.managers.QuizAssignmentManager; import uk.ac.cam.cl.dtg.isaac.api.managers.QuizAttemptManager; @@ -140,6 +141,7 @@ public class AbstractIsaacIntegrationTest { protected static QuizManager quizManager; protected static PgPasswordDataManager passwordDataManager; protected static UserAttemptManager userAttemptManager; + protected static FastTrackManger fastTrackManger; // Manager dependencies protected static IQuizAssignmentPersistenceManager quizAssignmentPersistenceManager; @@ -307,6 +309,7 @@ public static void setUpClass() throws Exception { quizQuestionAttemptPersistenceManager = new PgQuizQuestionAttemptPersistenceManager(postgresSqlDb, contentMapper); quizQuestionManager = new QuizQuestionManager(questionManager, contentMapper, quizQuestionAttemptPersistenceManager, quizManager, quizAttemptManager); userAttemptManager = new UserAttemptManager(questionManager); + fastTrackManger = new FastTrackManger(properties, contentManager, gameManager); misuseMonitor = new InMemoryMisuseMonitor(); misuseMonitor.registerHandler(GroupManagerLookupMisuseHandler.class.getSimpleName(), new GroupManagerLookupMisuseHandler(emailManager, properties)); diff --git a/src/test/java/uk/ac/cam/cl/dtg/isaac/api/CookieJarFilter.java b/src/test/java/uk/ac/cam/cl/dtg/isaac/api/CookieJarFilter.java new file mode 100644 index 0000000000..fb4e54c346 --- /dev/null +++ b/src/test/java/uk/ac/cam/cl/dtg/isaac/api/CookieJarFilter.java @@ -0,0 +1,33 @@ +package uk.ac.cam.cl.dtg.isaac.api; + +import jakarta.ws.rs.client.ClientRequestContext; +import jakarta.ws.rs.client.ClientRequestFilter; +import jakarta.ws.rs.client.ClientResponseContext; +import jakarta.ws.rs.client.ClientResponseFilter; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.NewCookie; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/* + * JAX-RS Client filter for storing and retrieving cookies across requests. + */ +public class CookieJarFilter implements ClientRequestFilter, ClientResponseFilter { + private final Map cookieJar = new ConcurrentHashMap<>(); + + @Override + public void filter(final ClientRequestContext requestContext) { + if (!cookieJar.isEmpty()) { + String header = cookieJar.values().stream() + .map(c -> c.getName() + "=" + c.getValue()) + .collect(Collectors.joining("; ")); + requestContext.getHeaders().putSingle(HttpHeaders.COOKIE, header); + } + } + + @Override + public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) { + responseContext.getCookies().values().forEach(c -> cookieJar.put(c.getName(), c)); + } +} diff --git a/src/test/java/uk/ac/cam/cl/dtg/isaac/api/GameboardsFacadeIT.java b/src/test/java/uk/ac/cam/cl/dtg/isaac/api/GameboardsFacadeIT.java new file mode 100644 index 0000000000..3633890732 --- /dev/null +++ b/src/test/java/uk/ac/cam/cl/dtg/isaac/api/GameboardsFacadeIT.java @@ -0,0 +1,94 @@ +package uk.ac.cam.cl.dtg.isaac.api; + +import org.junit.jupiter.api.Test; +import uk.ac.cam.cl.dtg.isaac.dto.GameFilter; +import uk.ac.cam.cl.dtg.isaac.dto.GameboardDTO; +import uk.ac.cam.cl.dtg.isaac.dto.GameboardItem; +import uk.ac.cam.cl.dtg.segue.api.AuthenticationFacade; + +import jakarta.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static uk.ac.cam.cl.dtg.isaac.api.ITConstants.ASSIGNMENT_TEST_PAGE_ID; + +public class GameboardsFacadeIT extends IsaacIntegrationTestWithREST { + TestServer subject() throws Exception { + return startServer( + new AuthenticationFacade(properties, userAccountManager, logManager, misuseMonitor), + new GameboardsFacade(properties, logManager, gameManager, questionManager, userAccountManager, + fastTrackManger) + ); + } + + @Test + public void saveNewGameboard_validGameboard_isAccepted() throws Exception { + // Arrange + GameboardDTO gameboardDTO = new GameboardDTO(); + gameboardDTO.setTitle("Test Gameboard"); + + // Create gameboard + GameFilter gameFilter = new GameFilter(); + List subjects = new ArrayList<>(); + subjects.add("physics"); + gameFilter.setSubjects(subjects); + gameboardDTO.setGameFilter(gameFilter); + + // Add 30 questions + List questions = new ArrayList<>(); + for (int i = 0; i < 30; i++) { + GameboardItem item = new GameboardItem(); + item.setId(ASSIGNMENT_TEST_PAGE_ID); + item.setTitle(ASSIGNMENT_TEST_PAGE_ID); + questions.add(item); + } + gameboardDTO.setContents(questions); + + TestClient client = subject().client(); + + // Log in as student + client.loginAs(integrationTestUsers.TEST_STUDENT); + + // Act + TestResponse r = client.post("/gameboards", gameboardDTO); + + // Assert + assertEquals(200, r.response.getStatus()); + } + + @Test + public void saveNewGameboard_tooManyQuestions_isRejected() throws Exception { + // Arrange + GameboardDTO gameboardDTO = new GameboardDTO(); + gameboardDTO.setTitle("Test Gameboard"); + + // Create an otherwise valid gameboard + GameFilter gameFilter = new GameFilter(); + List subjects = new ArrayList<>(); + subjects.add("physics"); + gameFilter.setSubjects(subjects); + gameboardDTO.setGameFilter(gameFilter); + + // Add over 30 questions + List questions = new ArrayList<>(); + for (int i = 0; i < 31; i++) { + GameboardItem item = new GameboardItem(); + item.setId(ASSIGNMENT_TEST_PAGE_ID); + item.setTitle(ASSIGNMENT_TEST_PAGE_ID); + questions.add(item); + } + gameboardDTO.setContents(questions); + + TestClient client = subject().client(); + + // Log in as student + client.loginAs(integrationTestUsers.TEST_STUDENT); + + // Act + TestResponse r = client.post("/gameboards", gameboardDTO); + + // Assert + r.assertError("The gameboard you provided is invalid", Response.Status.BAD_REQUEST); + } +} diff --git a/src/test/java/uk/ac/cam/cl/dtg/isaac/api/IsaacIntegrationTestWithREST.java b/src/test/java/uk/ac/cam/cl/dtg/isaac/api/IsaacIntegrationTestWithREST.java index 4055920f48..fa5c71e7f0 100644 --- a/src/test/java/uk/ac/cam/cl/dtg/isaac/api/IsaacIntegrationTestWithREST.java +++ b/src/test/java/uk/ac/cam/cl/dtg/isaac/api/IsaacIntegrationTestWithREST.java @@ -8,10 +8,16 @@ import org.json.JSONObject; import org.junit.function.ThrowingRunnable; import org.junit.jupiter.api.AfterEach; +import uk.ac.cam.cl.dtg.isaac.dos.users.RegisteredUser; +import uk.ac.cam.cl.dtg.isaac.dto.LocalAuthDTO; +import uk.ac.cam.cl.dtg.isaac.dto.users.RegisteredUserDTO; +import jakarta.ws.rs.client.Client; import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.client.Invocation; import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import java.util.HashSet; import java.util.Map; @@ -110,22 +116,36 @@ static class TestClient { String baseUrl; Consumer registerCleanup; RequestBuilder builder; + RegisteredUserDTO currentUser; + Client client; - TestClient( - final String baseUrl, final Consumer registerCleanup, final RequestBuilder builder - ) { + TestClient(final String baseUrl, final Consumer registerCleanup, final RequestBuilder builder) { this.baseUrl = baseUrl; this.registerCleanup = registerCleanup; this.builder = builder; + this.client = ClientBuilder.newClient().register(new CookieJarFilter()); } public TestResponse get(final String url) { - try (var client = ClientBuilder.newClient()) { - var request = client.target(baseUrl + url).request(); - var response = builder.apply(request).get(); - registerCleanup.accept(response::close); - return new TestResponse(response); - } + var request = client.target(baseUrl + url).request(MediaType.APPLICATION_JSON); + var response = builder.apply(request).get(); + registerCleanup.accept(response::close); + return new TestResponse(response); + } + + public TestResponse post(final String url, final Object body) { + var request = client.target(baseUrl + url).request(MediaType.APPLICATION_JSON); + var response = builder.apply(request).post(Entity.json(body)); + registerCleanup.accept(response::close); + return new TestResponse(response); + } + + public void loginAs(final RegisteredUser user) { + var request = client.target(baseUrl + "/auth/SEGUE/authenticate").request(MediaType.APPLICATION_JSON); + var body = new LocalAuthDTO(); + body.setEmail(user.getEmail()); + body.setPassword("test1234"); + this.currentUser = builder.apply(request).post(Entity.json(body), RegisteredUserDTO.class); } } From 7a6a9b9116868703d392232f9ab08c21a2250ad1 Mon Sep 17 00:00:00 2001 From: Matthew Trew Date: Mon, 15 Sep 2025 09:46:52 +0100 Subject: [PATCH 4/4] Use default gameboard size as limit if config property absent --- .../uk/ac/cam/cl/dtg/isaac/api/managers/GameManager.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManager.java b/src/main/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManager.java index 0f7ee8665e..40945ba2a8 100644 --- a/src/main/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManager.java +++ b/src/main/java/uk/ac/cam/cl/dtg/isaac/api/managers/GameManager.java @@ -122,7 +122,11 @@ public GameManager(final GitContentManager contentManager, this.mapper = mapper; - GameManager.gameboardQuestionsLimit = Integer.parseInt(properties.getProperty(GAMEBOARD_QUESTION_LIMIT)); + try { + GameManager.gameboardQuestionsLimit = Integer.parseInt(properties.getProperty(GAMEBOARD_QUESTION_LIMIT)); + } catch (NumberFormatException e) { + GameManager.gameboardQuestionsLimit = GAMEBOARD_QUESTIONS_DEFAULT; + } } /**