-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* Migrate InstructorStudentListPageE2ETest * Add InstructorStudentListPageE2ETest to sql xml --------- Co-authored-by: Wei Qing <48304907+weiquu@users.noreply.github.com>
- Loading branch information
1 parent
ce839ab
commit 4aa2af7
Showing
4 changed files
with
605 additions
and
0 deletions.
There are no files selected for viewing
123 changes: 123 additions & 0 deletions
123
src/e2e/java/teammates/e2e/cases/sql/InstructorStudentListPageE2ETest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
package teammates.e2e.cases.sql; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import org.testng.annotations.Test; | ||
|
||
import teammates.common.util.AppUrl; | ||
import teammates.common.util.Const; | ||
import teammates.e2e.pageobjects.InstructorCourseEnrollPage; | ||
import teammates.e2e.pageobjects.InstructorCourseStudentDetailsEditPage; | ||
import teammates.e2e.pageobjects.InstructorCourseStudentDetailsViewPage; | ||
import teammates.e2e.pageobjects.InstructorStudentListPageSql; | ||
import teammates.e2e.pageobjects.InstructorStudentRecordsPage; | ||
import teammates.storage.sqlentity.Course; | ||
import teammates.storage.sqlentity.Instructor; | ||
import teammates.storage.sqlentity.Student; | ||
|
||
/** | ||
* SUT: {@link Const.WebPageURIs#INSTRUCTOR_STUDENT_LIST_PAGE}. | ||
*/ | ||
public class InstructorStudentListPageE2ETest extends BaseE2ETestCase { | ||
|
||
@Override | ||
protected void prepareTestData() { | ||
testData = removeAndRestoreDataBundle( | ||
loadSqlDataBundle("/InstructorStudentListPageE2ETestSql.json")); | ||
} | ||
|
||
@Test | ||
@Override | ||
public void testAll() { | ||
|
||
______TS("verify loaded data"); | ||
|
||
Instructor instructor = testData.instructors.get("instructorOfCourse1"); | ||
String instructorId = instructor.getGoogleId(); | ||
|
||
AppUrl listPageUrl = createFrontendUrl(Const.WebPageURIs.INSTRUCTOR_STUDENT_LIST_PAGE); | ||
InstructorStudentListPageSql listPage = loginToPage(listPageUrl, InstructorStudentListPageSql.class, instructorId); | ||
|
||
listPage.verifyAllCoursesHaveTabs(testData.courses.values()); | ||
|
||
Course course1 = testData.courses.get("course1"); | ||
Course course2 = testData.courses.get("course2"); | ||
Course course3 = testData.courses.get("course3"); | ||
|
||
// Expand all headers first | ||
|
||
listPage.clickCourseTabHeader(course1); | ||
listPage.clickCourseTabHeader(course2); | ||
listPage.clickCourseTabHeader(course3); | ||
|
||
Student[] studentsInCourse1 = {}; | ||
|
||
Student[] studentsInCourse3 = { | ||
testData.students.get("Student1Course3"), | ||
testData.students.get("Student2Course3"), | ||
testData.students.get("Student3Course3"), | ||
testData.students.get("Student4Course3"), | ||
}; | ||
|
||
Map<String, Student[]> courseIdToStudents = new HashMap<>(); | ||
courseIdToStudents.put(course1.getId(), studentsInCourse1); | ||
courseIdToStudents.put(course3.getId(), studentsInCourse3); | ||
|
||
Map<String, Course> courseIdToCourse = new HashMap<>(); | ||
courseIdToCourse.put(course1.getId(), course1); | ||
courseIdToCourse.put(course3.getId(), course3); | ||
|
||
listPage.verifyStudentDetails(courseIdToCourse, courseIdToStudents); | ||
listPage.verifyStudentDetailsNotViewable(course2); | ||
|
||
______TS("link: enroll page"); | ||
|
||
InstructorCourseEnrollPage enrollPage = listPage.clickEnrollStudents(course3); | ||
enrollPage.verifyIsCorrectPage(course3.getId()); | ||
|
||
listPage = getNewPageInstance(listPageUrl, InstructorStudentListPageSql.class); | ||
listPage.clickCourseTabHeader(course3); | ||
|
||
______TS("link: view student details page"); | ||
|
||
Student studentToView = testData.students.get("Student1Course3"); | ||
String studentEmail = studentToView.getEmail(); | ||
|
||
InstructorCourseStudentDetailsViewPage studentDetailsViewPage = | ||
listPage.clickViewStudent(course3, studentEmail); | ||
studentDetailsViewPage.verifyIsCorrectPage(course3.getId(), studentEmail); | ||
studentDetailsViewPage.closeCurrentWindowAndSwitchToParentWindow(); | ||
|
||
______TS("link: edit student details page"); | ||
|
||
InstructorCourseStudentDetailsEditPage studentDetailsEditPage = | ||
listPage.clickEditStudent(course3, studentEmail); | ||
studentDetailsEditPage.verifyIsCorrectPage(course3.getId(), studentEmail); | ||
studentDetailsEditPage.closeCurrentWindowAndSwitchToParentWindow(); | ||
|
||
______TS("link: view all records page"); | ||
|
||
InstructorStudentRecordsPage studentRecordsPage = | ||
listPage.clickViewAllRecords(course3, studentEmail); | ||
studentRecordsPage.verifyIsCorrectPage(course3.getId(), studentToView.getName()); | ||
studentRecordsPage.closeCurrentWindowAndSwitchToParentWindow(); | ||
|
||
______TS("action: delete student"); | ||
|
||
Student studentToDelete = testData.students.get("Student3Course3"); | ||
|
||
listPage.deleteStudent(course3, studentToDelete.getEmail()); | ||
|
||
Student[] studentsAfterDelete = { | ||
testData.students.get("Student1Course3"), | ||
testData.students.get("Student2Course3"), | ||
testData.students.get("Student4Course3"), | ||
}; | ||
|
||
listPage.verifyStudentDetails(course3, studentsAfterDelete); | ||
verifyAbsentInDatabase(studentToDelete); | ||
|
||
} | ||
|
||
} |
199 changes: 199 additions & 0 deletions
199
src/e2e/java/teammates/e2e/pageobjects/InstructorStudentListPageSql.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
package teammates.e2e.pageobjects; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.fail; | ||
|
||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import org.openqa.selenium.By; | ||
import org.openqa.selenium.WebElement; | ||
|
||
import teammates.e2e.util.TestProperties; | ||
import teammates.storage.sqlentity.Course; | ||
import teammates.storage.sqlentity.Student; | ||
import teammates.test.ThreadHelper; | ||
|
||
/** | ||
* Page Object Model for instructor student list page. | ||
*/ | ||
public class InstructorStudentListPageSql extends AppPage { | ||
|
||
public InstructorStudentListPageSql(Browser browser) { | ||
super(browser); | ||
} | ||
|
||
@Override | ||
protected boolean containsExpectedPageContents() { | ||
return getPageSource().contains("Students"); | ||
} | ||
|
||
private List<WebElement> getCoursesTabs() { | ||
return browser.driver.findElements(By.className("course-table")); | ||
} | ||
|
||
private String createHeaderText(Course course) { | ||
return String.format("[%s]: %s", course.getId(), course.getName()); | ||
} | ||
|
||
public void clickCourseTabHeader(Course course) { | ||
String targetHeader = createHeaderText(course); | ||
List<WebElement> courseTabs = getCoursesTabs(); | ||
for (WebElement courseTab : courseTabs) { | ||
WebElement headerElement = courseTab.findElement(By.className("card-header")); | ||
String header = headerElement.getText(); | ||
if (header.equals(targetHeader)) { | ||
click(headerElement); | ||
waitForPageToLoad(); | ||
waitUntilAnimationFinish(); | ||
} | ||
} | ||
} | ||
|
||
public void verifyAllCoursesHaveTabs(Collection<Course> courses) { | ||
List<WebElement> courseTabs = getCoursesTabs(); | ||
assertEquals(courses.size(), courseTabs.size()); | ||
} | ||
|
||
public void verifyStudentDetails(Map<String, Course> courses, Map<String, Student[]> students) { | ||
assertEquals(students.size(), courses.size()); | ||
|
||
students.forEach((courseId, studentsForCourse) -> verifyStudentDetails(courses.get(courseId), studentsForCourse)); | ||
} | ||
|
||
public void verifyStudentDetails(Course course, Student[] students) { | ||
WebElement targetCourse = getCourseTab(course); | ||
if (targetCourse == null) { | ||
fail("Course with ID " + course.getId() + " is not found"); | ||
} | ||
|
||
if (students.length == 0) { | ||
String noStudentText = targetCourse.findElement(By.className("card-body")).getText(); | ||
// Need to account for the text from the enroll students button as well | ||
String expectedText = "There are no students in this course." | ||
+ TestProperties.LINE_SEPARATOR + "Enroll Students"; | ||
assertEquals(expectedText, noStudentText); | ||
} else { | ||
WebElement studentList = targetCourse.findElement(By.tagName("table")); | ||
verifyTableBodyValues(studentList, getExpectedStudentValues(students)); | ||
verifyDisplayedNumbers(targetCourse, students); | ||
} | ||
} | ||
|
||
public void verifyStudentDetailsNotViewable(Course course) { | ||
WebElement targetCourse = getCourseTab(course); | ||
if (targetCourse == null) { | ||
fail("Course with ID " + course.getId() + " is not found"); | ||
} | ||
String noViewStudentsPermissionText = targetCourse.findElement(By.className("card-body")).getText(); | ||
String expectedText = "You do not have permission to view the details of the students in this course."; | ||
assertEquals(expectedText, noViewStudentsPermissionText); | ||
} | ||
|
||
private WebElement getCourseTab(Course course) { | ||
String targetHeader = createHeaderText(course); | ||
List<WebElement> courseTabs = getCoursesTabs(); | ||
|
||
return courseTabs.stream().filter(courseTab -> { | ||
String courseHeader = courseTab.findElement(By.className("card-header")).getText(); | ||
return targetHeader.equals(courseHeader); | ||
}).findFirst().orElse(null); | ||
} | ||
|
||
private void verifyDisplayedNumbers(WebElement courseTab, Student[] students) { | ||
String nStudents = courseTab.findElement(By.id("num-students")).getText(); | ||
String nSections = courseTab.findElement(By.id("num-sections")).getText(); | ||
String nTeams = courseTab.findElement(By.id("num-teams")).getText(); | ||
|
||
String expectedNStudents = students.length + " students"; | ||
String expectedNSections = Arrays.stream(students) | ||
.map(Student::getSection) | ||
.distinct() | ||
.count() + " sections"; | ||
String expectedNTeams = Arrays.stream(students) | ||
.map(Student::getTeam) | ||
.distinct() | ||
.count() + " teams"; | ||
|
||
assertEquals(expectedNStudents, nStudents); | ||
assertEquals(expectedNSections, nSections); | ||
assertEquals(expectedNTeams, nTeams); | ||
} | ||
|
||
private String[][] getExpectedStudentValues(Student[] students) { | ||
String[][] expected = new String[students.length][5]; | ||
for (int i = 0; i < students.length; i++) { | ||
Student student = students[i]; | ||
expected[i][0] = student.getSectionName(); | ||
expected[i][1] = student.getTeamName(); | ||
expected[i][2] = student.getName(); | ||
expected[i][3] = student.getGoogleId() == null ? "Yet to Join" : "Joined"; | ||
expected[i][4] = student.getEmail(); | ||
} | ||
return expected; | ||
} | ||
|
||
public void deleteStudent(Course course, String studentEmail) { | ||
clickAndConfirm(getDeleteButton(course, studentEmail)); | ||
waitUntilAnimationFinish(); | ||
} | ||
|
||
private WebElement getDeleteButton(Course course, String studentEmail) { | ||
WebElement studentRow = getStudentRow(course, studentEmail); | ||
return studentRow.findElement(By.cssSelector("[id^='btn-delete-']")); | ||
} | ||
|
||
private WebElement getStudentRow(Course course, String studentEmail) { | ||
WebElement targetCourse = getCourseTab(course); | ||
if (targetCourse == null) { | ||
fail("Course with ID " + course.getId() + " is not found"); | ||
} | ||
|
||
List<WebElement> studentRows = targetCourse.findElements(By.cssSelector("tbody tr")); | ||
for (WebElement studentRow : studentRows) { | ||
List<WebElement> studentCells = studentRow.findElements(By.tagName("td")); | ||
if (studentCells.get(4).getText().equals(studentEmail)) { | ||
return studentRow; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
public InstructorCourseEnrollPage clickEnrollStudents(Course course) { | ||
WebElement studentRow = getCourseTab(course); | ||
WebElement enrollButton = studentRow.findElement(By.id("btn-enroll")); | ||
click(enrollButton); | ||
waitForPageToLoad(); | ||
return changePageType(InstructorCourseEnrollPage.class); | ||
} | ||
|
||
public InstructorCourseStudentDetailsViewPage clickViewStudent(Course course, String studentEmail) { | ||
WebElement studentRow = getStudentRow(course, studentEmail); | ||
WebElement viewButton = studentRow.findElement(By.cssSelector("[id^='btn-view-details-']")); | ||
click(viewButton); | ||
ThreadHelper.waitFor(2000); | ||
switchToNewWindow(); | ||
return changePageType(InstructorCourseStudentDetailsViewPage.class); | ||
} | ||
|
||
public InstructorCourseStudentDetailsEditPage clickEditStudent(Course course, String studentEmail) { | ||
WebElement studentRow = getStudentRow(course, studentEmail); | ||
WebElement viewButton = studentRow.findElement(By.cssSelector("[id^='btn-edit-details-']")); | ||
click(viewButton); | ||
ThreadHelper.waitFor(2000); | ||
switchToNewWindow(); | ||
return changePageType(InstructorCourseStudentDetailsEditPage.class); | ||
} | ||
|
||
public InstructorStudentRecordsPage clickViewAllRecords(Course course, String studentEmail) { | ||
WebElement studentRow = getStudentRow(course, studentEmail); | ||
WebElement viewButton = studentRow.findElement(By.cssSelector("[id^='btn-view-records-']")); | ||
click(viewButton); | ||
ThreadHelper.waitFor(2000); | ||
switchToNewWindow(); | ||
return changePageType(InstructorStudentRecordsPage.class); | ||
} | ||
|
||
} |
Oops, something went wrong.