diff --git a/domain/src/test/java/org/oppia/android/domain/exploration/ExplorationProgressControllerTest.kt b/domain/src/test/java/org/oppia/android/domain/exploration/ExplorationProgressControllerTest.kt index 9ec59a96f2b..3026b834567 100644 --- a/domain/src/test/java/org/oppia/android/domain/exploration/ExplorationProgressControllerTest.kt +++ b/domain/src/test/java/org/oppia/android/domain/exploration/ExplorationProgressControllerTest.kt @@ -26,6 +26,7 @@ import org.oppia.android.app.model.EventLog.Context.ActivityContextCase.PROGRESS import org.oppia.android.app.model.EventLog.Context.ActivityContextCase.REACH_INVESTED_ENGAGEMENT import org.oppia.android.app.model.EventLog.Context.ActivityContextCase.RESUME_LESSON_SUBMIT_CORRECT_ANSWER_CONTEXT import org.oppia.android.app.model.EventLog.Context.ActivityContextCase.RESUME_LESSON_SUBMIT_INCORRECT_ANSWER_CONTEXT +import org.oppia.android.app.model.EventLog.Context.ActivityContextCase.START_EXPLORATION_CONTEXT import org.oppia.android.app.model.Exploration import org.oppia.android.app.model.ExplorationCheckpoint import org.oppia.android.app.model.Fraction @@ -2247,7 +2248,7 @@ class ExplorationProgressControllerTest { val exploration = loadExploration(TEST_EXPLORATION_ID_2) val eventLog = fakeAnalyticsEventLogger.getOldestEvent() - assertThat(fakeAnalyticsEventLogger.getEventListCount()).isEqualTo(4) + assertThat(fakeAnalyticsEventLogger.getEventListCount()).isEqualTo(5) assertThat(eventLog).hasStartCardContextThat { hasExplorationDetailsThat().containsTestExp2Details() hasExplorationDetailsThat().hasStateNameThat().isEqualTo(exploration.initStateName) @@ -2311,8 +2312,8 @@ class ExplorationProgressControllerTest { ) waitForGetCurrentStateSuccessfulLoad() - val eventLog = fakeAnalyticsEventLogger.getMostRecentEvent() - assertThat(fakeAnalyticsEventLogger.getEventListCount()).isEqualTo(1) + val eventLog = fakeAnalyticsEventLogger.getMostRecentEvents(2)[0] + assertThat(fakeAnalyticsEventLogger.getEventListCount()).isEqualTo(2) assertThat(eventLog).hasStartCardContextThat { hasExplorationDetailsThat().containsTestExp2Details() // The exploration should have been started over. @@ -2470,6 +2471,23 @@ class ExplorationProgressControllerTest { } } + @Test + fun testPlayNewExp_logsStartExplorationEvent() { + logIntoAnalyticsReadyAdminProfile() + startPlayingNewExploration( + TEST_CLASSROOM_ID_0, TEST_TOPIC_ID_0, TEST_STORY_ID_0, TEST_EXPLORATION_ID_2 + ) + waitForGetCurrentStateSuccessfulLoad() + + val hasStartExplorationEvent = fakeAnalyticsEventLogger.hasEventLogged { + it.context.activityContextCase == START_EXPLORATION_CONTEXT + } + assertThat(hasStartExplorationEvent).isTrue() + + val eventLog = fakeAnalyticsEventLogger.getMostRecentEvents(4)[0] + assertThat(eventLog).hasStartExplorationContextThat().containsTestExp2Details() + } + @Test fun testResumeExp_stateOneTwoDone_finishThreeAndMoveForward_noLogReachInvestedEngagementEvent() { logIntoAnalyticsReadyAdminProfile() @@ -2622,6 +2640,28 @@ class ExplorationProgressControllerTest { assertThat(resumeLessonSubmitIncorrectAnswerEventCount).isEqualTo(1) } + @Test + fun testResumeExp_doesNotLogStartExplorationEvent() { + logIntoAnalyticsReadyAdminProfile() + startPlayingNewExploration( + TEST_CLASSROOM_ID_0, TEST_TOPIC_ID_0, TEST_STORY_ID_0, TEST_EXPLORATION_ID_2 + ) + waitForGetCurrentStateSuccessfulLoad() + endExploration() + + fakeAnalyticsEventLogger.clearAllEvents() + + val checkPoint = retrieveExplorationCheckpoint(TEST_EXPLORATION_ID_2) + resumeExploration( + TEST_CLASSROOM_ID_0, TEST_TOPIC_ID_0, TEST_STORY_ID_0, TEST_EXPLORATION_ID_2, checkPoint + ) + + val hasStartExplorationEvent = fakeAnalyticsEventLogger.hasEventLogged { + it.context.activityContextCase == START_EXPLORATION_CONTEXT + } + assertThat(hasStartExplorationEvent).isFalse() + } + @Test fun testStartOverExp_submitCorrectAnswer_doesNotLogResumeLessonSubmitCorrectAnswerEvent() { logIntoAnalyticsReadyAdminProfile() @@ -2668,6 +2708,27 @@ class ExplorationProgressControllerTest { assertThat(resumeLessonSubmitIncorrectAnswerEventCount).isEqualTo(0) } + @Test + fun testStartOverExp_doesNotLogStartExplorationEvent() { + logIntoAnalyticsReadyAdminProfile() + startPlayingNewExploration( + TEST_CLASSROOM_ID_0, TEST_TOPIC_ID_0, TEST_STORY_ID_0, TEST_EXPLORATION_ID_2 + ) + waitForGetCurrentStateSuccessfulLoad() + endExploration() + + fakeAnalyticsEventLogger.clearAllEvents() + + restartExploration( + TEST_CLASSROOM_ID_0, TEST_TOPIC_ID_0, TEST_STORY_ID_0, TEST_EXPLORATION_ID_2 + ) + + val hasStartExplorationEvent = fakeAnalyticsEventLogger.hasEventLogged { + it.context.activityContextCase == START_EXPLORATION_CONTEXT + } + assertThat(hasStartExplorationEvent).isFalse() + } + @Test fun testReplayExp_submitCorrectAnswer_doesNotLogResumeLessonSubmitCorrectAnswerEvent() { logIntoAnalyticsReadyAdminProfile() @@ -2843,7 +2904,12 @@ class ExplorationProgressControllerTest { @Test fun testHint_existingHintViewed_logsExistingHintViewedEvent() { logIntoAnalyticsReadyAdminProfile() - startPlayingNewExploration(TEST_TOPIC_ID_0, TEST_STORY_ID_0, TEST_EXPLORATION_ID_2) + startPlayingNewExploration( + TEST_CLASSROOM_ID_0, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2 + ) waitForGetCurrentStateSuccessfulLoad() playThroughPrototypeState1AndMoveToNextState() // Submit 2 wrong answers to trigger a hint becoming available. @@ -3003,7 +3069,12 @@ class ExplorationProgressControllerTest { @Test fun testSolution_viewExistingSolution_logsExistingSolutionViewedEvent() { logIntoAnalyticsReadyAdminProfile() - startPlayingNewExploration(TEST_TOPIC_ID_0, TEST_STORY_ID_0, TEST_EXPLORATION_ID_2) + startPlayingNewExploration( + TEST_CLASSROOM_ID_0, + TEST_TOPIC_ID_0, + TEST_STORY_ID_0, + TEST_EXPLORATION_ID_2 + ) waitForGetCurrentStateSuccessfulLoad() playThroughPrototypeState1AndMoveToNextState() // Submit 2 wrong answers to trigger the hint. @@ -3676,6 +3747,7 @@ class ExplorationProgressControllerTest { pendingState.helpIndex.isSolutionRevealed() private fun EventLogSubject.ExplorationContextSubject.containsTestExp2Details() { + hasClassroomIdThat().isEqualTo(TEST_CLASSROOM_ID_0) hasTopicIdThat().isEqualTo(TEST_TOPIC_ID_0) hasStoryIdThat().isEqualTo(TEST_STORY_ID_0) hasExplorationIdThat().isEqualTo(TEST_EXPLORATION_ID_2) @@ -3688,6 +3760,7 @@ class ExplorationProgressControllerTest { } private fun EventLogSubject.ExplorationContextSubject.containsFractionsExp0Details() { + hasClassroomIdThat().isEqualTo(TEST_CLASSROOM_ID_1) hasTopicIdThat().isEqualTo(FRACTIONS_TOPIC_ID) hasStoryIdThat().isEqualTo(FRACTIONS_STORY_ID_0) hasExplorationIdThat().isEqualTo(FRACTIONS_EXPLORATION_ID_0) diff --git a/domain/src/test/java/org/oppia/android/domain/oppialogger/analytics/LearnerAnalyticsLoggerTest.kt b/domain/src/test/java/org/oppia/android/domain/oppialogger/analytics/LearnerAnalyticsLoggerTest.kt index 3e6e4861338..30523eb52e7 100644 --- a/domain/src/test/java/org/oppia/android/domain/oppialogger/analytics/LearnerAnalyticsLoggerTest.kt +++ b/domain/src/test/java/org/oppia/android/domain/oppialogger/analytics/LearnerAnalyticsLoggerTest.kt @@ -615,6 +615,48 @@ class LearnerAnalyticsLoggerTest { } } + @Test + fun testExpLogger_logStartExploration_outsideCard_logsConsoleWarningAndNoEvents() { + val exploration5 = loadExploration(TEST_EXPLORATION_ID_5) + val expLogger = learnerAnalyticsLogger.beginExploration(exploration5) + testCoroutineDispatchers.runCurrent() + + expLogger.logStartExploration() + testCoroutineDispatchers.runCurrent() + + val log = ShadowLog.getLogs().getMostRecentWithTag("LearnerAnalyticsLogger") + assertThat(log.msg).contains("Attempting to log a state event outside state") + assertThat(log.type).isEqualTo(Log.WARN) + assertThat(fakeAnalyticsEventLogger.noEventsPresent()).isTrue() + } + + @Test + fun testExpLogger_logStartExploration_insideCard_logsStateEventWithStateName() { + val exploration5 = loadExploration(TEST_EXPLORATION_ID_5) + val expLogger = learnerAnalyticsLogger.beginExploration(exploration5) + expLogger.startCard(exploration5.getStateByName(TEST_EXP_5_STATE_THREE_NAME)) + testCoroutineDispatchers.runCurrent() + + expLogger.logStartExploration() + testCoroutineDispatchers.runCurrent() + + val eventLog = fakeAnalyticsEventLogger.getMostRecentEvent() + assertThat(eventLog).isEssentialPriority() + assertThat(eventLog).hasStartExplorationContextThat { + hasClassroomIdThat().isEqualTo(TEST_CLASSROOM_ID) + hasTopicIdThat().isEqualTo(TEST_TOPIC_ID) + hasStoryIdThat().isEqualTo(TEST_STORY_ID) + hasExplorationIdThat().isEqualTo(TEST_EXPLORATION_ID_5) + hasSessionIdThat().isEqualTo(DEFAULT_INITIAL_SESSION_ID) + hasVersionThat().isEqualTo(5) + hasStateNameThat().isEqualTo(TEST_EXP_5_STATE_THREE_NAME) + hasLearnerDetailsThat { + hasLearnerIdThat().isEqualTo(TEST_LEARNER_ID) + hasInstallationIdThat().isEqualTo(TEST_INSTALL_ID) + } + } + } + @Test fun testExpLogger_logExitExploration_outsideCard_logsConsoleWarningAndNoEvents() { val exploration5 = loadExploration(TEST_EXPLORATION_ID_5) @@ -893,6 +935,7 @@ class LearnerAnalyticsLoggerTest { assertThat(eventLog).isEssentialPriority() assertThat(eventLog).hasViewExistingHintContextThat { hasExplorationDetailsThat { + hasClassroomIdThat().isEqualTo(TEST_CLASSROOM_ID) hasTopicIdThat().isEqualTo(TEST_TOPIC_ID) hasStoryIdThat().isEqualTo(TEST_STORY_ID) hasExplorationIdThat().isEqualTo(TEST_EXPLORATION_ID_5) @@ -948,6 +991,7 @@ class LearnerAnalyticsLoggerTest { val eventLog = fakeAnalyticsEventLogger.getMostRecentEvent() assertThat(eventLog).isEssentialPriority() assertThat(eventLog).hasRevealSolutionContextThat { + hasClassroomIdThat().isEqualTo(TEST_CLASSROOM_ID) hasTopicIdThat().isEqualTo(TEST_TOPIC_ID) hasStoryIdThat().isEqualTo(TEST_STORY_ID) hasExplorationIdThat().isEqualTo(TEST_EXPLORATION_ID_5) @@ -1217,6 +1261,51 @@ class LearnerAnalyticsLoggerTest { } } + @Test + @Iteration("no_install_id", "lid=learn", "iid=null", "elid=learn", "eid=") + @Iteration("no_learner_id", "lid=null", "iid=install", "elid=", "eid=install") + fun testExpLogger_logStartExploration_missingOneId_logsEventWithMissingId() { + val exploration5 = loadExploration(TEST_EXPLORATION_ID_5) + val expLogger = + learnerAnalyticsLogger.beginExploration( + exploration5, learnerId = learnerIdParameter, installationId = installIdParameter + ) + testCoroutineDispatchers.runCurrent() + expLogger.startCard(exploration5.getStateByName(exploration5.initStateName)) + + expLogger.logStartExploration() + testCoroutineDispatchers.runCurrent() + + val eventLog = fakeAnalyticsEventLogger.getMostRecentEvent() + assertThat(eventLog).hasStartExplorationContextThat { + hasLearnerDetailsThat { + hasLearnerIdThat().isEqualTo(expectedLearnerIdParameter) + hasInstallationIdThat().isEqualTo(expectedInstallIdParameter) + } + } + } + + @Test + fun testExpLogger_logStartExploration_noInstallOrLearnerIds_logsEventAndConsoleErrors() { + val exploration5 = loadExploration(TEST_EXPLORATION_ID_5) + val expLogger = + learnerAnalyticsLogger.beginExploration(exploration5, learnerId = null, installationId = null) + testCoroutineDispatchers.runCurrent() + expLogger.startCard(exploration5.getStateByName(exploration5.initStateName)) + + expLogger.logStartExploration() + testCoroutineDispatchers.runCurrent() + + // Since both the learner & installation IDs are missing, the event logging fails since it would + // have no context. An unknown installation ID is used to indicate the installation ID was + // missing. + val eventLog = fakeAnalyticsEventLogger.getMostRecentEvent() + val log = ShadowLog.getLogs().getMostRecentWithTag("LearnerAnalyticsLogger") + assertThat(eventLog).hasInstallIdForAnalyticsLogFailureThat().isEqualTo(UNKNOWN_INSTALL_ID) + assertThat(log.msg).contains("Event is being dropped due to incomplete event") + assertThat(log.type).isEqualTo(Log.ERROR) + } + @Test @Iteration("no_install_id", "lid=learn", "iid=null", "elid=learn", "eid=") @Iteration("no_learner_id", "lid=null", "iid=install", "elid=", "eid=install")