diff --git a/App/controllers/courses.py b/App/controllers/courses.py index 50df09e0e..3d285f0f1 100644 --- a/App/controllers/courses.py +++ b/App/controllers/courses.py @@ -3,26 +3,40 @@ from App.database import db import json, csv -def create_course(file_path): +def createPrerequistes(prereqs, courseName): + for prereq_code in prereqs: + prereq_course = Course.query.filter_by(courseCode=prereq_code).first() + + if prereq_course: + create_prereq(prereq_code,courseName) + +def create_course(code, name, rating, credits, prereqs): + already = get_course_by_courseCode(code) + if already is None: + course = Course(code, name, rating, credits) + + if prereqs: + createPrerequistes(prereqs, name) + + db.session.add(course) + db.session.commit() + return course + else: + return None + + +def createCoursesfromFile(file_path): try: with open(file_path, 'r') as file: csv_reader = csv.DictReader(file) for row in csv_reader: - course = Course() - course.courseCode = row["courseCode"] - course.courseName = row["courseName"] - course.credits = int(row["numCredits"]) - course.rating = int(row["rating"]) + courseCode = row["courseCode"] + courseName = row["courseName"] + credits = int(row["numCredits"]) + rating = int(row["rating"]) prerequisites_codes = row["preReqs"].split(',') - - if prerequisites_codes[0]: - prerequisites = [] - for prereq_code in prerequisites_codes: - prereq_course = Course.query.filter_by(courseCode=prereq_code).first() - - if prereq_course: - create_prereq(prereq_code, course.courseName) - db.session.add(course) + + create_course(courseCode, courseName, rating, credits, prerequisites_codes) except FileNotFoundError: print("File not found.") @@ -30,8 +44,7 @@ def create_course(file_path): except Exception as e: print(f"An error occurred: {e}") return False - - db.session.commit() + print("Courses added successfully.") def get_course_by_courseCode(code): @@ -46,6 +59,10 @@ def courses_Sorted_byRating(): return codes +def courses_Sorted_byRating_Objects(): + return Course.query.order_by(Course.rating.asc()).all() + + def get_prerequisites(code): course = get_course_by_courseCode(code) prereqs = get_all_prerequisites(course.courseName) diff --git a/App/controllers/staff.py b/App/controllers/staff.py index b233c1200..c90b3eec1 100644 --- a/App/controllers/staff.py +++ b/App/controllers/staff.py @@ -15,6 +15,10 @@ def verify_staff(username): return True return False +def get_staff_by_id(ID): + return Staff.query.filter_by(id=ID).first() + + # def add_program(self, program_name, description): # try: # new_program = Program(name=program_name, description=description) diff --git a/App/controllers/student.py b/App/controllers/student.py index 843c056b2..273ebd065 100644 --- a/App/controllers/student.py +++ b/App/controllers/student.py @@ -42,32 +42,10 @@ def enroll_in_programme(student_id, programme_id): db.session.add(student) db.session.commit() -def add_course_to_plan(student, course_id): - addCourse(student,course_id) - return - -def remove_course_from_plan(student, course_id): - removeCourse(student,course_id) - return - -def view_course_plan(student): - plan=getCoursePlan(student.id) - return plan - def verify_student(username): student=Student.query.filter_by(id=username).first() if student: return True return False -# def add_courses_from_file(student, file_path): -# try: -# with open(file_path, 'r') as file: -# course_ids = [line.strip() for line in file.readlines()] -# for course_id in course_ids: -# add_course_to_plan(student, course_id) -# db.session.commit() # Commit the changes after adding courses -# except FileNotFoundError: -# return "File not found." -# except Exception as e: -# return str(e) + diff --git a/App/models/courses.py b/App/models/courses.py index 386b59102..c198814c0 100644 --- a/App/models/courses.py +++ b/App/models/courses.py @@ -16,8 +16,11 @@ class Course(db.Model): # planIds = db.relationship('CoursePlanCourses', backref='courses', lazy=True) - def __init__(self): - pass + def __init__(self, code, name, rating, credits): + self.courseCode = code + self.courseName = name + self.rating = rating + self.credits = credits def get_json(self): return{ @@ -25,5 +28,4 @@ def get_json(self): 'Course Name: ': self.courseName, 'Course Rating: ': self.rating, 'No. of Credits: ': self.credits, - 'Prerequistes: ': self.prerequisites } \ No newline at end of file diff --git a/App/tests/__init__.py b/App/tests/__init__.py index f5c872faf..c3c0114f6 100644 --- a/App/tests/__init__.py +++ b/App/tests/__init__.py @@ -1 +1,4 @@ -from .test_app import * \ No newline at end of file +from .test_app import * +from .courses import * +from .program import * +from .staff import * \ No newline at end of file diff --git a/App/tests/courses.py b/App/tests/courses.py new file mode 100644 index 000000000..27ab8687e --- /dev/null +++ b/App/tests/courses.py @@ -0,0 +1,68 @@ +import pytest, unittest +from App.models import Course +from App.controllers import create_course, courses_Sorted_byRating_Objects, get_course_by_courseCode +from App.main import create_app +from App.database import db, create_db + +class CourseUnitTests(unittest.TestCase): + + def test_new_course(self): + courseCode = "INFO2605" + courseName = "Professional Ethics and Law" + credits = 3 + rating = 4 + + course = Course(courseCode, courseName, rating, credits) + + self.assertEqual(course.courseCode, courseCode) + self.assertEqual(course.courseName, courseName) + self.assertEqual(course.credits, credits) + self.assertEqual(course.rating, rating) + + def test_course_json(self): + courseCode = "INFO2605" + courseName = "Professional Ethics and Law" + credits = 3 + rating = 4 + + course = Course(courseCode, courseName, rating, credits) + course_json = course.get_json() + + self.assertDictEqual(course_json, { + 'Course Code:': courseCode, + 'Course Name: ': courseName, + 'Course Rating: ': rating, + 'No. of Credits: ': credits + }) + +@pytest.fixture(autouse=True, scope="module") +def empty_db(): + app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + create_db() + yield app.test_client() + db.drop_all() + +def test_create_course(): + courseCode = "INFO2605" + courseName = "Professional Ethics and Law" + credits = 3 + rating = 4 + prereqs=[] + + course = create_course(courseCode, courseName, rating, credits, prereqs) + + assert get_course_by_courseCode("INFO2605") != None + + +class CourseIntegrationTests(unittest.TestCase): + def test_courses_sorted_by_rating(self): + prereqs=[] + + create_course("COMP6000", "DNS", 3, 3, prereqs) + create_course("COMP6001", "DSN", 1, 3, prereqs) + sortedCourses = courses_Sorted_byRating_Objects() + + self.assertTrue(sortedCourses) + + for i in range(len(sortedCourses) - 1): + self.assertLessEqual(sortedCourses[i].rating, sortedCourses[i + 1].rating) diff --git a/App/tests/program.py b/App/tests/program.py new file mode 100644 index 000000000..7fd762af4 --- /dev/null +++ b/App/tests/program.py @@ -0,0 +1,47 @@ +import unittest, pytest +from App.models import Program +from App.main import create_app +from App.database import db, create_db +from App.controllers import create_program, get_program_by_name + +class ProgramUnitTests(unittest.TestCase): + + def test_new_program(self): + programname = "Information Technology Special" + core_credits = 69 + elective_credits = 15 + foun_credits = 9 + program = Program(programname, core_credits, elective_credits, foun_credits) + self.assertEqual(program.name, programname) + self.assertEqual(program.core_credits, core_credits) + self.assertEqual(program.elective_credits, elective_credits) + self.assertEqual(program.foun_credits, foun_credits) + + def test_program_toJSON(self): + programname = "Information Technology Special" + core_credits = 69 + elective_credits = 15 + foun_credits = 9 + + program = Program(programname, core_credits, elective_credits, foun_credits) + program_json = program.get_json() + + self.assertDictEqual(program_json, { + 'Program ID:': None, + 'Program Name: ': programname, + 'Core Credits: ': core_credits, + 'Elective Credits ': elective_credits, + 'Foundation Credits: ': foun_credits, + }) + +@pytest.fixture(autouse=True, scope="module") +def empty_db(): + app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + create_db() + yield app.test_client() + db.drop_all() + +class ProgramIntegrationTests(unittest.TestCase): + def test_create_program(self): + program = create_program("IT", 69, 15, 9) + assert get_program_by_name("IT") != None \ No newline at end of file diff --git a/App/tests/staff.py b/App/tests/staff.py new file mode 100644 index 000000000..47d04e78d --- /dev/null +++ b/App/tests/staff.py @@ -0,0 +1,59 @@ +import unittest, pytest +from App.main import create_app +from App.database import db, create_db +from App.models import Staff +from App.controllers import create_staff, get_staff_by_id, login +from werkzeug.security import generate_password_hash + +class StaffUnitTests(unittest.TestCase): + + def test_new_staff(self): + staffid = 999 + staffName = "Jane Doe" + staffpass = "janepass" + staff = Staff(staffpass, staffid, staffName) + self.assertEqual(staff.name, staffName) + self.assertEqual(staff.id, staffid) + + def test_staff_toJSON(self): + staffid = 999 + staffName = "Jane Doe" + staffpass = "janepass" + + staff = Staff(staffpass, staffid, staffName) + staff_json = staff.get_json() + + self.assertDictEqual(staff_json, { + 'staff_id': staffid, + 'name': staffName, + }) + + def test_set_password(self): + password = "mypass" + staff = Staff(password, 999, "Jane Doe") + assert staff.password != password + + def test_check_password(self): + password = "mypass" + staff = Staff(password, 999, "Jane Doe") + assert staff.check_password(password) + +@pytest.fixture(autouse=True, scope="module") +def empty_db(): + app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///test.db'}) + create_db() + yield app.test_client() + db.drop_all() + +class StaffIntegrationTests(unittest.TestCase): + def test_create_staff(self): + staffid = 9 + staffName = "Jane Doe" + staffpass = "janepass" + staff = create_staff(staffpass, staffid, staffName) + + assert staff is not None + assert get_staff_by_id(9) != None + + + \ No newline at end of file diff --git a/wsgi.py b/wsgi.py index 9ea59b8cd..fa2eab189 100644 --- a/wsgi.py +++ b/wsgi.py @@ -13,7 +13,7 @@ create_program, get_all_OfferedCodes, get_core_credits, - create_course, + createCoursesfromFile, get_course_by_courseCode, get_prerequisites, get_all_courses, @@ -48,7 +48,7 @@ def initialize(): db.drop_all() db.create_all() create_user('bob', 'bobpass') - create_course('testData/courseData.csv') + createCoursesfromFile('testData/courseData.csv') create_program("Computer Science Major", 69, 15, 9) create_student(816, "boo", "testing", "Computer Science Major") create_staff("adminpass","999", "admin") @@ -203,13 +203,48 @@ def add_offered_course(code): @click.argument("type", default="all") def user_tests_command(type): if type == "unit": - sys.exit(pytest.main(["-k", "UserUnitTests"])) + sys.exit(pytest.main(["-k", "UnitTests"])) elif type == "int": sys.exit(pytest.main(["-k", "UserIntegrationTests"])) else: sys.exit(pytest.main(["-k", "App"])) + +@test.command("course", help="Run Course tests") +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/courses.py::CourseUnitTests"])) + + elif type == "int": + sys.exit(pytest.main(["App/tests/courses.py::CourseIntegrationTests"])) + + else: + sys.exit(pytest.main(["App/tests/courses.py"])) + +@test.command("program", help="Run Program tests") +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/program.py::ProgramUnitTests"])) + elif type == "int": + sys.exit(pytest.main(["App/tests/program.py::ProgramIntegrationTests"])) + else: + sys.exit(pytest.main(["App/tests/program.py"])) + + +@test.command("staff", help="Run Staff tests") +@click.argument("type", default="all") +def courses_tests_command(type): + if type == "unit": + sys.exit(pytest.main(["App/tests/staff.py::StaffUnitTests"])) + elif type == "int": + sys.exit(pytest.main(["App/tests/staff.py::StaffIntegrationTests"])) + else: + sys.exit(pytest.main(["App/tests/staff.py"])) + + app.cli.add_command(test) ################################################################# @@ -279,11 +314,11 @@ def addProgramCourse(programname): course = AppGroup('course', help = 'Program object commands') -@course.command('create', help='Create a new course') -@click.argument('file_path') -def create_course_command(file_path): - newcourse = create_course(file_path) - print(f'Course created with course code "{newcourse.courseCode}", name "{newcourse.courseName}", credits "{newcourse.credits}", ratings "{newcourse.rating}" and prerequites "{newcourse.prerequisites}"') +# @course.command('create', help='Create a new course') +# @click.argument('file_path') +# def create_course_command(file_path): +# newcourse = create_course(file_path) +# print(f'Course created with course code "{newcourse.courseCode}", name "{newcourse.courseName}", credits "{newcourse.credits}", ratings "{newcourse.rating}" and prerequites "{newcourse.prerequisites}"') @course.command('prereqs', help='Create a new course') @@ -296,7 +331,8 @@ def create_course_command(code): @click.argument('code', type=str) def get_course(code): course = get_course_by_courseCode(code) - print(f'Course Name: {course.courseName}') if course else print(f'error') + course_json = course.get_json() + print(f'{course_json}') if course else print(f'error') @course.command('getprereqs', help='Get all prerequistes for a course') @click.argument('code', type=str)