Compare commits

...

27 Commits

Author SHA1 Message Date
Lan Hui 21918cf883 Extend assignment due date so that it can pass my tests 2025-02-22 10:08:41 +08:00
Lan Hui 62966c82fa Script.php: remove RESET Password stuff because there is no form with ID 'form_reset_password' 2024-10-26 09:46:29 +08:00
Lan Hui bc77fa1aa4 Update starter DB data so that the course_sutdents_table contains duplicate student-course info. 2024-10-26 09:38:44 +08:00
Lan Hui 9a4a8d2818 Courses.php: Fix Bug 36 2024-10-26 09:32:16 +08:00
Lan Hui 07ba57eebb Fix bug 195. 2024-10-10 15:35:00 +08:00
Lan Hui 1f602e3db2 Fix bug 204: use better parameter name. 2024-10-08 09:41:45 +08:00
Lan Hui 5ce55c3f1e Fix bug 204 2024-10-08 09:34:09 +08:00
Lan Hui 9d170fea87 Fix bug 484 2024-10-07 07:52:22 +08:00
Lan Hui 0f42a68461 Fix bug 558 2024-10-06 09:39:58 +08:00
Lan Hui e8bbce386a More informative message when no search result is returned 2024-10-05 07:43:10 +08:00
Lan Hui 545915b8be Stay on the same tab after creating a new TA account 2024-10-04 09:07:40 +08:00
Lan Hui aa82e9b5db Add one new regression test: test_student_with_weak_password_cannot_sign_up 2024-10-02 11:09:07 +08:00
Lan Hui 0a12b69d2c Show Chinese characters properly (related to Bug 200) 2024-10-02 10:30:46 +08:00
Lan Hui 54cb51d3a6 Add one new regression test: test_lecturer_can_mark_assignment (revised) 2024-10-01 14:40:58 +08:00
Lan Hui 5cef5875f6 Add one new regression test: test_lecturer_can_mark_assignment 2024-10-01 11:51:36 +08:00
Lan Hui 5e1cfcbbcc Add 2 new regression tests: test_student_can_submit_assignment & test_student_can_request_remarking 2024-09-30 16:16:03 +08:00
Lan Hui 44aa38be76 Add a new regression test: test_student_can_join_course 2024-09-28 09:46:52 +08:00
Lan Hui debd85e74d Add two new regression tests: test_student_with_valid_student_number_can_sign_up, test_student_with_invalid_student_number_cannot_sign_up 2024-09-27 10:16:01 +08:00
Lan Hui 39c14f7425 Add a new regression test: test_lecturer_can_add_student_numbers 2024-09-26 18:14:37 +08:00
Lan Hui 1ed7e2e394 Add test case: test_lecturer_can_post_assignment 2024-09-25 16:10:55 +08:00
Lan Hui a34ab61916 Add a new regression test 2024-09-24 09:09:54 +08:00
Lan Hui 33f997412b Improve the test script 2024-09-22 11:28:02 +08:00
Lan Hui b1dbd94b00 Add a regression test script and fix bug 2024-09-22 10:50:49 +08:00
Lan Hui 7388868678 README.md: edit 2024-09-17 14:58:47 +08:00
Lan Hui aa85b742f5 README.md: how to restore database 2024-09-17 14:51:22 +08:00
Lan Hui e1c95395ef README.md: seperate Q and A into two different lines 2024-09-17 14:40:23 +08:00
mrlan 65920bc0ac Merge pull request 'Fix bug 193 http://118.25.96.118/bugzilla/show_bug.cgi?id=193' (#35) from Bug193-Martha into Hui-Organize
Reviewed-on: #35
2024-09-16 19:25:29 +08:00
10 changed files with 485 additions and 95 deletions

View File

@ -30,7 +30,7 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") {
<ul class="nav nav-tabs" id="myTab">
<li class="nav-item">
<a class="nav-link active" href="#tab-student-accounts" id="batch_tab">Create student accounts</a>
<a class="nav-link active" href="#tab-student-accounts" id="batch_tab">Enter student numbers</a>
</li>
<li class="nav-item">
@ -66,7 +66,7 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") {
?>
<form method="post" action="Script.php" id="create_account_form">
<input type="hidden" name="form_createlecturrer" value="true" required="" />
<input type="hidden" name="form_createlecturer" value="true" required="" />
Full name
<input type="text" name="fullname" placeholder="Full Name" class="form-control" required=""> <br>
Email
@ -93,10 +93,6 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") {
echo '<hr><div class="alert alert-warning" role="alert">' . $_SESSION['info_Admin_Users'] . '</div>';
$_SESSION['info_Admin_Users'] = null;
}
if (isset($_SESSION['info_Admin_Users'])) {
echo '<hr><div class="alert alert-warning" role="alert">' . $_SESSION['info_Admin_Users'] . '</div>';
$_SESSION['info_Admin_Users'] = null;
}
?>
</form>
@ -117,10 +113,21 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") {
<?php
if ($_SESSION['user_type'] == "Lecturer") {
$user_id = $_SESSION['user_id'];
echo "<script>console.log('here {$user_id}');</script>"; // debug trick
// find the TAs in the courses taught by this instructor
$ta_result = mysqli_query(
$con,
"SELECT TA FROM course_ta INNER JOIN courses_table ON course_ta.Course_ID=courses_table.Course_ID WHERE courses_table.Lecturer_User_ID=$user_id"
);
$ta_ids = array(-1); // -1 is non-existent ID
while ($row = mysqli_fetch_assoc($ta_result)) {
array_push($ta_ids, $row['TA']);
}
$ta_ids2 = implode(', ', $ta_ids);
$result = mysqli_query(
$con,
"SELECT * FROM users_table WHERE UserType in ('TA')"
"SELECT * FROM users_table WHERE UserType in ('TA') and User_ID in ($ta_ids2)"
);
}
@ -131,6 +138,7 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") {
);
}
$num_rows = 0;
while ($row = mysqli_fetch_assoc($result)) {
$pass = $row['Password'];
$btn = "<button class='btn btn-warning' onclick=\"updatePassword(" . $row['User_ID'] . ",'$pass')\">Reset</button>";
@ -143,6 +151,10 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") {
}
echo "<tr><td>" . $row['User_ID'] . "</td><td>" . $row['Full_Name'] . "</td><td>" . $row['Email'] . "</td><td>$btn</td><td>$btnBlock</td></tr>";
$num_rows += 1;
}
if ($num_rows == 0) {
echo "<p>No TA</p>";
}
?>
</table>
@ -227,8 +239,22 @@ if ($_SESSION['user_type'] != "Lecturer" && $_SESSION['user_type'] != "Admin") {
</div>
<?php include 'Footer.php';?>
<script>
/** After creating a TA account, stay on the same tab "Create instructor account"
Side effect: ?tacreated will be appended on the URL
*/
document.addEventListener("DOMContentLoaded", () => {
const url = new URL(window.location.href);
if (url.searchParams.has('tacreated')) {
const elem = document.querySelector('#tab_ins_accounts');
elem.click();
}
});
</script>
<script>
function updatePassword(id, pass) {
if (!confirm('Are you sure to reset user password?')) {

View File

@ -152,7 +152,7 @@ include 'Header.php';
$att3 = $row['Attachment_link_3'];
$att4 = $row['Attachment_link_4'];
$labid = $row['Lab_Report_ID'];
$days_remaining = date_diff(date_create($deadline), date_create())->format('%a days, %h hours, %i minutes');
$days_remaining = "Days remaining: ".date_diff(date_create($deadline), date_create())->format('%a days, %h hours, %i minutes');
$full_link = "<a href='~\..\Download.php?file=$att1'>$att1</a>";
if($att2 != "") {
@ -165,6 +165,11 @@ include 'Header.php';
$full_link = $full_link."| <a href='~\..\Download.php?file=$att4'>$att4</a>";
}
// check if the student has already submitted the assignment
$query_result = mysqli_query($con, "SELECT * FROM lab_report_submissions WHERE Student_id=$student_id AND Lab_Report_ID=$labid");
if (mysqli_num_rows($query_result) > 0)
$days_remaining = 'You have already submitted this assignment.';
echo "<div class='card mt-md-2' style='word-wrap: break-word;'>
<div class='card-body'>
<h5 class='card-title'>$title</h5>
@ -172,7 +177,7 @@ include 'Header.php';
<p class='card-text'> $ins </p>
<p> <small>Attachments</small>: $full_link </p>
<p class='card-text'> <small> Posted: $posted &nbsp;&nbsp; Deadline: $deadline </small> </p>
<div class='alert alert-warning'>Time left: $days_remaining</div>
<div class='alert alert-warning'>$days_remaining</div>
<p><a href='~\..\SubmitLab.php?id=$labid&url=$url' class='btn btn-primary'>Submit</a></p>
</div>
</div>";
@ -324,10 +329,10 @@ include 'Header.php';
$att2 = $row['Attachment2'];
$att3 = $row['Attachment3'];
$att4 = $row['Attachment4'];
$base_att1 = basename($att1);
$base_att2 = basename($att2);
$base_att3 = basename($att3);
$base_att4 = basename($att4);
$base_att1 = basename(rawurldecode($att1));
$base_att2 = basename(rawurldecode($att2));
$base_att3 = basename(rawurldecode($att3));
$base_att4 = basename(rawurldecode($att4));
$full_link = "<a href='~\..\Download.php?file=$att1&attachment=1'>$base_att1</a>"; // prevent students from directly accessing their classmates' submissions
@ -647,11 +652,12 @@ include 'Header.php';
function remarking(data)
function remarking(url)
{
const details = prompt("Please enter your remarking reasons","");
window.location.href = data+"&details="+details;
if (details != null) {
window.location.href = url+"&details="+details;
}
}

View File

@ -324,7 +324,7 @@ include 'Header.php';
}
echo "</div>";
$resultx1 = mysqli_query($con, "SELECT course_students_table.Student_ID, users_table.Full_Name
$resultx1 = mysqli_query($con, "SELECT DISTINCT course_students_table.Student_ID, users_table.Full_Name
FROM course_students_table
INNER JOIN users_table on users_table.Student_ID=course_students_table.Student_ID
WHERE Course_ID=$course_id");
@ -538,7 +538,7 @@ include 'Header.php';
}
if (mysqli_num_rows($result) == 0) {
echo "No results. <hr>";
echo "No such course offered in this academic year. Please check that your have entered the correct course code.<hr>";
} else {
while($row = mysqli_fetch_assoc($result)) {
$name = $row['Course_Name'];

View File

@ -4,11 +4,16 @@ error_reporting(0);
date_default_timezone_set('Asia/Shanghai');
include "get_mysql_credentials.php";
$con = mysqli_connect("localhost", $mysql_username, $mysql_password, "lrr");
try {
$con = mysqli_connect("localhost", $mysql_username, $mysql_password, "lrr");
} catch (mysqli_sql_exception $e) {
echo $e->getMessage();
}
// Check database connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
echo " Error number: ".mysqli_connect_errno();
exit();
}
?>

View File

@ -3,9 +3,9 @@
LRR (Lab Report Repository) is an online software application for course instructors to post, receive and mark assignments, and for students to submit assignments, or submit re-marking requests.
This software was originally developed by Mahomed Nor in 2018, a graduate student in the Department of Computer Science at the Zhejiang Normal University,
while he was taking a graduate course called **Advanced Software Engineering** (http://lanlab.org/course/2018f/se/homepage.html).
while he was taking a graduate course called Advanced Software Engineering.
The LRR's project home page is at http://121.4.94.30/homepage/. For potential project contributors, we recommend that you browse its home page first to familiarize yourself with the project.
For potential project contributors, we recommend that you browse its home page at ./homepage/index.html first to familiarize yourself with the project.
@ -159,7 +159,16 @@ https://github.com/spm2020spring/TeamCollaborationTutorial/blob/master/team.rst
## Testing
Make sure your changes can pass all the tests in folder [./test](http://121.4.94.30:3000/mrlan/LRR/src/branch/master/test).
Make sure your changes can pass all the tests in folder ./test.
You cannot do too much unit testing for LRR because it almost does not
have functions or classes. However, you can do end-to-end testing.
It is important that you *restore* the database each time before your
run a test case. The fixture *restore_database* in ./test/conftest.py
is used to restore the database. Please check that. A use case for
this fixture can be found in the test script
./test/SeleniumMpiana/test_bug418_yaaqob.py. You could run this test script
by typing the following command: `pytest ./SeleniumMpiana/test_bug418_yaaqob.py`
## Communications Method
@ -173,10 +182,10 @@ We can also communicate through pull requests. You make a pull request, I revie
## Frequently Asked Questions
1. Q: The web application's front page does not show properly, i.e., elements are not well aligned.
1. Q: The web application's front page does not show properly, i.e., elements are not well aligned.
A: You missed two folders `css` and `font-awesome`. These folders include third-party js or css files and therefore are not included.
1. Q: What if I do not have any information about the `lrr` database?
1. Q: What if I do not have any information about the `lrr` database?
A: You could use `lrr_database.sql` to make a new database.
@ -249,6 +258,6 @@ Nicole-Rutagengwa - Nicole Rutagengwa - 2019169
# References
- 詹沈晨. (2020). [网页程序测试自动化 (Selenium) 测试效率](http://lanlab.org/ZhanShenchen-On-Automated-Web-Application-Test-Efficiency-with-Selenium.doc)
- 詹沈晨. (2020). 网页程序测试自动化 (Selenium) 测试效率.
- Ibrahim. (2021). [Defect analysis for LRR](http://lanlab.org/thesis/Defect-Analysis-for-LRR.docx)
- Ibrahim. (2021). Defect analysis for LRR]

View File

@ -170,8 +170,8 @@ if (!empty($_POST["form_signup"])) {
// apply password_hash()
$password_hash = password_hash($password, PASSWORD_DEFAULT);
$sql = "INSERT INTO `users_table`(`Email`, `Password`, `Full_Name`, `UserType`, `Student_ID`) VALUES "
. "('$email','$password_hash','$fullname','Student','$student_id')";
$sql = "INSERT INTO `users_table`(`Email`, `Password`, `HashPassword`, `Full_Name`, `UserType`, `Student_ID`) VALUES "
. "('$email','$password_hash','','$fullname','Student','$student_id')";
$_SESSION['user_fullname'] =$_SESSION['user_fullname_temp'];
@ -290,53 +290,8 @@ if (!empty($_POST["form_recover_password"])) {
}
}
// ################################ RESET Password #####################################
if (!empty($_POST["form_reset_password"])) {
$password = mysqli_real_escape_string($con, $_POST["password"]);
$token = mysqli_real_escape_string($con, $_POST["token"]);
$email = mysqli_real_escape_string($con, $_POST["email"]);
$result = mysqli_query(
$con,
"SELECT * FROM Users_Table WHERE email='$email'"
);
if (mysqli_num_rows($result) == 0) {
echo "invalid email";
return;
} else {
while ($row = mysqli_fetch_assoc($result)) {
$userid = $row['User_ID'];
$email = $row['Email'];
$id = $row['Student_ID'];
$user_token = $userid * $userid * $userid + $userid * 0.00343;
if ($user_token == $token) {
// Password Update
// Password Update
$hashed_password = hash('sha512', $password);
$sql = "UPDATE users_table set HashPassword='$hashed_password' where User_ID='$userid';";
if ($con->query($sql) === TRUE) {
error_reporting(0);
$_SESSION["info_login"] = " Password changed successfully , you can login now with your new password ";
header("Location: index.php");
} else {
echo "Error: " . $sql . "<br>" . $con->error;
}
} else {
echo "Invalid Token ";
}
}
}
}
// ############################### CREATE Lecturer/TA USER ##################################
if (!empty($_POST["form_createlecturrer"])){
if (!empty($_POST["form_createlecturer"])){
$email = mysqli_real_escape_string($con, $_POST["email"]);
$fullname = mysqli_real_escape_string($con, $_POST["fullname"]);
$type = mysqli_real_escape_string($con, $_POST["type"]);
@ -356,17 +311,15 @@ if (!empty($_POST["form_createlecturrer"])){
exit;
}
$password_hash = password_hash("$password", PASSWORD_DEFAULT);
$sql = "INSERT INTO `users_table`(`Email`, `Password`, `Full_Name`, `UserType`) VALUES "
. "('$email','$password_hash','$fullname','$type')";
$sql = "INSERT INTO `users_table`(`Email`, `Password`, `HashPassword`, `Full_Name`, `UserType`) VALUES ('$email','$password_hash','','$fullname','$type')";
if ($con->query($sql) === TRUE) {
try {
$result = mysqli_query($con, $sql);
$_SESSION["info_Admin_Users"] = $type . " user created successfully. Use email " . $email . " as account name and ". $password ." as password.";
header("Location: Admin.php");
} else {
alert("Error: " . $sql . "<br>" . $con->error);
header("Location: Admin.php?tacreated");
} catch (Exception $ex) {
echo "$ex";
}
}
// ### FUNCTION TO GENERATE INITIAL PASSWORDS ###//

View File

@ -151,10 +151,10 @@ echo "<div><a href='Courses.php?course=$url'> $header </a></div>";
$submitted_by = "$student_name ($submitter_student_number) for group $groupname ";
}
$base_att1 = basename($att1);
$base_att2 = basename($att2);
$base_att3 = basename($att3);
$base_att4 = basename($att4);
$base_att1 = basename(rawurldecode($att1));
$base_att2 = basename(rawurldecode($att2));
$base_att3 = basename(rawurldecode($att3));
$base_att4 = basename(rawurldecode($att4));
$full_link = "<a href='~\..\Download.php?file=$att1&attachment=1'>$base_att1</a>"; // prevent students from directly accessing their classmates' submissions

View File

@ -61,7 +61,7 @@ CREATE TABLE `courses_table` (
INSERT INTO `courses_table` (`Course_ID`, `Course_Name`, `Academic_Year`, `Faculty`, `Lecturer_User_ID`, `TA_User_ID`, `Course_Code`, `URL`, `Verify_New_Members`) VALUES
(10, 'Software Engineering', '2018', 'Computing', 8, 0, 'CSC1234', 'CSC12342018', '1'),
(11, 'Project Management', '2019', 'Computing', 8, 0, 'P.M2019', 'P.M20192019', '0'),
(11, 'Project Management', '2024', 'Computing', 8, 0, 'CSC1111', 'CSC11112024', '0'),
(12, 'Ashly Course Testing', '2020', 'Testing', 8, 0, 'Teecloudy', 'Teecloudy2020', '1');
-- --------------------------------------------------------
@ -136,7 +136,7 @@ INSERT INTO `course_students_table` (`Course_ID`, `Student_ID`, `ID`, `Status`)
(10, '201825800050', 13, 'Joined'),
(10, '201825800054', 14, 'Joined'),
(12, '201632120150', 15, 'Joined'),
(12, '2016321201502', 16, 'Joined'),
(12, '201632120150', 16, 'Joined'),
(12, '201825800050', 17, 'Joined');
-- --------------------------------------------------------
@ -200,7 +200,7 @@ CREATE TABLE `lab_reports_table` (
INSERT INTO `lab_reports_table` (`Lab_Report_ID`, `Course_ID`, `Posted_Date`, `Deadline`, `Instructions`, `Title`, `Attachment_link_1`, `Attachment_link_2`, `Attachment_link_3`, `Attachment_link_4`, `Marks`, `Type`) VALUES
(1, 10, '2019-01-11 16:52', '2019-02-11 17:00', 'Description of the lab....', 'Reading 1', '700IMPORTANT WORDS.txt', '', '', '', '4', 'Individual'),
(2, 10, '2019-01-17 11:12', '2019-01-25 23:59', 'Read this paper http://sunnyday.mit.edu/16.355/budgen-david.pdf', 'Reading 2', '586LRR-Test-caseS.pdf', '', '', '', '6', 'Individual'),
(2, 10, '2024-09-29 11:12', '2025-07-30 23:59', 'Read this paper http://sunnyday.mit.edu/16.355/budgen-david.pdf', 'Reading 2', '586LRR-Test-caseS.pdf', '', '', '', '6', 'Individual'),
(3, 12, '2020-04-05 02:48', '2020-04-12 ', 'Do this assignment in time for testing', 'First Assignment Testing', '', '', '', '', '3', 'Group'),
(4, 12, '2020-04-05 05:36', '2020-04-06 ', 'We are testing to see if the instructor can be able to modify the work', 'Second Assignment Testing', '', '', '', '', '3', 'Individual'),
(5, 12, '2020-04-05 05:51', '2020-04-08 ', 'ASQDASDASCDD', 'Third Assignment Testingas', '', '', '', '', '3', 'Individual'),
@ -235,7 +235,7 @@ CREATE TABLE `lab_report_submissions` (
--
INSERT INTO `lab_report_submissions` (`Submission_ID`, `Submission_Date`, `Lab_Report_ID`, `Student_id`, `Course_Group_id`, `Attachment1`, `Notes`, `Attachment2`, `Attachment3`, `Attachment4`, `Marks`, `Status`, `Title`, `Visibility`, `Remarking_Reason`) VALUES
(1, '2019-01-17 00:00:00', 1, '201825800050', 0, 'Reading list.txt', '-', '', '', '', 5, 'Marked', 'Reading 1 submission', 'Public', ''),
(1, '2019-01-17 00:00:00', 1, '201825800050', 0, 'Reading list.txt', '-', '', '', '', NULL, 'Pending', 'Reading 1 submission', 'Public', ''),
(5, '2019-01-21 08:31:00', 2, '201825800050', 0, 'Trial Balance.txt', ' - @2019-01-21 09:35 : Sorry I missed some details from your report', 'Boorka.jpg', '', '', 6, 'Marked', 'Submission x', 'Private', ''),
(30, '2020-04-06 23:18:00', 3, '0', 31, '/2016321201502/First Assignment Testing/UR Diagram.pdf', '<br>@2020-04-06 23:19 : ', '', '', '', 3, 'Marked', 'First Assignment Testing', 'Private', '');
@ -259,7 +259,8 @@ INSERT INTO `students_data` (`ID`, `Student_ID`, `Passport_Number`) VALUES
(1, '201825800054', 'LJ7951632'),
(2, '201825800050', 'P00581929'),
(3, '201632120150', 'FN524516'),
(4, '11', '11');
(4, '202400000001', 'NA');
-- --------------------------------------------------------
@ -285,8 +286,9 @@ CREATE TABLE `users_table` (
INSERT INTO `users_table` (`User_ID`, `Email`, `Password`, `HashPassword`, `Full_Name`, `UserType`, `Student_ID`, `Passport_Number`, `Status`) VALUES
(3, 'admin@qq.com', '$2y$10$8GCG6lTo1LFRD3bOkAyKYeOMOrFSBUgrTxaPLS5ynWN1bYDHf89pO', '', 'Kamal', 'Admin', '0', NULL, 'Active'),
(8, 'lanhui@qq.com', '1234', '', 'Lanhui', 'Lecturer', NULL, '123', 'Active'),
(9, 'mohamed@qq.com', '123', '', 'Mohamed', 'Student', '201825800050', 'P00581929', 'Active'),
(7, 'peter@qq.com', '$2y$10$8GCG6lTo1LFRD3bOkAyKYeOMOrFSBUgrTxaPLS5ynWN1bYDHf89pO', '', 'Peter', 'Lecturer', NULL, '123', 'Active'),
(8, 'lanhui@qq.com', '$2y$10$8GCG6lTo1LFRD3bOkAyKYeOMOrFSBUgrTxaPLS5ynWN1bYDHf89pO', '', 'Lanhui', 'Lecturer', NULL, '123', 'Active'),
(9, 'mohamed@qq.com', '$2y$10$8GCG6lTo1LFRD3bOkAyKYeOMOrFSBUgrTxaPLS5ynWN1bYDHf89pO', '', 'Mohamed', 'Student', '201825800050', 'P00581929', 'Active'),
(10, 'mark@qq.com', '123', '', 'Mark ', 'TA', NULL, '123', 'Active'),
(11, 'john@qq.com', '123', '', 'John', 'TA', NULL, '123', 'Active'),
(12, 'mehdi@qq.com', '123', '', 'El-mehdi Houzi', 'Student', '201825800054', 'LJ7951632', 'Active'),

View File

@ -0,0 +1,37 @@
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException, UnexpectedAlertPresentException
def login(driver, url, username, password):
try:
driver.get(url)
# Fill in the login form
user_input = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "user_name"))
)
user_input.send_keys(username)
password_input = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "user_password"))
)
password_input.send_keys(password)
# Click the login button
login_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "login_btn"))
)
login_button.click()
except (NoSuchElementException, UnexpectedAlertPresentException) as e:
return f"Error: {str(e)}"
def logout(driver):
logout_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable(
(By.XPATH, "//a[contains(@class, 'nav-link') and contains(@href, 'logout.php')]")
)
)
logout_button.click()

View File

@ -0,0 +1,352 @@
from helper import login, logout
import time
import pytest
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def test_admin_can_create_lecturer_account(driver, url, admin_username, admin_password, restore_database):
# Administrator (admin@qq.com, password 123) logs in
driver.maximize_window()
login(driver, url, admin_username, admin_password)
# Create a Lecturer account for Mr Lan (mrlan@qq.com, password [123Abc!])
tab = driver.find_element(By.ID, 'tab_ins_accounts')
tab.click()
elem = driver.find_element(By.NAME, 'fullname')
elem.send_keys('Mr Lan')
elem = driver.find_element(By.NAME, 'email')
elem.send_keys('mrlan@qq.com')
elem = driver.find_element(By.NAME, 'password')
elem.send_keys('123Abc!!')
radio_button = driver.find_element(By.NAME, 'type')
radio_button.click()
button = driver.find_element(By.NAME, 'create_btn')
button.click()
# Log out Admin account
logout(driver)
# Log in Lecturer account
login(driver, url, 'mrlan@qq.com', '123Abc!!')
elems = driver.find_elements(By.CLASS_NAME, 'nav-link')
assert '(Lecturer)' in elems[0].text
assert 'Mr Lan' in elems[0].text
driver.quit()
def test_lecturer_can_create_course(driver, url, restore_database):
# Lecturer lanhui@qq.com logs in
driver.maximize_window()
login(driver, url, 'lanhui@qq.com', '123')
# Create a course called CSC1001 Advanced Software Engineering, 2024
elem = driver.find_element(By.NAME, 'name')
elem.send_keys('Advanced Software Engineering')
elem = driver.find_element(By.NAME, 'code')
elem.send_keys('CSC1001')
elem = driver.find_element(By.NAME, 'academic')
elem.send_keys('2004')
elem = driver.find_element(By.NAME, 'faculty')
elem.send_keys('School of Computer Science and Technology')
elem = driver.find_element(By.CLASS_NAME, 'btn-primary')
elem.click()
elems = driver.find_elements(By.CLASS_NAME, 'btn-default')
last_elem = elems[-1]
assert 'Advanced Software Engineering' in last_elem.text
assert '(CSC1001)' in last_elem.text
# Logout
logout(driver)
driver.quit()
def test_lecturer_can_post_assignment(driver, url, restore_database):
# Lecturer lanhui@qq.com logs in
driver.maximize_window()
login(driver, url, 'lanhui@qq.com', '123')
# Create an assignment called Take-home quiz 1 for course (CSC1111) - Project Management
elem = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, '//div[@class="col-md-8"]/a[1]/div'))
)
elem.click()
elem = driver.find_element(By.NAME, 'deadlinedate')
elem.send_keys('002024/12/30')
elem = driver.find_element(By.NAME, 'deadlinetime')
elem.send_keys('23:59')
elem = driver.find_element(By.NAME, 'title')
elem.send_keys('Take-home quiz 1')
elem = driver.find_element(By.NAME, 'instructions')
elem.send_keys('This is a closed-book quiz.')
elem = driver.find_element(By.NAME, 'marks')
elem.send_keys('10')
radio_button = driver.find_element(By.NAME, 'type')
radio_button.click()
elem = driver.find_element(By.CLASS_NAME, 'btn-primary')
elem.click()
# Check if the assignment has been successfully posted
elem = driver.find_element(By.CLASS_NAME, 'card-title')
assert 'Take-home quiz 1 (10 Marks, Individual)' in elem.text
elem = driver.find_element(By.CLASS_NAME, 'text-muted')
assert 'Deadline: 2024-12-30' in elem.text
driver.quit()
def test_lecturer_can_add_student_numbers(driver, url, restore_database):
# Lecturer lanhui@qq.com logs in
driver.maximize_window()
login(driver, url, 'lanhui@qq.com', '123')
# Add ASE student numbers
student_numbers = '''
202420781739
202420781740
202420781741
202420781742
202420781743
202420781745
202420581366
202420581368
202420581369
202420581370
202420581372
202420581373
202420581374
202420581376
202420581378
202420581381
'''
elem = driver.find_element(By.ID, 'admin_tab')
elem.click()
elem = driver.find_element(By.NAME, 'users')
elem.send_keys(student_numbers)
elem = driver.find_element(By.ID, 'register_btn')
elem.click()
elems = driver.find_elements(By.CSS_SELECTOR, 'p')
added = 0
student_lst = [number.strip() for number in student_numbers.strip().split('\n')]
print(student_lst)
for student_no in student_lst:
for elem in elems:
if student_no in elem.text and 'added' in elem.text:
added += 1
break
assert added == len(student_lst)
driver.quit()
def test_student_with_valid_student_number_can_sign_up(driver, url, restore_database):
# Student with recognizable student number 202400000001 can sign up an account
driver.get(url)
driver.maximize_window()
elem = driver.find_element(By.ID, 'signup_link')
elem.click()
elem = driver.find_element(By.NAME, 'fullname')
elem.send_keys('Good Student')
elem = driver.find_element(By.NAME, 'user_student_id')
elem.send_keys('202400000001')
elem = driver.find_element(By.NAME, 'email')
elem.send_keys('goodstudent@qq.com')
elem = driver.find_element(By.NAME, 'password')
elem.send_keys('[123Abc]')
elem = driver.find_element(By.NAME, 'confirmpassword')
elem.send_keys('[123Abc]')
elem = driver.find_element(By.ID, 'signup_btn')
elem.click()
logout(driver)
# Log in Student account
login(driver, url, '202400000001', '[123Abc]')
elems = driver.find_elements(By.CLASS_NAME, 'nav-link')
assert 'Student ID' in elems[0].text
assert 'Good Student' in elems[0].text
driver.quit()
def test_student_with_invalid_student_number_cannot_sign_up(driver, url, restore_database):
# Student with unrecognizable student number cannot sign up an account
driver.get(url)
driver.maximize_window()
elem = driver.find_element(By.ID, 'signup_link')
elem.click()
elem = driver.find_element(By.NAME, 'fullname')
elem.send_keys('Good Student')
elem = driver.find_element(By.NAME, 'user_student_id')
elem.send_keys('202400000002')
elem = driver.find_element(By.NAME, 'email')
elem.send_keys('goodstudent@qq.com')
elem = driver.find_element(By.NAME, 'password')
elem.send_keys('[123Abc]')
elem = driver.find_element(By.NAME, 'confirmpassword')
elem.send_keys('[123Abc]')
elem = driver.find_element(By.ID, 'signup_btn')
elem.click()
# Log in Student account
login(driver, url, '202400000002', '[123Abc]')
elems = driver.find_elements(By.CLASS_NAME, 'nav-link')
assert not 'Student ID' in elems[0].text
assert not 'Good Student' in elems[0].text
driver.quit()
def test_student_with_weak_password_cannot_sign_up(driver, url, restore_database):
driver.get(url)
driver.maximize_window()
weak_password = '123Abc'
elem = driver.find_element(By.ID, 'signup_link')
elem.click()
elem = driver.find_element(By.NAME, 'fullname')
elem.send_keys('Good Student')
elem = driver.find_element(By.NAME, 'user_student_id')
elem.send_keys('202400000001')
elem = driver.find_element(By.NAME, 'email')
elem.send_keys('goodstudent@qq.com')
elem = driver.find_element(By.NAME, 'password')
elem.send_keys(weak_password)
elem = driver.find_element(By.NAME, 'confirmpassword')
elem.send_keys(weak_password)
elem = driver.find_element(By.ID, 'signup_btn')
elem.click()
# Log in Student account
login(driver, url, '202400000001', weak_password)
elems = driver.find_elements(By.CLASS_NAME, 'nav-link')
assert not 'Student ID' in elems[0].text
assert not 'Good Student' in elems[0].text
driver.quit()
def test_student_can_join_course(driver, url, restore_database):
# Student can join (CSC1111) - Project Management
login(driver, url, '201825800050', '123')
driver.maximize_window()
# Search for CSC1111
elem = driver.find_element(By.NAME, 'search')
elem.send_keys('CSC1111')
elem = driver.find_element(By.CLASS_NAME, 'btn-primary')
elem.click()
elems = driver.find_elements(By.CLASS_NAME, 'btn-default')
assert 'CSC1111' in elems[0].text
# Join
elem = driver.find_element(By.CLASS_NAME, 'btn-success') # find the green Join button
elem.click()
# Log out, then log in to check the course-joining status
logout(driver)
login(driver, url, '201825800050', '123')
elems = driver.find_elements(By.CLASS_NAME, 'btn-default')
assert 'CSC1111' in elems[0].text
assert 'Project Management' in elems[0].text
assert 'Joined' in elems[0].text
def test_student_can_submit_assignment(driver, url, restore_database):
''' Note: Make sure the fields Posted_Date and Deadline in the second row of lab_reports_table are in the current year'''
# Student can submit assignment for CSC1111
login(driver, url, '201825800050', '123')
driver.maximize_window()
# Enter into the course and the find the assignment
elems = driver.find_elements(By.CLASS_NAME, 'btn-default')
elems[1].click()
elem = driver.find_element(By.XPATH, '//div[@id="menu1"]/div/div/p/a[text()="Submit"]') # find the submit button
elem.click()
# Fill submission title, attach file, and submit
elem = driver.find_element(By.NAME, 'title')
elem.send_keys('Assignment submission from Mohamed')
elem = driver.find_element(By.NAME, 'attachment1')
elem.send_keys('/home/mrlan/Downloads/test/SeleniumHui/helper.py') # attach a file
elem = driver.find_element(By.XPATH, '//form/button')
elem.click()
# Go the Submitted tab
elem = driver.find_element(By.ID, 'myTab')
elems = elem.find_elements(By.CLASS_NAME, 'nav-link')
elems[2].click()
elem = driver.find_element(By.XPATH, '//div[@id="menu3"]/div')
assert 'Reading 2 (6 Marks)' in elem.text
assert 'SUBMITTED' in elem.text
assert 'helper.py' in elem.text
def test_student_can_request_remarking(driver, url, restore_database):
# Student logs in
login(driver, url, '201825800050', '123')
driver.maximize_window()
# Enter into the course
elems = driver.find_elements(By.CLASS_NAME, 'btn-default')
elems[1].click()
# Go the Marked tab
elem = driver.find_element(By.ID, 'myTab')
elems = elem.find_elements(By.CLASS_NAME, 'nav-link')
elems[3].click()
# Send remarking request
remarking_buttons = driver.find_elements(By.CLASS_NAME, 'btn-light')
remarking_buttons[0].click()
alert = driver.switch_to.alert
alert.send_keys('I need higher marks, teacher.')
alert.accept()
elem = driver.find_element(By.XPATH, '//div[@id="menu4"]/div/div/p/span')
assert 'Remarking request sent' == elem.text
def test_lecturer_can_mark_assignment(driver, url, restore_database):
# Lecturer lanhui@qq.com logs in
driver.maximize_window()
login(driver, url, 'lanhui@qq.com', '123')
# Enter into the course and the find the assignment
elem = driver.find_element(By.XPATH, '//div[1]/a[3]/div') # course Software Engineering
elem.click()
elem = driver.find_element(By.XPATH, '//div[2]/div[2]/div/a[2]') # View link
elem.click()
elem = driver.find_element(By.CLASS_NAME, 'btn-primary') # Blue Mark button
elem.click()
# Submit mark and comment
elem = driver.find_element(By.NAME, 'marks')
elem.send_keys('1')
elem = driver.find_element(By.NAME, 'feedback')
elem.send_keys('Inadequate')
form = driver.find_element(By.ID, 'submit-form')
form.submit()
elem = driver.find_element(By.ID, 'myTab')
elems = elem.find_elements(By.CLASS_NAME, 'nav-link')
assert 'Marked submissions (1)' == elems[1].text
elems[1].click()
elem = driver.find_element(By.XPATH, "//div[@id='menu2']/div/b")
assert 'Reading 1 submission' in elem.text
def test_lecturer_cannot_see_tas_not_from_his_course(driver, url, restore_database):
# Lecturer lanhui@qq.com logs in
driver.maximize_window()
login(driver, url, 'peter@qq.com', '123')
elem = driver.find_element(By.ID, 'admin_tab')
elem.click()
tab = driver.find_element(By.ID, 'existing_accounts_tab')
tab.click()
elem = driver.find_element(By.ID, 'tab-existing-accounts')
assert 'No TA' in elem.text
# Logout
logout(driver)
driver.quit()