From 622ed4350f417667c4ac0e8515b794b58d1aa781 Mon Sep 17 00:00:00 2001
From: yaaqob <3237084594@qq.com>
Date: Mon, 29 Apr 2024 14:14:19 +0800
Subject: [PATCH 1/3] added my version of the test script

---
 test/SeleniumMpiana/conftest.py           |  32 +++++
 test/SeleniumMpiana/test_bug418_yaaqob.py | 157 ++++++++++++++++++++++
 2 files changed, 189 insertions(+)
 create mode 100644 test/SeleniumMpiana/conftest.py
 create mode 100644 test/SeleniumMpiana/test_bug418_yaaqob.py

diff --git a/test/SeleniumMpiana/conftest.py b/test/SeleniumMpiana/conftest.py
new file mode 100644
index 0000000..bf0d051
--- /dev/null
+++ b/test/SeleniumMpiana/conftest.py
@@ -0,0 +1,32 @@
+import os
+import pytest
+
+
+@pytest.fixture
+def restore_database():
+    ''' Restore the database.
+        It is useful for making sure that each end-to-end test
+        starts with the same database.
+        Benefit: we can reproduce the same test result.
+    '''
+
+    PASSWORD = ''  # root password
+    DB_NAME = 'lrr' # database name used for LRR
+
+    # commands used to import data to DB_NAME
+    cmds = [
+        f'mysql -u root -p{PASSWORD} -e "DROP DATABASE IF EXISTS {DB_NAME};"',        
+        f'mysql -u root -p{PASSWORD} -e "CREATE DATABASE {DB_NAME};"',
+        f'mysql -u root -p{PASSWORD} -e "GRANT ALL PRIVILEGES ON {DB_NAME}.* TO lrr@localhost WITH GRANT OPTION;"',
+        f'mysql -u root -p{PASSWORD} {DB_NAME} < lrr_database.sql']
+
+    yield
+
+    for command in cmds:
+        os.system(command)
+    return None
+
+
+@pytest.fixture
+def url():
+    return '' # URL of the LRR
\ No newline at end of file
diff --git a/test/SeleniumMpiana/test_bug418_yaaqob.py b/test/SeleniumMpiana/test_bug418_yaaqob.py
new file mode 100644
index 0000000..155d353
--- /dev/null
+++ b/test/SeleniumMpiana/test_bug418_yaaqob.py
@@ -0,0 +1,157 @@
+import pytest
+from selenium import webdriver
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.ui import Select
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.support import expected_conditions as EC
+from selenium.common.exceptions import NoSuchElementException, UnexpectedAlertPresentException
+
+# Credentials for login, make sure to create a user with Admin role for these test to work
+username = "" # Admin user email
+password = "" # Admin user password
+
+driver = webdriver.Chrome()
+driver.get("") # URL of the LRR
+
+def login(driver, username, password):
+    try:
+        # 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()
+
+        # Wait for the admin_tab to become clickable
+        admin_tab = WebDriverWait(driver, 10).until(
+            EC.element_to_be_clickable((By.ID, "admin_tab"))
+        )
+
+        return True
+
+    except (NoSuchElementException, UnexpectedAlertPresentException) as e:
+        return f"Error: {str(e)}"
+
+
+@pytest.mark.parametrize("course_id, course_name, ta_name", [(1, "Teecloudy - Ashly Course Testing", "Mark")])
+def test_assign_a_new_ta_to_a_course(course_id, course_name, ta_name):
+    try:
+
+        login(driver, username, password)
+
+        admin_tab = WebDriverWait(driver, 10).until(
+            EC.element_to_be_clickable((By.ID, "admin_tab"))
+        )
+        admin_tab.click()
+
+        # Locate the form and select the TA
+        ta_form = WebDriverWait(driver, 15).until(
+            EC.presence_of_element_located((By.XPATH, f"//form[@id='drop_menu_form_{course_id}']"))
+        )
+
+        ta_dropdown = Select(ta_form.find_element(By.XPATH, ".//select[@name='ta']"))
+        ta_dropdown.select_by_visible_text(ta_name)
+
+        # Submit the form using JavaScript
+        driver.execute_script("arguments[0].submit();", ta_form)
+
+        # find table courses
+        table_courses = WebDriverWait(driver, 10).until(
+            EC.presence_of_element_located((By.XPATH, ".//*[@id='tab-existing-courses']/table"))
+        )
+        # find the row with matching course_name
+        course_row = table_courses.find_element(By.XPATH, f".//tr[td='{course_name}']")
+        # find the column with TA name
+        ta_column = course_row.find_element(By.XPATH, ".//td[4]")
+
+        # assert the TA name in the column
+        assert ta_name in ta_column.text, f"Error: TA name {ta_name} not found in the column {ta_column.text}"
+        
+        driver.quit()
+        
+        return True
+    
+    except NoSuchElementException as e:
+        return f"Error: {str(e)}"
+    except UnexpectedAlertPresentException as e:
+        return f"Error: {str(e)}"
+    except AssertionError as e:
+        return f"Error: {str(e)}"
+    except Exception as e:
+        return f"Error: {str(e)}"
+
+
+@pytest.mark.parametrize("course_id, course_name, ta_name", [(1, "Teecloudy - Ashly Course Testing", "Mark")])
+def test_assign_the_same_ta_to_the_same_course_twice(course_id, course_name, ta_name, restore_database):
+    try:
+        
+        login(driver, username, password)
+
+        admin_tab = WebDriverWait(driver, 10).until(
+            EC.element_to_be_clickable((By.ID, "admin_tab"))
+        )
+        admin_tab.click()
+
+        # find table courses
+        table_courses_before = WebDriverWait(driver, 10).until(
+            EC.presence_of_element_located((By.XPATH, ".//*[@id='tab-existing-courses']/table"))
+        )
+        # find the row with matching course_name
+        course_row_before = table_courses_before.find_element(By.XPATH, f".//tr[td='{course_name}']")
+        # find the column with TA name
+        old_cell_content = course_row_before.find_element(By.XPATH, ".//td[4]")
+
+        # Locate the form and select the TA
+        ta_form = WebDriverWait(driver, 15).until(
+            EC.presence_of_element_located((By.XPATH, f"//form[@id='drop_menu_form_{course_id}']"))
+        )
+
+        ta_dropdown = Select(ta_form.find_element(By.XPATH, ".//select[@name='ta']"))
+        ta_dropdown.select_by_visible_text(ta_name)
+
+        # Submit the form using JavaScript
+        driver.execute_script("arguments[0].submit();", ta_form)
+
+        # Wait for an expected alert and accept it
+        WebDriverWait(driver, 10).until(EC.alert_is_present())
+        alert = driver.switch_to.alert
+        alert_text = alert.text
+        alert.accept()
+
+        # find table courses
+        table_courses_after = WebDriverWait(driver, 10).until(
+            EC.presence_of_element_located((By.XPATH, ".//*[@id='tab-existing-courses']/table"))
+        )
+        # find the row with matching course_name
+        course_row_after = table_courses_after.find_element(By.XPATH, f".//tr[td='{course_name}']")
+        # find the column with TA name
+        new_cell_content = course_row_after.find_element(By.XPATH, ".//td[4]")
+
+        # assert the TA name in the column
+        assert old_cell_content == new_cell_content, f"Error: TA name in the column has changed from {old_cell_content} to {new_cell_content}"
+        assert alert_text == "The selected TA is already assigned to this course.", f"Error: Alert text is not as expected: {alert_text}"
+        assert restore_database == None, f"Error: Database was not restored"
+
+        driver.quit()
+
+        return True, alert_text
+    
+    except NoSuchElementException as e:
+        return f"Error: {str(e)}"
+    except UnexpectedAlertPresentException as e:
+        return f"Error: {str(e)}"
+    except AssertionError as e:
+        return f"Error: {str(e)}"
+    except Exception as e:
+        return f"Error: {str(e)}"
+    
\ No newline at end of file

From f2aa60c994e2de482902c66aaa2eefb95a1121f8 Mon Sep 17 00:00:00 2001
From: Lan Hui <lanhui@zjnu.edu.cn>
Date: Fri, 3 May 2024 15:34:39 +0800
Subject: [PATCH 2/3] Define extra fixtures (i.e., driver, url, admin_username,
 admin_password) in conftest.py and use them

---
 test/SeleniumMpiana/conftest.py           | 22 ++++--
 test/SeleniumMpiana/test_bug418_yaaqob.py | 83 +++++++++++------------
 2 files changed, 57 insertions(+), 48 deletions(-)

diff --git a/test/SeleniumMpiana/conftest.py b/test/SeleniumMpiana/conftest.py
index bf0d051..704cdb7 100644
--- a/test/SeleniumMpiana/conftest.py
+++ b/test/SeleniumMpiana/conftest.py
@@ -1,5 +1,6 @@
 import os
 import pytest
+from selenium import webdriver
 
 
 @pytest.fixture
@@ -18,9 +19,7 @@ def restore_database():
         f'mysql -u root -p{PASSWORD} -e "DROP DATABASE IF EXISTS {DB_NAME};"',        
         f'mysql -u root -p{PASSWORD} -e "CREATE DATABASE {DB_NAME};"',
         f'mysql -u root -p{PASSWORD} -e "GRANT ALL PRIVILEGES ON {DB_NAME}.* TO lrr@localhost WITH GRANT OPTION;"',
-        f'mysql -u root -p{PASSWORD} {DB_NAME} < lrr_database.sql']
-
-    yield
+        f'mysql -u root -p{PASSWORD} {DB_NAME} < ../../lrr_database.sql']
 
     for command in cmds:
         os.system(command)
@@ -29,4 +28,19 @@ def restore_database():
 
 @pytest.fixture
 def url():
-    return '' # URL of the LRR
\ No newline at end of file
+    return 'http://localhost/LRR/' # URL of LRR
+
+
+@pytest.fixture
+def driver():
+    return  webdriver.Chrome()
+
+
+@pytest.fixture
+def admin_username():
+    return 'admin@qq.com'
+
+
+@pytest.fixture
+def admin_password():
+    return '123'
diff --git a/test/SeleniumMpiana/test_bug418_yaaqob.py b/test/SeleniumMpiana/test_bug418_yaaqob.py
index 155d353..2c2835d 100644
--- a/test/SeleniumMpiana/test_bug418_yaaqob.py
+++ b/test/SeleniumMpiana/test_bug418_yaaqob.py
@@ -6,15 +6,11 @@ from selenium.webdriver.support.ui import WebDriverWait
 from selenium.webdriver.support import expected_conditions as EC
 from selenium.common.exceptions import NoSuchElementException, UnexpectedAlertPresentException
 
-# Credentials for login, make sure to create a user with Admin role for these test to work
-username = "" # Admin user email
-password = "" # Admin user password
 
-driver = webdriver.Chrome()
-driver.get("") # URL of the LRR
-
-def login(driver, username, password):
+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"))
@@ -36,24 +32,22 @@ def login(driver, username, password):
         admin_tab = WebDriverWait(driver, 10).until(
             EC.element_to_be_clickable((By.ID, "admin_tab"))
         )
-
-        return True
-
     except (NoSuchElementException, UnexpectedAlertPresentException) as e:
         return f"Error: {str(e)}"
 
 
 @pytest.mark.parametrize("course_id, course_name, ta_name", [(1, "Teecloudy - Ashly Course Testing", "Mark")])
-def test_assign_a_new_ta_to_a_course(course_id, course_name, ta_name):
+def test_assign_a_new_ta_to_a_course(course_id, course_name, ta_name, driver, url, admin_username, admin_password, restore_database):
     try:
+        driver.maximize_window()
 
-        login(driver, username, password)
+        login(driver, url, admin_username, admin_password)
 
         admin_tab = WebDriverWait(driver, 10).until(
             EC.element_to_be_clickable((By.ID, "admin_tab"))
         )
         admin_tab.click()
-
+        
         # Locate the form and select the TA
         ta_form = WebDriverWait(driver, 15).until(
             EC.presence_of_element_located((By.XPATH, f"//form[@id='drop_menu_form_{course_id}']"))
@@ -77,10 +71,6 @@ def test_assign_a_new_ta_to_a_course(course_id, course_name, ta_name):
         # assert the TA name in the column
         assert ta_name in ta_column.text, f"Error: TA name {ta_name} not found in the column {ta_column.text}"
         
-        driver.quit()
-        
-        return True
-    
     except NoSuchElementException as e:
         return f"Error: {str(e)}"
     except UnexpectedAlertPresentException as e:
@@ -89,45 +79,55 @@ def test_assign_a_new_ta_to_a_course(course_id, course_name, ta_name):
         return f"Error: {str(e)}"
     except Exception as e:
         return f"Error: {str(e)}"
+    finally:
+        driver.quit()
 
 
 @pytest.mark.parametrize("course_id, course_name, ta_name", [(1, "Teecloudy - Ashly Course Testing", "Mark")])
-def test_assign_the_same_ta_to_the_same_course_twice(course_id, course_name, ta_name, restore_database):
+def test_assign_the_same_ta_to_the_same_course_twice(course_id, course_name, ta_name, driver, url, admin_username, admin_password, restore_database):
     try:
-        
-        login(driver, username, password)
+        driver.maximize_window()        
+        login(driver, url, admin_username, admin_password)
 
         admin_tab = WebDriverWait(driver, 10).until(
             EC.element_to_be_clickable((By.ID, "admin_tab"))
         )
         admin_tab.click()
 
-        # find table courses
-        table_courses_before = WebDriverWait(driver, 10).until(
-            EC.presence_of_element_located((By.XPATH, ".//*[@id='tab-existing-courses']/table"))
-        )
-        # find the row with matching course_name
-        course_row_before = table_courses_before.find_element(By.XPATH, f".//tr[td='{course_name}']")
-        # find the column with TA name
-        old_cell_content = course_row_before.find_element(By.XPATH, ".//td[4]")
-
-        # Locate the form and select the TA
+        # Hui: assign the TA for the first time
+        # (1) Locate the form and select the TA
         ta_form = WebDriverWait(driver, 15).until(
-            EC.presence_of_element_located((By.XPATH, f"//form[@id='drop_menu_form_{course_id}']"))
-        )
+            EC.presence_of_element_located((By.XPATH,
+            f"//form[@id='drop_menu_form_{course_id}']")) )
 
         ta_dropdown = Select(ta_form.find_element(By.XPATH, ".//select[@name='ta']"))
         ta_dropdown.select_by_visible_text(ta_name)
 
-        # Submit the form using JavaScript
+        # (2) Submit the form using JavaScript
         driver.execute_script("arguments[0].submit();", ta_form)
 
+        # (3) Find table courses
+        table_courses_before = WebDriverWait(driver, 10).until(
+            EC.presence_of_element_located((By.XPATH, ".//*[@id='tab-existing-courses']/table"))
+        )
+        # (4) Find the row with matching course_name
+        course_row_before = table_courses_before.find_element(By.XPATH, f".//tr[td='{course_name}']")
+        # (5) Find the column with TA name
+        old_cell_content = course_row_before.find_element(By.XPATH, ".//td[4]").text
+
+
+        # Hui: assign the same TA again
+        ta_form = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.XPATH, f"//form[@id='drop_menu_form_{course_id}']")))
+        ta_dropdown = Select(ta_form.find_element(By.XPATH, ".//select[@name='ta']"))
+        ta_dropdown.select_by_visible_text(ta_name)        
+        driver.execute_script("arguments[0].submit();", ta_form)
+        
         # Wait for an expected alert and accept it
         WebDriverWait(driver, 10).until(EC.alert_is_present())
         alert = driver.switch_to.alert
         alert_text = alert.text
         alert.accept()
-
+        
         # find table courses
         table_courses_after = WebDriverWait(driver, 10).until(
             EC.presence_of_element_located((By.XPATH, ".//*[@id='tab-existing-courses']/table"))
@@ -135,23 +135,18 @@ def test_assign_the_same_ta_to_the_same_course_twice(course_id, course_name, ta_
         # find the row with matching course_name
         course_row_after = table_courses_after.find_element(By.XPATH, f".//tr[td='{course_name}']")
         # find the column with TA name
-        new_cell_content = course_row_after.find_element(By.XPATH, ".//td[4]")
+        new_cell_content = course_row_after.find_element(By.XPATH, ".//td[4]").text
 
         # assert the TA name in the column
         assert old_cell_content == new_cell_content, f"Error: TA name in the column has changed from {old_cell_content} to {new_cell_content}"
-        assert alert_text == "The selected TA is already assigned to this course.", f"Error: Alert text is not as expected: {alert_text}"
-        assert restore_database == None, f"Error: Database was not restored"
-
-        driver.quit()
-
-        return True, alert_text
     
     except NoSuchElementException as e:
         return f"Error: {str(e)}"
     except UnexpectedAlertPresentException as e:
         return f"Error: {str(e)}"
     except AssertionError as e:
-        return f"Error: {str(e)}"
+       return f"Error: {str(e)}"
     except Exception as e:
-        return f"Error: {str(e)}"
-    
\ No newline at end of file
+       return f"Error: {str(e)}"
+    finally:
+        driver.quit()

From 4024a36021068bf30acaa1eb4cc0607475d99ff9 Mon Sep 17 00:00:00 2001
From: Lan Hui <lanhui@zjnu.edu.cn>
Date: Fri, 10 May 2024 07:17:56 +0800
Subject: [PATCH 3/3] (1) Move conftest.py to the top level test directory so
 that it applies to all test subfolders; (2) Move login() to helper.py so that
 it could be reused by other test scripts.

---
 test/SeleniumMpiana/helper.py             | 33 +++++++++++++++++++++++
 test/SeleniumMpiana/test_bug418_yaaqob.py | 32 +---------------------
 test/{SeleniumMpiana => }/conftest.py     |  4 +--
 3 files changed, 36 insertions(+), 33 deletions(-)
 create mode 100644 test/SeleniumMpiana/helper.py
 rename test/{SeleniumMpiana => }/conftest.py (90%)

diff --git a/test/SeleniumMpiana/helper.py b/test/SeleniumMpiana/helper.py
new file mode 100644
index 0000000..bea59f9
--- /dev/null
+++ b/test/SeleniumMpiana/helper.py
@@ -0,0 +1,33 @@
+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()
+
+        # Wait for the admin_tab to become clickable
+        admin_tab = WebDriverWait(driver, 10).until(
+            EC.element_to_be_clickable((By.ID, "admin_tab"))
+        )
+    except (NoSuchElementException, UnexpectedAlertPresentException) as e:
+        return f"Error: {str(e)}"
diff --git a/test/SeleniumMpiana/test_bug418_yaaqob.py b/test/SeleniumMpiana/test_bug418_yaaqob.py
index 2c2835d..bb1a95d 100644
--- a/test/SeleniumMpiana/test_bug418_yaaqob.py
+++ b/test/SeleniumMpiana/test_bug418_yaaqob.py
@@ -1,40 +1,10 @@
 import pytest
-from selenium import webdriver
 from selenium.webdriver.common.by import By
 from selenium.webdriver.support.ui import Select
 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()
-
-        # Wait for the admin_tab to become clickable
-        admin_tab = WebDriverWait(driver, 10).until(
-            EC.element_to_be_clickable((By.ID, "admin_tab"))
-        )
-    except (NoSuchElementException, UnexpectedAlertPresentException) as e:
-        return f"Error: {str(e)}"
-
+from helper import login
 
 @pytest.mark.parametrize("course_id, course_name, ta_name", [(1, "Teecloudy - Ashly Course Testing", "Mark")])
 def test_assign_a_new_ta_to_a_course(course_id, course_name, ta_name, driver, url, admin_username, admin_password, restore_database):
diff --git a/test/SeleniumMpiana/conftest.py b/test/conftest.py
similarity index 90%
rename from test/SeleniumMpiana/conftest.py
rename to test/conftest.py
index 704cdb7..3741f44 100644
--- a/test/SeleniumMpiana/conftest.py
+++ b/test/conftest.py
@@ -11,7 +11,7 @@ def restore_database():
         Benefit: we can reproduce the same test result.
     '''
 
-    PASSWORD = ''  # root password
+    PASSWORD = 'p-@va9'  # root password
     DB_NAME = 'lrr' # database name used for LRR
 
     # commands used to import data to DB_NAME
@@ -19,7 +19,7 @@ def restore_database():
         f'mysql -u root -p{PASSWORD} -e "DROP DATABASE IF EXISTS {DB_NAME};"',        
         f'mysql -u root -p{PASSWORD} -e "CREATE DATABASE {DB_NAME};"',
         f'mysql -u root -p{PASSWORD} -e "GRANT ALL PRIVILEGES ON {DB_NAME}.* TO lrr@localhost WITH GRANT OPTION;"',
-        f'mysql -u root -p{PASSWORD} {DB_NAME} < ../../lrr_database.sql']
+        f'mysql -u root -p{PASSWORD} {DB_NAME} < ../lrr_database.sql']
 
     for command in cmds:
         os.system(command)