diff --git a/src/e2e/java/teammates/e2e/cases/sql/FeedbackRankOptionQuestionE2ETest.java b/src/e2e/java/teammates/e2e/cases/sql/FeedbackRankOptionQuestionE2ETest.java new file mode 100644 index 00000000000..742f6e06299 --- /dev/null +++ b/src/e2e/java/teammates/e2e/cases/sql/FeedbackRankOptionQuestionE2ETest.java @@ -0,0 +1,128 @@ +package teammates.e2e.cases.sql; + +import java.util.Arrays; +import java.util.List; + +import org.testng.annotations.Test; + +import teammates.common.datatransfer.questions.FeedbackRankOptionsQuestionDetails; +import teammates.common.datatransfer.questions.FeedbackRankOptionsResponseDetails; +import teammates.common.datatransfer.questions.FeedbackRankQuestionDetails; +import teammates.common.util.Const; +import teammates.e2e.pageobjects.FeedbackSubmitPage; +import teammates.e2e.pageobjects.InstructorFeedbackEditPage; +import teammates.storage.sqlentity.FeedbackQuestion; +import teammates.storage.sqlentity.FeedbackResponse; +import teammates.storage.sqlentity.Student; + +/** + * SUT: {@link Const.WebPageURIs#INSTRUCTOR_SESSION_EDIT_PAGE}, + * {@link Const.WebPageURIs#SESSION_SUBMISSION_PAGE} + * specifically for RankOption questions. + */ +public class FeedbackRankOptionQuestionE2ETest extends BaseFeedbackQuestionE2ETest { + + @Override + protected void prepareTestData() { + testData = removeAndRestoreDataBundle(loadSqlDataBundle("/FeedbackRankOptionQuestionE2ESqlTest.json")); + + instructor = testData.instructors.get("instructor"); + course = testData.courses.get("course"); + feedbackSession = testData.feedbackSessions.get("openSession"); + student = testData.students.get("alice.tmms@FRankOptQn.CS2104"); + } + + @Test + @Override + public void testAll() { + testEditPage(); + logout(); + testSubmitPage(); + } + + @Override + protected void testEditPage() { + InstructorFeedbackEditPage feedbackEditPage = loginToFeedbackEditPage(); + + ______TS("verify loaded question"); + FeedbackQuestion loadedQuestion = testData.feedbackQuestions.get("qn1ForFirstSession") + .makeDeepCopy(feedbackSession); + FeedbackRankOptionsQuestionDetails questionDetails = (FeedbackRankOptionsQuestionDetails) loadedQuestion + .getQuestionDetailsCopy(); + feedbackEditPage.verifyRankQuestionDetails(1, questionDetails); + + ______TS("add new question"); + // add new question exactly like loaded question + loadedQuestion.setQuestionNumber(2); + feedbackEditPage.addRankOptionsQuestion(loadedQuestion); + + feedbackEditPage.verifyRankQuestionDetails(2, questionDetails); + verifyPresentInDatabase(loadedQuestion); + + ______TS("copy question"); + FeedbackQuestion copiedQuestion = testData.feedbackQuestions.get("qn1ForSecondSession"); + questionDetails = (FeedbackRankOptionsQuestionDetails) copiedQuestion.getQuestionDetailsCopy(); + feedbackEditPage.copyQuestion(copiedQuestion.getCourseId(), + copiedQuestion.getQuestionDetailsCopy().getQuestionText()); + copiedQuestion.setFeedbackSession(feedbackSession); + copiedQuestion.setQuestionNumber(3); + + feedbackEditPage.verifyRankQuestionDetails(3, questionDetails); + verifyPresentInDatabase(copiedQuestion); + + ______TS("edit question"); + questionDetails = (FeedbackRankOptionsQuestionDetails) loadedQuestion.getQuestionDetailsCopy(); + List options = questionDetails.getOptions(); + options.remove(0); + options.set(1, "Edited option."); + questionDetails.setOptions(options); + questionDetails.setAreDuplicatesAllowed(true); + questionDetails.setMaxOptionsToBeRanked(Const.POINTS_NO_VALUE); + questionDetails.setMinOptionsToBeRanked(1); + loadedQuestion.setQuestionDetails(questionDetails); + feedbackEditPage.editRankQuestion(2, questionDetails); + feedbackEditPage.waitForPageToLoad(); + + feedbackEditPage.verifyRankQuestionDetails(2, questionDetails); + verifyPresentInDatabase(loadedQuestion); + } + + @Override + protected void testSubmitPage() { + FeedbackSubmitPage feedbackSubmitPage = loginToFeedbackSubmitPage(); + + ______TS("verify loaded question"); + FeedbackQuestion question = testData.feedbackQuestions.get("qn1ForFirstSession"); + Student receiver = testData.students.get("benny.tmms@FRankOptQn.CS2104"); + feedbackSubmitPage.verifyRankQuestion(1, receiver.getName(), + (FeedbackRankQuestionDetails) question.getQuestionDetailsCopy()); + + ______TS("submit response"); + FeedbackResponse response = getResponse(question, receiver, Arrays.asList(2, 1, 3, + Const.POINTS_NOT_SUBMITTED)); + feedbackSubmitPage.fillRankOptionResponse(1, receiver.getName(), response); + feedbackSubmitPage.clickSubmitQuestionButton(1); + + // verifyPresentInDatabase(response); + + // ______TS("check previous response"); + // feedbackSubmitPage = getFeedbackSubmitPage(); + // feedbackSubmitPage.verifyRankOptionResponse(1, receiver.getName(), response); + + // ______TS("edit response"); + // response = getResponse(questionId, receiver, + // Arrays.asList(Const.POINTS_NOT_SUBMITTED, 1, 3, 2)); + // feedbackSubmitPage.fillRankOptionResponse(1, receiver.getName(), response); + // feedbackSubmitPage.clickSubmitQuestionButton(1); + + // feedbackSubmitPage = getFeedbackSubmitPage(); + // feedbackSubmitPage.verifyRankOptionResponse(1, receiver.getName(), response); + // verifyPresentInDatabase(response); + } + + private FeedbackResponse getResponse(FeedbackQuestion question, Student receiver, List answers) { + FeedbackRankOptionsResponseDetails details = new FeedbackRankOptionsResponseDetails(); + details.setAnswers(answers); + return FeedbackResponse.makeResponse(question, student.getEmail(), null, receiver.getEmail(), null, details); + } +} diff --git a/src/e2e/java/teammates/e2e/pageobjects/FeedbackSubmitPage.java b/src/e2e/java/teammates/e2e/pageobjects/FeedbackSubmitPage.java index 21810e41525..2690df6e866 100644 --- a/src/e2e/java/teammates/e2e/pageobjects/FeedbackSubmitPage.java +++ b/src/e2e/java/teammates/e2e/pageobjects/FeedbackSubmitPage.java @@ -557,6 +557,20 @@ public void fillRankOptionResponse(int qnNumber, String recipient, FeedbackRespo } } + public void fillRankOptionResponse(int qnNumber, String recipient, FeedbackResponse response) { + FeedbackRankOptionsResponseDetails responseDetails = + (FeedbackRankOptionsResponseDetails) response.getFeedbackResponseDetailsCopy(); + List answers = responseDetails.getAnswers(); + for (int i = 0; i < answers.size(); i++) { + if (answers.get(i) == Const.POINTS_NOT_SUBMITTED) { + selectDropdownOptionByText(getRankOptionsDropdowns(qnNumber, recipient).get(i), ""); + } else { + selectDropdownOptionByText(getRankOptionsDropdowns(qnNumber, recipient).get(i), + Integer.toString(answers.get(i))); + } + } + } + public void verifyRankOptionResponse(int qnNumber, String recipient, FeedbackResponseAttributes response) { FeedbackRankOptionsResponseDetails responseDetails = (FeedbackRankOptionsResponseDetails) response.getResponseDetailsCopy(); diff --git a/src/e2e/java/teammates/e2e/pageobjects/InstructorFeedbackEditPage.java b/src/e2e/java/teammates/e2e/pageobjects/InstructorFeedbackEditPage.java index 8bcbe5a898f..4eeebab77b9 100644 --- a/src/e2e/java/teammates/e2e/pageobjects/InstructorFeedbackEditPage.java +++ b/src/e2e/java/teammates/e2e/pageobjects/InstructorFeedbackEditPage.java @@ -816,6 +816,16 @@ public void addRankOptionsQuestion(FeedbackQuestionAttributes feedbackQuestion) clickSaveNewQuestionButton(); } + public void addRankOptionsQuestion(FeedbackQuestion feedbackQuestion) { + addNewQuestion(10); + int questionNum = getNumQuestions(); + inputQuestionDetails(questionNum, feedbackQuestion); + FeedbackRankOptionsQuestionDetails questionDetails = + (FeedbackRankOptionsQuestionDetails) feedbackQuestion.getQuestionDetailsCopy(); + inputRankDetails(questionNum, questionDetails); + clickSaveNewQuestionButton(); + } + public void addRankRecipientsQuestion(FeedbackQuestionAttributes feedbackQuestion) { addNewQuestion(11); int questionNum = getNumQuestions(); diff --git a/src/e2e/resources/data/FeedbackRankOptionQuestionE2ESqlTest.json b/src/e2e/resources/data/FeedbackRankOptionQuestionE2ESqlTest.json new file mode 100644 index 00000000000..407d6a7c513 --- /dev/null +++ b/src/e2e/resources/data/FeedbackRankOptionQuestionE2ESqlTest.json @@ -0,0 +1,322 @@ +{ + "accounts": { + "instructorWithSessions": { + "id": "00000000-0000-4000-8000-000000000001", + "googleId": "tm.e2e.FRankOptQn.instructor", + "name": "Teammates Test", + "email": "tmms.test@gmail.tmt" + }, + "tm.e2e.FRankOptQn.alice.tmms": { + "id": "00000000-0000-4000-8000-000000000002", + "googleId": "tm.e2e.FRankOptQn.alice.tmms", + "name": "Alice Betsy", + "email": "alice.b.tmms@gmail.tmt" + }, + "tm.e2e.FRankOptQn.benny.tmms": { + "id": "00000000-0000-4000-8000-000000000003", + "googleId": "tm.e2e.FRankOptQn.benny.tmms", + "name": "Benny Charles", + "email": "benny.c.tmms@gmail.tmt" + }, + "tm.e2e.FRankOptQn.charlie.tmms": { + "id": "00000000-0000-4000-8000-000000000004", + "googleId": "tm.e2e.FRankOptQn.charlie.tmms", + "name": "Charlie Davis", + "email": "charlie.d.tmms@gmail.tmt" + }, + "tm.e2e.FRankOptQn.danny.tmms": { + "id": "00000000-0000-4000-8000-000000000005", + "googleId": "tm.e2e.FRankOptQn.danny.tmms", + "name": "Danny Engrid", + "email": "Danny.e.tmms@gmail.tmt" + } + }, + "accountRequests": {}, + "courses": { + "course": { + "id": "tm.e2e.FRankOptQn.CS2104", + "name": "Programming Language Concepts", + "institute": "TEAMMATES Test Institute 1", + "timeZone": "Africa/Johannesburg" + }, + "course2": { + "id": "tm.e2e.FRankOptQn.CS1101", + "name": "Programming Methodology", + "institute": "TEAMMATES Test Institute 1", + "timeZone": "Africa/Johannesburg" + } + }, + "instructors": { + "instructor": { + "id": "00000000-0000-4000-8000-000000000501", + "account": { + "id": "00000000-0000-4000-8000-000000000001" + }, + "name": "Teammates Test", + "email": "tmms.test@gmail.tmt", + "role": "INSTRUCTOR_PERMISSION_ROLE_COOWNER", + "isDisplayedToStudents": true, + "displayName": "Co-owner", + "privileges": { + "courseLevel": { + "canViewStudentInSections": true, + "canSubmitSessionInSections": true, + "canModifySessionCommentsInSections": true, + "canModifyCourse": true, + "canViewSessionInSections": true, + "canModifySession": true, + "canModifyStudent": true, + "canModifyInstructor": true + }, + "sectionLevel": {}, + "sessionLevel": {} + }, + "course": { + "id": "tm.e2e.FRankOptQn.CS2104" + } + }, + "instructor2": { + "id": "00000000-0000-4000-8000-000000000502", + "account": { + "id": "00000000-0000-4000-8000-000000000001" + }, + "course": { + "id": "tm.e2e.FRankOptQn.CS1101" + }, + "displayName": "Co-owner", + "email": "tmms.test@gmail.tmt", + "isDisplayedToStudents": true, + "name": "Teammates Test", + "privileges": { + "courseLevel": { + "canModifyCourse": true, + "canModifyInstructor": true, + "canModifySession": true, + "canModifySessionCommentsInSections": true, + "canModifyStudent": true, + "canSubmitSessionInSections": true, + "canViewSessionInSections": true, + "canViewStudentInSections": true + }, + "sectionLevel": { + }, + "sessionLevel": { + } + }, + "role": "INSTRUCTOR_PERMISSION_ROLE_COOWNER" + } + }, + "sections": { + "ProgrammingLanguageConceptsSection1": { + "id": "00000000-0000-4000-8000-000000000101", + "course": { + "id": "tm.e2e.FRankOptQn.CS2104" + }, + "name": "Section 1" + } + }, + "teams": { + "ProgrammingLanguageConceptsTeam1": { + "id": "00000000-0000-4000-8000-000000000201", + "section": { + "id": "00000000-0000-4000-8000-000000000101" + }, + "name": "Team 1" + }, + "ProgrammingLanguageConceptsTeam2": { + "id": "00000000-0000-4000-8000-000000000202", + "section": { + "id": "00000000-0000-4000-8000-000000000101" + }, + "name": "Team 2" + } + }, + "students": { + "alice.tmms@FRankOptQn.CS2104": { + "id": "00000000-0000-4000-8000-000000000601", + "account": { + "id": "00000000-0000-4000-8000-000000000002" + }, + "course": { + "id": "tm.e2e.FRankOptQn.CS2104" + }, + "team": { + "id": "00000000-0000-4000-8000-000000000201" + }, + "email": "alice.b.tmms@gmail.tmt", + "name": "Alice Betsy", + "comments": "This student's name is Alice Betsy" + }, + "benny.tmms@FRankOptQn.CS2104": { + "id": "00000000-0000-4000-8000-000000000602", + "account": { + "id": "00000000-0000-4000-8000-000000000003" + }, + "course": { + "id": "tm.e2e.FRankOptQn.CS2104" + }, + "team": { + "id": "00000000-0000-4000-8000-000000000201" + }, + "email": "benny.c.tmms@gmail.tmt", + "name": "Benny Charles", + "comments": "This student's name is Benny Charles" + }, + "charlie.tmms@FRankOptQn.CS2104": { + "id": "00000000-0000-4000-8000-000000000603", + "account": { + "id": "00000000-0000-4000-8000-000000000004" + }, + "course": { + "id": "tm.e2e.FRankOptQn.CS2104" + }, + "team": { + "id": "00000000-0000-4000-8000-000000000201" + }, + "email": "charlie.d.tmms@gmail.tmt", + "name": "Charlie Davis", + "comments": "This student's name is Charlie Davis" + }, + "danny.tmms@FRankOptQn.CS2104": { + "id": "00000000-0000-4000-8000-000000000604", + "account": { + "id": "00000000-0000-4000-8000-000000000005" + }, + "course": { + "id": "tm.e2e.FRankOptQn.CS2104" + }, + "team": { + "id": "00000000-0000-4000-8000-000000000202" + }, + "email": "danny.e.tmms@gmail.tmt", + "name": "Danny Engrid", + "comments": "This student's name is Danny Engrid" + } + }, + "feedbackSessions": { + "openSession": { + "id": "00000000-0000-4000-8000-000000000701", + "name": "First Session", + "creatorEmail": "tmms.test@gmail.tmt", + "instructions": "

Instructions for first session

", + "createdTime": "2012-04-01T23:59:00Z", + "startTime": "2012-04-01T22:00:00Z", + "endTime": "2026-04-30T22:00:00Z", + "sessionVisibleFromTime": "2012-04-01T22:00:00Z", + "resultsVisibleFromTime": "2026-05-01T22:00:00Z", + "timeZone": "Africa/Johannesburg", + "gracePeriod": 10, + "sentOpenEmail": false, + "sentClosingEmail": false, + "sentClosedEmail": false, + "sentPublishedEmail": false, + "isOpeningEmailEnabled": true, + "isClosingEmailEnabled": true, + "isPublishedEmailEnabled": true, + "studentDeadlines": {}, + "instructorDeadlines": {}, + "course": { + "id": "tm.e2e.FRankOptQn.CS2104" + } + }, + "openSession2": { + "id": "00000000-0000-4000-8000-000000000702", + "name": "Second Session", + "creatorEmail": "tmms.test@gmail.tmt", + "instructions": "

Instructions for Second session

", + "createdTime": "2012-04-01T23:59:00Z", + "startTime": "2012-04-01T22:00:00Z", + "endTime": "2026-04-30T22:00:00Z", + "sessionVisibleFromTime": "2012-04-01T22:00:00Z", + "resultsVisibleFromTime": "2026-05-01T22:00:00Z", + "timeZone": "Africa/Johannesburg", + "gracePeriod": 10, + "sentOpenEmail": false, + "sentClosingEmail": false, + "sentClosedEmail": false, + "sentPublishedEmail": false, + "isOpeningEmailEnabled": true, + "isClosingEmailEnabled": true, + "isPublishedEmailEnabled": true, + "studentDeadlines": {}, + "instructorDeadlines": {}, + "course": { + "id": "tm.e2e.FRankOptQn.CS1101" + } + } + + }, + "feedbackQuestions": { + "qn1ForFirstSession": { + "id": "00000000-0000-4000-8000-000000000801", + "feedbackSession": { + "id": "00000000-0000-4000-8000-000000000701" + }, + "questionDetails": { + "areDuplicatesAllowed": false, + "questionType": "RANK_OPTIONS", + "questionText": "As a student, rank for every teammate, the areas of improvement that they should work on", + "maxOptionsToBeRanked" : 3, + "options": [ + "Teamwork", + "Time management", + "Quality Control", + "Quality Assurance" + ] + }, + "description": "

Testing description for first session

", + "questionNumber": 1, + "giverType": "STUDENTS", + "recipientType": "OWN_TEAM_MEMBERS", + "numOfEntitiesToGiveFeedbackTo": -100, + "showResponsesTo": [ + "INSTRUCTORS", + "RECEIVER" + ], + "showGiverNameTo": [ + "INSTRUCTORS" + ], + "showRecipientNameTo": [ + "INSTRUCTORS", + "RECEIVER" + ] + }, + "qn1ForSecondSession": { + "id": "00000000-0000-4000-8000-000000000802", + "feedbackSession": { + "id": "00000000-0000-4000-8000-000000000702" + }, + "questionDetails": { + "areDuplicatesAllowed": true, + "questionText": "As an student, rank for every team, the areas of improvement that they should work on", + "questionType": "RANK_OPTIONS", + "minOptionsToBeRanked": 1, + "options": [ + "Teamwork", + "Time management", + "Quality Control", + "Quality Assurance" + ] + }, + "description": "

Testing description for second session

", + "questionNumber": 1, + "giverType": "STUDENTS", + "recipientType": "TEAMS_EXCLUDING_SELF", + "numOfEntitiesToGiveFeedbackTo": -100, + "showResponsesTo": [ + "INSTRUCTORS", + "RECEIVER" + ], + "showGiverNameTo": [ + "INSTRUCTORS" + ], + "showRecipientNameTo": [ + "INSTRUCTORS", + "RECEIVER" + ] + } + }, + "feedbackResponseComments": {}, + "notifications": {}, + "readNotifications": {} +} diff --git a/src/e2e/resources/testng-e2e-sql.xml b/src/e2e/resources/testng-e2e-sql.xml index 9f114503b43..533f8e5343f 100644 --- a/src/e2e/resources/testng-e2e-sql.xml +++ b/src/e2e/resources/testng-e2e-sql.xml @@ -9,6 +9,7 @@ + diff --git a/src/main/java/teammates/storage/sqlentity/questions/FeedbackRankOptionsQuestion.java b/src/main/java/teammates/storage/sqlentity/questions/FeedbackRankOptionsQuestion.java index e4ae21fa14c..ba135c7cae8 100644 --- a/src/main/java/teammates/storage/sqlentity/questions/FeedbackRankOptionsQuestion.java +++ b/src/main/java/teammates/storage/sqlentity/questions/FeedbackRankOptionsQuestion.java @@ -33,8 +33,7 @@ public FeedbackRankOptionsQuestion( String description, FeedbackParticipantType giverType, FeedbackParticipantType recipientType, Integer numOfEntitiesToGiveFeedbackTo, List showResponsesTo, List showGiverNameTo, List showRecipientNameTo, - FeedbackQuestionDetails feedbackQuestionDetails - ) { + FeedbackQuestionDetails feedbackQuestionDetails) { super(feedbackSession, questionNumber, description, giverType, recipientType, numOfEntitiesToGiveFeedbackTo, showResponsesTo, showGiverNameTo, showRecipientNameTo); setFeedBackQuestionDetails((FeedbackRankOptionsQuestionDetails) feedbackQuestionDetails); @@ -52,8 +51,7 @@ public FeedbackRankOptionsQuestion makeDeepCopy(FeedbackSession newFeedbackSessi this.getRecipientType(), this.getNumOfEntitiesToGiveFeedbackTo(), new ArrayList<>(this.getShowResponsesTo()), new ArrayList<>(this.getShowGiverNameTo()), new ArrayList<>(this.getShowRecipientNameTo()), - new FeedbackRankOptionsQuestionDetails(this.questionDetails.getQuestionText()) - ); + this.questionDetails.getDeepCopy()); } @Override