Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test e2e #11

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
567 changes: 567 additions & 0 deletions src/e2e/java/teammates/e2e/cases/sql/FeedbackResultsPageE2ETest.java

Large diffs are not rendered by default.

283 changes: 254 additions & 29 deletions src/e2e/java/teammates/e2e/pageobjects/FeedbackResultsPage.java

Large diffs are not rendered by default.

2,370 changes: 2,370 additions & 0 deletions src/e2e/resources/data/FeedbackResultsPageE2ESqlTest.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions src/e2e/resources/testng-e2e-sql.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@
<package name="teammates.e2e.util" />
</packages>
<classes>
<class name="teammates.e2e.cases.sql.FeedbackMcqQuestionE2ETest" />
<class name="teammates.e2e.cases.sql.FeedbackResultsPageE2ETest" />
<!-- <class name="teammates.e2e.cases.sql.FeedbackMcqQuestionE2ETest" />
<class name="teammates.e2e.cases.sql.FeedbackMsqQuestionE2ETest" />
<class name="teammates.e2e.cases.sql.FeedbackTextQuestionE2ETest" />
<class name="teammates.e2e.cases.sql.FeedbackNumScaleQuestionE2ETest" />
<class name="teammates.e2e.cases.sql.InstructorCourseDetailsPageE2ETest" />
<class name="teammates.e2e.cases.sql.StudentHomePageE2ETest" />
<class name="teammates.e2e.cases.sql.AdminSearchPageE2ETest" />
<class name="teammates.e2e.cases.sql.FeedbackRankOptionQuestionE2ETest" />
<class name="teammates.e2e.cases.sql.InstructorNotificationsPageE2ETest" />
<class name="teammates.e2e.cases.sql.InstructorNotificationsPageE2ETest" /> -->
</classes>
</test>
</suite>
4 changes: 2 additions & 2 deletions src/e2e/resources/testng-e2e.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<package name="teammates.e2e.util" />
</packages>
<classes>
<class name="teammates.e2e.cases.AutomatedSessionRemindersE2ETest" />
<!-- <class name="teammates.e2e.cases.AutomatedSessionRemindersE2ETest" />
<class name="teammates.e2e.cases.SystemErrorEmailReportE2ETest" />
<class name="teammates.e2e.cases.TimezoneSyncerTest" />
<class name="teammates.e2e.cases.AdminHomePageE2ETest" />
Expand Down Expand Up @@ -47,7 +47,7 @@
<class name="teammates.e2e.cases.StudentCourseJoinConfirmationPageE2ETest" />
<class name="teammates.e2e.cases.StudentHomePageE2ETest" />
<class name="teammates.e2e.cases.InstructorNotificationsPageE2ETest" />
<class name="teammates.e2e.cases.StudentNotificationsPageE2ETest" />
<class name="teammates.e2e.cases.StudentNotificationsPageE2ETest" /> -->
</classes>
</test>
</suite>
27 changes: 27 additions & 0 deletions src/it/java/teammates/it/ui/webapi/GetSessionResultsActionIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import teammates.common.util.HibernateUtil;
import teammates.common.util.JsonUtils;
import teammates.storage.sqlentity.Course;
import teammates.storage.sqlentity.FeedbackQuestion;
import teammates.storage.sqlentity.FeedbackSession;
import teammates.storage.sqlentity.Instructor;
import teammates.storage.sqlentity.Section;
Expand Down Expand Up @@ -153,6 +154,32 @@ protected void testExecute() {
student);

assertTrue(isSessionResultsDataEqual(expectedResults, output));

______TS("Typical: Student accesses results of their course by questionId");

loginAsStudent(student.getGoogleId());

FeedbackQuestion question = typicalBundle.feedbackQuestions.get("qn1InSession1InCourse1");

submissionParams = new String[] {
Const.ParamsNames.FEEDBACK_SESSION_NAME, accessibleFeedbackSession.getName(),
Const.ParamsNames.COURSE_ID, accessibleFeedbackSession.getCourse().getId(),
Const.ParamsNames.FEEDBACK_QUESTION_ID, question.getId().toString(),
Const.ParamsNames.INTENT, Intent.STUDENT_RESULT.name(),
};

a = getAction(submissionParams);
r = getJsonResult(a);

output = (SessionResultsData) r.getOutput();
expectedResults = SessionResultsData.initForStudent(
logic.getSessionResultsForUser(accessibleFeedbackSession,
accessibleFeedbackSession.getCourse().getId(),
student.getEmail(),
false, question.getId(), false),
student);

assertTrue(isSessionResultsDataEqual(expectedResults, output));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import teammates.common.datatransfer.FeedbackParticipantType;
import teammates.common.datatransfer.SessionResultsBundle;
import teammates.common.datatransfer.SqlSessionResultsBundle;
import teammates.common.datatransfer.TeamEvalResult;
import teammates.common.datatransfer.attributes.FeedbackQuestionAttributes;
import teammates.common.datatransfer.attributes.FeedbackResponseAttributes;
Expand All @@ -21,6 +22,8 @@
import teammates.common.util.JsonUtils;
import teammates.common.util.Logger;
import teammates.storage.sqlentity.FeedbackQuestion;
import teammates.storage.sqlentity.FeedbackResponse;
import teammates.storage.sqlentity.Student;

/**
* Contains specific structure and processing logic for contribution feedback questions.
Expand Down Expand Up @@ -70,6 +73,99 @@ public boolean isIndividualResponsesShownToStudents() {
return false;
}

@Override
public String getQuestionResultStatisticsJson(
FeedbackQuestion question, String studentEmail, SqlSessionResultsBundle bundle) {
List<FeedbackResponse> responses = bundle.getQuestionResponseMap().get(question);

boolean isStudent = studentEmail != null;

List<String> teamNames;
if (isStudent) {
teamNames = getTeamsWithAtLeastOneResponse(responses, bundle);
} else {
teamNames = new ArrayList<>(bundle.getRoster().getTeamToMembersTable().keySet());
}

// Each team's member (email) list
Map<String, List<String>> teamMembersEmail = getTeamMembersEmail(bundle, teamNames);

// Each team's responses
Map<String, List<FeedbackResponse>> teamResponses = getTeamResponses(responses, bundle, teamNames);

// Get each team's submission array. -> int[teamSize][teamSize]
// Where int[0][1] refers points from student 0 to student 1
// Where student 0 is the 0th student in the list in teamMembersEmail
Map<String, int[][]> teamSubmissionArray = getTeamSubmissionArraySql(teamNames, teamMembersEmail, teamResponses);

// Each team's contribution question results.
Map<String, TeamEvalResult> teamResults = getTeamResults(teamNames, teamSubmissionArray);
ContributionStatistics output = new ContributionStatistics();

if (isStudent) {
String currentUserTeam = bundle.getRoster().getInfoForIdentifier(studentEmail).getTeamName();
TeamEvalResult currentUserTeamResults = teamResults.get(currentUserTeam);
if (currentUserTeamResults != null) {
List<String> teamEmails = teamMembersEmail.get(currentUserTeam);
int currentUserIndex = teamEmails.indexOf(studentEmail);
int[] claimedNumbers = currentUserTeamResults.claimed[currentUserIndex];
int[] perceivedNumbers = currentUserTeamResults.denormalizedAveragePerceived[currentUserIndex];

int claimed = 0;
int perceived = 0;
Map<String, Integer> claimedOthers = new HashMap<>();
List<Integer> perceivedOthers = new ArrayList<>();

for (int i = 0; i < claimedNumbers.length; i++) {
if (i == currentUserIndex) {
claimed = claimedNumbers[i];
} else {
claimedOthers.put(teamEmails.get(i), claimedNumbers[i]);
}
}

for (int i = 0; i < perceivedNumbers.length; i++) {
if (i == currentUserIndex) {
perceived = perceivedNumbers[i];
} else {
perceivedOthers.add(perceivedNumbers[i]);
}
}
perceivedOthers.sort(Comparator.reverseOrder());

output.results.put(studentEmail, new ContributionStatisticsEntry(claimed, perceived,
claimedOthers,
perceivedOthers.stream().mapToInt(i -> i).toArray()));
}
} else {
Map<String, int[]> studentResults = getStudentResults(teamMembersEmail, teamResults);

for (Map.Entry<String, int[]> entry : studentResults.entrySet()) {
int[] summary = entry.getValue();
String email = entry.getKey();
String team = bundle.getRoster().getStudentForEmail(email).getTeam().getName();
List<String> teamEmails = teamMembersEmail.get(team);
TeamEvalResult teamResult = teamResults.get(team);
int studentIndex = teamEmails.indexOf(email);
Map<String, Integer> claimedOthers = new HashMap<>();
List<Integer> perceivedOthers = new ArrayList<>();
for (int i = 0; i < teamResult.normalizedPeerContributionRatio.length; i++) {
if (i != studentIndex) {
claimedOthers.put(teamEmails.get(i), teamResult.normalizedPeerContributionRatio[studentIndex][i]);
perceivedOthers.add(teamResult.normalizedPeerContributionRatio[i][studentIndex]);
}
}
perceivedOthers.sort(Comparator.reverseOrder());

output.results.put(email, new ContributionStatisticsEntry(summary[SUMMARY_INDEX_CLAIMED],
summary[SUMMARY_INDEX_PERCEIVED],
claimedOthers, perceivedOthers.stream().mapToInt(i -> i).toArray()));
}
}

return JsonUtils.toJson(output);
}

@Override
public String getQuestionResultStatisticsJson(
FeedbackQuestionAttributes question, String studentEmail, SessionResultsBundle bundle) {
Expand Down Expand Up @@ -220,6 +316,35 @@ private Map<String, int[][]> getTeamSubmissionArray(List<String> teamNames,
return teamSubmissionArray;
}

private Map<String, int[][]> getTeamSubmissionArraySql(List<String> teamNames,
Map<String, List<String>> teamMembersEmail,
Map<String, List<FeedbackResponse>> teamResponses) {
Map<String, int[][]> teamSubmissionArray = new LinkedHashMap<>();
for (String team : teamNames) {
int teamSize = teamMembersEmail.get(team).size();
teamSubmissionArray.put(team, new int[teamSize][teamSize]);
//Initialize all as not submitted.
for (int i = 0; i < teamSize; i++) {
for (int j = 0; j < teamSize; j++) {
teamSubmissionArray.get(team)[i][j] = Const.POINTS_NOT_SUBMITTED;
}
}
//Fill in submitted points
List<FeedbackResponse> teamResponseList = teamResponses.get(team);
List<String> memberEmailList = teamMembersEmail.get(team);
for (FeedbackResponse response : teamResponseList) {
int giverIndx = memberEmailList.indexOf(response.getGiver());
int recipientIndx = memberEmailList.indexOf(response.getRecipient());
if (giverIndx == -1 || recipientIndx == -1) {
continue;
}
int points = ((FeedbackContributionResponseDetails) response.getFeedbackResponseDetailsCopy()).getAnswer();
teamSubmissionArray.get(team)[giverIndx][recipientIndx] = points;
}
}
return teamSubmissionArray;
}

private Map<String, List<FeedbackResponseAttributes>> getTeamResponses(
List<FeedbackResponseAttributes> responses, SessionResultsBundle bundle, List<String> teamNames) {
Map<String, List<FeedbackResponseAttributes>> teamResponses = new LinkedHashMap<>();
Expand All @@ -235,6 +360,21 @@ private Map<String, List<FeedbackResponseAttributes>> getTeamResponses(
return teamResponses;
}

private Map<String, List<FeedbackResponse>> getTeamResponses(
List<FeedbackResponse> responses, SqlSessionResultsBundle bundle, List<String> teamNames) {
Map<String, List<FeedbackResponse>> teamResponses = new LinkedHashMap<>();
for (String teamName : teamNames) {
teamResponses.put(teamName, new ArrayList<>());
}
for (FeedbackResponse response : responses) {
String team = bundle.getRoster().getInfoForIdentifier(response.getGiver()).getTeamName();
if (teamResponses.containsKey(team)) {
teamResponses.get(team).add(response);
}
}
return teamResponses;
}

private Map<String, List<String>> getTeamMembersEmail(
SessionResultsBundle bundle, List<String> teamNames) {
Map<String, List<String>> teamMembersEmail = new LinkedHashMap<>();
Expand All @@ -247,6 +387,18 @@ private Map<String, List<String>> getTeamMembersEmail(
return teamMembersEmail;
}

private Map<String, List<String>> getTeamMembersEmail(
SqlSessionResultsBundle bundle, List<String> teamNames) {
Map<String, List<String>> teamMembersEmail = new LinkedHashMap<>();
for (String teamName : teamNames) {
List<String> memberEmails = bundle.getRoster().getTeamToMembersTable().get(teamName)
.stream().map(Student::getEmail)
.collect(Collectors.toList());
teamMembersEmail.put(teamName, memberEmails);
}
return teamMembersEmail;
}

private List<String> getTeamsWithAtLeastOneResponse(
List<FeedbackResponseAttributes> responses, SessionResultsBundle bundle) {
Set<String> teamNames = new HashSet<>();
Expand All @@ -257,6 +409,16 @@ private List<String> getTeamsWithAtLeastOneResponse(
return new ArrayList<>(teamNames);
}

private List<String> getTeamsWithAtLeastOneResponse(
List<FeedbackResponse> responses, SqlSessionResultsBundle bundle) {
Set<String> teamNames = new HashSet<>();
for (FeedbackResponse response : responses) {
String teamNameOfResponseGiver = bundle.getRoster().getInfoForIdentifier(response.getGiver()).getTeamName();
teamNames.add(teamNameOfResponseGiver);
}
return new ArrayList<>(teamNames);
}

@Override
public List<String> validateQuestionDetails() {
List<String> errors = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ public void updateRankRecipientQuestionResponsesAfterDeletingStudent(String cour
*/
private void makeRankRecipientQuestionResponsesConsistent(
FeedbackQuestion question, SqlCourseRoster roster) {
assert !question.getQuestionDetailsCopy().getQuestionType()
assert question.getQuestionDetailsCopy().getQuestionType()
.equals(FeedbackQuestionType.RANK_RECIPIENTS);

FeedbackParticipantType giverType = question.getGiverType();
Expand Down Expand Up @@ -593,7 +593,7 @@ private SqlSessionResultsBundle buildResultsBundle(
Set<String> studentsEmailInTeam = new HashSet<>();
if (student != null) {
for (Student studentInTeam
: roster.getTeamToMembersTable().getOrDefault(student.getTeam(), Collections.emptyList())) {
: roster.getTeamToMembersTable().getOrDefault(student.getTeam().getName(), Collections.emptyList())) {
studentsEmailInTeam.add(studentInTeam.getEmail());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ public class FeedbackResponseComment extends BaseEntity {
@UpdateTimestamp
private Instant updatedAt;

@Column(nullable = false)
private String lastEditorEmail;

protected FeedbackResponseComment() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import teammates.storage.sqlentity.FeedbackSession;
import teammates.storage.sqlentity.Instructor;
import teammates.storage.sqlentity.Student;
import teammates.storage.sqlentity.Team;
import teammates.ui.output.SessionResultsData;
import teammates.ui.request.Intent;

Expand Down Expand Up @@ -126,7 +127,7 @@ public JsonResult execute() {
if (isCourseMigrated(courseId)) {
if (questionId != null) {
UUID questionUuid = getUuidRequestParamValue(Const.ParamsNames.FEEDBACK_QUESTION_ID);
executeWithSql(courseId, feedbackSessionName, questionUuid,
return executeWithSql(courseId, feedbackSessionName, questionUuid,
selectedSection, fetchType, intent, isPreviewResults);
}
return executeWithSql(courseId, feedbackSessionName, null, selectedSection,
Expand Down Expand Up @@ -195,14 +196,16 @@ private JsonResult executeWithSql(
return new JsonResult(SessionResultsData.initForInstructor(bundle));
case INSTRUCTOR_RESULT:
// Section name filter is not applicable here
instructor = getPossiblyUnregisteredSqlInstructor(courseId);
// getSqlInstructorOfCourseFromRequest covers the case of
// getPossiblyUnregisteredSqlInstructor
instructor = getSqlInstructorOfCourseFromRequest(courseId);

bundle = sqlLogic.getSessionResultsForUser(feedbackSession, courseId, instructor.getEmail(),
true, questionUuid, isPreviewResults);

// Build a fake student object, as the results will be displayed as if they are displayed to a student
student = new Student(instructor.getCourse(), instructor.getName(), instructor.getEmail(), "");
student.setTeam(instructor.getTeam());
student.setTeam(new Team(null, Const.USER_TEAM_FOR_INSTRUCTOR));

return new JsonResult(SessionResultsData.initForStudent(bundle, student));
case STUDENT_RESULT:
Expand Down