From bfd9ca539ce589cd6e7c061efe45bef262085f78 Mon Sep 17 00:00:00 2001 From: MatthewDaggitt Date: Fri, 15 May 2026 11:21:00 +0800 Subject: [PATCH 1/2] Add Selenium and a basic CI script --- .github/workflows/python-app.yml | 26 +++++++++++++++++ app/controllers.py | 5 ++-- app/templates/index.html | 8 ++--- tests/selenium_tests.py | 50 ++++++++++++++++++++++++++++++-- 4 files changed, 81 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/python-app.yml diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml new file mode 100644 index 0000000..28c69c6 --- /dev/null +++ b/.github/workflows/python-app.yml @@ -0,0 +1,26 @@ +name: Application Tests + +on: + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Set up Python 3.13 + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run tests + run: | + python -m unittest tests.selenium_tests -v + python -m unittest tests.unit_tests -v \ No newline at end of file diff --git a/app/controllers.py b/app/controllers.py index 3bd086b..3ba72af 100644 --- a/app/controllers.py +++ b/app/controllers.py @@ -47,9 +47,10 @@ def create_new_group( return new_group def check_valid_student(expected_number, student_number, student_id: Optional[str]): + # print(expected_number, student_number, student_id, student_id is not None or student_id != '') if student_number > expected_number: - if student_id is not None: - raise ValueError(f"Student {student_number} should not be provided for a group of {expected_number} members.") + # if student_id is not None or student_id != '': + # raise ValueError(f"Student {student_number} should not be provided for a group of {expected_number} members.") return if not student_id: diff --git a/app/templates/index.html b/app/templates/index.html index 77b8260..329e983 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -44,10 +44,10 @@

Group project sign-up

{% for group in all_groups %} {{group.group_id}} - {{group.student1}} - {{group.student2}} - {{group.student3}} - {{group.student4}} + {{group.student1}} + {{group.student2}} + {{group.student3}} + {{group.student4}}
diff --git a/tests/selenium_tests.py b/tests/selenium_tests.py index bc1fc1f..5eb585e 100644 --- a/tests/selenium_tests.py +++ b/tests/selenium_tests.py @@ -1,5 +1,6 @@ import multiprocessing +import time from unittest import TestCase from flask import url_for @@ -8,6 +9,9 @@ from app.config import TestConfig from app.models import Group, Student, create_test_data from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC localHost = "http://127.0.0.1:5000/" @@ -34,5 +38,47 @@ def tearDown(self): self.app_context.pop() return super().tearDown() - def test_password_hashing(self): - self.driver.get(localHost) \ No newline at end of file + def test_group_creation(self): + page = CreateGroupPage(self.driver).set_group_members("3").set_student1("12345678").set_student2("87654321") + + self.driver.get(localHost) + + self.driver.find_element(By.ID, "student3").send_keys("11223344") + + self.driver.find_element(By.ID, "submitBtn").click() + + # Wait for the page to reload and the new group to be displayed + WebDriverWait(self.driver, timeout=10).until( + EC.presence_of_element_located((By.ID, "12345678")) + ) + + student1_element = self.driver.find_element(By.ID, "12345678") + self.assertIsNotNone(student1_element) + + # Assert that the student1 element contains the correct text + self.assertEqual(student1_element.text, "12345678", f"Expected student1 element to contain '12345678', but got '{student1_element.text}'") + + + def test_invalid_group_creation(self): + self.driver.find_element(By.ID, "groupMembers").send_keys("4") + self.driver.find_element(By.ID, "student1").send_keys("12345678") + self.driver.find_element(By.ID, "student2").send_keys("87654321") + self.driver.find_element(By.ID, "student3").send_keys("11223344") + + self.driver.find_element(By.ID, "submitBtn").click() + + +class CreateGroupPage: + def __init__(self, driver): + self.driver = driver + + def set_student1(self, student_id): + self.driver.find_element(By.ID, "student1").send_keys(student_id) + return self + + def set_student2(self, student_id): + self.driver.find_element(By.ID, "student2").send_keys(student_id) + return self + + def submit_form(self): + self.driver.find_element(By.ID, "submitBtn").click() \ No newline at end of file From d8c04f0fb120dd4c071ac4daa29c372f6135a0a0 Mon Sep 17 00:00:00 2001 From: MatthewDaggitt Date: Fri, 15 May 2026 11:28:16 +0800 Subject: [PATCH 2/2] Update requirements file --- requirements.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/requirements.txt b/requirements.txt index bad38d9..0719739 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,31 @@ +alembic==1.18.4 +attrs==26.1.0 blinker==1.9.0 +certifi==2026.4.22 click==8.3.3 Flask==3.1.3 +Flask-Migrate==4.1.0 +Flask-SQLAlchemy==3.1.1 +Flask-WTF==1.3.0 +greenlet==3.5.0 +h11==0.16.0 +idna==3.13 itsdangerous==2.2.0 Jinja2==3.1.6 +Mako==1.3.12 MarkupSafe==3.0.3 +outcome==1.3.0.post0 +PySocks==1.7.1 +python-dotenv==1.2.2 +selenium==4.43.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +SQLAlchemy==2.0.49 +trio==0.33.0 +trio-websocket==0.12.2 +typing_extensions==4.15.0 +urllib3==2.7.0 +websocket-client==1.9.0 Werkzeug==3.1.8 +wsproto==1.3.2 +WTForms==3.2.2