diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccess.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccess.java index 4867d15e..d5c80db7 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccess.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccess.java @@ -143,7 +143,7 @@ public class MoodleCourseAccess extends CourseAccess { MOODLE_COURSE_API_FUNCTION_NAME, MOODLE_QUIZ_API_FUNCTION_NAME); } catch (final RuntimeException e) { - log.error("Failed to access Open edX course API: ", e); + log.error("Failed to access Moodle course API: ", e); return LmsSetupTestResult.ofQuizAccessAPIError(e.getMessage()); } @@ -164,22 +164,21 @@ public class MoodleCourseAccess extends CourseAccess { private ArrayList collectAllQuizzes(final MoodleAPIRestTemplate restTemplate) { final String urlPrefix = this.lmsSetup.lmsApiUrl + MOODLE_QUIZ_START_URL_PATH; - return collectAllCourses( - restTemplate) - .stream() - .reduce( - new ArrayList<>(), - (list, courseData) -> { - list.addAll(quizDataOf( - this.lmsSetup, - courseData, - urlPrefix)); - return list; - }, - (list1, list2) -> { - list1.addAll(list2); - return list1; - }); + return collectAllCourses(restTemplate) + .stream() + .reduce( + new ArrayList<>(), + (list, courseData) -> { + list.addAll(quizDataOf( + this.lmsSetup, + courseData, + urlPrefix)); + return list; + }, + (list1, list2) -> { + list1.addAll(list2); + return list1; + }); } private List collectAllCourses(final MoodleAPIRestTemplate restTemplate) { diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseRestriction.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseRestriction.java index 179db87e..bf06d33b 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseRestriction.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseRestriction.java @@ -81,7 +81,7 @@ public class MoodleCourseRestriction { LmsSetupTestResult initAPIAccess() { // TODO test availability - return LmsSetupTestResult.ofQuizAccessAPIError("not available yet"); + return LmsSetupTestResult.ofQuizRestrictionAPIError("not available yet"); } Result getSEBRestriction( diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleRestTemplateFactory.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleRestTemplateFactory.java index 0c073b89..08c76ff7 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleRestTemplateFactory.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleRestTemplateFactory.java @@ -48,7 +48,7 @@ import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Utils; -final class MoodleRestTemplateFactory { +class MoodleRestTemplateFactory { final JSONMapper jsonMapper; final LmsSetup lmsSetup; @@ -134,7 +134,7 @@ final class MoodleRestTemplateFactory { }); } - private MoodleAPIRestTemplate createRestTemplate( + protected MoodleAPIRestTemplate createRestTemplate( final ClientCredentials credentials, final String accessTokenRequestPath) { @@ -158,7 +158,7 @@ final class MoodleRestTemplateFactory { return restTemplate; } - public final class MoodleAPIRestTemplate extends RestTemplate { + public class MoodleAPIRestTemplate extends RestTemplate { public static final String URI_VAR_USER_NAME = "username"; public static final String URI_VAR_PASSWORD = "pwd"; diff --git a/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccessTest.java b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccessTest.java new file mode 100644 index 00000000..05a678fa --- /dev/null +++ b/src/test/java/ch/ethz/seb/sebserver/webservice/servicelayer/lms/impl/moodle/MoodleCourseAccessTest.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle; + +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.util.TreeMap; + +import org.junit.Test; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; + +import ch.ethz.seb.sebserver.gbl.api.JSONMapper; +import ch.ethz.seb.sebserver.gbl.async.AsyncService; +import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult; +import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetupTestResult.ErrorType; +import ch.ethz.seb.sebserver.gbl.model.user.ExamineeAccountDetails; +import ch.ethz.seb.sebserver.gbl.util.Result; +import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.moodle.MoodleRestTemplateFactory.MoodleAPIRestTemplate; + +public class MoodleCourseAccessTest { + + @Test + public void testGetExamineeAccountDetails() { + + final MoodleRestTemplateFactory moodleRestTemplateFactory = mock(MoodleRestTemplateFactory.class); + final MoodleAPIRestTemplate moodleAPIRestTemplate = mock(MoodleAPIRestTemplate.class); + when(moodleRestTemplateFactory.createRestTemplate()).thenReturn(Result.of(moodleAPIRestTemplate)); + when(moodleAPIRestTemplate.callMoodleAPIFunction( + anyString(), + any())).thenReturn("[\r\n" + + " {\r\n" + + " \"id\": 15,\r\n" + + " \"username\": \"seb1\",\r\n" + + " \"firstname\": \"seb\",\r\n" + + " \"lastname\": \"user1\",\r\n" + + " \"fullname\": \"seb user1\",\r\n" + + " \"email\": \"demo1@safeexambrowser.org\",\r\n" + + " \"department\": \"\",\r\n" + + " \"firstaccess\": 1523400731,\r\n" + + " \"lastaccess\": 1596457337,\r\n" + + " \"auth\": \"manual\",\r\n" + + " \"suspended\": false,\r\n" + + " \"confirmed\": true,\r\n" + + " \"lang\": \"en\",\r\n" + + " \"theme\": \"\",\r\n" + + " \"timezone\": \"99\",\r\n" + + " \"mailformat\": 1,\r\n" + + " \"description\": \"\",\r\n" + + " \"descriptionformat\": 1,\r\n" + + " \"profileimageurlsmall\": \"https://demo.safeexambrowser.org/moodle/theme/image.php/boost/core/1561047635/u/f2\",\r\n" + + + " \"profileimageurl\": \"https://demo.safeexambrowser.org/moodle/theme/image.php/boost/core/1561047635/u/f1\"\r\n" + + + " }\r\n" + + "]"); + + final MoodleCourseAccess moodleCourseAccess = new MoodleCourseAccess( + new JSONMapper(), + null, + moodleRestTemplateFactory, + mock(AsyncService.class), + false); + + final String examId = "123"; + final Result examineeAccountDetails = + moodleCourseAccess.getExamineeAccountDetails(examId); + + final MultiValueMap queryAttributes = new LinkedMultiValueMap<>(); + queryAttributes.add("field", "id"); + queryAttributes.add("values[0]", examId); + + verify(moodleAPIRestTemplate, times(1)).callMoodleAPIFunction( + eq("core_user_get_users_by_field"), + eq(queryAttributes)); + assertNotNull(examineeAccountDetails); + assertFalse(examineeAccountDetails.hasError()); + final ExamineeAccountDetails userDetails = examineeAccountDetails.getOrThrow(); + assertEquals("15", userDetails.id); + assertEquals("seb1", userDetails.username); + assertEquals("seb user1", userDetails.name); + assertEquals("demo1@safeexambrowser.org", userDetails.email); + assertEquals( + "{auth=manual, " + + "confirmed=true, " + + "department=, " + + "description=, " + + "descriptionformat=1, " + + "firstaccess=1523400731, " + + "firstname=seb, " + + "lang=en, " + + "lastaccess=1596457337, " + + "lastname=user1, " + + "mailformat=1, " + + "suspended=false, " + + "theme=, timezone=99}", + new TreeMap<>(userDetails.additionalAttributes).toString()); + } + + @Test + public void testInitAPIAccessError1() { + final MoodleRestTemplateFactory moodleRestTemplateFactory = mock(MoodleRestTemplateFactory.class); + when(moodleRestTemplateFactory.createRestTemplate()).thenReturn(Result.ofRuntimeError("Error1")); + when(moodleRestTemplateFactory.test()).thenReturn(LmsSetupTestResult.ofOkay()); + + final MoodleCourseAccess moodleCourseAccess = new MoodleCourseAccess( + new JSONMapper(), + null, + moodleRestTemplateFactory, + mock(AsyncService.class), + false); + + final LmsSetupTestResult initAPIAccess = moodleCourseAccess.initAPIAccess(); + assertNotNull(initAPIAccess); + assertFalse(initAPIAccess.errors.isEmpty()); + assertTrue(initAPIAccess.hasError(ErrorType.TOKEN_REQUEST)); + + } + + @Test + public void testInitAPIAccessError2() { + final MoodleRestTemplateFactory moodleRestTemplateFactory = mock(MoodleRestTemplateFactory.class); + final MoodleAPIRestTemplate moodleAPIRestTemplate = mock(MoodleAPIRestTemplate.class); + when(moodleRestTemplateFactory.createRestTemplate()).thenReturn(Result.of(moodleAPIRestTemplate)); + doThrow(RuntimeException.class).when(moodleAPIRestTemplate).testAPIConnection(any()); + when(moodleRestTemplateFactory.test()).thenReturn(LmsSetupTestResult.ofOkay()); + + final MoodleCourseAccess moodleCourseAccess = new MoodleCourseAccess( + new JSONMapper(), + null, + moodleRestTemplateFactory, + mock(AsyncService.class), + false); + + final LmsSetupTestResult initAPIAccess = moodleCourseAccess.initAPIAccess(); + assertNotNull(initAPIAccess); + assertFalse(initAPIAccess.errors.isEmpty()); + assertTrue(initAPIAccess.hasError(ErrorType.QUIZ_ACCESS_API_REQUEST)); + + } + + @Test + public void testInitAPIAccessOK() { + final MoodleRestTemplateFactory moodleRestTemplateFactory = mock(MoodleRestTemplateFactory.class); + final MoodleAPIRestTemplate moodleAPIRestTemplate = mock(MoodleAPIRestTemplate.class); + when(moodleRestTemplateFactory.createRestTemplate()).thenReturn(Result.of(moodleAPIRestTemplate)); + //doThrow(RuntimeException.class).when(moodleAPIRestTemplate).testAPIConnection(any()); + when(moodleRestTemplateFactory.test()).thenReturn(LmsSetupTestResult.ofOkay()); + + final MoodleCourseAccess moodleCourseAccess = new MoodleCourseAccess( + new JSONMapper(), + null, + moodleRestTemplateFactory, + mock(AsyncService.class), + false); + + final LmsSetupTestResult initAPIAccess = moodleCourseAccess.initAPIAccess(); + assertNotNull(initAPIAccess); + assertTrue(initAPIAccess.errors.isEmpty()); + + } + +}